DuplicatorInfo CDuplicateOutputDx11::GetNewFrame(ID3D11Texture2D** p2dTexture) { DXGI_OUTDUPL_FRAME_INFO frameInfo; IDXGIResource* pDesktopResource = nullptr; HRESULT hr = S_OK; hr = m_pOutputDuplication->AcquireNextFrame(15, &frameInfo, &pDesktopResource); if (hr == DXGI_ERROR_ACCESS_LOST) { return DuplicatorInfo_Lost; } else if (hr == DXGI_ERROR_WAIT_TIMEOUT) { return DuplicatorInfo_Timeout; } else if (hr == DXGI_ERROR_INVALID_CALL) { return DuplicatorInfo_InvalidCall; } else if (FAILED(hr)) { return DuplicatorInfo_Error; } if (FAILED(hr = pDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(p2dTexture)))) { SAFE_RELEASE(pDesktopResource); DOLOG(" pDesktopResource->QueryInterface failed"); return DuplicatorInfo_Error; } SAFE_RELEASE(pDesktopResource); return DuplicatorInfo_Acquired; }
HRESULT CSurfaceQueueDeviceD3D10::GetSharedHandle(IUnknown* pUnknown, HANDLE* pHandle) { ASSERT(pUnknown); ASSERT(pHandle); if (NULL == pUnknown || NULL == pHandle) { return E_FAIL; } HRESULT hr = S_OK; *pHandle = NULL; IDXGIResource* pSurface; if (FAILED(hr = pUnknown->QueryInterface(__uuidof(IDXGIResource), (void**)&pSurface))) { return hr; } hr = pSurface->GetSharedHandle(pHandle); pSurface->Release(); return hr; }
void createPbufferFromClientBufferSurface() { EGLAttrib device = 0; EGLAttrib angleDevice = 0; PFNEGLQUERYDISPLAYATTRIBEXTPROC queryDisplayAttribEXT; PFNEGLQUERYDEVICEATTRIBEXTPROC queryDeviceAttribEXT; const char *extensionString = static_cast<const char *>(eglQueryString(mDisplay, EGL_EXTENSIONS)); EXPECT_TRUE(strstr(extensionString, "EGL_EXT_device_query")); queryDisplayAttribEXT = (PFNEGLQUERYDISPLAYATTRIBEXTPROC)eglGetProcAddress("eglQueryDisplayAttribEXT"); queryDeviceAttribEXT = (PFNEGLQUERYDEVICEATTRIBEXTPROC)eglGetProcAddress("eglQueryDeviceAttribEXT"); ASSERT_NE(nullptr, queryDisplayAttribEXT); ASSERT_NE(nullptr, queryDeviceAttribEXT); ASSERT_EGL_TRUE(queryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &angleDevice)); ASSERT_EGL_TRUE(queryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), EGL_D3D11_DEVICE_ANGLE, &device)); ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device *>(device); D3D11_TEXTURE2D_DESC textureDesc = {0}; textureDesc.Width = mWindowWidth; textureDesc.Height = mWindowWidth; textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; textureDesc.MipLevels = 1; textureDesc.ArraySize = 1; textureDesc.SampleDesc.Count = 1; textureDesc.SampleDesc.Quality = 0; textureDesc.Usage = D3D11_USAGE_DEFAULT; textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; textureDesc.CPUAccessFlags = 0; textureDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; ASSERT_TRUE(SUCCEEDED( d3d11Device->CreateTexture2D(&textureDesc, nullptr, &mOffscreenSurfaceD3D11Texture))); IDXGIResource *dxgiResource = DynamicCastComObject<IDXGIResource>(mOffscreenSurfaceD3D11Texture); ASSERT_NE(nullptr, dxgiResource); HANDLE sharedHandle = 0; ASSERT_TRUE(SUCCEEDED(dxgiResource->GetSharedHandle(&sharedHandle))); SafeRelease(dxgiResource); EGLint pBufferAttributes[] = {EGL_WIDTH, mWindowWidth, EGL_HEIGHT, mWindowWidth, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_NONE}; mSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, sharedHandle, mConfig, pBufferAttributes); ASSERT_TRUE(EGL_NO_SURFACE != mSurface); }
bool DoD3D11Hook(ID3D11Device *device) { HRESULT hErr; D3D11_TEXTURE2D_DESC texGameDesc; ZeroMemory(&texGameDesc, sizeof(texGameDesc)); texGameDesc.Width = d3d11CaptureInfo.cx; texGameDesc.Height = d3d11CaptureInfo.cy; texGameDesc.MipLevels = 1; texGameDesc.ArraySize = 1; texGameDesc.Format = dxgiFormat; texGameDesc.SampleDesc.Count = 1; texGameDesc.BindFlags = D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE; texGameDesc.Usage = D3D11_USAGE_DEFAULT; texGameDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; ID3D11Texture2D *d3d11Tex; if(FAILED(hErr = device->CreateTexture2D(&texGameDesc, NULL, &d3d11Tex))) { RUNONCE logOutput << "DoD3D11Hook: creation of intermediary texture failed, result = " << UINT(hErr) << endl; return false; } if(FAILED(hErr = d3d11Tex->QueryInterface(__uuidof(ID3D11Resource), (void**)©TextureGame))) { RUNONCE logOutput << "DoD3D11Hook: d3d11Tex->QueryInterface(ID3D11Resource) failed, result = " << UINT(hErr) << endl; d3d11Tex->Release(); return false; } IDXGIResource *res; if(FAILED(hErr = d3d11Tex->QueryInterface(IID_IDXGIResource, (void**)&res))) { RUNONCE logOutput << "DoD3D11Hook: d3d11Tex->QueryInterface(IID_IDXGIResource) failed, result = " << UINT(hErr) << endl; d3d11Tex->Release(); return false; } if(FAILED(hErr = res->GetSharedHandle(&sharedHandle))) { RUNONCE logOutput << "DoD3D11Hook: res->GetSharedHandle failed, result = " << UINT(hErr) << endl; d3d11Tex->Release(); res->Release(); return false; } d3d11Tex->Release(); res->Release(); return true; }
static HRESULT STDMETHODCALLTYPE hook_present(IDXGISwapChain *swap, UINT sync_interval, UINT flags) { IDXGIResource *backbuffer = nullptr; bool capture_overlay = global_hook_info->capture_overlay; bool test_draw = (flags & DXGI_PRESENT_TEST) != 0; bool capture; HRESULT hr; if (!data.swap && !capture_active()) { setup_dxgi(swap); } capture = !test_draw && swap == data.swap && !!data.capture; if (capture && !capture_overlay) { backbuffer = get_dxgi_backbuffer(swap); if (!!backbuffer) { data.capture(swap, backbuffer); backbuffer->Release(); } } unhook(&present); present_t call = (present_t)present.call_addr; hr = call(swap, sync_interval, flags); rehook(&present); if (capture && capture_overlay) { /* * It seems that the first call to Present after ResizeBuffers * will cause the backbuffer to be invalidated, so do not * perform the post-overlay capture if ResizeBuffers has * recently been called. (The backbuffer returned by * get_dxgi_backbuffer *will* be invalid otherwise) */ if (resize_buffers_called) { resize_buffers_called = false; } else { backbuffer = get_dxgi_backbuffer(swap); if (!!backbuffer) { data.capture(swap, backbuffer); backbuffer->Release(); } } } return hr; }
bool GetDescriptor(ID3D10Texture2D* aTexture, SurfaceDescriptorD3D10* aDescr) { NS_ABORT_IF_FALSE(aTexture && aDescr, "Params must be nonnull"); HRESULT hr; IDXGIResource* dr = nullptr; hr = aTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&dr); if (!SUCCEEDED(hr) || !dr) return false; hr = dr->GetSharedHandle(reinterpret_cast<HANDLE*>(&aDescr->handle())); return !!SUCCEEDED(hr); }
HRESULT D3DImageEx::GetSharedHandle(IUnknown *pUnknown, HANDLE * pHandle) { HRESULT hr = S_OK; *pHandle = NULL; IDXGIResource* pSurface; if (FAILED(hr = pUnknown->QueryInterface(__uuidof(IDXGIResource), (void**)&pSurface))) return hr; hr = pSurface->GetSharedHandle(pHandle); pSurface->Release(); return hr; }
// // Returns shared handle // HANDLE OUTPUTMANAGER::GetSharedHandle() { HANDLE Hnd = nullptr; // QI IDXGIResource interface to synchronized shared surface. IDXGIResource* DXGIResource = nullptr; HRESULT hr = m_SharedSurf->QueryInterface(__uuidof(IDXGIResource), reinterpret_cast<void**>(&DXGIResource)); if (SUCCEEDED(hr)) { // Obtain handle to IDXGIResource object. DXGIResource->GetSharedHandle(&Hnd); DXGIResource->Release(); DXGIResource = nullptr; } return Hnd; }
static inline bool d3d9_shtex_init_shtex() { IDXGIResource *res; HRESULT hr; D3D11_TEXTURE2D_DESC desc = {}; desc.Width = data.cx; desc.Height = data.cy; desc.Format = data.dxgi_format; desc.MipLevels = 1; desc.ArraySize = 1; desc.SampleDesc.Count = 1; desc.Usage = D3D11_USAGE_DEFAULT; desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; hr = data.d3d11_device->CreateTexture2D(&desc, nullptr, (ID3D11Texture2D**)&data.d3d11_tex); if (FAILED(hr)) { hlog_hr("d3d9_shtex_init_shtex: Failed to create D3D11 texture", hr); return false; } hr = data.d3d11_tex->QueryInterface(__uuidof(IDXGIResource), (void**)&res); if (FAILED(hr)) { hlog_hr("d3d9_shtex_init_shtex: Failed to query IDXGIResource", hr); return false; } hr = res->GetSharedHandle(&data.handle); res->Release(); if (FAILED(hr)) { hlog_hr("d3d9_shtex_init_shtex: Failed to get shared handle", hr); return false; } return true; }
IDXGISurface* OpenD3D11TextureOnD3D10Device(ID3D11Texture2D* texture, ID3D10Device1* device) { // Obtain share handle for texture IDXGIResource* dxgiResource = NULL; CHECK_HR(texture->QueryInterface(IID_PPV_ARGS(&dxgiResource))); HANDLE shareHandle = NULL; CHECK_HR(dxgiResource->GetSharedHandle(&shareHandle)); SafeRelease(dxgiResource); // Open D3D11 texture on D3D10 device IDXGISurface* dxgiSurface = NULL; CHECK_HR(device->OpenSharedResource(shareHandle, IID_PPV_ARGS(&dxgiSurface))); return dxgiSurface; }
ID3D11Texture2D* DX11Texture2::CreateSharedDXObject(ID3D11Device* device) const { IDXGIResource* resource = nullptr; HRESULT hr = mDXObject->QueryInterface(__uuidof(IDXGIResource), (void**)&resource); CHECK_HR_RETURN("QueryInterface failed", nullptr); HANDLE handle = nullptr; hr = resource->GetSharedHandle(&handle); resource->Release(); CHECK_HR_RETURN("GetSharedHandle failed", nullptr); ID3D11Texture2D* dxShared = nullptr; hr = device->OpenSharedResource(handle, __uuidof(ID3D11Texture2D), (void**)&dxShared); CHECK_HR_RETURN("OpenSharedResource failed", nullptr); return dxShared; }
ID3D11Texture2D* DesktopDuplication::acquireNextFrame(DXGI_OUTDUPL_FRAME_INFO& frameInfoOut) { IDXGIResource* frameResource; hr = outputDuplication->AcquireNextFrame(acquireTimeout, &frameInfoOut, &frameResource); if (hr != S_OK) { reinitialize(); // Second chance to recover adapter failure. std::cout << "Next frame acquisition failed: " << hr << ". Reinitializing DXGI subsystems..." << std::endl; CHECKED(hr, outputDuplication->AcquireNextFrame(acquireTimeout, &frameInfoOut, &frameResource)); } ID3D11Texture2D* frameTex; CHECKED(hr, frameResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&frameTex))); frameResource->Release(); ID3D11Texture2D* frameStagingTex = copyToStaging(frameTex); frameTex->Release(); CHECKED(hr, outputDuplication->ReleaseFrame()); return frameStagingTex; }
bool RenderManagerD3D11OpenGL::RegisterRenderBuffersInternal( const std::vector<RenderBuffer>& buffers, bool appWillNotOverwriteBeforeNewPresent) { // Make sure we're doing okay. if (!doingOkay()) { std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers(): " "Display not opened." << std::endl; return false; } // Make sure we don't have more eyes than buffers. We can have fewer // because the client may have consolidated a number of eyes onto // one buffer. size_t numEyes = GetNumEyes(); if (buffers.size() > numEyes) { std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: " "Wrong number of buffers: " << buffers.size() << ", need " << numEyes << std::endl; return false; } // Delete any previously-registered buffers. for (size_t i = 0; i < m_oglToD3D.size(); i++) { wglDXUnregisterObjectNV(m_glD3DHandle, m_oglToD3D[i].glColorHandle); m_oglToD3D[i].D3DrenderTargetView->Release(); m_oglToD3D[i].D3DTexture->Release(); } m_oglToD3D.clear(); // Allocate D3D buffers to be used and tie them to the OpenGL buffers. for (size_t i = 0; i < buffers.size(); i++) { // If we have already mapped this buffer, we go ahead and skip it, // so that we don't tie the same OpenGL buffer to multiple D3D // buffers. It is not an error to map the same buffer twice. bool found = false; for (size_t j = 0; j < i; j++) { if (buffers[i].OpenGL->colorBufferName == buffers[j].OpenGL->colorBufferName) { found = true; } } if (found) { continue; } // Figure out how large the buffer should be by binding this texture // and querying the size of the 0th mipmap level. GLint width = 0, height = 0; glBindTexture(GL_TEXTURE_2D, buffers[i].OpenGL->colorBufferName); const GLint mipLevel = 0; glGetTexLevelParameteriv(GL_TEXTURE_2D, mipLevel, GL_TEXTURE_WIDTH, &width); glGetTexLevelParameteriv(GL_TEXTURE_2D, mipLevel, GL_TEXTURE_HEIGHT, &height); if ((width == 0) || (height == 0)) { std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: " "Zero-sized buffer for buffer: " << i << std::endl; return false; } // Initialize a new render target texture description. // Make it a shared texture so that we can use it with OpenGL // Interop. D3D11_TEXTURE2D_DESC textureDesc = {}; textureDesc.Width = width; textureDesc.Height = height; textureDesc.MipLevels = 1; textureDesc.ArraySize = 1; // textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; textureDesc.SampleDesc.Count = 1; textureDesc.SampleDesc.Quality = 0; textureDesc.Usage = D3D11_USAGE_DEFAULT; // We need it to be both a render target and a shader resource textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; textureDesc.CPUAccessFlags = 0; textureDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; // Create a new render target texture to use. ID3D11Texture2D* D3DTexture = nullptr; HRESULT hr = m_D3D11Renderer->m_D3D11device->CreateTexture2D( &textureDesc, NULL, &D3DTexture); if (FAILED(hr)) { std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: " "Can't create texture" << std::endl; return false; } // Fill in the resource view for your render texture buffer here D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc = {}; // This must match what was created in the texture to be rendered // @todo Figure this out by introspection on the texture? // renderTargetViewDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; renderTargetViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; renderTargetViewDesc.Texture2D.MipSlice = 0; // Create the render target view. ID3D11RenderTargetView* renderTargetView; //< Pointer to our render target view hr = m_D3D11Renderer->m_D3D11device->CreateRenderTargetView( D3DTexture, &renderTargetViewDesc, &renderTargetView); if (FAILED(hr)) { std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: " "Could not create render target" << std::endl; return false; } // Create a share handle for the texture, to enable it to be shared // between multiple devices. Then register the share handle with // interop. // https://msdn.microsoft.com/en-us/library/windows/desktop/ff476531(v=vs.85).aspx // https://www.opengl.org/registry/specs/NV/DX_interop.txt IDXGIResource* pOtherResource = nullptr; hr = D3DTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&pOtherResource); HANDLE sharedHandle; hr = pOtherResource->GetSharedHandle(&sharedHandle); if (FAILED(hr)) { std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: " "Could not get shared handle" << std::endl; return false; } if (wglDXSetResourceShareHandleNV(D3DTexture, sharedHandle) != TRUE) { std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers()" ": Could not share resource" << std::endl; return false; } // Prepare the things we need for wrapping Direct3D // objects. Information on how to do this comes from // the DX_interop2.txt file from opengl.org and from the // secondstory/ofDxSharedTextureExample project on Github. // Bind the OpenGL texture to the D3D texture for rendering HANDLE glColorHandle = wglDXRegisterObjectNV( m_glD3DHandle, D3DTexture, buffers[i].OpenGL->colorBufferName, GL_TEXTURE_2D, WGL_ACCESS_WRITE_DISCARD_NV); if (glColorHandle == nullptr) { std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: " "Can't get Color buffer handle" << " (error " << GetLastError() << ")"; switch (GetLastError()) { case ERROR_INVALID_HANDLE: std::cerr << " (Invalid handle)" << std::endl; break; case ERROR_INVALID_DATA: std::cerr << " (Invalid data)" << std::endl; break; case ERROR_OPEN_FAILED: std::cerr << " (Could not open Direct3D resource)" << std::endl; break; default: std::cerr << " (Unexpected error code)" << std::endl; } return false; } // New object to fill in OglToD3DTexture map; map.OpenGLTexture = buffers[i].OpenGL->colorBufferName; map.glColorHandle = glColorHandle; map.D3DTexture = D3DTexture; map.D3DrenderTargetView = renderTargetView; m_oglToD3D.push_back(map); // Lock the render target for OpenGL access if (!wglDXLockObjectsNV(m_glD3DHandle, 1, &map.glColorHandle)) { std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: " "Can't lock Color buffer" << std::endl; return false; } } // We're done -- call the base-class function to notify that we've // registered our buffers return RenderManager::RegisterRenderBuffersInternal(buffers, appWillNotOverwriteBeforeNewPresent); }
void D3D9Hook::gdiCreateSceneObjects() { if(m_sceneObjectsCreated) return; // Already created if(!isCapturable()) return; // Not capturable // Is the back buffer format compatible with DXGI? if(d3d9ToGdiCompatible(m_bbD3D9Format) == DXGI_FORMAT_UNKNOWN) { HookLog2(InterprocessLog::Warning, "Back buffer not compatible with DXGI, falling back to CPU capture"); m_useCpuCopy = true; return; } // Create a dummy DirectX 10 or 10.1 device depending on the system ID3D10Device *m_dx10Device = HookMain::s_instance->refDummyDX10Device(); if(m_dx10Device == NULL) { HookLog2(InterprocessLog::Warning, "Failed to create DirectX 10 device, falling back to CPU capture"); m_useCpuCopy = true; return; } HookLog(stringf("Creating D3D9 scene objects for window of size %d x %d", m_width, m_height)); // Create D3D9 render target surface HRESULT res = m_device->CreateRenderTarget( m_width, m_height, m_bbD3D9Format, D3DMULTISAMPLE_NONE, 0, TRUE, &m_rtSurface, NULL); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to create shared D3D9 render target. Reason = %s", getD3D9ErrorCode(res).data())); goto gdiCreateSceneObjectsFailed1; } // Create shared DX10 textures D3D10_TEXTURE2D_DESC desc; desc.Width = m_width; desc.Height = m_height; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = d3d9ToGdiCompatible(m_bbD3D9Format); desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D10_USAGE_DEFAULT; desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET; desc.CPUAccessFlags = 0; desc.MiscFlags = D3D10_RESOURCE_MISC_SHARED | D3D10_RESOURCE_MISC_GDI_COMPATIBLE; for(int i = 0; i < NUM_SHARED_TEXTURES; i++) { res = m_dx10Device->CreateTexture2D(&desc, NULL, &m_dx10Texs[i]); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to create shared DX10 target. Reason = %s", getDX10ErrorCode(res).data())); goto gdiCreateSceneObjectsFailed1; } } m_nextDx10Tex = 0; // Get DXGI shared handles from the textures for(int i = 0; i < NUM_SHARED_TEXTURES; i++) { IDXGIResource *dxgiRes = NULL; res = m_dx10Texs[i]->QueryInterface( __uuidof(IDXGIResource), (void **)&dxgiRes); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to get DXGI resource. Reason = %s", getDX10ErrorCode(res).data())); goto gdiCreateSceneObjectsFailed1; } m_dx10TexHandles[i] = NULL; res = dxgiRes->GetSharedHandle(&m_dx10TexHandles[i]); dxgiRes->Release(); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to get DXGI shared handle. Reason = %s", getDX10ErrorCode(res).data())); goto gdiCreateSceneObjectsFailed1; } } #if 0 // Create D3D9 render target surface HRESULT res = m_device->CreateRenderTarget( m_width, m_height, m_bbD3D9Format, D3DMULTISAMPLE_NONE, 0, FALSE, &m_rtSurface, NULL); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to create shared D3D9 render target. Reason = %s", getD3D9ErrorCode(res).data())); return; // TODO: Not safe to return here } // Create shared D3D9 texture HANDLE sharedHandle = NULL; res = m_device->CreateTexture( m_width, m_height, 1, D3DUSAGE_RENDERTARGET, m_bbD3D9Format, D3DPOOL_DEFAULT, &m_dx9Tex, &sharedHandle); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to create D3D9 texture. Reason = %s", getD3D9ErrorCode(res).data())); return; // TODO: Not safe to return here } // Open shared surface as a DX10 texture ID3D10Resource *resource = NULL; res = m_dx10Device->OpenSharedResource( sharedHandle, __uuidof(ID3D10Resource), (void **)(&resource)); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to open D3D9 surface as a DX10 resource. Reason = %s", getDX10ErrorCode(res).data())); return; // TODO: Not safe to return here } res = resource->QueryInterface( __uuidof(ID3D10Texture2D), (void **)(&m_dx10Tex)); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to query DX10 texture interface. Reason = %s", getDX10ErrorCode(res).data())); return; // TODO: Not safe to return here } resource->Release(); #endif // 0 #if 0 // Create shared DX10 texture D3D10_TEXTURE2D_DESC desc; desc.Width = m_width; desc.Height = m_height; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = d3d9ToDxgiFormat(m_bbD3D9Format); desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D10_USAGE_DEFAULT; desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET; desc.CPUAccessFlags = 0; desc.MiscFlags = D3D10_RESOURCE_MISC_SHARED; HRESULT res = m_dx10Device->CreateTexture2D(&desc, NULL, &m_dx10Tex); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to create DX10 target. Reason = %s", getDX10ErrorCode(res).data())); // TODO: Don't continue } // Get DXGI shared handle from the texture IDXGIResource *dxgiRes = NULL; res = m_dx10Tex->QueryInterface( __uuidof(IDXGIResource), (void **)&dxgiRes); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to get DXGI resource. Reason = %s", getDX10ErrorCode(res).data())); // TODO: Don't continue } HANDLE sharedHandle = NULL; res = dxgiRes->GetSharedHandle(&sharedHandle); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to get DXGI shared handle. Reason = %s", getDX10ErrorCode(res).data())); // TODO: Don't continue } dxgiRes->Release(); // Create D3D9 render target surface from the shared handle res = m_device->CreateRenderTarget( m_width, m_height, m_bbD3D9Format, D3DMULTISAMPLE_NONE, 0, TRUE, &m_rtSurface, &sharedHandle); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to create shared D3D9 render target. Reason = %s", getD3D9ErrorCode(res).data())); // TODO: Don't continue } #endif // 0 m_sceneObjectsCreated = true; return; // Error handling gdiCreateSceneObjectsFailed1: // Return everything to the same state as when we started if(m_rtSurface != NULL) m_rtSurface->Release(); for(int i = 0; i < NUM_SHARED_TEXTURES; i++) { m_dx10TexHandles[i] = NULL; if(m_dx10Texs[i] != NULL) { m_dx10Texs[i]->Release(); m_dx10Texs[i] = NULL; } } }
EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight) { ASSERT(mNeedsOffscreenTexture); TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture"); ID3D11Device *device = mRenderer->getDevice(); ASSERT(device != NULL); // D3D11 does not allow zero size textures ASSERT(backbufferWidth >= 1); ASSERT(backbufferHeight >= 1); // Preserve the render target content ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; if (previousOffscreenTexture) { previousOffscreenTexture->AddRef(); } const int previousWidth = mWidth; const int previousHeight = mHeight; releaseOffscreenColorBuffer(); const d3d11::Format &backbufferFormatInfo = d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); // If the app passed in a share handle, open the resource // See EGL_ANGLE_d3d_share_handle_client_buffer if (mAppCreatedShareHandle) { ID3D11Resource *tempResource11; HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11); if (FAILED(result)) { ERR("Failed to open the swap chain pbuffer share handle: %08lX", result); release(); return EGL_BAD_PARAMETER; } result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture); SafeRelease(tempResource11); if (FAILED(result)) { ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result); release(); return EGL_BAD_PARAMETER; } // Validate offscreen texture parameters D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; mOffscreenTexture->GetDesc(&offscreenTextureDesc); if (offscreenTextureDesc.Width != (UINT)backbufferWidth || offscreenTextureDesc.Height != (UINT)backbufferHeight || offscreenTextureDesc.Format != backbufferFormatInfo.texFormat || offscreenTextureDesc.MipLevels != 1 || offscreenTextureDesc.ArraySize != 1) { ERR("Invalid texture parameters in the shared offscreen texture pbuffer"); release(); return EGL_BAD_PARAMETER; } } else { const bool useSharedResource = !mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport(); D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; offscreenTextureDesc.Width = backbufferWidth; offscreenTextureDesc.Height = backbufferHeight; offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; offscreenTextureDesc.MipLevels = 1; offscreenTextureDesc.ArraySize = 1; offscreenTextureDesc.SampleDesc.Count = 1; offscreenTextureDesc.SampleDesc.Quality = 0; offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT; offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; offscreenTextureDesc.CPUAccessFlags = 0; offscreenTextureDesc.MiscFlags = useSharedResource ? ANGLE_RESOURCE_SHARE_TYPE : 0; HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture); if (FAILED(result)) { ERR("Could not create offscreen texture: %08lX", result); release(); if (d3d11::isDeviceLostError(result)) { return EGL_CONTEXT_LOST; } else { return EGL_BAD_ALLOC; } } d3d11::SetDebugName(mOffscreenTexture, "Offscreen back buffer texture"); // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client if (useSharedResource) { IDXGIResource *offscreenTextureResource = NULL; result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource); // Fall back to no share handle on failure if (FAILED(result)) { ERR("Could not query offscreen texture resource: %08lX", result); } else { result = offscreenTextureResource->GetSharedHandle(&mShareHandle); SafeRelease(offscreenTextureResource); if (FAILED(result)) { mShareHandle = NULL; ERR("Could not get offscreen texture shared handle: %08lX", result); } } } } // This may return null if the original texture was created without a keyed mutex. mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture); D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc; offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat; offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; offscreenRTVDesc.Texture2D.MipSlice = 0; HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target"); D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc; offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; offscreenSRVDesc.Texture2D.MostDetailedMip = 0; offscreenSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1); result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource"); if (previousOffscreenTexture != nullptr) { D3D11_BOX sourceBox = {0}; sourceBox.left = 0; sourceBox.right = std::min(previousWidth, backbufferWidth); sourceBox.top = std::max(previousHeight - backbufferHeight, 0); sourceBox.bottom = previousHeight; sourceBox.front = 0; sourceBox.back = 1; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); const int yoffset = std::max(backbufferHeight - previousHeight, 0); deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox); SafeRelease(previousOffscreenTexture); if (mSwapChain) { swapRect(0, 0, backbufferWidth, backbufferHeight); } } return EGL_SUCCESS; }
Coherent::UI::CoherentHandle CCoherentUISystem::CreateSharedTextureDX11( const CreateSurfaceTask& task, TexturePair* outTexturePair ) { // The shared texture's format for DX11 must be DXGI_FORMAT_B8G8R8A8_UNORM. // There is no corresponding ETEX_Format and after injecting the created // texture, COM errors occur. // TODO: Find a way to fool CryEngine into accepting a DXGI_FORMAT_B8G8R8A8_UNORM texture. // Create shared texture D3D11_TEXTURE2D_DESC desc; memset( &desc, 0, sizeof( desc ) ); desc.Width = task.Width; desc.Height = task.Height; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; desc.SampleDesc.Count = 1; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; ID3D11Device* pDevice = static_cast<ID3D11Device*>( gD3DDevice ); ID3D11Texture2D* pD3DTex = NULL; HRESULT hr = pDevice->CreateTexture2D( &desc, NULL, &pD3DTex ); if ( FAILED( hr ) ) { return Coherent::UI::CoherentHandle( 0 ); } IDXGIResource* pTempResource = NULL; hr = pD3DTex->QueryInterface( __uuidof( IDXGIResource ), ( void** )&pTempResource ); if ( FAILED( hr ) ) { SAFE_RELEASE( pD3DTex ); return Coherent::UI::CoherentHandle( 0 ); } HANDLE result; hr = pTempResource->GetSharedHandle( &result ); pTempResource->Release(); if ( FAILED( hr ) ) { SAFE_RELEASE( pD3DTex ); return Coherent::UI::CoherentHandle( 0 ); } ITexture* pCryTex = gD3DSystem->InjectTexture( pD3DTex, task.Width, task.Height, eTF_A8R8G8B8, 0 ); // The native texture has one more reference after InjectTexture if ( outTexturePair ) { outTexturePair->CryTextureID = pCryTex->GetTextureID(); outTexturePair->NativeTexture.pTexDX11 = pD3DTex; } SAFE_RELEASE( pD3DTex ); return Coherent::UI::CoherentHandle( result ); }
bool DoD3D11Hook(ID3D11Device *device) { HRESULT hErr; bD3D101Hooked = true; HMODULE hD3D10_1 = LoadLibrary(TEXT("d3d10_1.dll")); if(!hD3D10_1) { RUNONCE logOutput << "DoD3D11Hook: could not load d3d10.1" << endl; return false; } HMODULE hDXGI = GetModuleHandle(TEXT("dxgi.dll")); if(!hDXGI) { RUNONCE logOutput << "DoD3D11Hook: could not load dxgi" << endl; return false; } CREATEDXGIFACTORY1PROC createDXGIFactory1 = (CREATEDXGIFACTORY1PROC)GetProcAddress(hDXGI, "CreateDXGIFactory1"); if(!createDXGIFactory1) { RUNONCE logOutput << "DoD3D11Hook: could not get address of CreateDXGIFactory1" << endl; return false; } PFN_D3D10_CREATE_DEVICE1 d3d10CreateDevice1 = (PFN_D3D10_CREATE_DEVICE1)GetProcAddress(hD3D10_1, "D3D10CreateDevice1"); if(!d3d10CreateDevice1) { RUNONCE logOutput << "DoD3D11Hook: could not get address of D3D10CreateDevice1" << endl; return false; } IDXGIFactory1 *factory; if(FAILED(hErr = (*createDXGIFactory1)(__uuidof(IDXGIFactory1), (void**)&factory))) { RUNONCE logOutput << "DoD3D11Hook: CreateDXGIFactory1 failed, result = " << UINT(hErr) << endl; return false; } IDXGIAdapter1 *adapter; if(FAILED(hErr = factory->EnumAdapters1(0, &adapter))) { RUNONCE logOutput << "DoD3D11Hook: factory->EnumAdapters1 failed, result = " << UINT(hErr) << endl; factory->Release(); return false; } if(FAILED(hErr = (*d3d10CreateDevice1)(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_FEATURE_LEVEL_10_1, D3D10_1_SDK_VERSION, &shareDevice))) { if(FAILED(hErr = (*d3d10CreateDevice1)(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_FEATURE_LEVEL_9_3, D3D10_1_SDK_VERSION, &shareDevice))) { RUNONCE logOutput << "DoD3D11Hook: device creation failed, result = " << UINT(hErr) << endl; adapter->Release(); factory->Release(); return false; } } adapter->Release(); factory->Release(); //------------------------------------------------ D3D11_TEXTURE2D_DESC texGameDesc; ZeroMemory(&texGameDesc, sizeof(texGameDesc)); texGameDesc.Width = d3d11CaptureInfo.cx; texGameDesc.Height = d3d11CaptureInfo.cy; texGameDesc.MipLevels = 1; texGameDesc.ArraySize = 1; texGameDesc.Format = dxgiFormat; texGameDesc.SampleDesc.Count = 1; texGameDesc.BindFlags = D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE; texGameDesc.Usage = D3D11_USAGE_DEFAULT; texGameDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; ID3D11Texture2D *d3d11Tex; if(FAILED(hErr = device->CreateTexture2D(&texGameDesc, NULL, &d3d11Tex))) { RUNONCE logOutput << "DoD3D11Hook: creation of intermediary texture failed, result = " << UINT(hErr) << endl; return false; } if(FAILED(hErr = d3d11Tex->QueryInterface(__uuidof(ID3D11Resource), (void**)©TextureGame))) { RUNONCE logOutput << "DoD3D11Hook: d3d11Tex->QueryInterface(ID3D11Resource) failed, result = " << UINT(hErr) << endl; d3d11Tex->Release(); return false; } IDXGIResource *res; if(FAILED(hErr = d3d11Tex->QueryInterface(IID_IDXGIResource, (void**)&res))) { RUNONCE logOutput << "DoD3D11Hook: d3d11Tex->QueryInterface(IID_IDXGIResource) failed, result = " << UINT(hErr) << endl; d3d11Tex->Release(); return false; } HANDLE handle; if(FAILED(hErr = res->GetSharedHandle(&handle))) { RUNONCE logOutput << "DoD3D11Hook: res->GetSharedHandle failed, result = " << UINT(hErr) << endl; d3d11Tex->Release(); res->Release(); return false; } d3d11Tex->Release(); res->Release(); //------------------------------------------------ if(FAILED(hErr = shareDevice->OpenSharedResource(handle, __uuidof(ID3D10Resource), (void**)©TextureIntermediary))) { RUNONCE logOutput << "DoD3D11Hook: shareDevice->OpenSharedResource failed, result = " << UINT(hErr) << endl; return false; } //------------------------------------------------ D3D10_TEXTURE2D_DESC texDesc; ZeroMemory(&texDesc, sizeof(texDesc)); texDesc.Width = d3d11CaptureInfo.cx; texDesc.Height = d3d11CaptureInfo.cy; texDesc.MipLevels = 1; texDesc.ArraySize = 1; texDesc.Format = dxgiFormat; texDesc.SampleDesc.Count = 1; texDesc.BindFlags = D3D10_BIND_RENDER_TARGET|D3D10_BIND_SHADER_RESOURCE; texDesc.Usage = D3D10_USAGE_DEFAULT; texDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX; for(UINT i=0; i<2; i++) { ID3D10Texture2D *d3d10tex; if(FAILED(hErr = shareDevice->CreateTexture2D(&texDesc, NULL, &d3d10tex))) { RUNONCE logOutput << "DoD3D11Hook: shareDevice->CreateTexture2D " << i << " failed, result = " << UINT(hErr) << endl; return false; } if(FAILED(hErr = d3d10tex->QueryInterface(__uuidof(ID3D10Resource), (void**)&sharedTextures[i]))) { RUNONCE logOutput << "DoD3D11Hook: d3d10tex->QueryInterface(ID3D10Resource) " << i << " failed, result = " << UINT(hErr) << endl; d3d10tex->Release(); return false; } if(FAILED(hErr = d3d10tex->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)&keyedMutexes[i]))) { RUNONCE logOutput << "DoD3D11Hook: d3d10tex->QueryInterface(IDXGIKeyedMutex) " << i << " failed, result = " << UINT(hErr) << endl; d3d10tex->Release(); return false; } IDXGIResource *res; if(FAILED(hErr = d3d10tex->QueryInterface(__uuidof(IDXGIResource), (void**)&res))) { RUNONCE logOutput << "DoD3D11Hook: d3d10tex->QueryInterface(IDXGIResource) " << i << " failed, result = " << UINT(hErr) << endl; d3d10tex->Release(); return false; } if(FAILED(hErr = res->GetSharedHandle(&sharedHandles[i]))) { RUNONCE logOutput << "DoD3D11Hook: res->GetSharedHandle " << i << " failed, result = " << UINT(hErr) << endl; res->Release(); d3d10tex->Release(); return false; } res->Release(); d3d10tex->Release(); } return true; }
DUPL_RETURN DUPLICATIONMANAGER::GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Timeout) { IDXGIResource* DesktopResource = nullptr; DXGI_OUTDUPL_FRAME_INFO FrameInfo; // Get new frame HRESULT hr = m_DeskDupl->AcquireNextFrame(500, &FrameInfo, &DesktopResource); if (hr == DXGI_ERROR_WAIT_TIMEOUT) { *Timeout = true; return DUPL_RETURN_SUCCESS; } *Timeout = false; if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to acquire next frame in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); } // If still holding old frame, destroy it if (m_AcquiredDesktopImage) { m_AcquiredDesktopImage->Release(); m_AcquiredDesktopImage = nullptr; } // QI for IDXGIResource hr = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&m_AcquiredDesktopImage)); DesktopResource->Release(); DesktopResource = nullptr; if (FAILED(hr)) { return ProcessFailure(nullptr, L"Failed to QI for ID3D11Texture2D from acquired IDXGIResource in DUPLICATIONMANAGER", L"Error", hr); } // Get metadata if (FrameInfo.TotalMetadataBufferSize) { // Old buffer too small if (FrameInfo.TotalMetadataBufferSize > m_MetaDataSize) { if (m_MetaDataBuffer) { delete [] m_MetaDataBuffer; m_MetaDataBuffer = nullptr; } m_MetaDataBuffer = new (std::nothrow) BYTE[FrameInfo.TotalMetadataBufferSize]; if (!m_MetaDataBuffer) { m_MetaDataSize = 0; Data->MoveCount = 0; Data->DirtyCount = 0; return ProcessFailure(nullptr, L"Failed to allocate memory for metadata in DUPLICATIONMANAGER", L"Error", E_OUTOFMEMORY); } m_MetaDataSize = FrameInfo.TotalMetadataBufferSize; } UINT BufSize = FrameInfo.TotalMetadataBufferSize; // Get move rectangles hr = m_DeskDupl->GetFrameMoveRects(BufSize, reinterpret_cast<DXGI_OUTDUPL_MOVE_RECT*>(m_MetaDataBuffer), &BufSize); if (FAILED(hr)) { Data->MoveCount = 0; Data->DirtyCount = 0; return ProcessFailure(nullptr, L"Failed to get frame move rects in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); } Data->MoveCount = BufSize / sizeof(DXGI_OUTDUPL_MOVE_RECT); BYTE* DirtyRects = m_MetaDataBuffer + BufSize; BufSize = FrameInfo.TotalMetadataBufferSize - BufSize; // Get dirty rectangles hr = m_DeskDupl->GetFrameDirtyRects(BufSize, reinterpret_cast<RECT*>(DirtyRects), &BufSize); if (FAILED(hr)) { Data->MoveCount = 0; Data->DirtyCount = 0; return ProcessFailure(nullptr, L"Failed to get frame dirty rects in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); } Data->DirtyCount = BufSize / sizeof(RECT); Data->MetaData = m_MetaDataBuffer; } Data->Frame = m_AcquiredDesktopImage; Data->FrameInfo = FrameInfo; return DUPL_RETURN_SUCCESS; }
EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight) { ID3D11Device *device = mRenderer->getDevice(); ASSERT(device != NULL); // D3D11 does not allow zero size textures ASSERT(backbufferWidth >= 1); ASSERT(backbufferHeight >= 1); // Preserve the render target content ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; if (previousOffscreenTexture) { previousOffscreenTexture->AddRef(); } const int previousWidth = mWidth; const int previousHeight = mHeight; releaseOffscreenTexture(); // If the app passed in a share handle, open the resource // See EGL_ANGLE_d3d_share_handle_client_buffer if (mAppCreatedShareHandle) { ID3D11Resource *tempResource11; HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11); if (FAILED(result)) { ERR("Failed to open the swap chain pbuffer share handle: %08lX", result); release(); return EGL_BAD_PARAMETER; } result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture); tempResource11->Release(); if (FAILED(result)) { ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result); release(); return EGL_BAD_PARAMETER; } // Validate offscreen texture parameters D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; mOffscreenTexture->GetDesc(&offscreenTextureDesc); if (offscreenTextureDesc.Width != (UINT)backbufferWidth || offscreenTextureDesc.Height != (UINT)backbufferHeight || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat) || offscreenTextureDesc.MipLevels != 1 || offscreenTextureDesc.ArraySize != 1) { ERR("Invalid texture parameters in the shared offscreen texture pbuffer"); release(); return EGL_BAD_PARAMETER; } } else { const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport(); D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; offscreenTextureDesc.Width = backbufferWidth; offscreenTextureDesc.Height = backbufferHeight; offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); offscreenTextureDesc.MipLevels = 1; offscreenTextureDesc.ArraySize = 1; offscreenTextureDesc.SampleDesc.Count = 1; offscreenTextureDesc.SampleDesc.Quality = 0; offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT; offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; offscreenTextureDesc.CPUAccessFlags = 0; offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0; HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture); if (FAILED(result)) { ERR("Could not create offscreen texture: %08lX", result); release(); if (d3d11::isDeviceLostError(result)) { return EGL_CONTEXT_LOST; } else { return EGL_BAD_ALLOC; } } d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture"); // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client if (useSharedResource) { IDXGIResource *offscreenTextureResource = NULL; result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource); // Fall back to no share handle on failure if (FAILED(result)) { ERR("Could not query offscreen texture resource: %08lX", result); } else { result = offscreenTextureResource->GetSharedHandle(&mShareHandle); offscreenTextureResource->Release(); if (FAILED(result)) { mShareHandle = NULL; ERR("Could not get offscreen texture shared handle: %08lX", result); } } } } HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target"); result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource"); if (mDepthBufferFormat != GL_NONE) { D3D11_TEXTURE2D_DESC depthStencilDesc = {0}; depthStencilDesc.Width = backbufferWidth; depthStencilDesc.Height = backbufferHeight; depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat); depthStencilDesc.MipLevels = 1; depthStencilDesc.ArraySize = 1; depthStencilDesc.SampleDesc.Count = 1; depthStencilDesc.SampleDesc.Quality = 0; depthStencilDesc.Usage = D3D11_USAGE_DEFAULT; depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; depthStencilDesc.CPUAccessFlags = 0; depthStencilDesc.MiscFlags = 0; result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture); if (FAILED(result)) { ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); release(); if (d3d11::isDeviceLostError(result)) { return EGL_CONTEXT_LOST; } else { return EGL_BAD_ALLOC; } } d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture"); result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view"); } mWidth = backbufferWidth; mHeight = backbufferHeight; if (previousOffscreenTexture != NULL) { D3D11_BOX sourceBox = {0}; sourceBox.left = 0; sourceBox.right = std::min(previousWidth, mWidth); sourceBox.top = std::max(previousHeight - mHeight, 0); sourceBox.bottom = previousHeight; sourceBox.front = 0; sourceBox.back = 1; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); const int yoffset = std::max(mHeight - previousHeight, 0); deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox); previousOffscreenTexture->Release(); if (mSwapChain) { swapRect(0, 0, mWidth, mHeight); } } return EGL_SUCCESS; }