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