Copy a rendertarget texture into a regular texture

Started by
4 comments, last by ext 17 years, 7 months ago
Hello, is it possible to copy the data in a texture which was created with the flag D3DUSAGE_RENDERTARGET (and the associated D3DPOOL_DEFAULT) into a regular texture with the pool D3DPOOL_MANAGED? It seems, that the IDirect3DDevice9::GetRenderTargetData can do this, but this call fails always with the INVALIDCALL-error.
Advertisement
It's possible, but you'd need to go via a temporary surface in system memory and your source must be in the default pool:

CreateOffscreenPlainSurface() to create a temporary surface,
GetRenderTargetData() on the source to the temporary surface,
LockRect() on the destination,
memcpy() from the tempporary surface to the destination
UnlockRect() on the destination

It would be much more convenient to GetRenderTargetData() straight from the RT to the texture, but MSDN says that's against the rules:

Quote:Original text from MSDN
IDirect3DDevice9::GetRenderTargetData Method
...
Remarks

The destination surface must be either an off-screen plain surface or a level of a texture (mipmap or cube texture) created with D3DPOOL_SYSTEMMEM.

The source surface must be a regular render target or a level of a render-target texture (mipmap or cube texture) created with POOL_DEFAULT.

This method will fail if:

* The render target is multisampled.
* The source render target is a different size than the destination surface.
* The source render target and destination surface formats do not match.


Regards
Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Cool, thank you :-)
When calling GetRenderTargetData I get always an D3DERR_INVALIDCALL error. I cannot find in the directx documentation a note that this function is _not_ supported by all graphics card.

My code:
IDirect3DTexture9* img = NULL;d3dDevice->CreateTexture( 256, 256, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8,  D3DPOOL_DEFAULT, &img, NULL );IDirect3DSurface9* sf = NULL;d3dDevice->CreateOffscreenPlainSurface( 256, 256, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &sf, NULL );IDirect3DSurface9* src = NULL;img->GetSurfaceLevel( 0, &src );d3dDevice->GetRenderTargetData( src, sf );


According to the directx documentation

Quote:
This method will fail if:

The render target is multisampled.
The source render target is a different size than the destination surface.
The source render target and destination surface formats do not match.



But my render target is not multisampled, it has the same format and they're the same size (I compared the values in their D3DSURFACE_DESC structures and they have the same format and same sizes and the multisampletype of the source surface is D3DMULTISAMPLE_NONE).
The destination surface (the temporary one) needs to be in system memory. You've set it to use the default pool (videomem), which is probably the reason for failure.
The directx documentation of CreateOffscreenPlainSurface confused me with their remark:

Quote:
D3DPOOL_SCRATCH will return a surface that has identical characteristics to a surface created by the DirectX 8.x method CreateImageSurface.

D3DPOOL_DEFAULT is the appropriate pool for use with the StretchRect and ColorFill.

D3DPOOL_MANAGED is not allowed when creating an offscreen plain surface. For more information about memory pools, see D3DPOOL.

Off-screen plain surfaces are always lockable, regardless of their pool types.


That's why I thought by using off-screen surfaces it doesn't matter when using the default pool.
But you're right that was the problem. Thank you very much :-)

This topic is closed to new replies.

Advertisement