#include "HiddenGlWindow.h" namespace { constexpr const char* kWindowClassName = "RenderCadenceCompositorHiddenGlWindow"; } HiddenGlWindow::~HiddenGlWindow() { Destroy(); } bool HiddenGlWindow::Create(unsigned width, unsigned height, std::string& error) { return CreateShared(width, height, nullptr, nullptr, error); } bool HiddenGlWindow::CreateShared(unsigned width, unsigned height, HDC sharedDeviceContext, HGLRC sharedContext, std::string& error) { Destroy(); mInstance = GetModuleHandle(nullptr); WNDCLASSA wc = {}; wc.style = CS_OWNDC; wc.lpfnWndProc = HiddenGlWindow::WindowProc; wc.hInstance = mInstance; wc.lpszClassName = kWindowClassName; mClassAtom = RegisterClassA(&wc); if (mClassAtom == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) { error = "RegisterClassA failed for hidden OpenGL window."; return false; } mWindow = CreateWindowA( kWindowClassName, "Render Cadence Compositor Hidden GL", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, static_cast(width), static_cast(height), nullptr, nullptr, mInstance, nullptr); if (!mWindow) { error = "CreateWindowA failed for hidden OpenGL window."; return false; } mDc = GetDC(mWindow); if (!mDc) { error = "GetDC failed for hidden OpenGL window."; return false; } PIXELFORMATDESCRIPTOR pfd = {}; pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 32; pfd.cDepthBits = 0; pfd.iLayerType = PFD_MAIN_PLANE; int pixelFormat = 0; if (sharedDeviceContext != nullptr) pixelFormat = GetPixelFormat(sharedDeviceContext); if (pixelFormat == 0) pixelFormat = ChoosePixelFormat(mDc, &pfd); if (pixelFormat == 0 || !SetPixelFormat(mDc, pixelFormat, &pfd)) { error = "Could not choose/set pixel format for hidden OpenGL window."; return false; } mGlrc = wglCreateContext(mDc); if (!mGlrc) { error = "wglCreateContext failed for hidden OpenGL window."; return false; } if (sharedContext != nullptr && wglShareLists(sharedContext, mGlrc) != TRUE) { error = "wglShareLists failed for hidden OpenGL shared context."; return false; } return true; } bool HiddenGlWindow::MakeCurrent() const { return mDc != nullptr && mGlrc != nullptr && wglMakeCurrent(mDc, mGlrc) == TRUE; } void HiddenGlWindow::ClearCurrent() const { wglMakeCurrent(nullptr, nullptr); } void HiddenGlWindow::Destroy() { ClearCurrent(); if (mGlrc) { wglDeleteContext(mGlrc); mGlrc = nullptr; } if (mWindow && mDc) { ReleaseDC(mWindow, mDc); mDc = nullptr; } if (mWindow) { DestroyWindow(mWindow); mWindow = nullptr; } mInstance = nullptr; mClassAtom = 0; } LRESULT CALLBACK HiddenGlWindow::WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hwnd, message, wParam, lParam); }