I can't seem to find a way to create a texture from the surface data I acquire through the front buffer data of my application
This is the code I'm pretty sure is working (Direct X 9, C++)
// capture screen IDirect3DSurface9* pSurface; g_pd3dDevice->CreateOffscreenPlainSurface(640, 480, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL); g_pd3dDevice->GetFrontBufferData(0, pSurface);
Now that I've got my frontBufferData, I would like to create a IDirect3DTexture9 object with it.
This function / D3DXCreateTextureFromFileInMemory / seemed the most logical but doesn't seem to do the trick.
I'm pretty sure there is a way to do this, tough I am unsure how. Any help would be greatly welcome!
Thanks!
It's preferable to utilize GetRenderTargetData()
instead of GetFrontBufferData()
, because the former is faster. With that said, that's not really the question. You wish to store the data you get from the frontbuffer, or the stuff you're currently observing on the screen, into a texture.
First of all, IDirect3DTexture9
and IDirect3DSurface9
are actually, kind of, siblings, but they're not the same even though at some point in their class hiearchy they converge to IDirect3DResource9
(which is logical, as they are resources). What's neat about both of them is that they implement common functionality, specifically the possibility of LockRect() and manually copying the data from the surface (which is, crudely, just one mipmap level surface (a bunch of pixels) to the texture (which may consist of multiple mipmap levels). Therefore, your target is the level0 surface of the texture object.
With that in mind, since all CreateOffscreenPlainSurface()
are considered to stand alone, we cannot find a parent texture of which this surface might be a child of (being a particular mipmap of a texture). Long story short, if we don't LockRect both of them and manually copy the data, we can use StretchRect()
.
While its name might not give away one of its purpose, it'll help us out here. Remember about our comparison talk between textures and surfaces, surfaces kind of being their little brother. Well, if you define a texture properly (same as the surface), you're actually getting automated miplevels which you can manually define how many of them are there. But in essence, each of these levels is a surface. And "converting" from IDirect3DSurface9 to IDirect3DTexture9 is just a matter of filling in the proper miplevel surface (which in this case ought to be level0, since it is a screenshot basically).
Therefore, sipping this into coarse code gives us:
IDirect3DTexture9* texture; // needs to be created, of course IDirect3DSurface9* dest = NULL; // to be our level0 surface of the texture texture->GetSurfaceLevel(0, &dest); g_pD3DDevice->StretchRect(pSurface, NULL, dest, NULL, D3DTEXF_LINEAR);
And there you go, one IDirect3DTexture9 to go. Would you like fries with that, sir? Do note I'm working off memory here, I haven't touched DX9 in quite a while (dropped in favor of DX10). Hope it helps.