2013-07-23 10 views
5

Stavo sperimentando modi per acquisire lo schermo su Windows e di conseguenza decidere il modo più veloce per farlo. Il più comune è ovviamente il modo GDI. Ed è decente anche nelle prestazioni. A seconda del carico del sistema e del contenuto dello schermo statico/non statico, la velocità di acquisizione dello schermo variava da 27 a 47 fps (Windows 7, Intel [email protected],6 GHz, 8 GB di RAM).Utilizzo di DirectX per acquisire lo schermo su Windows

Ora, con l'approccio del front-buffer DirectX (utilizzando l'API GetFrontBufferData()), le prestazioni erano paragonabili ma leggermente più lente (non riuscivo a raggiungere i 48 fps).

Ho passato questo post: Fastest method of screen capturing e ho provato il modo suggerito nella risposta accettata usando getRenderTarget() e getRenderTargetData(), ma come suggerito nei commenti, tutto quello che ottengo è un'immagine nera. Qui è il mio codice completo incluse le configurazioni iniziali per il dispositivo:

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(); 

E per la parte di inizializzazione del dispositivo:

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); 

Si prega di segnalare l'errore nel codice di cui sopra. Qualsiasi suggerimento è benvenuto. Ho anche provato l'API GetBackBuffer() ma non ho potuto ottenere i dati dell'immagine.

EDIT:

mio caso d'uso è stato quello di bloccare lo schermo del desktop che sembra essere fatto solo utilizzando GetFrontBufferData() tramite DirectX. GetBackBuffer()/GetRenderTargetData() non è l'API corretta per chiamare questo caso. Riferimento: The desktop capture with DirectX does not work e How to get the screenshot of the desktop from back buffer with DirectX.

Tuttavia, qualsiasi suggerimento per un metodo più veloce per l'acquisizione dello schermo del desktop o l'ottimizzazione del modo GDI sono i benvenuti.

+1

Mi sembra che 'GetRenderTarget' restituirà il buffer posteriore per il dispositivo. Si potrebbe voler esaminare la funzione 'GetFrontBufferData'. –

+0

Ho usato GetFrontBufferData() come menzionato nella domanda, funziona perfettamente. Ma, non c'è alcun guadagno in termini di prestazioni rispetto al modo GDI. Stavo cercando un approccio più veloce, se esiste. –

+0

Sto anche scrivendo un'applicazione per screencapture. [Qui] (http://stackoverflow.com/q/31286503/4794952) è il link al mio problema. Ottengo uno schermo nero quando catturo qualsiasi gioco, mentre per qualsiasi altra applicazione, restituisce lo schermo catturato giusto. C'è un modo per farlo funzionare con i giochi a schermo intero? – newbie2015

risposta

2

Hai reso qualcosa prima di prendere lo screenshot?

  • GetFrontBufferData - questa funzione ottenere i dati della schermata
  • GetRenderTargetData - questa funzione ottiene i dati da rendere bersaglio

Quindi, se non si rendeva nulla, sicuramente sarà ottenuto un vuoto Immagine.

+0

Sono probabilmente fuori dal contesto qui. Il mio caso d'uso è quello di ottenere i dati dello schermo del desktop. Quindi, stai suggerendo che GetRenderTargetData() non sia l'API corretta da chiamare. Potete per favore elaborare la parte di rendering? –

+0

Controlla la tua risposta qui http://stackoverflow.com/questions/12859894/the-desktop-capture-with-directx-does-not-work/12863143#12863143 .. così, GetFrontBufferData() è l'unica API da essere utilizzato per catturare lo schermo del desktop tramite DirectX. –

+1

Sì, GetRenderTargetData() è stato utilizzato per ottenere dati dalla destinazione di rendering dell'applicazione, non dal desktop. – zdd

Problemi correlati