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