#include "shared_gl_context.h" #define WIN32_LEAN_AND_MEAN #include #include #include struct SharedGlContext::Native { using CreatePbuffer = HANDLE (WINAPI *)(HDC, int, int, int, const int *); using GetPbufferDC = HDC (WINAPI *)(HANDLE); using ReleasePbufferDC = int (WINAPI *)(HANDLE, HDC); using DestroyPbuffer = BOOL (WINAPI *)(HANDLE); using CreateContext = HGLRC (WINAPI *)(HDC, HGLRC, const int *); HANDLE surface = nullptr; HDC display = nullptr; HGLRC context = nullptr; ReleasePbufferDC release_dc = nullptr; DestroyPbuffer destroy_surface = nullptr; void *resolve(const char *name) const { PROC address = wglGetProcAddress(name); intptr_t value = reinterpret_cast(address); if (value == 0 || value == 1 || value == 2 || value == 3 || value == -1) { address = reinterpret_cast(GetProcAddress(GetModuleHandleW(L"opengl32.dll"), name)); } return reinterpret_cast(address); } bool create() { HDC parent_display = wglGetCurrentDC(); HGLRC parent_context = wglGetCurrentContext(); if (!parent_display || !parent_context) return false; auto create_surface = reinterpret_cast(resolve("wglCreatePbufferARB")); auto get_dc = reinterpret_cast(resolve("wglGetPbufferDCARB")); release_dc = reinterpret_cast(resolve("wglReleasePbufferDCARB")); destroy_surface = reinterpret_cast(resolve("wglDestroyPbufferARB")); auto create_context = reinterpret_cast(resolve("wglCreateContextAttribsARB")); if (!create_surface || !get_dc || !release_dc || !destroy_surface || !create_context) return false; const int surface_attributes[] = {0}; surface = create_surface(parent_display, GetPixelFormat(parent_display), 1, 1, surface_attributes); if (!surface) return false; display = get_dc(surface); if (!display) return false; constexpr int major_version = 0x2091; constexpr int minor_version = 0x2092; constexpr int profile_mask = 0x9126; constexpr int core_profile = 1; const int attributes[] = {major_version, 3, minor_version, 3, profile_mask, core_profile, 0}; context = create_context(display, parent_context, attributes); return context != nullptr; } ~Native() { if (context) wglDeleteContext(context); if (display) release_dc(surface, display); if (surface) destroy_surface(surface); } }; SharedGlContext::SharedGlContext() = default; SharedGlContext::~SharedGlContext() = default; bool SharedGlContext::create() { native = std::make_unique(); if (native->create()) return true; destroy(); return false; } bool SharedGlContext::activate() { return native && wglMakeCurrent(native->display, native->context); } void SharedGlContext::release() { wglMakeCurrent(nullptr, nullptr); } void SharedGlContext::destroy() { native.reset(); } void *SharedGlContext::resolve(const char *name) const { return native ? native->resolve(name) : nullptr; }