43GLWinWindow::GLWinWindow()
71void WinOpenGLContext::swapBuffers()
75 SwapBuffers(m_aGLWin.hDC);
80void WinOpenGLContext::resetCurrent()
86 wglMakeCurrent(
nullptr,
nullptr);
92 thread_local bool bEpoxyDispatchMakeCurrentCalled =
false;
93 if (!bEpoxyDispatchMakeCurrentCalled)
95 epoxy_handle_external_wglMakeCurrent();
96 bEpoxyDispatchMakeCurrentCalled =
true;
100bool WinOpenGLContext::isCurrent()
106 return wglGetCurrentContext() == m_aGLWin.hRC && wglGetCurrentDC() == m_aGLWin.hDC;
109bool WinOpenGLContext::isAnyCurrent()
114void WinOpenGLContext::makeCurrent()
125 if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
128 DWORD nLastError = GetLastError();
129 if (nLastError != ERROR_SUCCESS)
130 SAL_WARN(
"vcl.opengl",
"wglMakeCurrent failed: " << WindowsErrorString(nLastError));
139void WinOpenGLContext::initWindow()
141 if( !m_pChildWindow )
147 InitChildWindow(m_pChildWindow.get());
148 const SystemEnvData* sysData(m_pChildWindow->GetSystemData());
154 LONG_PTR style = GetWindowLongPtrW(sysData->hWnd, GWL_STYLE);
156 SetWindowLongPtrW(sysData->hWnd, GWL_STYLE, style);
158 m_aGLWin.hWnd = sysData->hWnd;
160 m_aGLWin.hDC =
GetDC(m_aGLWin.hWnd);
163void WinOpenGLContext::destroyCurrentContext()
171 if (wglGetCurrentContext() !=
nullptr)
173 wglMakeCurrent(
nullptr,
nullptr);
176 wglDeleteContext( m_aGLWin.hRC );
177 ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
178 m_aGLWin.hRC =
nullptr;
194 return DefWindowProcW(hwnd, message, wParam, lParam);
198static bool InitTempWindow(HWND& hwnd,
int width,
int height,
const PIXELFORMATDESCRIPTOR& inPfd, GLWinWindow& glWin)
202 PIXELFORMATDESCRIPTOR pfd = inPfd;
207 wc.cbClsExtra = wc.cbWndExtra = 0;
208 wc.hInstance =
nullptr;
210 wc.hCursor =
nullptr;
211 wc.hbrBackground =
nullptr;
212 wc.lpszMenuName =
nullptr;
213 wc.lpszClassName = L
"GLRenderer";
215 hwnd = CreateWindowW(wc.lpszClassName,
nullptr, WS_DISABLED, 0, 0, width, height,
nullptr,
nullptr, wc.hInstance,
nullptr);
216 glWin.hDC =
GetDC(hwnd);
218 int nPixelFormat = ChoosePixelFormat(glWin.hDC, &pfd);
221 ReleaseDC(hwnd, glWin.hDC);
225 ret = SetPixelFormat(glWin.hDC, nPixelFormat, &pfd);
228 ReleaseDC(hwnd, glWin.hDC);
232 glWin.hRC = wglCreateContext(glWin.hDC);
235 ReleaseDC(hwnd, glWin.hDC);
239 ret = wglMakeCurrent(glWin.hDC, glWin.hRC);
242 wglMakeCurrent(
nullptr,
nullptr);
244 wglDeleteContext(glWin.hRC);
245 ReleaseDC(hwnd, glWin.hDC);
258 const size_t extlen = strlen(extension);
259 const char *supported =
nullptr;
262 PROC wglGetExtString = wglGetProcAddress(
"wglGetExtensionsStringARB");
265 supported =
reinterpret_cast<char*(__stdcall*)(HDC)
>(wglGetExtString)(wglGetCurrentDC());
267 if (supported ==
nullptr)
268 supported =
reinterpret_cast<char const *
>(glGetString(GL_EXTENSIONS));
270 if (supported ==
nullptr)
274 for (
const char*
p = supported; ;
p++)
277 p = strstr(
p, extension);
288 if ((
p==supported ||
p[-1]==
' ') && (
p[extlen]==
'\0' ||
p[extlen]==
' '))
294 bool bUseDoubleBufferedRendering,
bool bRequestVirtualDevice)
303 SAL_WARN(
"vcl.opengl",
"Can't create temp window to test");
310 SAL_WARN(
"vcl.opengl",
"Device doesn't support multisample");
311 wglMakeCurrent(
nullptr,
nullptr);
313 wglDeleteContext(glWin.hRC);
314 ReleaseDC(hWnd, glWin.hDC);
319 PFNWGLCHOOSEPIXELFORMATARBPROC fn_wglChoosePixelFormatARB =
reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC
>(wglGetProcAddress(
"wglChoosePixelFormatARB"));
320 if (!fn_wglChoosePixelFormatARB)
322 wglMakeCurrent(
nullptr,
nullptr);
324 wglDeleteContext(glWin.hRC);
325 ReleaseDC(hWnd, glWin.hDC);
330 HDC hDC =
GetDC(hWnd);
335 float fAttributes[] = {0,0};
343 WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
344 WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
345 WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
346 WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
347 WGL_COLOR_BITS_ARB,24,
348 WGL_ALPHA_BITS_ARB,8,
349 WGL_DEPTH_BITS_ARB,24,
350 WGL_STENCIL_BITS_ARB,0,
351 WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
356 if (!bUseDoubleBufferedRendering)
360 assert(iAttributes[0] == WGL_DOUBLE_BUFFER_ARB);
361 iAttributes[1] = GL_FALSE;
364 if (bRequestVirtualDevice)
366 assert(iAttributes[2] == WGL_DRAW_TO_WINDOW_ARB);
367 iAttributes[2] = WGL_DRAW_TO_BITMAP_ARB;
370 bool bArbMultisampleSupported =
false;
373 valid = fn_wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
375 if (valid && numFormats >= 1)
377 bArbMultisampleSupported =
true;
378 rPixelFormat = pixelFormat;
379 wglMakeCurrent(
nullptr,
nullptr);
381 wglDeleteContext(glWin.hRC);
382 ReleaseDC(hWnd, glWin.hDC);
384 return bArbMultisampleSupported;
387 assert(iAttributes[18] == WGL_SAMPLES_ARB);
389 valid = fn_wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
390 if (valid && numFormats >= 1)
392 bArbMultisampleSupported =
true;
393 rPixelFormat = pixelFormat;
394 wglMakeCurrent(
nullptr,
nullptr);
396 wglDeleteContext(glWin.hRC);
397 ReleaseDC(hWnd, glWin.hDC);
399 return bArbMultisampleSupported;
402 wglMakeCurrent(
nullptr,
nullptr);
404 wglDeleteContext(glWin.hRC);
405 ReleaseDC(hWnd, glWin.hDC);
408 return bArbMultisampleSupported;
414bool tryShaders(
const OUString& rVertexShader,
const OUString& rFragmentShader,
const OUString& rGeometryShader =
"", std::string_view rPreamble =
"")
422 if (rGeometryShader.isEmpty())
424 nId =
OpenGLHelper::LoadShaders(rVertexShader, rFragmentShader, rPreamble, OpenGLHelper::GetDigest( rVertexShader, rFragmentShader, rPreamble));
428 assert(rPreamble.empty());
437 glDeleteProgram(nId);
438 return glGetError() == GL_NO_ERROR;
441bool compiledShaderBinariesWork()
443 static bool bBeenHere =
false;
455 tryShaders(
"dummyVertexShader",
"linearMultiColorGradientFragmentShader") &&
456 tryShaders(
"dummyVertexShader",
"linearTwoColorGradientFragmentShader") &&
457 tryShaders(
"dummyVertexShader",
"radialMultiColorGradientFragmentShader") &&
458 tryShaders(
"dummyVertexShader",
"radialTwoColorGradientFragmentShader") &&
459 tryShaders(
"dummyVertexShader",
"rectangularMultiColorGradientFragmentShader") &&
460 tryShaders(
"dummyVertexShader",
"rectangularTwoColorGradientFragmentShader") &&
463 tryShaders(
"reflectionVertexShader",
"reflectionFragmentShader") &&
464 tryShaders(
"basicVertexShader",
"basicFragmentShader") &&
465 tryShaders(
"vortexVertexShader",
"vortexFragmentShader",
"vortexGeometryShader") &&
466 tryShaders(
"basicVertexShader",
"rippleFragmentShader") &&
467 tryShaders(
"glitterVertexShader",
"glitterFragmentShader") &&
468 tryShaders(
"honeycombVertexShader",
"honeycombFragmentShader",
"honeycombGeometryShader"));
475bool WinOpenGLContext::ImplInit()
477 static bool bFirstCall =
true;
483 PIXELFORMATDESCRIPTOR PixelFormatFront =
485 sizeof(PIXELFORMATDESCRIPTOR),
503 PixelFormatFront.dwFlags |= PFD_DOUBLEBUFFER;
504 PixelFormatFront.dwFlags |= PFD_DRAW_TO_WINDOW;
508 bool bMultiSampleSupport =
false;
510 bMultiSampleSupport =
InitMultisample(PixelFormatFront, WindowPix,
true,
false);
512 if (bMultiSampleSupport && WindowPix != 0)
514 m_aGLWin.bMultiSampleSupported =
true;
518 WindowPix = ChoosePixelFormat(m_aGLWin.hDC, &PixelFormatFront);
519#if OSL_DEBUG_LEVEL > 0
520 PIXELFORMATDESCRIPTOR pfd;
521 DescribePixelFormat(m_aGLWin.hDC, WindowPix,
sizeof(PIXELFORMATDESCRIPTOR), &pfd);
522 SAL_WARN(
"vcl.opengl",
"Render Target: Window: " <<
static_cast<int>((pfd.dwFlags & PFD_DRAW_TO_WINDOW) != 0) <<
", Bitmap: " <<
static_cast<int>((pfd.dwFlags & PFD_DRAW_TO_BITMAP) != 0));
523 SAL_WARN(
"vcl.opengl",
"Supports OpenGL: " <<
static_cast<int>((pfd.dwFlags & PFD_SUPPORT_OPENGL) != 0));
529 SAL_WARN(
"vcl.opengl",
"Invalid pixelformat");
533 if (!SetPixelFormat(m_aGLWin.hDC, WindowPix, &PixelFormatFront))
535 SAL_WARN(
"vcl.opengl",
"SetPixelFormat failed: " << WindowsErrorString(GetLastError()));
539 HGLRC hTempRC = wglCreateContext(m_aGLWin.hDC);
540 if (hTempRC ==
nullptr)
542 SAL_WARN(
"vcl.opengl",
"wglCreateContext failed: "<< WindowsErrorString(GetLastError()));
546 if (!wglMakeCurrent(m_aGLWin.hDC, hTempRC))
549 SAL_WARN(
"vcl.opengl",
"wglMakeCurrent failed: "<< WindowsErrorString(GetLastError()));
557 wglMakeCurrent(
nullptr,
nullptr);
559 wglDeleteContext(hTempRC);
563 HGLRC hSharedCtx =
nullptr;
567 if (!wglCreateContextAttribsARB)
569 wglMakeCurrent(
nullptr,
nullptr);
571 wglDeleteContext(hTempRC);
577 int const attribs [] =
580 WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
584 m_aGLWin.hRC = wglCreateContextAttribsARB(m_aGLWin.hDC, hSharedCtx, attribs);
585 if (m_aGLWin.hRC ==
nullptr)
587 SAL_WARN(
"vcl.opengl",
"wglCreateContextAttribsARB failed: "<< WindowsErrorString(GetLastError()));
588 wglMakeCurrent(
nullptr,
nullptr);
590 wglDeleteContext(hTempRC);
594 if (!compiledShaderBinariesWork())
596 wglMakeCurrent(
nullptr,
nullptr);
598 wglDeleteContext(hTempRC);
602 wglMakeCurrent(
nullptr,
nullptr);
604 wglDeleteContext(hTempRC);
606 if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
609 SAL_WARN(
"vcl.opengl",
"wglMakeCurrent failed: " << WindowsErrorString(GetLastError()));
618 GLint nMaxTextureSize;
619 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &nMaxTextureSize);
620 if (nMaxTextureSize <= 4096)
621 SAL_WARN(
"vcl.opengl",
"Max texture size is " << nMaxTextureSize
622 <<
". This may not be enough for normal operation.");
624 VCL_GL_INFO(
"Max texture size: " << nMaxTextureSize);
627 for (GLint nWidthHeight = 1023; nWidthHeight < nMaxTextureSize; nWidthHeight += (nWidthHeight + 1))
629 glTexImage2D(GL_PROXY_TEXTURE_2D, 0, 4, nWidthHeight, nWidthHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8,
nullptr);
631 if (glGetError() == GL_NO_ERROR)
635 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &nWidth);
636 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &nHeight);
637 VCL_GL_INFO(
"Created texture " << nWidthHeight <<
"," << nWidthHeight <<
" reports size: " << nWidth <<
", " << nHeight);
641 SAL_WARN(
"vcl.opengl",
"Error when creating a " << nWidthHeight <<
", " << nWidthHeight <<
" test texture.");
651 GetClientRect(WindowFromDC(m_aGLWin.hDC), &clientRect);
652 m_aGLWin.Width = clientRect.right - clientRect.left;
653 m_aGLWin.Height = clientRect.bottom - clientRect.top;
655 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
666 return new WinOpenGLContext;
#define VCL_GL_INFO(stream)
Helper to do a SAL_INFO as well as a GL log.
virtual const GLWindow & getOpenGLWindow() const =0
virtual void makeCurrent()
make this GL context current - so it is implicit in subsequent GL calls
virtual void destroyCurrentContext()
virtual void initWindow()
virtual bool isAnyCurrent()
Is any GL context the current context ?
virtual void swapBuffers()
virtual void resetCurrent()
reset the GL context so this context is not implicit in subsequent GL calls.
virtual GLWindow & getModifiableOpenGLWindow()=0
virtual bool isCurrent()
Is this GL context the current context ?
We want to be able to detect if a given crash came from the OpenGL code, so use this helper to track ...
static VclPtr< reference_type > Create(Arg &&... arg)
A construction helper for VclPtr.
virtual OpenGLContext * CreateOpenGLContext() override
#define SAL_WARN(area, stream)
Holds the information of our new child window.
static GLint LoadShaders(const OUString &rVertexShaderName, const OUString &rFragmentShaderName, const OUString &rGeometryShaderName, std::string_view preamble, std::string_view rDigest)
static std::vector< HGLRC > g_vShareList
static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
static bool InitMultisample(const PIXELFORMATDESCRIPTOR &pfd, int &rPixelFormat, bool bUseDoubleBufferedRendering, bool bRequestVirtualDevice)
static void ensureDispatchTable()
static bool WGLisExtensionSupported(const char *extension)
static bool g_bAnyCurrent
static bool InitTempWindow(HWND &hwnd, int width, int height, const PIXELFORMATDESCRIPTOR &inPfd, GLWinWindow &glWin)