28 #if defined(USE_WGL) || defined(USE_SDL_MAINLOOP)
29 static const int REQUESTED_GL_CTX_MAJOR = 3;
30 static const int REQUESTED_GL_CTX_MINOR = 2;
39 glDisable(GL_DEPTH_TEST);
41 glDisable(GL_CULL_FACE);
44 std::vector<GLuint> toBeDeleted;
51 toBeDeleted.push_back(
hVAOs[i]);
56 glDeleteVertexArrays(toBeDeleted.size(), &toBeDeleted[0]);
63 #include <epoxy/wgl.h>
65 static PIXELFORMATDESCRIPTOR pfd;
66 static HGLRC hrc =
nullptr;
73 static std::vector<int> EnumeratePixelFormats(HDC hdc)
75 std::vector<int> result;
76 if(!epoxy_has_wgl_extension(hdc,
"WGL_ARB_pixel_format"))
return result;
79 int attributes = WGL_NUMBER_PIXEL_FORMATS_ARB;
80 if(!wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attributes, &n_formats))
return result;
82 for(
int i = 1; i < n_formats+1; ++i)
84 int new_attributes[] = { WGL_DRAW_TO_WINDOW_ARB, WGL_SUPPORT_OPENGL_ARB, WGL_DOUBLE_BUFFER_ARB, WGL_COLOR_BITS_ARB, WGL_DEPTH_BITS_ARB, WGL_STENCIL_BITS_ARB, WGL_AUX_BUFFERS_ARB, WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB, WGL_PIXEL_TYPE_ARB };
85 const unsigned int nnew_attributes =
sizeof(new_attributes)/
sizeof(
int);
87 int new_results[nnew_attributes];
88 if(!wglGetPixelFormatAttribivARB(hdc, i, 0, nnew_attributes, new_attributes, new_results))
continue;
89 if(!new_results[0] || !new_results[1] || !new_results[2])
continue;
90 if(new_results[3] < 16 || new_results[4] < 16)
continue;
95 if(new_results[4] > 24)
continue;
98 if (new_results[9] != WGL_TYPE_RGBA_ARB)
103 if(new_results[7] == 1 && new_results[8] == 1)
112 int old_attributes[] = { WGL_COLOR_BITS_ARB };
113 const unsigned int nold_attributes =
sizeof(old_attributes)/
sizeof(
int);
114 int old_results[nold_attributes];
116 if(!wglGetPixelFormatAttribivARB(hdc, result[0], 0, nold_attributes, old_attributes, old_results))
continue;
118 if(new_results[3] > old_results[0])
123 else if(new_results[3] == old_results[0])
126 for(j = 0; j < result.size(); ++j)
128 int equiv_attributes[] = { WGL_DEPTH_BITS_ARB, WGL_STENCIL_BITS_ARB, WGL_AUX_BUFFERS_ARB, WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB };
129 const unsigned int nequiv_attributes =
sizeof(equiv_attributes)/
sizeof(
int);
130 int equiv_results[nequiv_attributes];
131 if(!wglGetPixelFormatAttribivARB(hdc, result[j], 0, nequiv_attributes, equiv_attributes, equiv_results))
continue;
133 if(new_results[7] == equiv_results[3] && new_results[8] == equiv_results[4])
135 if(new_results[4] > equiv_results[0] || (new_results[4] == equiv_results[0] && (new_results[5] < equiv_results[1] || (new_results[5] == equiv_results[1] && new_results[6] < equiv_results[2]))))
141 if(j == result.size()) result.push_back(i);
149 static int GetPixelFormatForMS(HDC hDC,
int samples)
151 std::vector<int> vec = EnumeratePixelFormats(hDC);
154 int attributes[] = { WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB };
155 const unsigned int n_attributes = 2;
157 if(!wglGetPixelFormatAttribivARB(hDC, i, 0, n_attributes, attributes, results))
continue;
159 if( (samples == 0 && results[0] == 0) ||
160 (samples > 0 && results[0] == 1 && results[1] == samples))
169 class WinAPIError :
public std::runtime_error
172 typedef DWORD error_code;
174 WinAPIError() : WinAPIError(GetLastError()) {}
175 WinAPIError(error_code err) :
std::runtime_error(format_error(err)) {}
178 static std::string format_error(error_code err)
180 LPWSTR buffer =
nullptr;
181 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
182 nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPWSTR
>(&buffer), 0,
nullptr);
185 return std::string(str.getData(), str.getLength());
197 wnd = CreateWindowExW(0, L
"STATIC",
nullptr, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0,
nullptr,
nullptr, GetModuleHandle(
nullptr),
nullptr);
201 auto pfd = PIXELFORMATDESCRIPTOR();
202 pfd.nSize =
sizeof(pfd);
204 pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
205 pfd.iPixelType = PFD_TYPE_RGBA;
206 pfd.iLayerType = PFD_MAIN_PLANE;
207 int format = ChoosePixelFormat(dc, &pfd);
209 !SetPixelFormat(dc, format, &pfd) ||
210 (glrc = wglCreateContext(dc)) ==
nullptr)
212 DWORD err = GetLastError();
215 throw WinAPIError(err);
217 if (!wglMakeCurrent(dc, glrc))
219 DWORD err = GetLastError();
220 wglDeleteContext(glrc);
223 throw WinAPIError(err);
228 if (glrc == wglGetCurrentContext())
229 wglMakeCurrent(dc,
nullptr);
230 wglDeleteContext(glrc);
242 ReleaseDC(
pWindow->renderwnd, hDC);
251 if (multisample_change)
255 wglDeleteContext(hrc);
265 std::unique_ptr<GLTempContext> tempContext;
271 tempContext = std::make_unique<GLTempContext>();
273 catch (
const WinAPIError &e)
275 pGL->
Error((std::string(
" gl: Unable to create temporary context: ") + e.what()).c_str());
284 hDC = GetDC(
pWindow->renderwnd);
287 pGL->
Error(
" gl: Error getting DC");
299 if((pixel_format = GetPixelFormatForMS(hDC, 0)) != 0)
304 pGL->
Error(
" gl: Error choosing pixel format");
308 ZeroMemory(&pfd,
sizeof(pfd)); pfd.nSize =
sizeof(pfd);
309 if(!DescribePixelFormat(hDC, pixel_format,
sizeof(pfd), &pfd))
311 pGL->
Error(
" gl: Error describing chosen pixel format");
313 else if(!SetPixelFormat(hDC, pixel_format, &pfd))
315 pGL->
Error(
" gl: Error setting chosen pixel format");
320 if (epoxy_has_wgl_extension(hDC,
"WGL_ARB_create_context"))
323 const int attribs[] = {
325 WGL_CONTEXT_MAJOR_VERSION_ARB, REQUESTED_GL_CTX_MAJOR,
326 WGL_CONTEXT_MINOR_VERSION_ARB, REQUESTED_GL_CTX_MINOR,
327 WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
331 hrc = wglCreateContextAttribsARB(hDC,
nullptr, attribs);
336 LogSilentF(
" gl: OpenGL %d.%d not available; falling back to 3.1 emergency context.", REQUESTED_GL_CTX_MAJOR, REQUESTED_GL_CTX_MINOR);
339 const int attribs[] = {
341 WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
342 WGL_CONTEXT_MINOR_VERSION_ARB, 1,
346 hrc = wglCreateContextAttribsARB(hDC,
nullptr, attribs);
351 DebugLog(
" gl: wglCreateContextAttribsARB not available; creating default context.");
352 hrc = wglCreateContext(hDC);
357 pGL->
Error(
" gl: Error creating gl context");
372 ReleaseDC(
pWindow->renderwnd, hDC); hDC =
nullptr;
376 std::vector<int> CStdGLCtx::EnumerateMultiSamples()
const
379 std::vector<int> result;
380 std::vector<int> vec = EnumeratePixelFormats(hDC);
383 int attributes[] = { WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB };
384 const unsigned int n_attributes = 2;
386 if(!wglGetPixelFormatAttribivARB(hDC, i, 0, n_attributes, attributes, results))
continue;
388 if(results[0] == 1) result.push_back(results[1]);
397 if (!
pGL || !hrc)
return false;
399 if (!wglMakeCurrent (hDC, hrc))
401 pGL->
Error(
"Unable to select context.");
416 wglMakeCurrent(
nullptr,
nullptr);
430 #elif defined(USE_SDL_MAINLOOP)
437 if (ctx) SDL_GL_DeleteContext(ctx);
451 if (!
pGL)
return false;
454 ctx = SDL_GL_CreateContext(
pWindow->window);
457 LogSilentF(
" gl: OpenGL %d.%d not available; falling back to 3.1 emergency context.", REQUESTED_GL_CTX_MAJOR, REQUESTED_GL_CTX_MINOR);
458 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
459 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
461 ctx = SDL_GL_CreateContext(
pWindow->window);
468 if (!
Select(
true))
return false;
476 if (SDL_GL_MakeCurrent(
pWindow->window, ctx) != 0)
483 if (verbose)
pGL->
Error(
" gl: UpdateClipper failed");
504 SDL_GL_SwapWindow(
pWindow->window);
510 #ifdef WITH_QT_EDITOR
511 #include <QOpenGLWidget>
512 #include <QOpenGLContext>
513 #include <QOffscreenSurface>
515 CStdGLCtxQt::CStdGLCtxQt() { context =
nullptr; surface =
nullptr; }
517 void CStdGLCtxQt::Clear(
bool multisample_change)
523 if (!pWindow->glwidget)
delete context;
531 if (!
pGL)
return false;
534 if (!pWindow->glwidget)
536 surface =
new QOffscreenSurface();
538 context =
new QOpenGLContext();
539 QOpenGLContext* share_context = QOpenGLContext::globalShareContext();
540 if (share_context) context->setShareContext(share_context);
541 if (!context->create())
544 if (!Select(
true))
return false;
549 context = pWindow->glwidget->context();
552 this_context = contexts.insert(contexts.end(),
this);
556 bool CStdGLCtxQt::Select(
bool verbose)
558 if (!pWindow->glwidget)
560 if (!context->makeCurrent(surface))
573 if (verbose)
pGL->
Error(
" gl: UpdateClipper failed");
580 void CStdGLCtxQt::Deselect()
582 if (!pWindow->glwidget)
583 context->doneCurrent();
596 bool CStdGLCtxQt::PageFlip()
600 if (!pWindow)
return false;
601 if (!pWindow->glwidget)
bool DebugLog(const char *strMessage)
bool LogSilentF(const char *strMessage,...)
StdStrBuf FormatString(const char *szFmt,...)
C4ConfigGraphics Graphics
std::vector< unsigned int > VAOsToBeDeleted
virtual bool Init(C4Window *pWindow, C4AbstractApp *pApp)
virtual bool Select(bool verbose=false)
virtual void Clear(bool multisample_change=false)
std::vector< GLuint > hVAOs
static std::list< CStdGLCtx * > contexts
std::list< CStdGLCtx * >::iterator this_context
bool Error(const char *szMsg) override
bool UpdateClipper() override
struct CStdGL::@10 Workarounds