Sign in to follow this  

GraphicsStream behaves weird in XP, fine in Vista?

This topic is 3197 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Okay so I have a direct3d app in C# that uses very large textures (same size as the display) and they have to be updated every so often. So after bitblitting the new image into an Hbitmap, I pretty much said Bitmap Vis = Image.FromHbitmap(hBmp); _tex = new Texture(Device, Vis, Usage.Dynamic, Pool.Default); Which works, but takes about 1.4 seconds to complete. So after fiddling with it for a while (I'm just learning DirectX) I came up with the following algorithm, which takes about 90 ms to complete: //Get GDI+ bitmap from handle Bitmap Vis = Image.FromHbitmap(hBmp); //save to a memory stream MemoryStream bmp_stream = new MemoryStream(); Vis.Save(bmp_stream, ImageFormat.Bmp); //copy to byte array int bytes = (Screen.PrimaryScreen.Bounds.Width + 32) * Screen.PrimaryScreen.Bounds.Height * 4; byte[] buffer = new byte[bytes]; bmp_stream.Seek(0, SeekOrigin.Begin); bmp_stream.Read(buffer, 0, bytes); //write to graphicsstream GraphicsStream GS = _tex.LockRectangle(0, LockFlags.None); GS.Write(buffer, 54, bytes); //finish up _tex.UnlockRectangle(0); bmp_stream.Close(); Yes, that long series of copying and shuffling bytes around executes in much less time than the built-in new Texture() function or a TextureLoader (which takes about 450 ms). So first of all, if anyone knows of a better/faster way to copy an HBitmap to a Texture in C#, I'm all ears. That having been said, the problem I'm currently having is that this works fine on Vista, but when I tried it on an XP machine, the Textures are all garbled. Even working with the graphicsstream on my Vista machine, I had to make my bitmap 32 bytes wider because the Texture has 32 bytes of padding on each line (what this is for, I don't know). But on the XP machine, it doesn't have those diagonal lines you would expect to see from a width mismatch. Instead the image is broken up into well-defined boxes about 32x32 pixels that contain the same colors as the original bitmap but all garbled, sometimes I can even see small pieces of the image in some of these blocks. It's worth noting that the "new Texture()" method works on the XP machine but is still slow as crap. I'm sure it has an older version of directx but I don't know what version is on it. The internet seems to have very little information about graphicsstreams. I wouldn't be surprised if there is some easier way of doing all this that I just don't know about. Any help would be appreciated, even if it's a shot in the dark.

Share this post


Link to post
Share on other sites
The reason the MDX Texture constructor is so slow is because it's doing a GetPixel call on the image for every single pixel in the bitmap. GetPixel is a notoriously slow call, so it's no wonder you're seeing such horrible performance.

As far as your actual issue goes, I'm not entirely sure how you're calculating the number of bytes to read, or where the image information is coming from (it looks like a screenshot maybe?). I'd guess that your problem lies in that calculation somewhere. Your magic 54 also would be on the top of my suspects list. Also note that the parameters you use to create the texture will influence the data it expects you to write to it.

Additionally, you shouldn't need the MemoryStream. You can simply call Save on the bitmap using the returned GraphicsStream from the texture. I'd try that and see if it works, which would let you get around all of the calculations you're presently performing.

Share this post


Link to post
Share on other sites
Thank you for taking the time to read all that.

The number of bytes to read begins as Image Width * Image Height * BytesPerPixel, but since the Texture has 32 bytes of padding on each scanline, I had to use (Image Width + 32) to make it compatible. Yes, the image is coming from a screenshot. The 54 is the 54-byte header of the bitmap data. The Texture already has the proper width/height, so all I need to do is block-transfer the data from the bitmap to the texture.

Here is where I defined the texture:
_tex = new Texture(Device, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, 1, Usage.Dynamic, Device.DisplayMode.Format, Pool.Default);

Both computers are in the same displaymode (X8R8G8B8).

As far as writing directly to the GraphicsStream is concerned, I tried the following code:

Bitmap Vis = Image.FromHbitmap(hBmp);
GraphicsStream GS = _tex.LockRectangle(0, LockFlags.None);
Vis.Save(GS, ImageFormate.Bmp);

That works, except I can't tell it to skip the 54-byte bitmap header. This results in a very green image with a 32-pixel horizontal offset. I tried GS.Seek(54, SeekOrigin.Begin) but it doesn't seem to have any effect. Maybe there is another way to move the pointer?

Share this post


Link to post
Share on other sites
Wow.

Remember how I said I was starting with an HBitmap? Well a lot of googling, I found out you can get a Graphics object for a Texture! No way, I thought!

//get an hdc
Surface S = _tex.GetSurfaceLevel(0);
Graphics G = S.GetGraphics();
IntPtr hdc = g.GetHdc();

//bitblit the buffer to the texture
BitBlt(hdc, 0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, ScreenBufferDC, 0, 0, 0xCC0020);

//release resources
g.ReleaseHdc(hdc);
S.ReleaseGraphics();

I still don't understand this difference between a Surface and a Texture, but this code does what I'd been trying to do from the beginning, skipping a zillion pointless steps. I think I need to find a good Direct3D book and start from scratch, because I'm willing to bet I should have known this.

Share this post


Link to post
Share on other sites

This topic is 3197 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this