2017-04-26 3 views
1

J'utilise l'API Windows Desktop Duplication pour créer mon propre protocole de mise en miroir. J'ai ce morceau de code:Comment accéder aux données de pixels à partir de ID3D11Texture2D?

// Get new frame 
HRESULT hr = m_DeskDupl->AcquireNextFrame(500, &FrameInfo, &DesktopResource); 
if (hr == DXGI_ERROR_WAIT_TIMEOUT) 
{ 
    *Timeout = true; 
    return DUPL_RETURN_SUCCESS; 
} 

Voici la structure FrameInfo:

`typedef struct _FRAME_DATA { 
ID3D11Texture2D* Frame; 
DXGI_OUTDUPL_FRAME_INFO FrameInfo; 
_Field_size_bytes_((MoveCount * sizeof(DXGI_OUTDUPL_MOVE_RECT)) + (DirtyCount * sizeof(RECT))) BYTE* MetaData; 
UINT DirtyCount; 
UINT MoveCount; 
} FRAME_DATA;` 

je voudrais extraire le tampon de pixel de ID3D11Texture2D* Frame; Comment puis-je extraire sur un BYTE * ou unsigned char * et ont une séquence RGB? Merci!

Répondre

3

Vous devez créer une deuxième texture de la même taille avec CPU accès en lecture à l'aide ID3D11Device::CreateTexture2D, copie cadre tout ou simplement mis à jour des pièces à cette texture sur GPU en utilisant ID3D11DeviceContext::CopyResource ou ID3D11DeviceContext::CopySubresourceRegion (il est possible de récupérer les parties ont été mis à jour à l'aide IDXGIOutputDuplication::GetFrameDirtyRects et IDXGIOutputDuplication::GetFrameMoveRects), mappez la deuxième texture pour la rendre accessible par CPU en utilisant ID3D11DeviceContext::Map ce qui vous donne D3D11_MAPPED_SUBRESOURCE struct contenant le pointeur vers le tampon avec les données d'image et sa taille, c'est ce que vous cherchez.

Microsoft fournit un rather detailed Desktop Duplication API usage sample implémentant toutes les étapes mentionnées ci-dessus. Il y a également straight sample demonstrating how to save ID3D11Texture2D data to file.

1

Salut, voici le code qui répond à vos besoins. la sortie sera en UCHAR tampon g_iMageBuffer

//Variable Declaration 
IDXGIOutputDuplication* IDeskDupl; 
IDXGIResource*   lDesktopResource = nullptr; 
DXGI_OUTDUPL_FRAME_INFO IFrameInfo; 
ID3D11Texture2D*  IAcquiredDesktopImage; 
ID3D11Texture2D*  lDestImage; 
ID3D11DeviceContext* lImmediateContext; 
UCHAR*     g_iMageBuffer=nullptr; 

//Screen capture start here 
hr = lDeskDupl->AcquireNextFrame(20, &lFrameInfo, &lDesktopResource); 

// >QueryInterface for ID3D11Texture2D 
hr = lDesktopResource->QueryInterface(IID_PPV_ARGS(&lAcquiredDesktopImage)); 
lDesktopResource.Release(); 

// Copy image into GDI drawing texture 
lImmediateContext->CopyResource(lDestImage,lAcquiredDesktopImage); 
lAcquiredDesktopImage.Release(); 
lDeskDupl->ReleaseFrame(); 

// Copy GPU Resource to CPU 
D3D11_TEXTURE2D_DESC desc; 
lDestImage->GetDesc(&desc); 
D3D11_MAPPED_SUBRESOURCE resource; 
UINT subresource = D3D11CalcSubresource(0, 0, 0); 
lImmediateContext->Map(lDestImage, subresource, D3D11_MAP_READ_WRITE, 0, &resource); 

std::unique_ptr<BYTE> pBuf(new BYTE[resource.RowPitch*desc.Height]); 
UINT lBmpRowPitch = lOutputDuplDesc.ModeDesc.Width * 4; 
BYTE* sptr = reinterpret_cast<BYTE*>(resource.pData); 
BYTE* dptr = pBuf.get() + resource.RowPitch*desc.Height - lBmpRowPitch; 
UINT lRowPitch = std::min<UINT>(lBmpRowPitch, resource.RowPitch); 

for (size_t h = 0; h < lOutputDuplDesc.ModeDesc.Height; ++h) 
{ 
    memcpy_s(dptr, lBmpRowPitch, sptr, lRowPitch); 
    sptr += resource.RowPitch; 
    dptr -= lBmpRowPitch; 
} 

lImmediateContext->Unmap(lDestImage, subresource); 
long g_captureSize=lRowPitch*desc.Height; 
g_iMageBuffer= new UCHAR[g_captureSize]; 
g_iMageBuffer = (UCHAR*)malloc(g_captureSize); 

//Copying to UCHAR buffer 
memcpy(g_iMageBuffer,pBuf,g_captureSize);