• 10
• 10
• 12
• 12
• 14

# Problem with CreateOffscreenPlainSurface

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

## Recommended Posts

I created an array of IDirect3DSurface9 objects and in the constructor I loop through them all, setting them to NULL, like this:
Graphics::Graphics()
{
...

for(int i=0; i<4; ++i)
surfaces = NULL;
}

Then, in my Init() function, I want to create the surfaces and load the bitmaps, so I use this code:
for(int i=0; i<4; ++i)
{
if(FAILED(d3dDevice->CreateOffscreenPlainSurface(250, 250,D3DFMT_R8G8B8,
D3DPOOL_SCRATCH, &surfaces, NULL)))
{
MessageBox(NULL, "Error creating bitmap surface.", "Error",         MB_OK);
PostQuitMessage(WM_QUIT);
return false;
}

char filename[15];
wsprintf(filename, "%d%s", i, ".bmp");

if(FAILED(D3DXLoadSurfaceFromFile(surfaces, NULL, NULL, filename, NULL, D3DX_DEFAULT, 0, NULL)))
{
PostQuitMessage(WM_QUIT);
return false;
}
}

It compiles with no errors and no warnings, but when I run it, I get an error and the "Send Error Report" window. When I debug, I notice that the problem is with the following piece of code:
if(FAILED(d3dDevice->CreateOffscreenPlainSurface(250, 250, D3DFMT_R8G8B8,
D3DPOOL_SCRATCH, &surfaces, NULL)))

The problem seems to be with the 2nd line of that code, and I think it may be to do with "&surfaces", but I'm unsure. The debugger gives the following error:
0xC0000005: Access violation reading location 0x00000000.
Does anyone have any ideas as to what I may be doing wrong? Thanks. [Edited by - weegizzy on July 8, 2006 9:23:50 AM]

##### Share on other sites
That's not a Direct3D error - thats a general program error. If you get the OCA/"Send Error Report" dialog it tends to mean that you've hard-crashed your application [wink]

The error you've posted indicates you're trying to read a null pointer. Null pointers can't be dereferenced [wink]

Given the line of code you've posted it is much more likely that d3dDevice is NULL; you can quite legitimately pass in a NULL surface (the whole idea of the call is to create something useful for it to point to!).

Use an assert (or step through your code) and verify that d3dDevice is NULL, if it is, trace it back to find out how/where [smile]

hth
Jack

##### Share on other sites
Ah, yes. d3dDevice was indeed NULL. Silly me, was tryin to use it when I hadn't created it yet.

Thanks for the help.

##### Share on other sites
Sorted that problem out, but now I have another. In each frame, I want to copy a surface to the backbuffer. I think I should be using the UpdateSurface function, as the CopyRects function is no longer used in DX9. I read the documentation and it mentions some conditions, such as:

The source surface must have been created with D3DPOOL_SYSTEMMEM.
The destination surface must have been created with D3DPOOL_DEFAULT.

I was creating my surfaces using D3DPOOL_SCRATCH, so after reading the documentation, I changed it to D3DPOOL_SYSTEMMEM, but it fails when I use that. It only works with D3DPOOL_SCRATCH.

if(FAILED(graphics.GetDevice()->CreateOffscreenPlainSurface(250, 250, D3DFMT_R8G8B8, D3DPOOL_SCRATCH, &surfaces, NULL)))	{		MessageBox(NULL, "Error creating bitmap surface.", "Error", MB_OK);		PostQuitMessage(WM_QUIT);		return false;	}

Is there any other way I could do this?

Thanks.

