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