int win_shadow_dxgi_fetch_frame_data(winShadowSubsystem* subsystem, BYTE** ppDstData, int* pnDstStep, int x, int y, int width, int height) { int status; HRESULT hr; D3D11_BOX Box; DXGI_MAPPED_RECT mappedRect; if ((width * height) < 1) return 0; Box.top = x; Box.left = y; Box.right = x + width; Box.bottom = y + height; Box.front = 0; Box.back = 1; subsystem->dxgiDeviceContext->lpVtbl->CopySubresourceRegion(subsystem->dxgiDeviceContext, (ID3D11Resource*) subsystem->dxgiStage, 0, 0, 0, 0, (ID3D11Resource*) subsystem->dxgiDesktopImage, 0, &Box); hr = subsystem->dxgiStage->lpVtbl->QueryInterface(subsystem->dxgiStage, &IID_IDXGISurface, (void**) &(subsystem->dxgiSurface)); if (FAILED(hr)) { WLog_ERR(TAG, "ID3D11Texture2D::QueryInterface(IDXGISurface) failure: %s 0x%04X", GetDxgiErrorString(hr), hr); return -1; } hr = subsystem->dxgiSurface->lpVtbl->Map(subsystem->dxgiSurface, &mappedRect, DXGI_MAP_READ); if (FAILED(hr)) { WLog_ERR(TAG, "IDXGISurface::Map failure: %s 0x%04X", GetDxgiErrorString(hr), hr); if (hr == DXGI_ERROR_DEVICE_REMOVED) { win_shadow_dxgi_uninit(subsystem); status = win_shadow_dxgi_init(subsystem); if (status < 0) return -1; return 0; } return -1; } subsystem->dxgiSurfaceMapped = TRUE; *ppDstData = mappedRect.pBits; *pnDstStep = mappedRect.Pitch; return 1; }
int win_shadow_subsystem_uninit(winShadowSubsystem* subsystem) { if (!subsystem) return -1; #if defined(WITH_WDS_API) win_shadow_wds_uninit(subsystem); #elif defined(WITH_DXGI_1_2) win_shadow_dxgi_uninit(subsystem); #endif return 1; }
int win_shadow_dxgi_get_next_frame(winShadowSubsystem* subsystem) { UINT i = 0; int status; HRESULT hr = 0; UINT timeout = 15; UINT DataBufferSize = 0; BYTE* DataBuffer = NULL; if (subsystem->dxgiFrameAcquired) { win_shadow_dxgi_release_frame_data(subsystem); } if (subsystem->dxgiDesktopImage) { subsystem->dxgiDesktopImage->lpVtbl->Release(subsystem->dxgiDesktopImage); subsystem->dxgiDesktopImage = NULL; } hr = subsystem->dxgiOutputDuplication->lpVtbl->AcquireNextFrame(subsystem->dxgiOutputDuplication, timeout, &(subsystem->dxgiFrameInfo), &(subsystem->dxgiResource)); if (SUCCEEDED(hr)) { subsystem->dxgiFrameAcquired = TRUE; subsystem->pendingFrames = subsystem->dxgiFrameInfo.AccumulatedFrames; } if (hr == DXGI_ERROR_WAIT_TIMEOUT) return 0; if (FAILED(hr)) { WLog_ERR(TAG, "IDXGIOutputDuplication::AcquireNextFrame failure: %s (0x%04X)", GetDxgiErrorString(hr), hr); if (hr == DXGI_ERROR_ACCESS_LOST) { win_shadow_dxgi_release_frame_data(subsystem); if (subsystem->dxgiDesktopImage) { subsystem->dxgiDesktopImage->lpVtbl->Release(subsystem->dxgiDesktopImage); subsystem->dxgiDesktopImage = NULL; } if (subsystem->dxgiOutputDuplication) { subsystem->dxgiOutputDuplication->lpVtbl->Release(subsystem->dxgiOutputDuplication); subsystem->dxgiOutputDuplication = NULL; } status = win_shadow_dxgi_init_duplication(subsystem); if (status < 0) return -1; return 0; } else if (hr == DXGI_ERROR_INVALID_CALL) { win_shadow_dxgi_uninit(subsystem); status = win_shadow_dxgi_init(subsystem); if (status < 0) return -1; return 0; } return -1; } hr = subsystem->dxgiResource->lpVtbl->QueryInterface(subsystem->dxgiResource, &IID_ID3D11Texture2D, (void**) &(subsystem->dxgiDesktopImage)); if (subsystem->dxgiResource) { subsystem->dxgiResource->lpVtbl->Release(subsystem->dxgiResource); subsystem->dxgiResource = NULL; } if (FAILED(hr)) { WLog_ERR(TAG, "IDXGIResource::QueryInterface(ID3D11Texture2D) failure: %s (0x%04X)", GetDxgiErrorString(hr), hr); return -1; } return 1; }