2013-07-23 3 views
5

Я экспериментировал с способами захвата экрана на окнах и, следовательно, самым быстрым способом сделать это. Наиболее распространенным является, очевидно, путь GDI. И это достойно и в производительности. В зависимости от загрузки системы и статического/нестатического содержимого экрана скорость захвата экрана варьировалась от 27-47 кадров в секунду (Windows 7, Intel i5 @ 2,6 ГГц, 8 ГБ оперативной памяти).Использование DirectX для захвата экрана в Windows

Теперь, используя подход Front Front front buffer (используя API GetFrontBufferData()), производительность была сопоставимой, но немного более медленной (я не мог достигать 48 кадров в секунду).

Я прошел через это сообщение: Fastest method of screen capturing и опробовал способ, предложенный в принятом ответе, используя getRenderTarget() и getRenderTargetData(), но, как было предложено в комментариях, все, что я получаю, является черным изображением. Вот мой полный код, включая начальные конфигурации для устройства:

IDirect3DSurface9* pRenderTarget=NULL; 
    IDirect3DSurface9* pDestTarget=NULL; 
    // sanity checks. 
    if (g_pd3dDevice == NULL){ 
     return; 
    } 
    HRESULT hr; 
    // get the render target surface. 
    hr = g_pd3dDevice->GetRenderTarget(0, &pRenderTarget); 
    // get the current adapter display mode. 
    //hr = pDirect3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddisplaymode); 

    // create a destination surface. 
    hr = g_pd3dDevice->CreateOffscreenPlainSurface(1600, 900, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pDestTarget, NULL); 
    //copy the render target to the destination surface. 
    hr = g_pd3dDevice->GetRenderTargetData(pRenderTarget, pDestTarget); 

    D3DLOCKED_RECT lockedRect; 
    hr =pDestTarget->LockRect(&lockedRect,NULL, D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY); 

    for(int i=0 ; i < 900 ; i++) 
    { 
     for(int j=0; j < 1600; j++){ 
      memcpy((BYTE*) data + i * 1600 * 3 + j * 3, (BYTE*) lockedRect.pBits + i* lockedRect.Pitch + j * 4, 3); 
     } 
    } 
    pDestTarget->UnlockRect(); 
    // clean up. 
    pRenderTarget->Release(); 
    pDestTarget->Release(); 

А для устройства инициализации части:

g_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION); 
D3DPRESENT_PARAMETERS PresentParams; 
memset(&PresentParams, 0, sizeof(D3DPRESENT_PARAMETERS)); 
PresentParams.Windowed = TRUE; 
PresentParams.SwapEffect =D3DSWAPEFFECT_DISCARD; 
g_pDirect3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL ,GetDesktopWindow(),D3DCREATE_SOFTWARE_VERTEXPROCESSING, &PresentParams,&g_pd3dDevice); 

Пожалуйста, укажите на ошибку в коде выше. Любые предложения приветствуются. Я также попробовал API GetBackBuffer(), но я не смог получить данные изображения.

EDIT:

Мой случай использования был захват рабочего стола экран, который, кажется, сделано только с помощью GetFrontBufferData() с помощью DirectX. GetBackBuffer()/GetRenderTargetData() не является правильным API для вызова этого случая. Ссылка: The desktop capture with DirectX does not work и How to get the screenshot of the desktop from back buffer with DirectX.

Однако любые предложения по ускоренному методу захвата экрана рабочего стола или оптимизации способа GDI приветствуются.

+1

Я чувствую, что 'GetRenderTarget' вернет задний буфер для устройства. Вы можете посмотреть функцию 'GetFrontBufferData'. –

+0

Я использовал GetFrontBufferData(), как упоминалось в вопросе, он отлично работает. Но нет никакой выгоды в производительности по сравнению с GDI. Я искал более быстрый подход, если он есть. –

+0

Я также пишу приложение screencapture. [Здесь] (http://stackoverflow.com/q/31286503/4794952) является ссылкой на мою проблему. Я получаю черный экран, когда я захватываю любую игру, тогда как для любого другого приложения он возвращает правый захваченный экран. Есть ли способ заставить его работать с полноэкранными играми? – newbie2015

ответ

2

Вы ничего визуализировали перед тем, как сделать снимок экрана?

  • GetFrontBufferData - это функция получения данных экрана
  • GetRenderTargetData - это функция получения данных от цели визуализации

Так что, если вы ничего не делают, вы, безусловно, есть пустой образ.

+0

Я, вероятно, не в контексте. Мой вариант использования - получить данные на экране рабочего стола. Итак, предлагаете ли вы GetRenderTargetData() не правильный API для вызова. Не могли бы вы рассказать о части рендеринга? –

+0

Проверьте свой ответ здесь http://stackoverflow.com/questions/12859894/the-desktop-capture-with-directx-does-not-work/12863143#12863143 .. поэтому GetFrontBufferData() - это единственный API, который будет используется для захвата рабочего стола через DirectX. –

+1

Да, GetRenderTargetData() использовался для получения данных из целевого объекта рендеринга приложения, а не рабочего стола. – zdd