3#include "GLFuncPointers.h"
6#include "../IGraphicsDevice.h"
7#include "Foundation/Logging/Logger.h"
8#include "Foundation/Platform/WindowData.h"
16 PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB =
nullptr;
17 PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB =
nullptr;
18 PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT =
nullptr;
19 PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB =
nullptr;
20 PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
nullptr;
26 LibFunc WGLFuncs[] = {
27 { (
void**)&wglChoosePixelFormatARB,
"wglChoosePixelFormatARB"},
28 { (
void**)&wglGetPixelFormatAttribivARB,
"wglGetPixelFormatAttribivARB"},
29 { (
void**)&wglSwapIntervalEXT,
"wglSwapIntervalEXT"},
30 { (
void**)&wglGetExtensionsStringARB,
"wglGetExtensionsStringARB"},
31 { (
void**)&wglCreateContextAttribsARB,
"wglCreateContextAttribsARB"},
34 bool getWGLFuncPointers()
36 for (
const LibFunc& libFunc : WGLFuncs) {
37 *libFunc.ptr = wglGetProcAddress(libFunc.name);
38 if (*libFunc.ptr ==
nullptr) {
39 LOG_FATAL(logger,
"Failed to look up %s (GetLastError()=%d).", libFunc.name, GetLastError());
59 LRESULT CALLBACK dummyWindowWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
61 if (message == WM_NCCREATE) {
62 HWND* hwndPtr =
reinterpret_cast<HWND*
>(((LPCREATESTRUCT)lParam)->lpCreateParams);
65 return ::DefWindowProc(hWnd, message, wParam, lParam);
69 bool dummyWindowCreate(HWND& hWnd, LPCWSTR windowName)
71 static ATOM classAtom = 0;
73 WNDCLASSEX wcex = { 0 };
74 wcex.cbSize =
sizeof(WNDCLASSEX);
75 wcex.style = CS_OWNDC;
76 wcex.lpfnWndProc = dummyWindowWndProc;
77 wcex.hInstance = GetModuleHandle(NULL);
78 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
79 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);
80 wcex.lpszClassName = TEXT(
"CogsRenderingWGLDummyWindow");
81 classAtom = RegisterClassEx(&wcex);
83 LOG_ERROR(logger,
"RegisterClass failed for dummy window(GetLastError()=%x).", GetLastError());
88 CreateWindow((LPCTSTR)classAtom, windowName,
96 GetModuleHandle(NULL),
99 if (hWnd ==
nullptr) {
105 void dummyWindowDestroy(HWND& hwnd)
115 ~DummyContext() { destroy(); }
119 if (!dummyWindowCreate(dummyWindow, TEXT(
"DummyContextWindow")))
return false;
121 PIXELFORMATDESCRIPTOR dummy_pfd = { 0 };
122 dummy_pfd.nSize =
sizeof(PIXELFORMATDESCRIPTOR);
123 dummy_pfd.nVersion = 1;
124 dummy_pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
125 dummy_pfd.iPixelType = PFD_TYPE_RGBA;
126 dummy_pfd.cColorBits = 32;
127 dummy_pfd.cDepthBits = 24;
128 dummy_pfd.cStencilBits = 8;
129 dummy_pfd.iLayerType = PFD_MAIN_PLANE;
131 hdc = GetDC(dummyWindow);
132 int dummy_pf = ChoosePixelFormat(hdc, &dummy_pfd);
134 LOG_FATAL(logger,
"Failed to choose pixel format (GetLastError()=%d).", GetLastError());
137 if (!SetPixelFormat(hdc, dummy_pf, &dummy_pfd)) {
138 LOG_FATAL(logger,
"Failed to set pixel format (GetLastError()=%d).", GetLastError());
141 context = wglCreateContext(hdc);
143 LOG_FATAL(logger,
"Failed to create dummy context (GetLastError()=%d).", GetLastError());
147 if (!wglMakeCurrent(hdc, context)) {
148 LOG_FATAL(logger,
"Failed to make dummy context current (GetLastError()=%d).", GetLastError());
158 wglMakeCurrent(hdc,
nullptr);
159 wglDeleteContext(context);
161 dummyWindowDestroy(dummyWindow);
164 HWND dummyWindow =
nullptr;
165 HGLRC context =
nullptr;
169 bool chooseAndSetPixelFormat(HDC hdc,
int requestedSampleCount,
bool sRGB)
171 PIXELFORMATDESCRIPTOR pfd = { 0 };
172 std::vector<int> pfAttribs = {
173 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
174 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
175 WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
176 WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
177 WGL_COLOR_BITS_ARB, 24,
178 WGL_ALPHA_BITS_ARB, 8,
179 WGL_DEPTH_BITS_ARB, 24,
180 WGL_STENCIL_BITS_ARB, 8,
184 pfAttribs.push_back(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
185 pfAttribs.push_back(GL_TRUE);
187 pfAttribs.push_back(0);
189 const int maxPixelFormats = 1024;
190 std::vector<int> pixelFormats(maxPixelFormats);
192 if (!wglChoosePixelFormatARB(hdc, pfAttribs.data(),
nullptr, maxPixelFormats, pixelFormats.data(), &numFormats))
194 LOG_FATAL(logger,
"wglChoosePixelFormatARB failed (GetLastError()=%d).", GetLastError());
198 size_t bestFormat = 0;
199 int bestSampleCount = 0;
200 if (requestedSampleCount) {
202 static const int attributeNames[2] = { WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB };
203 for (
size_t i = 0; i < numFormats; i++) {
204 int attributeValues[2] = {};
205 if (!wglGetPixelFormatAttribivARB(hdc, pixelFormats[i], 0, 2, attributeNames, attributeValues)) {
206 LOG_FATAL(logger,
"wglGetPixelFormatAttribivARB failed (GetLastError()=%d).", GetLastError());
209 int sampleBuffers = attributeValues[0];
210 int sampleCount = attributeValues[1];
211 if (sampleBuffers && (bestSampleCount < sampleCount) && (sampleCount <= requestedSampleCount)) {
213 bestSampleCount = sampleCount;
215 LOG_DEBUG(logger,
"%zu: format=0x%x sampleBufs=%d sampleCount=%d", i, pixelFormats[i], attributeValues[0], attributeValues[1]);
218 LOG_DEBUG(logger,
"Requested %d samples, chose pixel format %zu: 0x%x", requestedSampleCount, bestFormat, pixelFormats[bestFormat]);
220 if (!SetPixelFormat(hdc, pixelFormats[bestFormat], &pfd)) {
221 LOG_FATAL(logger,
"Failed to set pixel format (GetLastError()=%d).", GetLastError());
228 bool finalizeContext(Cogs::GLContextBase::Platform platform,
bool debug,
bool sRGB)
231 Cogs::setUpGLDebugging(
nullptr, platform);
235 glEnable(GL_FRAMEBUFFER_SRGB_EXT);
243bool Cogs::GLContext::create(NativeDisplay , WindowData* windowData, GLContext* shareContext,
const GraphicsDeviceSettings* settings, Platform desiredPlatform,
bool debug)
245 assert(hdc ==
nullptr);
246 assert(context ==
nullptr);
247 platform = Platform::GL;
249 DummyContext dummyContext;
250 if (!dummyContext.create()) {
253 if (!getWGLFuncPointers()) {
254 LOG_FATAL(logger,
"Failed to get required WGL function pointers");
259 if (windowData ==
nullptr) {
260 LOG_DEBUG(logger,
"Creating headless dummy window");
261 if (!dummyWindowCreate(headlessHwnd, TEXT(
"HeadlessContextWindow"))) {
262 LOG_FATAL(logger,
"Failed to create context sharing dummy window");
265 hdc = GetDC(headlessHwnd);
268 hdc = GetDC(windowData->windowHandle);
271 const char* wglExtensions = wglGetExtensionsStringARB(hdc);
272 bool sRGB = std::strstr(wglExtensions,
"WGL_EXT_framebuffer_sRGB") !=
nullptr;
273 int numSamples = settings && (std::strstr(wglExtensions,
"WGL_ARB_multisample") !=
nullptr) ? settings->numSamples : 0;
274 if (!chooseAndSetPixelFormat(hdc, numSamples, sRGB)) {
278 std::vector<int> cxAttribs;
280 cxAttribs.push_back(WGL_CONTEXT_FLAGS_ARB); cxAttribs.push_back(WGL_CONTEXT_DEBUG_BIT_ARB);
284 if (desiredPlatform == Platform::ES3) {
285 if (std::strstr(wglExtensions,
"WGL_EXT_create_context_es2_profile") !=
nullptr) {
286 LOG_DEBUG(logger,
"WGL_EXT_create_context_es2_profile present, creating real ES3 context");
287 cxAttribs.push_back(WGL_CONTEXT_PROFILE_MASK_ARB); cxAttribs.push_back(WGL_CONTEXT_ES2_PROFILE_BIT_EXT);
288 cxAttribs.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB); cxAttribs.push_back(3);
289 cxAttribs.push_back(WGL_CONTEXT_MINOR_VERSION_ARB); cxAttribs.push_back(0);
290 platform = Platform::ES3;
293 platform = Platform::GL;
301 cxAttribs.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB); cxAttribs.push_back(3);
302 cxAttribs.push_back(WGL_CONTEXT_MINOR_VERSION_ARB); cxAttribs.push_back(0);
303 platform = Platform::GL;
305 cxAttribs.push_back(0);
307 context = wglCreateContextAttribsARB(hdc, shareContext ? shareContext->context :
nullptr, cxAttribs.data());
309 LOG_ERROR(logger,
"wglCreateContextAttribsARB failed (GetLastError()=%d).", GetLastError());
314 dummyContext.destroy();
316 if (!makeCurrent()) {
317 LOG_ERROR(logger,
"Failed to make context current (GetLastError()=%d).", GetLastError());
322 if (desiredPlatform == Platform::ES3) {
323 if (!getGLES3FuncPointers(platform)) {
327 if (platform == Platform::GL && (std::strstr((
const char*)glGetString(GL_EXTENSIONS),
"ARB_ES3_compatibility") ==
nullptr)) {
328 LOG_FATAL(logger,
"Neither WGL_EXT_create_context_es2_profile nor ARB_ES3_compatibility extensions are present");
336 if (!getGLFuncPointers()) {
342 finalizeContext(platform, debug, sRGB);
346bool Cogs::GLContext::makeCurrent()
348 return wglMakeCurrent(hdc, context);
351void Cogs::GLContext::swapBuffers(uint32_t syncInterval, uint32_t presentFlags)
354 if (context == 0)
return;
356 if ((presentFlags & PresentFlags::NoSwap) == 0) {
357 if (wglSwapIntervalEXT) {
358 wglSwapIntervalEXT(syncInterval != 0 ? 1 : 0);
366void Cogs::GLContext::destroy()
369 wglMakeCurrent(hdc,
nullptr);
370 wglDeleteContext(context);
Log implementation class.
@ sRGB
Value is a color and is subject to gamma correction.
constexpr Log getLogger(const char(&name)[LEN]) noexcept