help! my D3DXLoadSurfaceFromMemory doesn't work

Started by
4 comments, last by jhq 15 years, 8 months ago
Yes, basically I just want to load a TGA image in the memory to the backbuffer, but I can get nothing except a black screen, can anyone help me out? here is my little render route

void render()
{
	_render->BeginScene();

        // pbmp is a pointer of my Bitmap class
	_render->drawSurface(phm->pbmp->rawData());
		
	_render->EndScene();
}

void DX9Render::drawSurface(void *pSurface)
{
	if(!pSurface)
	  return;

	LPDIRECT3DSURFACE9 pDstSurface = 0;
	HRESULT hr = _pD3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pDstSurface);
	assert(SUCCEEDED(hr));

        // yes, I garantee that the input image's size is the same as backbuffer
	RECT rect = { 0, 0, _presentParams.BackBufferWidth - 1, _presentParams.BackBufferHeight - 1 };
	hr = D3DXLoadSurfaceFromMemory(pDstSurface, 0, 0, pSurface, _presentParams.BackBufferFormat, 
		(_presentParams.BackBufferFormat == D3DFMT_A8R8G8B8 ? 4 : 3) * _presentParams.BackBufferWidth,
		0, &rect, D3DX_FILTER_NONE, 0);

	pDstSurface->Release();
}
The code can run, however nothing shows on the screen, is there anything I missed? Thanks in advance :)
Advertisement
That function expects the buffer you give it to contain only raw pixel data. If you want to load a TGA, you should use D3DXCreateTextureFromFile or D3DXCreateTextureFromFileInMemory to decode the TGA into a format D3D can understand. You can then use IDirect3DDevice9::StretchRect to just copy it over to the backbuffer.
As an aside, you're never checking the return value of the function, so when it fails you don't notice. I'd be inclined to use the FAILED() macro to see if the return value is an error code, and if it is then return false or something (Make sure you release the backbuffer still), so the rest of your code can cope with it.

You could also do with using the Debug Runtimes, which will help you spot bugs like this.
Quote: MJP:
That function expects the buffer you give it to contain only raw pixel data.

I think the raw data is fine. Because before this I have used it to build a heightmap which is OK. To make is sure, I even write this:
// load image		phm->pbmp = new ico::Bitmap();		char errorMsg[256];		phm->pbmp->loadTGA("..\\media\\ps2.tga", errorMsg);		int width, height;		width = phm->pbmp->xSize();		height = phm->pbmp->ySize();		unsigned char* pData = (unsigned char*)phm->pbmp->rawData();                // load the same image into texture with the same format                 // of backbuffer		phm->pTex =	_render->createTextureFromFile(L"..\\media\\ps2.tga");		phm->pTex->getSize(width, height);			phm->heightInfo.resize(width * height, 0);		int pitch = 0;		void* pt = phm->pTex->lock(pitch);                // copy it back from tex		for(int y = 0; y < height; ++y)		    for(int x = 0; x < width; ++x)			{                             memcpy((void*)&pData[y * width + x],                                 (void*)(&((unsigned int*)pt)[y * pitch + x]), sizeof(unsigned int));			}		phm->pTex->unLock();

But, still a black screen. Any comment?

Quote:
Evil Steve:
As an aside, you're never checking the return value of the function

I checked, the return value hr is S_OK
I think the problem maybe related to some d3ddevice config stuff, cause when I change the .tga to .bmp, nothing changes ...
Now I have changed my drawSurface function to this, and everything is fine both with .bmp and .tga

void DX9Render::drawSurface(void *pSurface){	if(!pSurface)		return;	LPDIRECT3DSURFACE9 pDstSurface = 0;	HRESULT hr = _pD3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pDstSurface);	assert(SUCCEEDED(hr));	RECT rect = { 0, 0, _presentParams.BackBufferWidth - 1, _presentParams.BackBufferHeight - 1 };	LPDIRECT3DSURFACE9 pSrcSurf = 0;	hr = _pD3DDevice->CreateOffscreenPlainSurface(640, 480, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSrcSurf, 0);	hr = D3DXLoadSurfaceFromMemory(pSrcSurf, 0, 0, pSurface, _presentParams.BackBufferFormat, 		(_presentParams.BackBufferFormat == D3DFMT_A8R8G8B8 ? 4 : 3) * _presentParams.BackBufferWidth,		0, &rect, D3DX_FILTER_NONE, 0);	assert(SUCCEEDED(hr));	hr = _pD3DDevice->StretchRect(pSrcSurf, 0, pDstSurface, 0, D3DTEXF_NONE);	pDstSurface->Release();	pSrcSurf->Release();}


It seems I have to load my raw data first to some mid-surface, then transfer to the backbuffer surface.
why can't I directly load the raw data to backbuffer surface? Could anyone give me some explanation, thanks ; )

This topic is closed to new replies.

Advertisement