void
D3D9RenderWindow::copyContentsToMemory(
const
PixelBox
&
dst, FrameBuffer buffer)
{
if ((dst.left < 0 ) || (dst.right > mWidth) ||
(dst.top < 0 ) || (dst.bottom > mHeight) ||
(dst.front != 0 ) || (dst.back != 1 ))
{
OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
" Invalid box. " ,
" D3D9RenderWindow::copyContentsToMemory " );
}
HRESULT hr;
LPDIRECT3DSURFACE9 pSurf = 0 , pTempSurf = 0 ;
D3DSURFACE_DESC desc;
D3DLOCKED_RECT lockedRect;
LPDIRECT3DDEVICE9 mpD3DDevice = mDriver -> getD3DDevice();
if (buffer == FB_AUTO)
{
// buffer = mIsFullScreen? FB_FRONT : FB_BACK;
buffer = FB_FRONT;
}
if (buffer == FB_FRONT)
{
D3DDISPLAYMODE dm;
LPDIRECT3DDEVICE9 mpD3DDevice = mDriver -> getD3DDevice();
if (FAILED(hr = mpD3DDevice -> GetDisplayMode( 0 , & dm)))
{
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't get display mode: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
desc.Width = dm.Width;
desc.Height = dm.Height;
desc.Format = D3DFMT_A8R8G8B8;
if (FAILED(hr = mpD3DDevice -> CreateOffscreenPlainSurface(desc.Width, desc.Height,
desc.Format,
D3DPOOL_SYSTEMMEM,
& pTempSurf,
0 )))
{
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't create offscreen buffer: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (FAILED(hr = mIsSwapChain ? mpSwapChain -> GetFrontBufferData(pTempSurf) :
mpD3DDevice -> GetFrontBufferData( 0 , pTempSurf)))
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't get front buffer: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (mIsFullScreen)
{
if ((dst.left == 0 ) && (dst.right == mWidth) && (dst.top == 0 ) && (dst.bottom == mHeight))
{
hr = pTempSurf -> LockRect( & lockedRect, 0 , D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
}
else
{
RECT rect;
rect.left = (LONG)dst.left;
rect.right = (LONG)dst.right;
rect.top = (LONG)dst.top;
rect.bottom = (LONG)dst.bottom;
hr = pTempSurf -> LockRect( & lockedRect, & rect, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
}
if (FAILED(hr))
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't lock rect: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
}
else
{
RECT srcRect;
// GetClientRect(mHWnd, &srcRect);
srcRect.left = (LONG)dst.left;
srcRect.top = (LONG)dst.top;
srcRect.right = (LONG)dst.right;
srcRect.bottom = (LONG)dst.bottom;
POINT point;
point.x = srcRect.left;
point.y = srcRect.top;
ClientToScreen(mHWnd, & point);
srcRect.top = point.y;
srcRect.left = point.x;
srcRect.bottom += point.y;
srcRect.right += point.x;
desc.Width = srcRect.right - srcRect.left;
desc.Height = srcRect.bottom - srcRect.top;
if (FAILED(hr = pTempSurf -> LockRect( & lockedRect, & srcRect, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)))
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't lock rect: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
}
}
else
{
SAFE_RELEASE(pSurf);
if (FAILED(hr = mIsSwapChain ? mpSwapChain -> GetBackBuffer( 0 , D3DBACKBUFFER_TYPE_MONO, & pSurf) :
mpD3DDevice -> GetBackBuffer( 0 , 0 , D3DBACKBUFFER_TYPE_MONO, & pSurf)))
{
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't get back buffer: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (FAILED(hr = pSurf -> GetDesc( & desc)))
{
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't get description: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (FAILED(hr = mpD3DDevice -> CreateOffscreenPlainSurface(desc.Width, desc.Height,
desc.Format,
D3DPOOL_SYSTEMMEM,
& pTempSurf,
0 )))
{
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't create offscreen surface: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (desc.MultiSampleType == D3DMULTISAMPLE_NONE)
{
if (FAILED(hr = mpD3DDevice -> GetRenderTargetData(pSurf, pTempSurf)))
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't get render target data: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
}
else
{
LPDIRECT3DSURFACE9 pStretchSurf = 0 ;
if (FAILED(hr = mpD3DDevice -> CreateRenderTarget(desc.Width, desc.Height,
desc.Format,
D3DMULTISAMPLE_NONE,
0 ,
false ,
& pStretchSurf,
0 )))
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't create render target: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (FAILED(hr = mpD3DDevice -> StretchRect(pSurf, 0 , pStretchSurf, 0 , D3DTEXF_NONE)))
{
SAFE_RELEASE(pTempSurf);
SAFE_RELEASE(pStretchSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't stretch rect: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (FAILED(hr = mpD3DDevice -> GetRenderTargetData(pStretchSurf, pTempSurf)))
{
SAFE_RELEASE(pTempSurf);
SAFE_RELEASE(pStretchSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't get render target data: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
SAFE_RELEASE(pStretchSurf);
}
if ((dst.left == 0 ) && (dst.right == mWidth) && (dst.top == 0 ) && (dst.bottom == mHeight))
{
hr = pTempSurf -> LockRect( & lockedRect, 0 , D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
}
else
{
RECT rect;
rect.left = (LONG)dst.left;
rect.right = (LONG)dst.right;
rect.top = (LONG)dst.top;
rect.bottom = (LONG)dst.bottom;
hr = pTempSurf -> LockRect( & lockedRect, & rect, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
}
if (FAILED(hr))
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't lock rect: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
}
PixelFormat format = Ogre::D3D9Mappings::_getPF(desc.Format);
if (format == PF_UNKNOWN)
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Unsupported format " , " D3D9RenderWindow::copyContentsToMemory " );
}
PixelBox src(dst.getWidth(), dst.getHeight(), 1 , format, lockedRect.pBits);
src.rowPitch = lockedRect.Pitch / PixelUtil::getNumElemBytes(format);
src.slicePitch = desc.Height * src.rowPitch;
PixelUtil::bulkPixelConversion(src, dst);
SAFE_RELEASE(pTempSurf);
SAFE_RELEASE(pSurf);
}
{
if ((dst.left < 0 ) || (dst.right > mWidth) ||
(dst.top < 0 ) || (dst.bottom > mHeight) ||
(dst.front != 0 ) || (dst.back != 1 ))
{
OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
" Invalid box. " ,
" D3D9RenderWindow::copyContentsToMemory " );
}
HRESULT hr;
LPDIRECT3DSURFACE9 pSurf = 0 , pTempSurf = 0 ;
D3DSURFACE_DESC desc;
D3DLOCKED_RECT lockedRect;
LPDIRECT3DDEVICE9 mpD3DDevice = mDriver -> getD3DDevice();
if (buffer == FB_AUTO)
{
// buffer = mIsFullScreen? FB_FRONT : FB_BACK;
buffer = FB_FRONT;
}
if (buffer == FB_FRONT)
{
D3DDISPLAYMODE dm;
LPDIRECT3DDEVICE9 mpD3DDevice = mDriver -> getD3DDevice();
if (FAILED(hr = mpD3DDevice -> GetDisplayMode( 0 , & dm)))
{
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't get display mode: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
desc.Width = dm.Width;
desc.Height = dm.Height;
desc.Format = D3DFMT_A8R8G8B8;
if (FAILED(hr = mpD3DDevice -> CreateOffscreenPlainSurface(desc.Width, desc.Height,
desc.Format,
D3DPOOL_SYSTEMMEM,
& pTempSurf,
0 )))
{
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't create offscreen buffer: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (FAILED(hr = mIsSwapChain ? mpSwapChain -> GetFrontBufferData(pTempSurf) :
mpD3DDevice -> GetFrontBufferData( 0 , pTempSurf)))
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't get front buffer: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (mIsFullScreen)
{
if ((dst.left == 0 ) && (dst.right == mWidth) && (dst.top == 0 ) && (dst.bottom == mHeight))
{
hr = pTempSurf -> LockRect( & lockedRect, 0 , D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
}
else
{
RECT rect;
rect.left = (LONG)dst.left;
rect.right = (LONG)dst.right;
rect.top = (LONG)dst.top;
rect.bottom = (LONG)dst.bottom;
hr = pTempSurf -> LockRect( & lockedRect, & rect, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
}
if (FAILED(hr))
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't lock rect: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
}
else
{
RECT srcRect;
// GetClientRect(mHWnd, &srcRect);
srcRect.left = (LONG)dst.left;
srcRect.top = (LONG)dst.top;
srcRect.right = (LONG)dst.right;
srcRect.bottom = (LONG)dst.bottom;
POINT point;
point.x = srcRect.left;
point.y = srcRect.top;
ClientToScreen(mHWnd, & point);
srcRect.top = point.y;
srcRect.left = point.x;
srcRect.bottom += point.y;
srcRect.right += point.x;
desc.Width = srcRect.right - srcRect.left;
desc.Height = srcRect.bottom - srcRect.top;
if (FAILED(hr = pTempSurf -> LockRect( & lockedRect, & srcRect, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)))
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't lock rect: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
}
}
else
{
SAFE_RELEASE(pSurf);
if (FAILED(hr = mIsSwapChain ? mpSwapChain -> GetBackBuffer( 0 , D3DBACKBUFFER_TYPE_MONO, & pSurf) :
mpD3DDevice -> GetBackBuffer( 0 , 0 , D3DBACKBUFFER_TYPE_MONO, & pSurf)))
{
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't get back buffer: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (FAILED(hr = pSurf -> GetDesc( & desc)))
{
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't get description: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (FAILED(hr = mpD3DDevice -> CreateOffscreenPlainSurface(desc.Width, desc.Height,
desc.Format,
D3DPOOL_SYSTEMMEM,
& pTempSurf,
0 )))
{
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't create offscreen surface: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (desc.MultiSampleType == D3DMULTISAMPLE_NONE)
{
if (FAILED(hr = mpD3DDevice -> GetRenderTargetData(pSurf, pTempSurf)))
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't get render target data: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
}
else
{
LPDIRECT3DSURFACE9 pStretchSurf = 0 ;
if (FAILED(hr = mpD3DDevice -> CreateRenderTarget(desc.Width, desc.Height,
desc.Format,
D3DMULTISAMPLE_NONE,
0 ,
false ,
& pStretchSurf,
0 )))
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't create render target: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (FAILED(hr = mpD3DDevice -> StretchRect(pSurf, 0 , pStretchSurf, 0 , D3DTEXF_NONE)))
{
SAFE_RELEASE(pTempSurf);
SAFE_RELEASE(pStretchSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't stretch rect: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
if (FAILED(hr = mpD3DDevice -> GetRenderTargetData(pStretchSurf, pTempSurf)))
{
SAFE_RELEASE(pTempSurf);
SAFE_RELEASE(pStretchSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't get render target data: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
SAFE_RELEASE(pStretchSurf);
}
if ((dst.left == 0 ) && (dst.right == mWidth) && (dst.top == 0 ) && (dst.bottom == mHeight))
{
hr = pTempSurf -> LockRect( & lockedRect, 0 , D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
}
else
{
RECT rect;
rect.left = (LONG)dst.left;
rect.right = (LONG)dst.right;
rect.top = (LONG)dst.top;
rect.bottom = (LONG)dst.bottom;
hr = pTempSurf -> LockRect( & lockedRect, & rect, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
}
if (FAILED(hr))
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Can't lock rect: " + Root::getSingleton().getErrorDescription(hr),
" D3D9RenderWindow::copyContentsToMemory " );
}
}
PixelFormat format = Ogre::D3D9Mappings::_getPF(desc.Format);
if (format == PF_UNKNOWN)
{
SAFE_RELEASE(pTempSurf);
OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
" Unsupported format " , " D3D9RenderWindow::copyContentsToMemory " );
}
PixelBox src(dst.getWidth(), dst.getHeight(), 1 , format, lockedRect.pBits);
src.rowPitch = lockedRect.Pitch / PixelUtil::getNumElemBytes(format);
src.slicePitch = desc.Height * src.rowPitch;
PixelUtil::bulkPixelConversion(src, dst);
SAFE_RELEASE(pTempSurf);
SAFE_RELEASE(pSurf);
}