static bool grabFrameD3D10(IDXGISwapChain *swap) { ID3D10Device *device = 0; ID3D10Texture2D *tex = 0, *captureTex = 0; if (FAILED(swap->GetBuffer(0, IID_ID3D10Texture2D, (void**)&tex))) return false; D3D10_TEXTURE2D_DESC desc; tex->GetDevice(&device); tex->GetDesc(&desc); // re-creating the capture staging texture each frame is definitely not the most efficient // way to handle things, but it frees me of all kind of resource management trouble, so // here goes... desc.MipLevels = 1; desc.ArraySize = 1; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D10_USAGE_STAGING; desc.BindFlags = 0; desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; desc.MiscFlags = 0; if(FAILED(device->CreateTexture2D(&desc,0,&captureTex))) printLog("video/d3d10: couldn't create staging texture for gpu->cpu download!\n"); else setCaptureResolution(desc.Width,desc.Height); if(device) device->CopySubresourceRegion(captureTex,0,0,0,0,tex,0,0); D3D10_MAPPED_TEXTURE2D mapped; bool grabOk = false; if(captureTex && SUCCEEDED(captureTex->Map(0,D3D10_MAP_READ,0,&mapped))) { switch(desc.Format) { case DXGI_FORMAT_R8G8B8A8_UNORM: blitAndFlipRGBAToCaptureData((unsigned char *) mapped.pData,mapped.RowPitch); grabOk = true; break; default: printLog("video/d3d10: unsupported backbuffer format, can't grab pixels!\n"); break; } captureTex->Unmap(0); } tex->Release(); if(captureTex) captureTex->Release(); if(device) device->Release(); return grabOk; }
void D3D10Grab(ID3D10Texture2D* pBackBuffer) { D3D10_TEXTURE2D_DESC tex_desc; pBackBuffer->GetDesc(&tex_desc); ID3D10Device *pDev; pBackBuffer->GetDevice(&pDev); ID3D10Texture2D * pTexture; D3D10_MAPPED_TEXTURE2D mappedTexture; tex_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; tex_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; tex_desc.ArraySize = 1; tex_desc.MipLevels = 1; tex_desc.BindFlags = 0; tex_desc.SampleDesc.Count = 1; tex_desc.SampleDesc.Quality = 0; tex_desc.Usage = D3D10_USAGE_STAGING; tex_desc.MiscFlags = 0; HRESULT hr = pDev->CreateTexture2D(&tex_desc, NULL, &pTexture); #ifdef DEBUG reportLog(EVENTLOG_INFORMATION_TYPE, L"pDev->CreateTexture2D 0x%x", hr); #endif pDev->CopyResource(pTexture, pBackBuffer); D3D10_BOX box = {0, 0, tex_desc.Width, tex_desc.Height, 0, 1}; pDev->CopySubresourceRegion(pTexture, 0, 0, 0, 0, pBackBuffer, 0, &box); DxgiFrameGrabber *dxgiFrameGrabber = DxgiFrameGrabber::getInstance(); IPCContext *ipcContext = dxgiFrameGrabber->m_ipcContext; Logger *logger = dxgiFrameGrabber->m_logger; if (S_OK != (hr = pTexture->Map(D3D10CalcSubresource(0, 0, 1), D3D10_MAP_READ, 0, &mappedTexture))) { logger->reportLogError(L"d3d10 couldn't map texture, hresult = 0x%x", hr); goto end; } ipcContext->m_memDesc.width = tex_desc.Width; ipcContext->m_memDesc.height = tex_desc.Height; ipcContext->m_memDesc.rowPitch = mappedTexture.RowPitch; ipcContext->m_memDesc.format = BufferFormatAbgr; ipcContext->m_memDesc.frameId++; // reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d10 texture description. width: %u, height: %u, pitch: %u", tex_desc.Width, tex_desc.Height, mappedTexture.RowPitch); DWORD errorcode; if (WAIT_OBJECT_0 == (errorcode = WaitForSingleObject(ipcContext->m_hMutex, 0))) { // __asm__("int $3"); // reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d10 writing description to mem mapped file"); memcpy(ipcContext->m_pMemMap, &ipcContext->m_memDesc, sizeof (ipcContext->m_memDesc)); // reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d10 writing data to mem mapped file"); PVOID pMemDataMap = incPtr(ipcContext->m_pMemMap, sizeof (ipcContext->m_memDesc)); if (mappedTexture.RowPitch == tex_desc.Width * 4) { memcpy(pMemDataMap, mappedTexture.pData, tex_desc.Width * tex_desc.Height * 4); } else { UINT cleanOffset = 0, pitchOffset = 0, i = 0; while (i < tex_desc.Height) { memcpy(incPtr(pMemDataMap, cleanOffset), incPtr(mappedTexture.pData, pitchOffset), tex_desc.Width * 4); cleanOffset += tex_desc.Width * 4; pitchOffset += mappedTexture.RowPitch; i++; } } ReleaseMutex(ipcContext->m_hMutex); SetEvent(ipcContext->m_hFrameGrabbedEvent); } else { logger->reportLogError(L"d3d10 couldn't wait mutex. errocode = 0x%x", errorcode); } pTexture->Unmap(D3D10CalcSubresource(0, 0, 1)); end: pTexture->Release(); pDev->Release(); }