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