Not logged in, Join Here! or Log In Below:  
News Articles Search    

 Home / 3D Theory & Graphics / D3DXLoadSurfaceFromMemory() -- what am I doing wrong? Account Manager
Archive Notice: This thread is old and no longer active. It is here for reference purposes. This thread was created on an older version of the flipcode forums, before the site closed in 2005. Please keep that in mind as you view this thread, as many of the topics and opinions may be outdated.

April 29, 2005, 02:55 PM


I have a graphics program operating correctly. For example, I can use CreateTexture() to create a texture, and it shows up correctly. But I want to convert source art in D3DFMT_P8 to DXT3 at load time, and it seems like I should be able to do this with D3DXLoadSurfaceFromMemory() even if the video card does not support the D3DFMT_P8 as a texture format.

Thing is, I'm having trouble using D3DXLoadSurfaceFromMemory() at all. I simply cannot figure out what I'm doing wrong. I have finally simplified the whole problem to a test case that simply creates a buffer that represents a white texture in D3DFMT_A8R8G8B8, then I try to use D3DXLoadSurfaceFromMemory() to load my texture with this white data. So, I expect to have white models, but instead they are black (the clear color). Please keep in mind that my "source image" in memory is simply filled with 0XFFFFFFFF (to avoid any possible color arrangement problems). Further, D3DXLoadSurfaceFromMemory() returns S_OK as though everything is good. But in the end, I'm left with black textures.

Here's my simple test case where:

t is my texture class (and here contains the height and width of source)
w2 and h2 are the power-of-two dimensions for the final texture.
pTest is my goal texture
tex is a temporary pointer and currently points to the normal texture (that works correctly)

  2. IDirect3DTexture9 *pTest;
  3. IDirect3DSurface9 *pSurface;
  4. HRESULT hr = S_OK;
  5. hr = m_pd3dDevice->CreateTexture(w2, h2, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTest, NULL);
  6. hr = pTest->GetSurfaceLevel(0, &pSurface);
  7.                                         RECT SrcRect = {0, 0, t->width, t->height};
  8. char *tempBuffer = new char[t->width * t->height * 4];
  9. memset(tempBuffer, 0xFF, t->width * t->height * 4);
  11. hr = D3DXLoadSurfaceFromMemory(pSurface, NULL, NULL, tempBuffer, D3DFMT_A8R8G8B8, t->width * 4, NULL, &SrcRect, D3DX_FILTER_NONE, 0);
  12. pSurface->Release();
  13. delete tempBuffer;
  15. if (hr == S_OK)
  16. {
  17.         tex->Release();
  18.         tex = pTest;
  19. }
  20. else
  21. {
  22.         pTest->Release();
  23. }

As you may notice, one wrinkle is that I release tex, then assign it from pTest. This wasn't necessary for the test, but I wanted to present the whole picture of what I'm doing. In this case I have a fallback if for some reason the conversion does not complete successfully. You may also notice I don't actually check the other hresult values in the code. I have verified these in the debugger, everything always completes with S_OK.

If some expert could clue me, I'd be eternally grateful. It's probably just a stupid bug that I'm not seeing.


April 29, 2005, 03:19 PM

Just a quick guess - black textures could be caused by having lighting turned on, but no lights hitting the textured geometry.


April 29, 2005, 03:37 PM

As I mentioned, when I use CreateTexture() to create the texture, everything shows up fine. It's when I use D3DXLoadSurfaceFromMemory() that I get black.

Steven Hansen

April 29, 2005, 05:39 PM

Ok. From what I'm seeing, everything looks good - so this "should" work, and I've used this before...

One thing I noticed was that you are using D3DX_FILTER_NONE. DX docs state: "No scaling or filtering will take place. Pixels outside the bounds of the source image are assumed to be transparent black." Now, this probably isn't your problem... but if t->Width or t->Height were 0, everything should succeed, but your final image would be transparent black.

Is your debug output turned up? Have you tried this by actually using D3DX to load an image from file, grabbing the top surface, locking it down, and using that as your source? Might be worth a try.

One other note, I think your rectangle should be:
RECT SrcRect = { 0, 0, t->Width - 1, t->Height - 1 };
Since the Rect structure isn't { x, y, width, height }, but rather { top, left, right, bottom }.

Michael Walter

April 29, 2005, 07:10 PM

You are seeing the mipmaps?


April 29, 2005, 08:01 PM

Steven, I really appreciate the help. Thanks for giving my test a good look over. You have a point about the filter mode making "left over" pixels transparent, and if I had a texture dimensions of 0 for some reason, that would certainly explain the results.

However, I've checked in the debugger, and I'm getting normal values (128, 256, etc.). BTW according to the docs, the rect actually is the "dimensions" of the texture, and I've seen a lot of samples that simply use {0, 0, width, height), but I tried with (0, 0, width - 1, height - 1) anyway, and got the same results.

I also turned up the d3d warning level all the way to see if there were any error messages -- none. I also used the reference driver to see if it was my video card driver -- boy was that painful -- and got the same black textures.

So as I said, if I simply create the texture, lock it and fill it with the data, everything works. But this call does not. If only I knew how to convert to DXT3 in software, I'd just lock the texture, memcpy, and be done with it. As it is, I don't, so I'm currently at the mercy of D3DXLoadSurfaceFromMemory().

Michael -- I am not using mipmaps.

I also tried calling AddDirtyRect() in case the texture was just not getting updated. This did not help either. Considering how simple this test is, I have a feeling I'm going to be very embarrassed once someone finds my mistake.


April 29, 2005, 08:17 PM

I forgot to mention that I inadvertently created the test texture in D3DFMT_A8R8G8B8 in my test code above. At the end of the day, what I really want to do is create a texture as D3DFMT_DXT3 and fill it from data in D3DFMT_P8 format. Still, in this test the formats are currently the same, so this seems like it should work.


April 30, 2005, 06:07 PM

Okay. I found the problem.

It was not in my code. The guy who wrote the pixel shader, took a (1 - alpha) approach, so my test data should have been D3DCOLOR_ARGB(0, 255, 255, 255) if I wanted to see white. Sheesh! Live and learn. Hopefully you won't hear from me again (on this topic), which will mean I got the DXT3 texture compression working.

I do want to thank everyone who earnestly desired to help me out. This was my first post here at FlipCode, and I got a lot of quick replies.


May 01, 2005, 06:18 AM

You need to use delete[] tempBuffer instead of delete, by the way.

This thread contains 9 messages.
Hosting by Solid Eight Studios, maker of PhotoTangler Collage Maker.