LibreOffice Module vcl (master) 1
win/context.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10#include <memory>
11#include <string_view>
12#include <thread>
15#include <vcl/syschild.hxx>
16
17#include <sal/log.hxx>
19#include <opengl/zone.hxx>
20#include <win/wincomp.hxx>
21#include <win/saldata.hxx>
22#include <win/salframe.h>
23#include <win/salinst.h>
24#include <epoxy/wgl.h>
25#include <ControlCacheKey.hxx>
26
27static std::vector<HGLRC> g_vShareList;
28static bool g_bAnyCurrent;
29
30namespace {
31
32class GLWinWindow : public GLWindow
33{
34public:
35 HWND hWnd;
36 HDC hDC;
37 HGLRC hRC;
38 GLWinWindow();
39};
40
41}
42
43GLWinWindow::GLWinWindow()
44 : hWnd(nullptr)
45 , hDC(nullptr)
46 , hRC(nullptr)
47{
48}
49
50namespace {
51
52class WinOpenGLContext : public OpenGLContext
53{
54public:
55 virtual void initWindow() override;
56private:
57 GLWinWindow m_aGLWin;
58 virtual const GLWindow& getOpenGLWindow() const override { return m_aGLWin; }
59 virtual GLWindow& getModifiableOpenGLWindow() override { return m_aGLWin; }
60 virtual bool ImplInit() override;
61 virtual void makeCurrent() override;
62 virtual void destroyCurrentContext() override;
63 virtual bool isCurrent() override;
64 virtual bool isAnyCurrent() override;
65 virtual void resetCurrent() override;
66 virtual void swapBuffers() override;
67};
68
69}
70
71void WinOpenGLContext::swapBuffers()
72{
73 OpenGLZone aZone;
74
75 SwapBuffers(m_aGLWin.hDC);
76
77 BuffersSwapped();
78}
79
80void WinOpenGLContext::resetCurrent()
81{
82 clearCurrent();
83
84 OpenGLZone aZone;
85
86 wglMakeCurrent(nullptr, nullptr);
87 g_bAnyCurrent = false;
88}
89
91{
92 thread_local bool bEpoxyDispatchMakeCurrentCalled = false;
93 if (!bEpoxyDispatchMakeCurrentCalled)
94 {
95 epoxy_handle_external_wglMakeCurrent();
96 bEpoxyDispatchMakeCurrentCalled = true;
97 }
98}
99
100bool WinOpenGLContext::isCurrent()
101{
102 OpenGLZone aZone;
103 if (!g_bAnyCurrent || !m_aGLWin.hRC)
104 return false;
106 return wglGetCurrentContext() == m_aGLWin.hRC && wglGetCurrentDC() == m_aGLWin.hDC;
107}
108
109bool WinOpenGLContext::isAnyCurrent()
110{
111 return g_bAnyCurrent && wglGetCurrentContext() != nullptr;
112}
113
114void WinOpenGLContext::makeCurrent()
115{
116 if (isCurrent())
117 return;
118
119 OpenGLZone aZone;
120
121 clearCurrent();
122
124
125 if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
126 {
127 g_bAnyCurrent = false;
128 DWORD nLastError = GetLastError();
129 if (nLastError != ERROR_SUCCESS)
130 SAL_WARN("vcl.opengl", "wglMakeCurrent failed: " << WindowsErrorString(nLastError));
131 return;
132 }
133
134 g_bAnyCurrent = true;
135
136 registerAsCurrent();
137}
138
139void WinOpenGLContext::initWindow()
140{
141 if( !m_pChildWindow )
142 {
143 SystemWindowData winData = generateWinData(mpWindow, false);
144 m_pChildWindow = VclPtr<SystemChildWindow>::Create(mpWindow, 0, &winData, false);
145 }
146
147 InitChildWindow(m_pChildWindow.get());
148 const SystemEnvData* sysData(m_pChildWindow->GetSystemData());
149
150 // Hack: the performance of OpenGL increases with non-child window.
151 // Also, this keeps the backing window opaque on GL context destruction,
152 // which doesn't prevent the flicker (tdf#122737) completely, but at
153 // least doesn't show user desktop during the flicker.
154 LONG_PTR style = GetWindowLongPtrW(sysData->hWnd, GWL_STYLE);
155 style &= ~WS_CHILD;
156 SetWindowLongPtrW(sysData->hWnd, GWL_STYLE, style);
157
158 m_aGLWin.hWnd = sysData->hWnd;
159
160 m_aGLWin.hDC = GetDC(m_aGLWin.hWnd);
161}
162
163void WinOpenGLContext::destroyCurrentContext()
164{
165 if (m_aGLWin.hRC)
166 {
167 std::vector<HGLRC>::iterator itr = std::remove(g_vShareList.begin(), g_vShareList.end(), m_aGLWin.hRC);
168 if (itr != g_vShareList.end())
169 g_vShareList.erase(itr);
170
171 if (wglGetCurrentContext() != nullptr)
172 {
173 wglMakeCurrent(nullptr, nullptr);
174 g_bAnyCurrent = false;
175 }
176 wglDeleteContext( m_aGLWin.hRC );
177 ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
178 m_aGLWin.hRC = nullptr;
179 }
180}
181
182static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
183{
184 switch (message)
185 {
186 case WM_CREATE:
187 return 0;
188 case WM_CLOSE:
189 PostQuitMessage(0);
190 return 0;
191 case WM_DESTROY:
192 return 0;
193 default:
194 return DefWindowProcW(hwnd, message, wParam, lParam);
195 }
196}
197
198static bool InitTempWindow(HWND& hwnd, int width, int height, const PIXELFORMATDESCRIPTOR& inPfd, GLWinWindow& glWin)
199{
200 OpenGLZone aZone;
201
202 PIXELFORMATDESCRIPTOR pfd = inPfd;
203 int ret;
204 WNDCLASSW wc;
205 wc.style = 0;
206 wc.lpfnWndProc = WndProc;
207 wc.cbClsExtra = wc.cbWndExtra = 0;
208 wc.hInstance = nullptr;
209 wc.hIcon = nullptr;
210 wc.hCursor = nullptr;
211 wc.hbrBackground = nullptr;
212 wc.lpszMenuName = nullptr;
213 wc.lpszClassName = L"GLRenderer";
214 RegisterClassW(&wc);
215 hwnd = CreateWindowW(wc.lpszClassName, nullptr, WS_DISABLED, 0, 0, width, height, nullptr, nullptr, wc.hInstance, nullptr);
216 glWin.hDC = GetDC(hwnd);
217
218 int nPixelFormat = ChoosePixelFormat(glWin.hDC, &pfd);
219 if (!nPixelFormat)
220 {
221 ReleaseDC(hwnd, glWin.hDC);
222 DestroyWindow(hwnd);
223 return false;
224 }
225 ret = SetPixelFormat(glWin.hDC, nPixelFormat, &pfd);
226 if(!ret)
227 {
228 ReleaseDC(hwnd, glWin.hDC);
229 DestroyWindow(hwnd);
230 return false;
231 }
232 glWin.hRC = wglCreateContext(glWin.hDC);
233 if(!(glWin.hRC))
234 {
235 ReleaseDC(hwnd, glWin.hDC);
236 DestroyWindow(hwnd);
237 return false;
238 }
239 ret = wglMakeCurrent(glWin.hDC, glWin.hRC);
240 if(!ret)
241 {
242 wglMakeCurrent(nullptr, nullptr);
243 g_bAnyCurrent = false;
244 wglDeleteContext(glWin.hRC);
245 ReleaseDC(hwnd, glWin.hDC);
246 DestroyWindow(hwnd);
247 return false;
248 }
249 g_bAnyCurrent = false;
250
251 return true;
252}
253
254static bool WGLisExtensionSupported(const char *extension)
255{
256 OpenGLZone aZone;
257
258 const size_t extlen = strlen(extension);
259 const char *supported = nullptr;
260
261 // Try to use wglGetExtensionStringARB on current DC, if possible
262 PROC wglGetExtString = wglGetProcAddress("wglGetExtensionsStringARB");
263
264 if (wglGetExtString)
265 supported = reinterpret_cast<char*(__stdcall*)(HDC)>(wglGetExtString)(wglGetCurrentDC());
266 // If that failed, try standard OpenGL extensions string
267 if (supported == nullptr)
268 supported = reinterpret_cast<char const *>(glGetString(GL_EXTENSIONS));
269 // If that failed too, must be no extensions supported
270 if (supported == nullptr)
271 return false;
272
273 // Begin examination at start of string, increment by 1 on false match
274 for (const char* p = supported; ; p++)
275 {
276 // Advance p up to the next possible match
277 p = strstr(p, extension);
278
279 if (p == nullptr)
280 return false; // No Match
281
282 // Make sure that match is at the start of the string or that
283 // the previous char is a space, or else we could accidentally
284 // match "wglFunkywglExtension" with "wglExtension"
285
286 // Also, make sure that the following character is space or null
287 // or else "wglExtensionTwo" might match "wglExtension"
288 if ((p==supported || p[-1]==' ') && (p[extlen]=='\0' || p[extlen]==' '))
289 return true; // Match
290 }
291}
292
293static bool InitMultisample(const PIXELFORMATDESCRIPTOR& pfd, int& rPixelFormat,
294 bool bUseDoubleBufferedRendering, bool bRequestVirtualDevice)
295{
296 OpenGLZone aZone;
297
298 HWND hWnd = nullptr;
299 GLWinWindow glWin;
300 // Create a temp window to check whether support multi-sample, if support, get the format
301 if (!InitTempWindow(hWnd, 32, 32, pfd, glWin))
302 {
303 SAL_WARN("vcl.opengl", "Can't create temp window to test");
304 return false;
305 }
306
307 // See if the string exists in WGL
308 if (!WGLisExtensionSupported("WGL_ARB_multisample"))
309 {
310 SAL_WARN("vcl.opengl", "Device doesn't support multisample");
311 wglMakeCurrent(nullptr, nullptr);
312 g_bAnyCurrent = false;
313 wglDeleteContext(glWin.hRC);
314 ReleaseDC(hWnd, glWin.hDC);
315 DestroyWindow(hWnd);
316 return false;
317 }
318 // Get our pixel format
319 PFNWGLCHOOSEPIXELFORMATARBPROC fn_wglChoosePixelFormatARB = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(wglGetProcAddress("wglChoosePixelFormatARB"));
320 if (!fn_wglChoosePixelFormatARB)
321 {
322 wglMakeCurrent(nullptr, nullptr);
323 g_bAnyCurrent = false;
324 wglDeleteContext(glWin.hRC);
325 ReleaseDC(hWnd, glWin.hDC);
326 DestroyWindow(hWnd);
327 return false;
328 }
329 // Get our current device context
330 HDC hDC = GetDC(hWnd);
331
332 int pixelFormat;
333 int valid;
334 UINT numFormats;
335 float fAttributes[] = {0,0};
336 // These attributes are the bits we want to test for in our sample.
337 // Everything is pretty standard, the only one we want to
338 // really focus on is the WGL_SAMPLE_BUFFERS_ARB and WGL_SAMPLES_ARB.
339 // These two are going to do the main testing for whether or not
340 // we support multisampling on this hardware.
341 int iAttributes[] =
342 {
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,
352 WGL_SAMPLES_ARB,8,
353 0,0
354 };
355
356 if (!bUseDoubleBufferedRendering)
357 {
358 // Use asserts to make sure the iAttributes array is not changed without changing these ugly
359 // hardcode indexes into it.
360 assert(iAttributes[0] == WGL_DOUBLE_BUFFER_ARB);
361 iAttributes[1] = GL_FALSE;
362 }
363
364 if (bRequestVirtualDevice)
365 {
366 assert(iAttributes[2] == WGL_DRAW_TO_WINDOW_ARB);
367 iAttributes[2] = WGL_DRAW_TO_BITMAP_ARB;
368 }
369
370 bool bArbMultisampleSupported = false;
371
372 // First we check to see if we can get a pixel format for 8 samples
373 valid = fn_wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
374 // If we returned true, and our format count is greater than 1
375 if (valid && numFormats >= 1)
376 {
377 bArbMultisampleSupported = true;
378 rPixelFormat = pixelFormat;
379 wglMakeCurrent(nullptr, nullptr);
380 g_bAnyCurrent = false;
381 wglDeleteContext(glWin.hRC);
382 ReleaseDC(hWnd, glWin.hDC);
383 DestroyWindow(hWnd);
384 return bArbMultisampleSupported;
385 }
386 // Our pixel format with 8 samples failed, test for 2 samples
387 assert(iAttributes[18] == WGL_SAMPLES_ARB);
388 iAttributes[19] = 2;
389 valid = fn_wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
390 if (valid && numFormats >= 1)
391 {
392 bArbMultisampleSupported = true;
393 rPixelFormat = pixelFormat;
394 wglMakeCurrent(nullptr, nullptr);
395 g_bAnyCurrent = false;
396 wglDeleteContext(glWin.hRC);
397 ReleaseDC(hWnd, glWin.hDC);
398 DestroyWindow(hWnd);
399 return bArbMultisampleSupported;
400 }
401 // Return the valid format
402 wglMakeCurrent(nullptr, nullptr);
403 g_bAnyCurrent = false;
404 wglDeleteContext(glWin.hRC);
405 ReleaseDC(hWnd, glWin.hDC);
406 DestroyWindow(hWnd);
407
408 return bArbMultisampleSupported;
409}
410
411namespace
412{
413
414bool tryShaders(const OUString& rVertexShader, const OUString& rFragmentShader, const OUString& rGeometryShader = "", std::string_view rPreamble = "")
415{
416 GLint nId;
417
418 // Somewhat mysteriously, the OpenGLHelper::LoadShaders() API saves a compiled binary of the
419 // shader only if you give it the digest of the shaders. We have API to calculate the digest
420 // only of the combination of vertex and fragment (but not geometry) shader. So if we have a
421 // geometry shader, we should not save the binary.
422 if (rGeometryShader.isEmpty())
423 {
424 nId = OpenGLHelper::LoadShaders(rVertexShader, rFragmentShader, rPreamble, OpenGLHelper::GetDigest( rVertexShader, rFragmentShader, rPreamble));
425 }
426 else
427 {
428 assert(rPreamble.empty());
429 nId = OpenGLHelper::LoadShaders(rVertexShader, rFragmentShader, rGeometryShader);
430 }
431 if (!nId)
432 return false;
433
434 // We're interested in the error returned by glDeleteProgram().
435 glGetError();
436
437 glDeleteProgram(nId);
438 return glGetError() == GL_NO_ERROR;
439}
440
441bool compiledShaderBinariesWork()
442{
443 static bool bBeenHere = false;
444 static bool bResult;
445
446 if (bBeenHere)
447 return bResult;
448
449 bBeenHere = true;
450
451 bResult =
452 (
453#if 0 // Only look at shaders used by slideshow for now
454 // canvas
455 tryShaders("dummyVertexShader", "linearMultiColorGradientFragmentShader") &&
456 tryShaders("dummyVertexShader", "linearTwoColorGradientFragmentShader") &&
457 tryShaders("dummyVertexShader", "radialMultiColorGradientFragmentShader") &&
458 tryShaders("dummyVertexShader", "radialTwoColorGradientFragmentShader") &&
459 tryShaders("dummyVertexShader", "rectangularMultiColorGradientFragmentShader") &&
460 tryShaders("dummyVertexShader", "rectangularTwoColorGradientFragmentShader") &&
461#endif
462 // slideshow
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"));
469
470 return bResult;
471}
472
473} // unnamed namespace
474
475bool WinOpenGLContext::ImplInit()
476{
477 static bool bFirstCall = true;
478
479 OpenGLZone aZone;
480
481 VCL_GL_INFO("OpenGLContext::ImplInit----start");
482 // PixelFormat tells Windows how we want things to be
483 PIXELFORMATDESCRIPTOR PixelFormatFront =
484 {
485 sizeof(PIXELFORMATDESCRIPTOR),
486 1, // Version Number
487 PFD_SUPPORT_OPENGL,
488 PFD_TYPE_RGBA, // Request An RGBA Format
489 BYTE(32), // Select Our Color Depth
490 0, 0, 0, 0, 0, 0, // Color Bits Ignored
491 0, // No Alpha Buffer
492 0, // Shift Bit Ignored
493 0, // No Accumulation Buffer
494 0, 0, 0, 0, // Accumulation Bits Ignored
495 24, // 24 bit z-buffer
496 8, // stencil buffer
497 0, // No Auxiliary Buffer
498 0, // now ignored
499 0, // Reserved
500 0, 0, 0 // Layer Masks Ignored
501 };
502
503 PixelFormatFront.dwFlags |= PFD_DOUBLEBUFFER;
504 PixelFormatFront.dwFlags |= PFD_DRAW_TO_WINDOW;
505
506 // we must check whether can set the MSAA
507 int WindowPix = 0;
508 bool bMultiSampleSupport = false;
509
510 bMultiSampleSupport = InitMultisample(PixelFormatFront, WindowPix, /*bUseDoubleBufferedRendering*/true, false);
511
512 if (bMultiSampleSupport && WindowPix != 0)
513 {
514 m_aGLWin.bMultiSampleSupported = true;
515 }
516 else
517 {
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));
524#endif
525 }
526
527 if (WindowPix == 0)
528 {
529 SAL_WARN("vcl.opengl", "Invalid pixelformat");
530 return false;
531 }
532
533 if (!SetPixelFormat(m_aGLWin.hDC, WindowPix, &PixelFormatFront))
534 {
535 SAL_WARN("vcl.opengl", "SetPixelFormat failed: " << WindowsErrorString(GetLastError()));
536 return false;
537 }
538
539 HGLRC hTempRC = wglCreateContext(m_aGLWin.hDC);
540 if (hTempRC == nullptr)
541 {
542 SAL_WARN("vcl.opengl", "wglCreateContext failed: "<< WindowsErrorString(GetLastError()));
543 return false;
544 }
545
546 if (!wglMakeCurrent(m_aGLWin.hDC, hTempRC))
547 {
548 g_bAnyCurrent = false;
549 SAL_WARN("vcl.opengl", "wglMakeCurrent failed: "<< WindowsErrorString(GetLastError()));
550 return false;
551 }
552
553 g_bAnyCurrent = true;
554
555 if (!InitGL())
556 {
557 wglMakeCurrent(nullptr, nullptr);
558 g_bAnyCurrent = false;
559 wglDeleteContext(hTempRC);
560 return false;
561 }
562
563 HGLRC hSharedCtx = nullptr;
564 if (!g_vShareList.empty())
565 hSharedCtx = g_vShareList.front();
566
567 if (!wglCreateContextAttribsARB)
568 {
569 wglMakeCurrent(nullptr, nullptr);
570 g_bAnyCurrent = false;
571 wglDeleteContext(hTempRC);
572 return false;
573 }
574
575 // now setup the shared context; this needs a temporary context already
576 // set up in order to work
577 int const attribs [] =
578 {
579#ifdef DBG_UTIL
580 WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
581#endif
582 0
583 };
584 m_aGLWin.hRC = wglCreateContextAttribsARB(m_aGLWin.hDC, hSharedCtx, attribs);
585 if (m_aGLWin.hRC == nullptr)
586 {
587 SAL_WARN("vcl.opengl", "wglCreateContextAttribsARB failed: "<< WindowsErrorString(GetLastError()));
588 wglMakeCurrent(nullptr, nullptr);
589 g_bAnyCurrent = false;
590 wglDeleteContext(hTempRC);
591 return false;
592 }
593
594 if (!compiledShaderBinariesWork())
595 {
596 wglMakeCurrent(nullptr, nullptr);
597 g_bAnyCurrent = false;
598 wglDeleteContext(hTempRC);
599 return false;
600 }
601
602 wglMakeCurrent(nullptr, nullptr);
603 g_bAnyCurrent = false;
604 wglDeleteContext(hTempRC);
605
606 if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
607 {
608 g_bAnyCurrent = false;
609 SAL_WARN("vcl.opengl", "wglMakeCurrent failed: " << WindowsErrorString(GetLastError()));
610 return false;
611 }
612
613 g_bAnyCurrent = true;
614
615 if (bFirstCall)
616 {
617 // Checking texture size
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.");
623 else
624 VCL_GL_INFO("Max texture size: " << nMaxTextureSize);
625
626 // Trying to make a texture and check its size
627 for (GLint nWidthHeight = 1023; nWidthHeight < nMaxTextureSize; nWidthHeight += (nWidthHeight + 1))
628 {
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)
632 {
633 GLint nWidth = 0;
634 GLint nHeight = 0;
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);
638 }
639 else
640 {
641 SAL_WARN("vcl.opengl", "Error when creating a " << nWidthHeight << ", " << nWidthHeight << " test texture.");
642 }
643 }
644 }
645
646 InitGLDebugging();
647
648 g_vShareList.push_back(m_aGLWin.hRC);
649
650 RECT clientRect;
651 GetClientRect(WindowFromDC(m_aGLWin.hDC), &clientRect);
652 m_aGLWin.Width = clientRect.right - clientRect.left;
653 m_aGLWin.Height = clientRect.bottom - clientRect.top;
654
655 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
656
657 registerAsCurrent();
658
659 bFirstCall = false;
660
661 return true;
662}
663
665{
666 return new WinOpenGLContext;
667}
668
669/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define VCL_GL_INFO(stream)
Helper to do a SAL_INFO as well as a GL log.
#define CHECK_GL_ERROR()
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 bool ImplInit()
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 ...
Definition: opengl/zone.hxx:23
static VclPtr< reference_type > Create(Arg &&... arg)
A construction helper for VclPtr.
Definition: vclptr.hxx:127
virtual OpenGLContext * CreateOpenGLContext() override
void * p
#define SAL_WARN(area, stream)
#define CALLBACK
sal_Int16 nId
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)
unsigned char BYTE
static std::vector< HGLRC > g_vShareList
Definition: win/context.cxx:27
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()
Definition: win/context.cxx:90
static bool WGLisExtensionSupported(const char *extension)
static bool g_bAnyCurrent
Definition: win/context.cxx:28
static bool InitTempWindow(HWND &hwnd, int width, int height, const PIXELFORMATDESCRIPTOR &inPfd, GLWinWindow &glWin)