##### Share on other sites
Copying surfaces directly to the back-buffer tends to be a horrifically slow way of rendering. Do you really need to do it this way? (Note: if you're coming from a DirectDraw background you may want to reasses your usage of D3D [wink]). You might want to look into IDirect3DDevice9::StretchRect() as your method of choice though.

The SCRATCH pool doesn't have any restrictions on what size or format resource you're creating. The other pools do - if you violate one of these restrictions then the call will fail.

The debug runtimes are an essential tool for finding out why a function is actually failing - they should output a plain-english message in your debug output. Check out the link in my signiture if you're not familiar with these.

Ideally you should be using proper enumeration before creating your resource (GetDeviceCaps() and CheckDeviceFormat()).

hth
Jack

##### Share on other sites
I'm following a book at the moment (SAMS Teach Yourself Game Programming With DirectX In 21 Days) and it uses the method I mentioned there. I was using that method so I could follow the book better. My aim is to create a simple 2D tile-based game, so I'm not sure if I'd notice much if it's a slower way. I'll read about this StretchRect thing though.

Thanks.

##### Share on other sites
Well, I tried using the StretchRect function, and I ran into the same type of problem - I was breaking the restrictions. Even when I changed the source surface to D3DPOOL_DEFAULT (as the restrictions suggested), the surface would fail to create:

if(FAILED(graphics.GetDevice()->CreateOffscreenPlainSurface(250, 250, D3DFMT_R8G8B8, D3DPOOL_DEFAULT, &surfaces, NULL)))	{		MessageBox(NULL, "Error creating bitmap surface.", "Error", MB_OK);		PostQuitMessage(WM_QUIT);		return false;	}

So, after a lot of time tweaking the code, I realised that I couldn't use D3DPOOL_DEFAULT with the Format D3DFMT_R8G8B8. So, I changed this to D3DFMT_X8R8G8B8...

if(FAILED(graphics.GetDevice()->CreateOffscreenPlainSurface(250, 250, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &surfaces, NULL)))	{		MessageBox(NULL, "Error creating bitmap surface.", "Error", MB_OK);		PostQuitMessage(WM_QUIT);		return false;	}

...and it worked! Finally.

Thanks for the help.

##### Share on other sites
I seem to have ran into the same problem again. I have the following code to get the backbuffer, create a surface and load a bitmap to the surface...

if(FAILED(graphics.GetDevice()->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_BackBuffer))){	MessageBox(NULL, "Error gettin back buffer.", "Error", MB_OK);	PostQuitMessage(WM_QUIT);	return false;}if(FAILED(graphics.GetDevice()->CreateOffscreenPlainSurface(64, 64, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &m_BitmapSurface, NULL))){	MessageBox(NULL, "Error creating tile surface.", "Error", MB_OK);	PostQuitMessage(WM_QUIT);	return false;}if(FAILED(D3DXLoadSurfaceFromFile(m_BitmapSurface, NULL, NULL, "image.bmp", NULL, D3DX_DEFAULT, 0, NULL))){	MessageBox(NULL, "Error loading tile file.", "Error", MB_OK);	PostQuitMessage(WM_QUIT);	return false;}

I then have the following function DrawTile(), which should do as the name suggests...

bool TestApp::DrawTile(IDirect3DSurface9 *backBuffer, IDirect3DSurface9 *tileSurface, int tileNumber, int dstCol, int dstRow, int numTileCols, int numMapCols, int tileSize, int xOffset, int yOffset){        RECT srcRect;	RECT dstRect;	srcRect.left = TileNumber2SourceX(tileNumber, numTileCols, tileSize);	srcRect.right = srcRect.left + tileSize;	srcRect.top = TileNumber2SourceY(tileNumber, numTileCols, tileSize);	srcRect.bottom = srcRect.top + tileSize;	dstRect.left = Column2X(dstCol, tileSize, numMapCols) + xOffset;	dstRect.right = Column2X(dstCol, tileSize, numMapCols) + xOffset;	dstRect.top = Row2Y(dstRow, tileSize) + yOffset;	if(FAILED(graphics.GetDevice()->StretchRect(tileSurface, &srcRect, backBuffer, &dstRect, D3DTEXF_NONE)))	{		return false;	}	return true;}

StretchRect requires two RECTS, so I created a RECT and tried to use it as a point. This is because the book I'm reading is using DirectX 8.1 and uses the function CopyRects, which uses a RECT and a POINT. I'm not sure if this is the correct way to do this, but I'm havin trouble finding functions to replace this CopyRects, because they take slightly different arguments and I'm not sure how to go about adjusting to fit the StretchRect function.

In my Frame() function, which is executed every frame, I have the following code which uses the DrawTile() function...

if(!(DrawTile(m_BackBuffer, m_BitmapSurface, tileNumber, x, y, COLUMNS_IN_TILE_FILE, MAP_COLUMNCOUNT, TILESIZE, XOFFSET, YOFFSET))){	MessageBox(NULL, "Error drawing tiles.", "Error", MB_OK);	PostQuitMessage(WM_QUIT);	return false;}

However, I always get the messagebox "Error drawing tiles." displayed when I run my app, so this part is failing for some reason. I reckon it is again to do with the types of surfaces, but I have no idea how to rectify this.