I was reading this arcile: http://www.ring3circus.com/gameprogramming/case-study-fraps/ and I've come to realize that given how old it is, (and the author even suggests against using his code), that this really isn't going to suite my needs (one, it's C#, two, it's for DX9). I am trying to get a rectangle capture of a DirectX game window and have it in memory as some sort of streaming video that I can reference. The window needs to be able to still be captured if not in foreground, or even visible (buried behind other windows). I have tried that C# library (the one made with EasyHook and SlimDX), but I've only managed to get the demo to work successfully once with a DirectX 11 game under 64bit (been unable to reproduce it since). Even then, the capture rate was eye-bleedingly slow. Along with a lot of other things that covered overlaying to DirectX (which I don't need). I'd like to mimic what fraps does as far as capture goes, but I just need a rectangle area of the game, not the whole thing, and I don't need to write it to a file. Could I perhaps get a code sample of how I'd manage to get a fast frame capture of a given rectangle of the game window, in C#, that works for DX9 trough DX11?
Asked
Active
Viewed 2,171 times
2
-
1This is a good question. There are no easy to find answers around on the net it seems - buried beneath lots of DX9 and other irrelevant solutions. – jheriko May 16 '12 at 17:34
1 Answers
3
Here is my C++ code for the same problem.
ID3D11Texture2D* pSurface;
HRESULT hr = m_swapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast< void** >( &pSurface ) );
if( pSurface )
{
const int width = static_cast<int>(m_window->Bounds.Width * m_dpi / 96.0f);
const int height = static_cast<int>(m_window->Bounds.Height * m_dpi / 96.0f);
unsigned int size = width * height;
if( m_captureData )
{
freeFramebufferData( m_captureData );
}
m_captureData = new unsigned char[ width * height * 4 ];
ID3D11Texture2D* pNewTexture = NULL;
D3D11_TEXTURE2D_DESC description;
pSurface->GetDesc( &description );
description.BindFlags = 0;
description.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
description.Usage = D3D11_USAGE_STAGING;
HRESULT hr = m_d3dDevice->CreateTexture2D( &description, NULL, &pNewTexture );
if( pNewTexture )
{
m_d3dContext->CopyResource( pNewTexture, pSurface );
D3D11_MAPPED_SUBRESOURCE resource;
unsigned int subresource = D3D11CalcSubresource( 0, 0, 0 );
HRESULT hr = m_d3dContext->Map( pNewTexture, subresource, D3D11_MAP_READ_WRITE, 0, &resource );
//resource.pData; // TEXTURE DATA IS HERE
const int pitch = width << 2;
const unsigned char* source = static_cast< const unsigned char* >( resource.pData );
unsigned char* dest = m_captureData;
for( int i = 0; i < height; ++i )
{
memcpy( dest, source, width * 4 );
source += pitch;
dest += pitch;
}
m_captureSize = size;
m_captureWidth = width;
m_captureHeight = height;
return;
}
freeFramebufferData( m_captureData );
}
You /might/ be able to port this to C#, or at least wrap it in a library. I asked a similar question, but then found the answer: DirectX 11 framebuffer capture (C++, no Win32 or D3DX)
-
1May I ask how do you initialize your swap chain? Can you grab the screen for other applications using this code? – Cesar Jan 05 '13 at 23:58
-