2

I'm trying to capture whole desktop screen (front buffer) and add a logo and caption to each frame.

I load the logo (.png or .jpeg file) as IDirect3DTexture9 and I try to add it to a IDirect3DSurface9 image frame (screenshot).

As I'm new to DirecX9, I have no idea how to copy the logo (texture) to the screenshot (surface/buffer). Any help would be appreciated.

(If there's any other way to add logo to each frame without involving texture, please do tell me.)

EDIT: I have used the code suggested in an answer below. The hr result returned is an error.

IDirect3DSurface9 *pSurface = NULL;
pDevice->GetFrontBufferData(0, pSurface); //my screenshot

LPDIRECT3DTEXTURE9 tex = NULL;  //my logo
//[code to load logo from file here]

IDirect3DSurface9 *pSurf = NULL;
tex->GetSurfaceLevel(0, &pSurf);

hr = pDevice->StretchRect(pSurf, NULL, pSurface, NULL, D3DTEXF_NONE);  //HR GIVES AN ERROR

1 Answers1

1

You can use StretchRect. The code will look something like this (pseudo):

ID3DSurface9 *pScreenSurface = ... // your screenshot surface should be created in default pool and the same format as your texture(see bellow), like this:
CreateOffscreenPlainSurface(width, height, D3DFMT_X8B8G8R8, D3DPOOL_DEFAULT, &pScreenSurface, NULL);

// Now get a screenshot by using either GetFrontBufferData, or GetBackBuffer/GetRenderTargetData by supplying pScreenSurface as a parameter (not shown here).

ID3DTexture9 *pTexture = ... // your texture should be loaded in default pool and the same format as your screenshot surface, like this:
D3DXCreateTextureFromFileEx(*ppDevice, L"icon.bmp", 40, 40, D3DX_DEFAULT, 0, 
  D3DFMT_X8B8G8R8, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, 
  NULL, &pTexture);

ID3DSurface9 *pSurf;
pTexture->GetSurfaceLevel(0, &pSurf); // don't forget to Release pSurf after StretchRect

RECT rc = { ... initialize the destination rectangle here };
pDevice->StretchRect(pSurf, NULL, pScreenSurface, &rc);

You need to specify a destination rectangle inside the destination surface, where you want your texture to be copied.

VuVirt
  • 1,887
  • 11
  • 13
  • will it work if surface and texture are of different sizes? – user11962394 Aug 22 '19 at 16:27
  • Yes it will. Check the docs for details on restrictions. Both surfaces ahould be in pool default for instance. – VuVirt Aug 22 '19 at 16:43
  • StretchRect gives me an error, I don't know why. I have tried using different filters. – user11962394 Aug 22 '19 at 19:44
  • I think you need to switch places of surface parameters – VuVirt Aug 22 '19 at 20:03
  • Is tex really null? – VuVirt Aug 22 '19 at 20:04
  • Thanks for the quick reply. 1) tex is not null, but I didn't include the function, 2) changing the order does nothing. – user11962394 Aug 22 '19 at 20:06
  • I used D3DXCreateTextureFromFileEx for this. Maybe, it creates compressed surface or something? – user11962394 Aug 22 '19 at 20:09
  • It creates a texture whichbis not in the default pool I think – VuVirt Aug 22 '19 at 20:14
  • do you know any solution to this? – user11962394 Aug 23 '19 at 04:38
  • please help, I'm stuck in my job. – user11962394 Aug 23 '19 at 06:03
  • You should be able to specify default pool when using D3DXCreateTextureFromFileEx. I'll need more details on how you used D3DXCreateTextureFromFileEx, in order to help you. What is the exact HRESULT error that StretchRect returns? – VuVirt Aug 23 '19 at 06:32
  • D3DXCreateTextureFromFileEx(*ppDevice, L"icon.bmp", 40, 40, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &tex); – user11962394 Aug 23 '19 at 06:59
  • What is the HRESULT returned by D3DXCreateTextureFromFileEx and StretchRect? – VuVirt Aug 23 '19 at 07:02
  • Also you better check this answer: https://stackoverflow.com/questions/26034360/using-getfrontbufferdata-place-screenshot-in-separate-device-backbuffer – VuVirt Aug 23 '19 at 07:05
  • You must also create the surface that you pass to GetFrontBufferData. The surface cannot be NULL. If you are creating it as an off screen surface then StretchRect will not work. – VuVirt Aug 23 '19 at 07:06
  • This should help you further (you might need to use GetBackBuffer and GetRenderTargetData instead of GetFrontBufferData): https://www.codeproject.com/Questions/545316/TakingplusScreenshotplususingplusDirectX9 – VuVirt Aug 23 '19 at 07:08
  • hr result: D3DERR_INVALIDCALL – user11962394 Aug 23 '19 at 07:08
  • Thanks, stranger. You are very helpful and kind. – user11962394 Aug 23 '19 at 07:09
  • btw, getting screenshot and getting texture work perfectly, independent of each other. I have tested them. – user11962394 Aug 23 '19 at 07:10
  • If you use GetFrontBufferData, then you'll need to have a temp d3dpool_default surface and copy the system_mem surface taken via GetFrontBufferData to the temp one by using UpdateSurface: https://learn.microsoft.com/en-us/windows/win32/api/d3d9helper/nf-d3d9helper-idirect3ddevice9-updatesurface. Then you can use StretchRect to copy your texture to the temp surface – VuVirt Aug 23 '19 at 08:21
  • You should also use: D3DXCreateTextureFromFileEx(*ppDevice, L"icon.bmp", 40, 40, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &tex); Check the updated answer and please accept it if it is helpful. Thanks! – VuVirt Aug 23 '19 at 08:54