egl::Error DXGISwapChainWindowSurfaceWGL::swap() { mFunctionsGL->flush(); egl::Error error = setObjectsLocked(false); if (error.isError()) { return error; } HRESULT result = mSwapChain->Present(mSwapInterval, 0); mFirstSwap = false; error = setObjectsLocked(true); if (error.isError()) { return error; } if (FAILED(result)) { return egl::Error(EGL_BAD_ALLOC, "Failed to present swap chain, result: 0x%X", result); } return checkForResize(); }
egl::Error DXGISwapChainWindowSurfaceWGL::swap(const gl::Context *context) { mFunctionsGL->flush(); ANGLE_TRY(setObjectsLocked(false)); HRESULT result = mSwapChain->Present(mSwapInterval, 0); mFirstSwap = false; ANGLE_TRY(setObjectsLocked(true)); if (FAILED(result)) { return egl::EglBadAlloc() << "Failed to present swap chain, " << gl::FmtHR(result); } return checkForResize(); }
egl::Error DXGISwapChainWindowSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) { ASSERT(mSwapChain1 != nullptr); mFunctionsGL->flush(); egl::Error error = setObjectsLocked(false); if (error.isError()) { return error; } HRESULT result = S_OK; if (mFirstSwap) { result = mSwapChain1->Present(mSwapInterval, 0); mFirstSwap = false; } else { RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height), static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)}; DXGI_PRESENT_PARAMETERS params = {1, &rect, nullptr, nullptr}; result = mSwapChain1->Present1(mSwapInterval, 0, ¶ms); } error = setObjectsLocked(true); if (error.isError()) { return error; } if (FAILED(result)) { return egl::Error(EGL_BAD_ALLOC, "Failed to present swap chain, result: 0x%X", result); } return checkForResize(); }
egl::Error DXGISwapChainWindowSurfaceWGL::postSubBuffer(const gl::Context *context, EGLint x, EGLint y, EGLint width, EGLint height) { ASSERT(width > 0 && height > 0); ASSERT(mSwapChain1 != nullptr); mFunctionsGL->flush(); ANGLE_TRY(setObjectsLocked(false)); HRESULT result = S_OK; if (mFirstSwap) { result = mSwapChain1->Present(mSwapInterval, 0); mFirstSwap = false; } else { RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height), static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)}; DXGI_PRESENT_PARAMETERS params = {1, &rect, nullptr, nullptr}; result = mSwapChain1->Present1(mSwapInterval, 0, ¶ms); } ANGLE_TRY(setObjectsLocked(true)); if (FAILED(result)) { return egl::EglBadAlloc() << "Failed to present swap chain, " << gl::FmtHR(result); } return checkForResize(); }
egl::Error DXGISwapChainWindowSurfaceWGL::createSwapChain() { egl::Error error = setObjectsLocked(false); if (error.isError()) { return error; } if (mRenderbufferBufferHandle) { mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mRenderbufferBufferHandle); mRenderbufferBufferHandle = nullptr; } // If this surface is bound to a texture, unregister it. bool hadBoundSurface = (mTextureHandle != nullptr); if (hadBoundSurface) { mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle); mTextureHandle = nullptr; } IDXGIFactory *dxgiFactory = GetDXGIFactoryFromDevice(mDevice); if (dxgiFactory == nullptr) { return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the DXGIFactory."); } IDXGIFactory2 *dxgiFactory2 = nullptr; HRESULT result = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory2)); if (SUCCEEDED(result)) { ASSERT(dxgiFactory2 != nullptr); DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; swapChainDesc.BufferCount = 1; swapChainDesc.Format = mSwapChainFormat; swapChainDesc.Width = static_cast<UINT>(mWidth); swapChainDesc.Height = static_cast<UINT>(mHeight); swapChainDesc.Format = mSwapChainFormat; swapChainDesc.Stereo = FALSE; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER; swapChainDesc.BufferCount = 1; swapChainDesc.Scaling = DXGI_SCALING_STRETCH; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL; swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; swapChainDesc.Flags = mSwapChainFlags; result = dxgiFactory2->CreateSwapChainForHwnd(mDevice, mWindow, &swapChainDesc, nullptr, nullptr, &mSwapChain1); SafeRelease(dxgiFactory2); SafeRelease(dxgiFactory); if (FAILED(result)) { return egl::Error(EGL_BAD_ALLOC, "Failed to create swap chain for window, result: 0x%X", result); } mSwapChain = mSwapChain1; mSwapChain->AddRef(); } else { DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = 1; swapChainDesc.BufferDesc.Format = mSwapChainFormat; swapChainDesc.BufferDesc.Width = static_cast<UINT>(mWidth); swapChainDesc.BufferDesc.Height = static_cast<UINT>(mHeight); swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER; swapChainDesc.Flags = mSwapChainFlags; swapChainDesc.OutputWindow = mWindow; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; swapChainDesc.Windowed = TRUE; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; result = dxgiFactory->CreateSwapChain(mDevice, &swapChainDesc, &mSwapChain); SafeRelease(dxgiFactory); if (FAILED(result)) { return egl::Error(EGL_BAD_ALLOC, "Failed to create swap chain for window, result: 0x%X", result); } } ID3D11Texture2D *colorBuffer = nullptr; result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&colorBuffer)); if (FAILED(result)) { return egl::Error(EGL_BAD_ALLOC, "Failed to query texture from swap chain, result: 0x%X", result); } mFunctionsGL->genRenderbuffers(1, &mColorRenderbufferID); mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mColorRenderbufferID); mRenderbufferBufferHandle = mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, mColorRenderbufferID, GL_RENDERBUFFER, WGL_ACCESS_READ_WRITE_NV); SafeRelease(colorBuffer); if (mRenderbufferBufferHandle == nullptr) { return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%X.", HRESULT_CODE(GetLastError())); } // Rebind the surface to the texture if needed. if (hadBoundSurface) { mTextureHandle = mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, mTextureID, GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV); if (mTextureHandle == nullptr) { return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%X.", HRESULT_CODE(GetLastError())); } } error = setObjectsLocked(true); if (error.isError()) { return error; } ASSERT(mFramebufferID != 0); mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mColorRenderbufferID); if (mDepthBufferFormat != GL_NONE) { ASSERT(mDepthRenderbufferID != 0); mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbufferID); mFunctionsGL->renderbufferStorage(GL_RENDERBUFFER, mDepthBufferFormat, static_cast<GLsizei>(mWidth), static_cast<GLsizei>(mHeight)); const gl::InternalFormat &depthStencilFormatInfo = gl::GetInternalFormatInfo(mDepthBufferFormat); if (depthStencilFormatInfo.depthBits > 0) { mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthRenderbufferID); } if (depthStencilFormatInfo.stencilBits > 0) { mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepthRenderbufferID); } } mFirstSwap = true; return egl::Error(EGL_SUCCESS); }