0032732: Visualization, TKOpenGl - do not include system headers within OpenGl_GlFunc...
[occt.git] / src / OpenGl / OpenGl_Window.cxx
1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #if defined(_WIN32)
17   #include <windows.h>
18 #endif
19
20 #include <OpenGl_GlCore12.hxx>
21
22 #include <OpenGl_Context.hxx>
23 #include <OpenGl_GraphicDriver.hxx>
24 #include <OpenGl_Window.hxx>
25 #include <OpenGl_FrameBuffer.hxx>
26
27 #include <Aspect_GraphicDeviceDefinitionError.hxx>
28 #include <Graphic3d_TransformUtils.hxx>
29 #include <TCollection_AsciiString.hxx>
30 #include <TCollection_ExtendedString.hxx>
31 #include <Graphic3d_GraphicDriver.hxx>
32
33 #include <memory>
34
35 #include <Standard_WarningDisableFunctionCast.hxx>
36
37 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Window,Standard_Transient)
38
39 #if defined(HAVE_EGL)
40   #include <EGL/egl.h>
41 #elif defined(HAVE_XLIB)
42   #include <GL/glx.h>
43 #endif
44
45 #if !defined(__APPLE__) || defined(HAVE_XLIB)
46
47 namespace
48 {
49
50 #if defined(HAVE_EGL)
51   //
52 #elif defined(_WIN32)
53
54   // WGL_ARB_pixel_format
55 #ifndef WGL_NUMBER_PIXEL_FORMATS_ARB
56   #define WGL_NUMBER_PIXEL_FORMATS_ARB            0x2000
57   #define WGL_DRAW_TO_WINDOW_ARB                  0x2001
58   #define WGL_DRAW_TO_BITMAP_ARB                  0x2002
59   #define WGL_ACCELERATION_ARB                    0x2003
60   #define WGL_NEED_PALETTE_ARB                    0x2004
61   #define WGL_NEED_SYSTEM_PALETTE_ARB             0x2005
62   #define WGL_SWAP_LAYER_BUFFERS_ARB              0x2006
63   #define WGL_SWAP_METHOD_ARB                     0x2007
64   #define WGL_NUMBER_OVERLAYS_ARB                 0x2008
65   #define WGL_NUMBER_UNDERLAYS_ARB                0x2009
66   #define WGL_TRANSPARENT_ARB                     0x200A
67   #define WGL_TRANSPARENT_RED_VALUE_ARB           0x2037
68   #define WGL_TRANSPARENT_GREEN_VALUE_ARB         0x2038
69   #define WGL_TRANSPARENT_BLUE_VALUE_ARB          0x2039
70   #define WGL_TRANSPARENT_ALPHA_VALUE_ARB         0x203A
71   #define WGL_TRANSPARENT_INDEX_VALUE_ARB         0x203B
72   #define WGL_SHARE_DEPTH_ARB                     0x200C
73   #define WGL_SHARE_STENCIL_ARB                   0x200D
74   #define WGL_SHARE_ACCUM_ARB                     0x200E
75   #define WGL_SUPPORT_GDI_ARB                     0x200F
76   #define WGL_SUPPORT_OPENGL_ARB                  0x2010
77   #define WGL_DOUBLE_BUFFER_ARB                   0x2011
78   #define WGL_STEREO_ARB                          0x2012
79   #define WGL_PIXEL_TYPE_ARB                      0x2013
80   #define WGL_COLOR_BITS_ARB                      0x2014
81   #define WGL_RED_BITS_ARB                        0x2015
82   #define WGL_RED_SHIFT_ARB                       0x2016
83   #define WGL_GREEN_BITS_ARB                      0x2017
84   #define WGL_GREEN_SHIFT_ARB                     0x2018
85   #define WGL_BLUE_BITS_ARB                       0x2019
86   #define WGL_BLUE_SHIFT_ARB                      0x201A
87   #define WGL_ALPHA_BITS_ARB                      0x201B
88   #define WGL_ALPHA_SHIFT_ARB                     0x201C
89   #define WGL_ACCUM_BITS_ARB                      0x201D
90   #define WGL_ACCUM_RED_BITS_ARB                  0x201E
91   #define WGL_ACCUM_GREEN_BITS_ARB                0x201F
92   #define WGL_ACCUM_BLUE_BITS_ARB                 0x2020
93   #define WGL_ACCUM_ALPHA_BITS_ARB                0x2021
94   #define WGL_DEPTH_BITS_ARB                      0x2022
95   #define WGL_STENCIL_BITS_ARB                    0x2023
96   #define WGL_AUX_BUFFERS_ARB                     0x2024
97
98   #define WGL_NO_ACCELERATION_ARB                 0x2025
99   #define WGL_GENERIC_ACCELERATION_ARB            0x2026
100   #define WGL_FULL_ACCELERATION_ARB               0x2027
101
102   #define WGL_SWAP_EXCHANGE_ARB                   0x2028
103   #define WGL_SWAP_COPY_ARB                       0x2029
104   #define WGL_SWAP_UNDEFINED_ARB                  0x202A
105
106   #define WGL_TYPE_RGBA_ARB                       0x202B
107   #define WGL_TYPE_COLORINDEX_ARB                 0x202C
108 #endif // WGL_NUMBER_PIXEL_FORMATS_ARB
109
110   // WGL_ARB_create_context_profile
111 #ifndef WGL_CONTEXT_MAJOR_VERSION_ARB
112   #define WGL_CONTEXT_MAJOR_VERSION_ARB           0x2091
113   #define WGL_CONTEXT_MINOR_VERSION_ARB           0x2092
114   #define WGL_CONTEXT_LAYER_PLANE_ARB             0x2093
115   #define WGL_CONTEXT_FLAGS_ARB                   0x2094
116   #define WGL_CONTEXT_PROFILE_MASK_ARB            0x9126
117
118   // WGL_CONTEXT_FLAGS bits
119   #define WGL_CONTEXT_DEBUG_BIT_ARB               0x0001
120   #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB  0x0002
121
122   // WGL_CONTEXT_PROFILE_MASK_ARB bits
123   #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB          0x00000001
124   #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
125 #endif // WGL_CONTEXT_MAJOR_VERSION_ARB
126
127   static LRESULT CALLBACK wndProcDummy (HWND theWin, UINT theMsg, WPARAM theParamW, LPARAM theParamL)
128   {
129     return DefWindowProcW (theWin, theMsg, theParamW, theParamL);
130   }
131 #elif defined(HAVE_XLIB)
132
133   // GLX_ARB_create_context
134 #ifndef GLX_CONTEXT_MAJOR_VERSION_ARB
135   #define GLX_CONTEXT_DEBUG_BIT_ARB         0x00000001
136   #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
137   #define GLX_CONTEXT_MAJOR_VERSION_ARB     0x2091
138   #define GLX_CONTEXT_MINOR_VERSION_ARB     0x2092
139   #define GLX_CONTEXT_FLAGS_ARB             0x2094
140
141   // GLX_ARB_create_context_profile
142   #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB  0x00000001
143   #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
144   #define GLX_CONTEXT_PROFILE_MASK_ARB      0x9126
145 #endif
146
147   //! Dummy XError handler which just skips errors
148   static int xErrorDummyHandler (Display*     /*theDisplay*/,
149                                  XErrorEvent* /*theErrorEvent*/)
150   {
151     return 0;
152   }
153
154   //! Auxiliary method to format list.
155   static void addMsgToList (TCollection_ExtendedString&       theList,
156                             const TCollection_ExtendedString& theMsg)
157   {
158     if (!theList.IsEmpty())
159     {
160       theList += ", ";
161     }
162     theList += theMsg;
163   }
164 #endif
165
166 }
167
168 // =======================================================================
169 // function : OpenGl_Window
170 // purpose  :
171 // =======================================================================
172 OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
173                               const Handle(Aspect_Window)&  thePlatformWindow,
174                               Aspect_RenderingContext       theGContext,
175                               const Handle(OpenGl_Caps)&    theCaps,
176                               const Handle(OpenGl_Context)& theShareCtx)
177 : myGlContext (new OpenGl_Context (theCaps)),
178   myOwnGContext (theGContext == 0),
179   myPlatformWindow (thePlatformWindow),
180   mySwapInterval (theCaps->swapInterval)
181 {
182   myPlatformWindow->Size (myWidth, myHeight);
183
184   Standard_Boolean isCoreProfile = Standard_False;
185
186 #if defined(HAVE_EGL)
187   EGLDisplay anEglDisplay = (EGLDisplay )theDriver->getRawGlDisplay();
188   EGLContext anEglContext = (EGLContext )theDriver->getRawGlContext();
189   EGLConfig  anEglConfig  = (EGLConfig  )theDriver->getRawGlConfig();
190   if (anEglDisplay == EGL_NO_DISPLAY
191    || anEglContext == EGL_NO_CONTEXT
192    || (anEglConfig == NULL
193     && (EGLContext )theGContext == EGL_NO_CONTEXT))
194   {
195     throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL does not provide compatible configurations!");
196     return;
197   }
198
199   EGLSurface anEglSurf = EGL_NO_SURFACE;
200   if ((EGLContext )theGContext == EGL_NO_CONTEXT)
201   {
202     // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
203     //const int aSurfAttribs[] =
204     //{
205     //  EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
206     //  EGL_NONE,
207     //};
208
209     // create new surface
210     anEglSurf = eglCreateWindowSurface (anEglDisplay,
211                                         anEglConfig,
212                                         (EGLNativeWindowType )myPlatformWindow->NativeHandle(),
213                                         NULL);
214     if (anEglSurf == EGL_NO_SURFACE
215      && myPlatformWindow->NativeHandle() != 0)
216     {
217       throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create surface for window!");
218     }
219     else if (anEglSurf == EGL_NO_SURFACE)
220     {
221       // window-less EGL context (off-screen)
222       //throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to retrieve current surface!");
223       if (anEglConfig != NULL)
224       {
225       #if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL
226         const int aSurfAttribs[] =
227         {
228           EGL_WIDTH,  myWidth,
229           EGL_HEIGHT, myHeight,
230           // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
231           //EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
232           EGL_NONE
233         };
234         anEglSurf = eglCreatePbufferSurface (anEglDisplay, anEglConfig, aSurfAttribs);
235         if (anEglSurf == EGL_NO_SURFACE)
236         {
237           throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create off-screen surface!");
238         }
239       #endif
240       }
241       myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
242                                 "OpenGl_Window::CreateWindow: WARNING, a Window is created without a EGL Surface!");
243     }
244   }
245   else if (theGContext != anEglContext)
246   {
247     throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is used in unsupported combination!");
248   }
249   else
250   {
251     anEglSurf = eglGetCurrentSurface(EGL_DRAW);
252     if (anEglSurf == EGL_NO_SURFACE)
253     {
254       // window-less EGL context (off-screen)
255       //throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to retrieve current surface!");
256       if (anEglConfig != NULL)
257       {
258       #if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL
259         const int aSurfAttribs[] =
260         {
261           EGL_WIDTH,  myWidth,
262           EGL_HEIGHT, myHeight,
263           // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
264           //EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
265           EGL_NONE
266         };
267         anEglSurf = eglCreatePbufferSurface (anEglDisplay, anEglConfig, aSurfAttribs);
268         if (anEglSurf == EGL_NO_SURFACE)
269         {
270           throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create off-screen surface!");
271         }
272       #endif
273       }
274       myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
275                                 "OpenGl_Window::CreateWindow: WARNING, a Window is created without a EGL Surface!");
276     }
277   }
278
279   myGlContext->Init ((Aspect_Drawable )anEglSurf, (Aspect_Display )anEglDisplay, (Aspect_RenderingContext )anEglContext, isCoreProfile);
280 #elif defined(_WIN32)
281   (void )theDriver;
282   HWND  aWindow   = (HWND )myPlatformWindow->NativeHandle();
283   HDC   aWindowDC = GetDC (aWindow);
284   HGLRC aGContext = (HGLRC )theGContext;
285
286   PIXELFORMATDESCRIPTOR aPixelFrmt;
287   memset (&aPixelFrmt, 0, sizeof(aPixelFrmt));
288   aPixelFrmt.nSize        = sizeof(PIXELFORMATDESCRIPTOR);
289   aPixelFrmt.nVersion     = 1;
290   aPixelFrmt.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
291   aPixelFrmt.iPixelType   = PFD_TYPE_RGBA;
292   aPixelFrmt.cColorBits   = 24;
293   aPixelFrmt.cDepthBits   = 24;
294   aPixelFrmt.cStencilBits = 8;
295   aPixelFrmt.iLayerType   = PFD_MAIN_PLANE;
296   if (theCaps->contextStereo)
297   {
298     aPixelFrmt.dwFlags |= PFD_STEREO;
299   }
300
301   int aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
302
303   // in case of failure try without stereo if any
304   const Standard_Boolean hasStereo = aPixelFrmtId != 0 && theCaps->contextStereo;
305   if (aPixelFrmtId == 0 && theCaps->contextStereo)
306   {
307     TCollection_ExtendedString aMsg ("OpenGl_Window::CreateWindow: "
308                                      "ChoosePixelFormat is unable to find stereo supported pixel format. "
309                                      "Choosing similar non stereo format.");
310     myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
311                               GL_DEBUG_TYPE_OTHER,
312                               0, GL_DEBUG_SEVERITY_HIGH, aMsg);
313
314     aPixelFrmt.dwFlags &= ~PFD_STEREO;
315     aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
316   }
317
318   if (aPixelFrmtId == 0)
319   {
320     ReleaseDC (aWindow, aWindowDC);
321
322     TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: ChoosePixelFormat failed. Error code: ");
323     aMsg += (int )GetLastError();
324     throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
325     return;
326   }
327
328   DescribePixelFormat (aWindowDC, aPixelFrmtId, sizeof(aPixelFrmt), &aPixelFrmt);
329
330   HGLRC aSlaveCtx = !theShareCtx.IsNull() ? (HGLRC )theShareCtx->myGContext : NULL;
331   if (aGContext == NULL)
332   {
333     // create temporary context to retrieve advanced context creation procedures
334     HMODULE aModule = GetModuleHandleW(NULL);
335     WNDCLASSW aClass; memset (&aClass, 0, sizeof(aClass));
336     aClass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
337     aClass.lpfnWndProc   = wndProcDummy;
338     aClass.hInstance     = aModule;
339     aClass.lpszClassName = L"OpenGl_WindowTmp";
340     HWND  aWinTmp     = NULL;
341     HDC   aDevCtxTmp  = NULL;
342     HGLRC aRendCtxTmp = NULL;
343     if ((!theCaps->contextDebug && !theCaps->contextNoAccel && theCaps->contextCompatible)
344      || RegisterClassW (&aClass) == 0)
345     {
346       aClass.lpszClassName = NULL;
347     }
348     if (aClass.lpszClassName != NULL)
349     {
350       DWORD anExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
351     #if (_WIN32_WINNT >= 0x0500)
352       anExStyle |= WS_EX_NOACTIVATE;
353     #endif
354       aWinTmp = CreateWindowExW(anExStyle,
355                                 aClass.lpszClassName, L"OpenGl_WindowTmp",
356                                 WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
357                                 2, 2, 4, 4,
358                                 NULL, NULL, aModule, NULL);
359     }
360     if (aWinTmp != NULL)
361     {
362       aDevCtxTmp = GetDC (aWinTmp);
363       SetPixelFormat (aDevCtxTmp, aPixelFrmtId, &aPixelFrmt);
364       aRendCtxTmp = wglCreateContext (aDevCtxTmp);
365     }
366
367     typedef BOOL (WINAPI *wglChoosePixelFormatARB_t)(HDC           theDevCtx,
368                                                      const int*    theIntAttribs,
369                                                      const float*  theFloatAttribs,
370                                                      unsigned int  theMaxFormats,
371                                                      int*          theFormatsOut,
372                                                      unsigned int* theNumFormatsOut);
373     typedef HGLRC (WINAPI *wglCreateContextAttribsARB_t)(HDC        theDevCtx,
374                                                          HGLRC      theShareContext,
375                                                          const int* theAttribs);
376     wglChoosePixelFormatARB_t    aChoosePixProc = NULL;
377     wglCreateContextAttribsARB_t aCreateCtxProc = NULL;
378     if (aRendCtxTmp != NULL)
379     {
380       wglMakeCurrent (aDevCtxTmp, aRendCtxTmp);
381
382       typedef const char* (WINAPI *wglGetExtensionsStringARB_t)(HDC theDeviceContext);
383       wglGetExtensionsStringARB_t aGetExtensions = (wglGetExtensionsStringARB_t  )wglGetProcAddress ("wglGetExtensionsStringARB");
384       const char* aWglExts = (aGetExtensions != NULL) ? aGetExtensions (wglGetCurrentDC()) : NULL;
385       if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_pixel_format"))
386       {
387         aChoosePixProc = (wglChoosePixelFormatARB_t    )wglGetProcAddress ("wglChoosePixelFormatARB");
388       }
389       if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_create_context_profile"))
390       {
391         aCreateCtxProc = (wglCreateContextAttribsARB_t )wglGetProcAddress ("wglCreateContextAttribsARB");
392       }
393     }
394
395     // choose extended pixel format
396     if (aChoosePixProc != NULL)
397     {
398       const int aPixAttribs[] =
399       {
400         WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
401         WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
402         WGL_DOUBLE_BUFFER_ARB,  GL_TRUE,
403         WGL_STEREO_ARB,         hasStereo ? GL_TRUE : GL_FALSE,
404         WGL_PIXEL_TYPE_ARB,     WGL_TYPE_RGBA_ARB,
405         //WGL_SAMPLE_BUFFERS_ARB, 1,
406         //WGL_SAMPLES_ARB,        8,
407         WGL_COLOR_BITS_ARB,     24,
408         WGL_DEPTH_BITS_ARB,     24,
409         WGL_STENCIL_BITS_ARB,   8,
410         // WGL_EXT_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
411         //WGL_COLORSPACE_EXT, !theCaps->sRGBDisable ? WGL_COLORSPACE_SRGB_EXT : WGL_COLORSPACE_LINEAR_EXT,
412         // requires WGL_ARB_framebuffer_sRGB or WGL_EXT_framebuffer_sRGB extensions
413         //WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT, !theCaps->sRGBDisable ? GL_TRUE : GL_FALSE,
414         WGL_ACCELERATION_ARB,   theCaps->contextNoAccel ? WGL_NO_ACCELERATION_ARB : WGL_FULL_ACCELERATION_ARB,
415         0, 0,
416       };
417       unsigned int aFrmtsNb = 0;
418       aChoosePixProc (aWindowDC, aPixAttribs, NULL, 1, &aPixelFrmtId, &aFrmtsNb);
419     }
420
421     // setup pixel format - may be set only once per window
422     if (!SetPixelFormat (aWindowDC, aPixelFrmtId, &aPixelFrmt))
423     {
424       ReleaseDC (aWindow, aWindowDC);
425
426       TCollection_AsciiString aMsg("OpenGl_Window::CreateWindow: SetPixelFormat failed. Error code: ");
427       aMsg += (int )GetLastError();
428       throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
429       return;
430     }
431
432     // create GL context with extra options
433     if (aCreateCtxProc != NULL)
434     {
435       if (!theCaps->contextCompatible)
436       {
437         int aCoreCtxAttribs[] =
438         {
439           WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
440           WGL_CONTEXT_MINOR_VERSION_ARB, 2,
441           WGL_CONTEXT_PROFILE_MASK_ARB,  WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
442           WGL_CONTEXT_FLAGS_ARB,         theCaps->contextDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
443           0, 0
444         };
445
446         // Try to create the core profile of highest OpenGL version supported by OCCT
447         // (this will be done automatically by some drivers when requesting 3.2,
448         //  but some will not (e.g. AMD Catalyst) since WGL_ARB_create_context_profile specification allows both implementations).
449         for (int aLowVer4 = 6; aLowVer4 >= 0 && aGContext == NULL; --aLowVer4)
450         {
451           aCoreCtxAttribs[1] = 4;
452           aCoreCtxAttribs[3] = aLowVer4;
453           aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCoreCtxAttribs);
454         }
455         for (int aLowVer3 = 3; aLowVer3 >= 2 && aGContext == NULL; --aLowVer3)
456         {
457           aCoreCtxAttribs[1] = 3;
458           aCoreCtxAttribs[3] = aLowVer3;
459           aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCoreCtxAttribs);
460         }
461         isCoreProfile = aGContext != NULL;
462       }
463
464       if (aGContext == NULL)
465       {
466         int aCtxAttribs[] =
467         {
468           // Beware! NVIDIA drivers reject context creation when WGL_CONTEXT_PROFILE_MASK_ARB are specified
469           // but not WGL_CONTEXT_MAJOR_VERSION_ARB/WGL_CONTEXT_MINOR_VERSION_ARB.
470           //WGL_CONTEXT_PROFILE_MASK_ARB,  WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
471           WGL_CONTEXT_FLAGS_ARB,         theCaps->contextDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
472           0, 0
473         };
474         isCoreProfile = Standard_False;
475         aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCtxAttribs);
476
477         if (aGContext != NULL
478         && !theCaps->contextCompatible)
479         {
480           TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
481           myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
482         }
483       }
484
485       if (aGContext != NULL)
486       {
487         aSlaveCtx = NULL;
488       }
489     }
490
491     if (aRendCtxTmp != NULL)
492     {
493       wglDeleteContext (aRendCtxTmp);
494     }
495     if (aDevCtxTmp != NULL)
496     {
497       ReleaseDC (aWinTmp, aDevCtxTmp);
498     }
499     if (aWinTmp != NULL)
500     {
501       DestroyWindow (aWinTmp);
502     }
503     if (aClass.lpszClassName != NULL)
504     {
505       UnregisterClassW (aClass.lpszClassName, aModule);
506     }
507
508     if (aGContext == NULL)
509     {
510       // create context using obsolete functionality
511       aGContext = wglCreateContext (aWindowDC);
512     }
513     if (aGContext == NULL)
514     {
515       ReleaseDC (aWindow, aWindowDC);
516
517       TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglCreateContext failed. Error code: ");
518       aMsg += (int )GetLastError();
519       throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
520       return;
521     }
522   }
523
524   // all GL context within one OpenGl_GraphicDriver should be shared!
525   if (aSlaveCtx != NULL && wglShareLists (aSlaveCtx, aGContext) != TRUE)
526   {
527     TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglShareLists failed. Error code: ");
528     aMsg += (int )GetLastError();
529     throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
530     return;
531   }
532
533   myGlContext->Init ((Aspect_Handle )aWindow, (Aspect_Handle )aWindowDC, (Aspect_RenderingContext )aGContext, isCoreProfile);
534 #elif defined(HAVE_XLIB)
535   Window     aWindow   = (Window )myPlatformWindow->NativeHandle();
536   Display*   aDisp     = (Display* )theDriver->GetDisplayConnection()->GetDisplayAspect();
537   GLXContext aGContext = (GLXContext )theGContext;
538   GLXContext aSlaveCtx = !theShareCtx.IsNull() ? (GLXContext )theShareCtx->myGContext : NULL;
539
540   XWindowAttributes aWinAttribs;
541   XGetWindowAttributes (aDisp, aWindow, &aWinAttribs);
542   XVisualInfo aVisInfo;
543   aVisInfo.visualid = aWinAttribs.visual->visualid;
544   aVisInfo.screen   = DefaultScreen (aDisp);
545   int aNbItems;
546   std::unique_ptr<XVisualInfo, int(*)(void*)> aVis (XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfo, &aNbItems), &XFree);
547   int isGl = 0;
548   if (aVis.get() == NULL)
549   {
550     throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: XGetVisualInfo is unable to choose needed configuration in existing OpenGL context. ");
551     return;
552   }
553   else if (glXGetConfig (aDisp, aVis.get(), GLX_USE_GL, &isGl) != 0 || !isGl)
554   {
555     throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: window Visual does not support GL rendering!");
556     return;
557   }
558
559   // create new context
560   GLXFBConfig anFBConfig = myPlatformWindow->NativeFBConfig();
561   const char* aGlxExts   = glXQueryExtensionsString (aDisp, aVisInfo.screen);
562   if (myOwnGContext
563    && anFBConfig != NULL
564    && OpenGl_Context::CheckExtension (aGlxExts, "GLX_ARB_create_context_profile"))
565   {
566     // Replace default XError handler to ignore errors.
567     // Warning - this is global for all threads!
568     typedef int (*xerrorhandler_t)(Display* , XErrorEvent* );
569     xerrorhandler_t anOldHandler = XSetErrorHandler(xErrorDummyHandler);
570
571     typedef GLXContext (*glXCreateContextAttribsARB_t)(Display* dpy, GLXFBConfig config,
572                                                        GLXContext share_context, Bool direct,
573                                                        const int* attrib_list);
574     glXCreateContextAttribsARB_t aCreateCtxProc = (glXCreateContextAttribsARB_t )glXGetProcAddress((const GLubyte* )"glXCreateContextAttribsARB");
575     if (!theCaps->contextCompatible)
576     {
577       int aCoreCtxAttribs[] =
578       {
579         GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
580         GLX_CONTEXT_MINOR_VERSION_ARB, 2,
581         GLX_CONTEXT_PROFILE_MASK_ARB,  GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
582         GLX_CONTEXT_FLAGS_ARB,         theCaps->contextDebug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
583         0, 0
584       };
585
586       // try to create the core profile of highest OpenGL version supported by OCCT
587       for (int aLowVer4 = 6; aLowVer4 >= 0 && aGContext == NULL; --aLowVer4)
588       {
589         aCoreCtxAttribs[1] = 4;
590         aCoreCtxAttribs[3] = aLowVer4;
591         aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCoreCtxAttribs);
592       }
593       for (int aLowVer3 = 3; aLowVer3 >= 2 && aGContext == NULL; --aLowVer3)
594       {
595         aCoreCtxAttribs[1] = 3;
596         aCoreCtxAttribs[3] = aLowVer3;
597         aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCoreCtxAttribs);
598       }
599       isCoreProfile = aGContext != NULL;
600     }
601
602     if (aGContext == NULL)
603     {
604       int aCtxAttribs[] =
605       {
606         GLX_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
607         0, 0
608       };
609       isCoreProfile = Standard_False;
610       aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCtxAttribs);
611
612       if (aGContext != NULL
613       && !theCaps->contextCompatible)
614       {
615         TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
616         myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
617       }
618     }
619     XSetErrorHandler(anOldHandler);
620   }
621
622   if (myOwnGContext
623    && aGContext == NULL)
624   {
625     aGContext = glXCreateContext (aDisp, aVis.get(), aSlaveCtx, GL_TRUE);
626     if (aGContext == NULL)
627     {
628       throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: glXCreateContext failed.");
629       return;
630     }
631   }
632
633   // check Visual for OpenGl context's parameters compatibility
634   TCollection_ExtendedString aList;
635   int isDoubleBuffer = 0, isRGBA = 0, isStereo = 0;
636   int aDepthSize = 0, aStencilSize = 0;
637   glXGetConfig (aDisp, aVis.get(), GLX_RGBA,         &isRGBA);
638   glXGetConfig (aDisp, aVis.get(), GLX_DOUBLEBUFFER, &isDoubleBuffer);
639   glXGetConfig (aDisp, aVis.get(), GLX_STEREO,       &isStereo);
640   glXGetConfig (aDisp, aVis.get(), GLX_DEPTH_SIZE,   &aDepthSize);
641   glXGetConfig (aDisp, aVis.get(), GLX_STENCIL_SIZE, &aStencilSize);
642   if (aDepthSize < 1)      addMsgToList (aList, "no depth buffer");
643   if (aStencilSize < 1)    addMsgToList (aList, "no stencil buffer");
644   if (isRGBA == 0)         addMsgToList (aList, "no RGBA color buffer");
645   if (isDoubleBuffer == 0) addMsgToList (aList, "no Double Buffer");
646   if (theCaps->contextStereo && isStereo == 0)
647   {
648     addMsgToList (aList, "no Quad Buffer");
649   }
650   else if (!theCaps->contextStereo && isStereo == 1)
651   {
652     addMsgToList (aList, "extra Quad Buffer");
653   }
654   if (!aList.IsEmpty())
655   {
656     TCollection_ExtendedString aMsg = TCollection_ExtendedString ("OpenGl_Window::CreateWindow: window Visual is incomplete: ") + aList;
657     myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
658                               GL_DEBUG_TYPE_OTHER,
659                               0, GL_DEBUG_SEVERITY_MEDIUM, aMsg);
660   }
661
662   myGlContext->Init ((Aspect_Drawable )aWindow, (Aspect_Display )aDisp, (Aspect_RenderingContext )aGContext, isCoreProfile);
663 #else
664   // not implemented
665   (void )isCoreProfile;
666 #endif
667   myGlContext->Share (theShareCtx);
668   myGlContext->SetSwapInterval (mySwapInterval);
669   Init();
670 }
671
672 // =======================================================================
673 // function : ~OpenGl_Window
674 // purpose  :
675 // =======================================================================
676 OpenGl_Window::~OpenGl_Window()
677 {
678   if (!myOwnGContext
679    ||  myGlContext.IsNull())
680   {
681     myGlContext.Nullify();
682     return;
683   }
684
685   // release "GL" context if it is owned by window
686   // Mesa implementation can fail to destroy GL context if it set for current thread.
687   // It should be safer to unset thread GL context before its destruction.
688 #if defined(HAVE_EGL)
689   if ((EGLSurface )myGlContext->myWindow != EGL_NO_SURFACE)
690   {
691     eglDestroySurface ((EGLDisplay )myGlContext->myDisplay,
692                        (EGLSurface )myGlContext->myWindow);
693   }
694 #elif defined(_WIN32)
695   HWND  aWindow          = (HWND  )myGlContext->myWindow;
696   HDC   aWindowDC        = (HDC   )myGlContext->myDisplay;
697   HGLRC aWindowGContext  = (HGLRC )myGlContext->myGContext;
698   HGLRC aThreadGContext  = wglGetCurrentContext();
699   myGlContext.Nullify();
700
701   if (aThreadGContext != NULL)
702   {
703     if (aThreadGContext == aWindowGContext)
704     {
705       wglMakeCurrent (NULL, NULL);
706     }
707
708     wglDeleteContext (aWindowGContext);
709   }
710   ReleaseDC (aWindow, aWindowDC);
711 #elif defined(HAVE_XLIB)
712   Display*    aDisplay        = (Display*    )myGlContext->myDisplay;
713   GLXContext  aWindowGContext = (GLXContext  )myGlContext->myGContext;
714   GLXContext  aThreadGContext = glXGetCurrentContext();
715   myGlContext.Nullify();
716
717   if (aDisplay != NULL)
718   {
719     if (aThreadGContext == aWindowGContext)
720     {
721       glXMakeCurrent (aDisplay, None, NULL);
722     }
723
724     // FSXXX sync necessary if non-direct rendering
725     glXWaitGL();
726     glXDestroyContext (aDisplay, aWindowGContext);
727   }
728 #else
729   // not implemented
730 #endif
731 }
732
733 #endif // !__APPLE__
734
735 // =======================================================================
736 // function : Activate
737 // purpose  :
738 // =======================================================================
739 Standard_Boolean OpenGl_Window::Activate()
740 {
741   return myGlContext->MakeCurrent();
742 }
743
744 #if !defined(__APPLE__) || defined(HAVE_XLIB)
745
746 // =======================================================================
747 // function : Resize
748 // purpose  : call_subr_resize
749 // =======================================================================
750 void OpenGl_Window::Resize()
751 {
752   Standard_Integer aWidth = 0, aHeight = 0;
753   myPlatformWindow->Size (aWidth, aHeight);
754   if (myWidth  == aWidth
755    && myHeight == aHeight)
756   {
757     // if the size is not changed - do nothing
758     return;
759   }
760
761   myWidth  = aWidth;
762   myHeight = aHeight;
763
764   Init();
765 }
766
767 // =======================================================================
768 // function : Init
769 // purpose  :
770 // =======================================================================
771 void OpenGl_Window::Init()
772 {
773   if (!Activate())
774     return;
775
776 #if defined(HAVE_EGL)
777   if ((EGLSurface )myGlContext->myWindow == EGL_NO_SURFACE)
778   {
779     // define an offscreen default FBO to avoid rendering into EGL_NO_SURFACE;
780     // note that this code is currently never called, since eglCreatePbufferSurface() is used instead as more robust solution
781     // for offscreen rendering on bugged OpenGL ES drivers
782     Handle(OpenGl_FrameBuffer) aDefFbo = myGlContext->SetDefaultFrameBuffer (Handle(OpenGl_FrameBuffer)());
783     if (!aDefFbo.IsNull())
784     {
785       aDefFbo->Release (myGlContext.operator->());
786     }
787     else
788     {
789       aDefFbo = new OpenGl_FrameBuffer();
790     }
791
792     OpenGl_ColorFormats aColorFormats;
793     aColorFormats.Append (GL_RGBA8);
794     if (!aDefFbo->InitRenderBuffer (myGlContext, Graphic3d_Vec2i (myWidth, myHeight), aColorFormats, GL_DEPTH24_STENCIL8))
795     {
796       TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed");
797       throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
798     }
799     myGlContext->SetDefaultFrameBuffer (aDefFbo);
800     aDefFbo->BindBuffer (myGlContext);
801   }
802   else if (!myPlatformWindow->IsVirtual())
803   {
804     eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH,  &myWidth);
805     eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &myHeight);
806   }
807 #else
808   //
809 #endif
810
811   myGlContext->core11fwd->glDisable (GL_DITHER);
812   myGlContext->core11fwd->glDisable (GL_SCISSOR_TEST);
813   const Standard_Integer aViewport[4] = { 0, 0, myWidth, myHeight };
814   myGlContext->ResizeViewport (aViewport);
815   myGlContext->SetDrawBuffer (GL_BACK);
816   if (myGlContext->core11ffp != NULL)
817   {
818     myGlContext->core11ffp->glMatrixMode (GL_MODELVIEW);
819   }
820 }
821
822 // =======================================================================
823 // function : SetSwapInterval
824 // purpose  :
825 // =======================================================================
826 void OpenGl_Window::SetSwapInterval (Standard_Boolean theToForceNoSync)
827 {
828   const Standard_Integer aSwapInterval = theToForceNoSync ? 0 : myGlContext->caps->swapInterval;
829   if (mySwapInterval != aSwapInterval)
830   {
831     mySwapInterval = aSwapInterval;
832     myGlContext->SetSwapInterval (mySwapInterval);
833   }
834 }
835
836 #endif // !__APPLE__