title: using GetFrontBufferData(), & place screenshot in separate device backbuffer
body: <p>Ok, so for anyone who's used it much - this should be a SUPER easy question.</p>
  
  <p>I was just searching online for a way to use DirectX/Direct3D to take faster screenshots, and everyone was talking about GetFrontBufferData() and how wonderful it was.</p>
  
  <p>I've pounded at it for a while but am starting to think they're using the term "screenshot" incorrectly... My call succeeds, but I never get a "screenshot".</p>
  
  <p>So <strong>the question is</strong>, can you actually use GetFrontBufferData() to make a REAL screenshot of the whole desktop, or is it merely a way to read the pixels out of the front buffer WITHIN the confines of your d3d-device's drawing area?</p>
  
  <p>(Upon success, I'd have expected to see the drawing area within my window do that old tv-in a tv-in a tv-in a tv-in a tv - kind of effect. I got nothing but black.)</p>
  
  <p>Edit:</p>
  
  <p>So, I was able to get a screenshot to work, but can't seem to put my image into the buffer for my app window.</p>
  
  <p>At first, I thought this was because they were separate devices, but I've tried creating a second surface on the correct device and then manually copying the contents over. (Although I might be copying it wrong ((not important right now)) the call to the stretchrect still fails for the correct device.</p>
  
  <p>Any idea why it won't let me apply this surface to my backbuffer???</p>
  
  <pre><code>D3DDISPLAYMODE          d3dDisplayMode;
  D3DPRESENT_PARAMETERS   d3dPresentationParameters;
  
  if( (d3d=Direct3DCreate9(D3D_SDK_VERSION))==NULL )
      exit(1);
  D3DCAPS9 d3dcps;
  d3d-&gt;GetDeviceCaps(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,&amp;d3dcps);
  DWORD targets = d3dcps.NumSimultaneousRTs;
  // TODO: ^ make a way for user to select one from this and put it into i
  DWORD i=D3DADAPTER_DEFAULT;
  
  if( d3d-&gt;GetAdapterDisplayMode(i,&amp;d3dDisplayMode)==D3DERR_INVALIDCALL )
      exit(1);
  
  ZeroMemory(&amp;d3dPresentationParameters,sizeof(D3DPRESENT_PARAMETERS));//Fills a block of memory with zeros.
  d3dPresentationParameters.Windowed = TRUE;
  d3dPresentationParameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
  d3dPresentationParameters.BackBufferFormat = d3dDisplayMode.Format;//d3dDisplayMode.Format;//D3DFMT_A8R8G8B8;
  d3dPresentationParameters.BackBufferCount = 1;
  d3dPresentationParameters.BackBufferHeight = d3dDisplayMode.Height;
  d3dPresentationParameters.BackBufferWidth = d3dDisplayMode.Width;
  d3dPresentationParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
  d3dPresentationParameters.MultiSampleQuality = 0;
  d3dPresentationParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
  d3dPresentationParameters.hDeviceWindow = hwDesktop;
  d3dPresentationParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
  d3dPresentationParameters.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  
  if( d3d-&gt;CreateDevice(i,D3DDEVTYPE_HAL,hwDesktop,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&amp;d3dPresentationParameters,&amp;d3dcdev) != D3D_OK )
      exit(1);
  
  if( d3dcdev-&gt;CreateOffscreenPlainSurface(d3dDisplayMode.Width,d3dDisplayMode.Height,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&amp;sfScrn, NULL) != D3D_OK )
      exit(1);
  
  if( d3dcdev-&gt;GetFrontBufferData(0,sfScrn) != D3D_OK)
      exit(1);   
  
  // we now have a screenshot in sfScrn. 
  // let's render it to a separate device in our app window!
  d3dPresentationParameters.hDeviceWindow = hwDrawArea;
  if( d3d-&gt;CreateDevice(i,D3DDEVTYPE_HAL,hwDrawArea,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&amp;d3dPresentationParameters,&amp;d3drdev) != D3D_OK )
      exit(1);
  d3drdev-&gt;GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&amp;sfBackBuffer);
  if( d3drdev-&gt;CreateOffscreenPlainSurface(d3dDisplayMode.Width,d3dDisplayMode.Height,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&amp;sfTransfer, NULL) != D3D_OK )
      exit(1);
  
  D3DLOCKED_RECT lockedRectScrn, lockedRectTransfer;
  ZeroMemory(&amp;lockedRectScrn, sizeof(D3DLOCKED_RECT));
  ZeroMemory(&amp;lockedRectTransfer, sizeof(D3DLOCKED_RECT));
  if(sfScrn-&gt;LockRect(&amp;lockedRectScrn,NULL,D3DLOCK_READONLY) != D3D_OK 
      || sfTransfer-&gt;LockRect(&amp;lockedRectTransfer,NULL,0) != D3D_OK )
      exit(1);
  memcpy((BYTE*)lockedRectTransfer.pBits,(BYTE*)lockedRectScrn.pBits,lockedRectScrn.Pitch*d3dDisplayMode.Height);
  sfScrn-&gt;UnlockRect();
  sfTransfer-&gt;UnlockRect();
  
  while(true)
  {
      if(d3drdev != NULL)
      {
          d3drdev-&gt;Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(75,0,0),1.0f,0);
          if(D3D_OK!=d3drdev-&gt;StretchRect(sfTransfer,NULL,sfBackBuffer,NULL,D3DTEXF_NONE))
          {
              MessageBox(NULL,"failed to use stretchrect","",0);
              exit(1);
          }
          if(d3drdev-&gt;BeginScene())
          {
              d3drdev-&gt;EndScene();
          }
          d3drdev-&gt;Present(NULL,NULL,NULL,NULL);
      }
  }
  </code></pre>
  
  <p>Edit2:</p>
  
  <p>Oh! So apparently you can't use StretchRect() on surfaces that are in D3DPOOL_SYSTEMMEM, but you must use GetFronBufferData() on D3DPOOL_SYSTEMMEM.</p>