33bf69c7f141a50bb1d984ff76c61c2f03a5b2fc
[occt.git] / src / OpenGl / OpenGl_GraphicDriver.cxx
1 // Created on: 2011-10-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2013 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_GraphicDriver.hxx>
21 #include <OpenGl_Context.hxx>
22 #include <OpenGl_Flipper.hxx>
23 #include <OpenGl_GraduatedTrihedron.hxx>
24 #include <OpenGl_Group.hxx>
25 #include <OpenGl_View.hxx>
26 #include <OpenGl_StencilTest.hxx>
27 #include <OpenGl_Text.hxx>
28 #include <OpenGl_Workspace.hxx>
29
30 #include <Aspect_GraphicDeviceDefinitionError.hxx>
31 #include <Aspect_IdentDefinitionError.hxx>
32 #include <Graphic3d_StructureManager.hxx>
33 #include <Message_Messenger.hxx>
34 #include <OSD_Environment.hxx>
35 #include <Standard_NotImplemented.hxx>
36
37 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_GraphicDriver,Graphic3d_GraphicDriver)
38
39 #if defined(_WIN32)
40   #include <WNT_Window.hxx>
41 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
42   #include <Cocoa_Window.hxx>
43 #else
44   #include <Xw_Window.hxx>
45 #endif
46
47 #if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
48   #include <X11/Xlib.h> // XOpenDisplay()
49   #include <GL/glx.h>
50 #endif
51
52 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
53   #include <EGL/egl.h>
54   #ifndef EGL_OPENGL_ES3_BIT
55     #define EGL_OPENGL_ES3_BIT 0x00000040
56   #endif
57 #endif
58
59 namespace
60 {
61   static const Handle(OpenGl_Context) TheNullGlCtx;
62
63 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
64   //! Wrapper over eglChooseConfig() called with preferred defaults.
65   static EGLConfig chooseEglSurfConfig (EGLDisplay theDisplay)
66   {
67     EGLint aConfigAttribs[] =
68     {
69       EGL_RED_SIZE,     8,
70       EGL_GREEN_SIZE,   8,
71       EGL_BLUE_SIZE,    8,
72       EGL_ALPHA_SIZE,   0,
73       EGL_DEPTH_SIZE,   24,
74       EGL_STENCIL_SIZE, 8,
75     #if defined(GL_ES_VERSION_2_0)
76       EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
77     #else
78       EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
79     #endif
80       EGL_NONE
81     };
82
83     EGLConfig aCfg = NULL;
84     EGLint aNbConfigs = 0;
85     for (Standard_Integer aGlesVer = 3; aGlesVer >= 2; --aGlesVer)
86     {
87     #if defined(GL_ES_VERSION_2_0)
88       aConfigAttribs[6 * 2 + 1] = aGlesVer == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
89     #else
90       if (aGlesVer == 2)
91       {
92         break;
93       }
94     #endif
95
96       if (eglChooseConfig (theDisplay, aConfigAttribs, &aCfg, 1, &aNbConfigs) == EGL_TRUE
97        && aCfg != NULL)
98       {
99         return aCfg;
100       }
101       eglGetError();
102
103       aConfigAttribs[4 * 2 + 1] = 16; // try config with smaller depth buffer
104       if (eglChooseConfig (theDisplay, aConfigAttribs, &aCfg, 1, &aNbConfigs) == EGL_TRUE
105        && aCfg != NULL)
106       {
107         return aCfg;
108       }
109       eglGetError();
110     }
111     return aCfg;
112   }
113 #elif !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
114   //! Search for RGBA double-buffered visual with stencil buffer.
115   static int TheDoubleBuffVisual[] =
116   {
117     GLX_RGBA,
118     GLX_DEPTH_SIZE, 16,
119     GLX_STENCIL_SIZE, 1,
120     GLX_DOUBLEBUFFER,
121     None
122   };
123
124   //! Search for RGBA double-buffered visual with stencil buffer.
125   static int TheDoubleBuffFBConfig[] =
126   {
127     GLX_X_RENDERABLE,  True,
128     GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
129     GLX_RENDER_TYPE,   GLX_RGBA_BIT,
130     GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
131     GLX_DEPTH_SIZE,    16,
132     GLX_STENCIL_SIZE,  1,
133     GLX_DOUBLEBUFFER,  True,
134     None
135   };
136 #endif
137
138 }
139
140 // =======================================================================
141 // function : OpenGl_GraphicDriver
142 // purpose  :
143 // =======================================================================
144 OpenGl_GraphicDriver::OpenGl_GraphicDriver (const Handle(Aspect_DisplayConnection)& theDisp,
145                                             const Standard_Boolean                  theToInitialize)
146 : Graphic3d_GraphicDriver (theDisp),
147   myIsOwnContext (Standard_False),
148   myEglDisplay (NULL),
149   myEglContext (NULL),
150   myEglConfig  (NULL),
151   myCaps           (new OpenGl_Caps()),
152   myMapOfView      (1, NCollection_BaseAllocator::CommonBaseAllocator()),
153   myMapOfStructure (1, NCollection_BaseAllocator::CommonBaseAllocator())
154 {
155 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
156   myEglDisplay = (Aspect_Display )EGL_NO_DISPLAY;
157   myEglContext = (Aspect_RenderingContext )EGL_NO_CONTEXT;
158 #endif
159
160 #if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
161   if (myDisplayConnection.IsNull())
162   {
163     //throw Aspect_GraphicDeviceDefinitionError("OpenGl_GraphicDriver: cannot connect to X server!");
164     return;
165   }
166
167   Display* aDisplay = myDisplayConnection->GetDisplay();
168   Bool toSync = ::getenv ("CSF_GraphicSync") != NULL
169              || ::getenv ("CALL_SYNCHRO_X")  != NULL;
170   XSynchronize (aDisplay, toSync);
171 #endif
172   if (theToInitialize
173   && !InitContext())
174   {
175     throw Aspect_GraphicDeviceDefinitionError("OpenGl_GraphicDriver: default context can not be initialized!");
176   }
177 }
178
179 // =======================================================================
180 // function : ~OpenGl_GraphicDriver
181 // purpose  :
182 // =======================================================================
183 OpenGl_GraphicDriver::~OpenGl_GraphicDriver()
184 {
185   ReleaseContext();
186 }
187
188 // =======================================================================
189 // function : ReleaseContext
190 // purpose  :
191 // =======================================================================
192 void OpenGl_GraphicDriver::ReleaseContext()
193 {
194   Handle(OpenGl_Context) aCtxShared;
195   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView);
196        aViewIter.More(); aViewIter.Next())
197   {
198     const Handle(OpenGl_View)& aView = aViewIter.Value();
199     const Handle(OpenGl_Window)& aWindow = aView->GlWindow();
200     if (aWindow.IsNull())
201     {
202       continue;
203     }
204
205     const Handle(OpenGl_Context)& aCtx = aWindow->GetGlContext();
206     if (aCtx->MakeCurrent()
207      && aCtxShared.IsNull())
208     {
209       aCtxShared = aCtx;
210     }
211   }
212
213   if (!aCtxShared.IsNull())
214   {
215     aCtxShared->MakeCurrent();
216   }
217   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView);
218        aViewIter.More(); aViewIter.Next())
219   {
220     const Handle(OpenGl_View)& aView = aViewIter.Value();
221     aView->ReleaseGlResources (aCtxShared);
222   }
223
224   for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
225        aStructIt.More (); aStructIt.Next())
226   {
227     OpenGl_Structure* aStruct = aStructIt.ChangeValue();
228     aStruct->ReleaseGlResources (aCtxShared);
229   }
230
231   const bool isDeviceLost = !myMapOfStructure.IsEmpty();
232   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView);
233        aViewIter.More(); aViewIter.Next())
234   {
235     const Handle(OpenGl_View)& aView = aViewIter.Value();
236     if (isDeviceLost)
237     {
238       aView->StructureManager()->SetDeviceLost();
239     }
240
241     const Handle(OpenGl_Window)& aWindow = aView->GlWindow();
242     if (aWindow.IsNull())
243     {
244       continue;
245     }
246
247     aWindow->GetGlContext()->forcedRelease();
248   }
249
250 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
251   if (myIsOwnContext)
252   {
253     if (myEglContext != (Aspect_RenderingContext )EGL_NO_CONTEXT)
254     {
255       if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE)
256       {
257         ::Message::SendWarning ("OpenGl_GraphicDriver, FAILED to release OpenGL context");
258       }
259       eglDestroyContext ((EGLDisplay )myEglDisplay, (EGLContext )myEglContext);
260     }
261
262     if (myEglDisplay != (Aspect_Display )EGL_NO_DISPLAY)
263     {
264       if (eglTerminate ((EGLDisplay )myEglDisplay) != EGL_TRUE)
265       {
266         ::Message::SendWarning ("OpenGl_GraphicDriver, EGL, eglTerminate FAILED");
267       }
268     }
269   }
270
271   myEglDisplay = (Aspect_Display )EGL_NO_DISPLAY;
272   myEglContext = (Aspect_RenderingContext )EGL_NO_CONTEXT;
273   myEglConfig  = NULL;
274 #endif
275   myIsOwnContext = Standard_False;
276 }
277
278 // =======================================================================
279 // function : InitContext
280 // purpose  :
281 // =======================================================================
282 Standard_Boolean OpenGl_GraphicDriver::InitContext()
283 {
284   ReleaseContext();
285 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
286
287 #if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
288   if (myDisplayConnection.IsNull())
289   {
290     return Standard_False;
291   }
292   Display* aDisplay = myDisplayConnection->GetDisplay();
293   myEglDisplay = (Aspect_Display )eglGetDisplay (aDisplay);
294 #else
295   myEglDisplay = (Aspect_Display )eglGetDisplay (EGL_DEFAULT_DISPLAY);
296 #endif
297   if ((EGLDisplay )myEglDisplay == EGL_NO_DISPLAY)
298   {
299     ::Message::SendFail ("Error: no EGL display");
300     return Standard_False;
301   }
302
303   EGLint aVerMajor = 0; EGLint aVerMinor = 0;
304   if (eglInitialize ((EGLDisplay )myEglDisplay, &aVerMajor, &aVerMinor) != EGL_TRUE)
305   {
306     ::Message::SendFail ("Error: EGL display is unavailable");
307     return Standard_False;
308   }
309
310   myEglConfig = chooseEglSurfConfig ((EGLDisplay )myEglDisplay);
311   if (myEglConfig == NULL)
312   {
313     ::Message::SendFail ("Error: EGL does not provide compatible configurations");
314     return Standard_False;
315   }
316
317 #if defined(GL_ES_VERSION_2_0)
318   EGLint anEglCtxAttribs3[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE, EGL_NONE };
319   EGLint anEglCtxAttribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
320   if (eglBindAPI (EGL_OPENGL_ES_API) != EGL_TRUE)
321   {
322     ::Message::SendFail ("Error: EGL does not provide OpenGL ES client");
323     return Standard_False;
324   }
325   if (myCaps->contextMajorVersionUpper != 2)
326   {
327     myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs3);
328   }
329   if ((EGLContext )myEglContext == EGL_NO_CONTEXT)
330   {
331     myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs2);
332   }
333 #else
334   EGLint* anEglCtxAttribs = NULL;
335   if (eglBindAPI (EGL_OPENGL_API) != EGL_TRUE)
336   {
337     ::Message::SendFail ("Error: EGL does not provide OpenGL client");
338     return Standard_False;
339   }
340   myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs);
341 #endif
342
343   if ((EGLContext )myEglContext == EGL_NO_CONTEXT)
344   {
345     ::Message::SendFail ("Error: EGL is unable to create OpenGL context");
346     return Standard_False;
347   }
348   // eglMakeCurrent() fails or even crash with EGL_NO_SURFACE on some implementations
349   //if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, (EGLContext )myEglContext) != EGL_TRUE)
350   //{
351   //  ::Message::SendFail ("Error: EGL is unable bind OpenGL context");
352   //  return Standard_False;
353   //}
354 #endif
355   chooseVisualInfo();
356   myIsOwnContext = Standard_True;
357   return Standard_True;
358 }
359
360 // =======================================================================
361 // function : InitEglContext
362 // purpose  :
363 // =======================================================================
364 Standard_Boolean OpenGl_GraphicDriver::InitEglContext (Aspect_Display          theEglDisplay,
365                                                        Aspect_RenderingContext theEglContext,
366                                                        void*                   theEglConfig)
367 {
368   ReleaseContext();
369 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
370 #if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
371   if (myDisplayConnection.IsNull())
372   {
373     return Standard_False;
374   }
375 #endif
376
377   if ((EGLDisplay )theEglDisplay == EGL_NO_DISPLAY
378    || (EGLContext )theEglContext == EGL_NO_CONTEXT)
379   {
380     return Standard_False;
381   }
382   myEglDisplay = theEglDisplay;
383   myEglContext = theEglContext;
384   myEglConfig  = theEglConfig;
385   if (theEglConfig == NULL)
386   {
387     myEglConfig = chooseEglSurfConfig ((EGLDisplay )myEglDisplay);
388     if (myEglConfig == NULL)
389     {
390       ::Message::SendFail ("Error: EGL does not provide compatible configurations");
391       return Standard_False;
392     }
393   }
394   chooseVisualInfo();
395   return Standard_True;
396 #else
397   (void )theEglDisplay;
398   (void )theEglContext;
399   (void )theEglConfig;
400   throw Standard_NotImplemented ("OpenGl_GraphicDriver::InitEglContext() is not implemented");
401 #endif
402 }
403
404 // =======================================================================
405 // function : chooseVisualInfo
406 // purpose  :
407 // =======================================================================
408 void OpenGl_GraphicDriver::chooseVisualInfo()
409 {
410   if (myDisplayConnection.IsNull())
411   {
412     return;
413   }
414
415 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
416   Display* aDisp = myDisplayConnection->GetDisplay();
417
418   XVisualInfo* aVisInfo = NULL;
419   Aspect_FBConfig anFBConfig = NULL;
420 #if defined(HAVE_EGL) || defined(HAVE_GLES2)
421   XVisualInfo aVisInfoTmp;
422   memset (&aVisInfoTmp, 0, sizeof(aVisInfoTmp));
423   aVisInfoTmp.screen = DefaultScreen (aDisp);
424   if (myEglDisplay != EGL_NO_DISPLAY
425    && myEglConfig != NULL
426    && eglGetConfigAttrib ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NATIVE_VISUAL_ID, (EGLint* )&aVisInfoTmp.visualid) == EGL_TRUE)
427   {
428     int aNbVisuals = 0;
429     aVisInfo = XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfoTmp, &aNbVisuals);
430   }
431 #else
432   int aScreen = DefaultScreen(aDisp);
433   int aDummy = 0;
434   if (!XQueryExtension (aDisp, "GLX", &aDummy, &aDummy, &aDummy)
435    || !glXQueryExtension (aDisp, &aDummy, &aDummy))
436   {
437     Message::SendFail ("Error: OpenGl_GraphicDriver, GLX extension is unavailable");
438   }
439
440   // FBConfigs were added in GLX version 1.3
441   int aGlxMajor = 0, aGlxMinor = 0;
442   const bool hasFBCfg = glXQueryVersion (aDisp, &aGlxMajor, &aGlxMinor)
443                      && ((aGlxMajor == 1 && aGlxMinor >= 3) || (aGlxMajor > 1));
444   if (hasFBCfg)
445   {
446     int aFBCount = 0;
447     GLXFBConfig* aFBCfgList = NULL;
448     if (hasFBCfg)
449     {
450       aFBCfgList = glXChooseFBConfig (aDisp, aScreen, TheDoubleBuffFBConfig, &aFBCount);
451     }
452     if(aFBCfgList != NULL
453     && aFBCount >= 1)
454     {
455       anFBConfig = aFBCfgList[0];
456       aVisInfo   = glXGetVisualFromFBConfig (aDisp, anFBConfig);
457
458       /*int aDepthSize = 0, aStencilSize = 0;
459       glXGetFBConfigAttrib (aDisp, anFBConfig, GLX_DEPTH_SIZE, &aDepthSize);
460       glXGetFBConfigAttrib (aDisp, anFBConfig, GLX_STENCIL_SIZE, &aStencilSize);
461       Message::SendInfo() << "GLX FBConfig:"
462                           << "\n  DepthSize= " << aDepthSize
463                           << "\n  StencilSize= " << aStencilSize;*/
464     }
465     XFree (aFBCfgList);
466   }
467
468   if (aVisInfo == NULL)
469   {
470     aVisInfo = glXChooseVisual (aDisp, aScreen, TheDoubleBuffVisual);
471   }
472 #endif
473   if (aVisInfo != NULL)
474   {
475     myDisplayConnection->SetDefaultVisualInfo (aVisInfo, anFBConfig);
476   }
477   else
478   {
479     Message::SendWarning ("OpenGl_GraphicDriver, couldn't find compatible Visual (RGBA, double-buffered)");
480   }
481 #endif
482 }
483
484 // =======================================================================
485 // function : InquireLimit
486 // purpose  :
487 // =======================================================================
488 Standard_Integer OpenGl_GraphicDriver::InquireLimit (const Graphic3d_TypeOfLimit theType) const
489 {
490   const Handle(OpenGl_Context)& aCtx = GetSharedContext();
491   switch (theType)
492   {
493     case Graphic3d_TypeOfLimit_MaxNbLights:
494       return Graphic3d_ShaderProgram::THE_MAX_LIGHTS_DEFAULT;
495     case Graphic3d_TypeOfLimit_MaxNbClipPlanes:
496       return !aCtx.IsNull() ? aCtx->MaxClipPlanes() : 0;
497     case Graphic3d_TypeOfLimit_MaxNbViews:
498       return 10000;
499     case Graphic3d_TypeOfLimit_MaxTextureSize:
500       return !aCtx.IsNull() ? aCtx->MaxTextureSize() : 1024;
501     case Graphic3d_TypeOfLimit_MaxCombinedTextureUnits:
502       return !aCtx.IsNull() ? aCtx->MaxCombinedTextureUnits() : 1;
503     case Graphic3d_TypeOfLimit_MaxMsaa:
504       return !aCtx.IsNull() ? aCtx->MaxMsaaSamples() : 0;
505     case Graphic3d_TypeOfLimit_MaxViewDumpSizeX:
506       return !aCtx.IsNull() ? aCtx->MaxDumpSizeX() : 1024;
507     case Graphic3d_TypeOfLimit_MaxViewDumpSizeY:
508       return !aCtx.IsNull() ? aCtx->MaxDumpSizeY() : 1024;
509     case Graphic3d_TypeOfLimit_HasPBR:
510       return (!aCtx.IsNull() && aCtx->HasPBR()) ? 1 : 0;
511     case Graphic3d_TypeOfLimit_HasRayTracing:
512       return (!aCtx.IsNull() && aCtx->HasRayTracing()) ? 1 : 0;
513     case Graphic3d_TypeOfLimit_HasRayTracingTextures:
514       return (!aCtx.IsNull() && aCtx->HasRayTracingTextures()) ? 1 : 0;
515     case Graphic3d_TypeOfLimit_HasRayTracingAdaptiveSampling:
516       return (!aCtx.IsNull() && aCtx->HasRayTracingAdaptiveSampling()) ? 1 : 0;
517     case Graphic3d_TypeOfLimit_HasRayTracingAdaptiveSamplingAtomic:
518       return (!aCtx.IsNull() && aCtx->HasRayTracingAdaptiveSamplingAtomic()) ? 1 : 0;
519     case Graphic3d_TypeOfLimit_HasSRGB:
520       return (!aCtx.IsNull() && aCtx->HasSRGB()) ? 1 : 0;
521     case Graphic3d_TypeOfLimit_HasBlendedOit:
522       return (!aCtx.IsNull()
523             && aCtx->hasDrawBuffers != OpenGl_FeatureNotAvailable
524             && (aCtx->hasFloatBuffer != OpenGl_FeatureNotAvailable || aCtx->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable)) ? 1 : 0;
525     case Graphic3d_TypeOfLimit_HasBlendedOitMsaa:
526       return (!aCtx.IsNull()
527             && aCtx->hasSampleVariables != OpenGl_FeatureNotAvailable
528             && (InquireLimit (Graphic3d_TypeOfLimit_HasBlendedOit) == 1)) ? 1 : 0;
529     case Graphic3d_TypeOfLimit_HasFlatShading:
530       return !aCtx.IsNull() && aCtx->hasFlatShading != OpenGl_FeatureNotAvailable ? 1 : 0;
531     case Graphic3d_TypeOfLimit_IsWorkaroundFBO:
532       return !aCtx.IsNull() && aCtx->MaxTextureSize() != aCtx->MaxDumpSizeX() ? 1 : 0;
533     case Graphic3d_TypeOfLimit_HasMeshEdges:
534       return !aCtx.IsNull() && aCtx->hasGeometryStage != OpenGl_FeatureNotAvailable ? 1 : 0;
535     case Graphic3d_TypeOfLimit_NB:
536       return 0;
537   }
538   return 0;
539 }
540
541 // =======================================================================
542 // function : DefaultTextHeight
543 // purpose  :
544 // =======================================================================
545 Standard_ShortReal OpenGl_GraphicDriver::DefaultTextHeight() const
546 {
547   return 16.;
548 }
549
550 // =======================================================================
551 // function : EnableVBO
552 // purpose  :
553 // =======================================================================
554 void OpenGl_GraphicDriver::EnableVBO (const Standard_Boolean theToTurnOn)
555 {
556   myCaps->vboDisable = !theToTurnOn;
557 }
558
559 // =======================================================================
560 // function : IsVerticalSync
561 // purpose  :
562 // =======================================================================
563 bool OpenGl_GraphicDriver::IsVerticalSync() const
564 {
565   return myCaps->swapInterval == 1;
566 }
567
568 // =======================================================================
569 // function : SetVerticalSync
570 // purpose  :
571 // =======================================================================
572 void OpenGl_GraphicDriver::SetVerticalSync (bool theToEnable)
573 {
574   myCaps->swapInterval = theToEnable ? 1 : 0;
575 }
576
577 // =======================================================================
578 // function : GetSharedContext
579 // purpose  :
580 // =======================================================================
581 const Handle(OpenGl_Context)& OpenGl_GraphicDriver::GetSharedContext (bool theBound) const
582 {
583   if (myMapOfView.IsEmpty())
584   {
585     return TheNullGlCtx;
586   }
587
588   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView); aViewIter.More(); aViewIter.Next())
589   {
590     if (const Handle(OpenGl_Window)& aWindow = aViewIter.Value()->GlWindow())
591     {
592       if (!theBound)
593       {
594         return aWindow->GetGlContext();
595       }
596       else if (aWindow->GetGlContext()->IsCurrent())
597       {
598         return aWindow->GetGlContext();
599       }
600     }
601   }
602
603   return TheNullGlCtx;
604 }
605
606 // =======================================================================
607 // function : MemoryInfo
608 // purpose  :
609 // =======================================================================
610 Standard_Boolean OpenGl_GraphicDriver::MemoryInfo (Standard_Size&           theFreeBytes,
611                                                    TCollection_AsciiString& theInfo) const
612 {
613   // this is extra work (for OpenGl_Context initialization)...
614   OpenGl_Context aGlCtx;
615   if (!aGlCtx.Init())
616   {
617     return Standard_False;
618   }
619   theFreeBytes = aGlCtx.AvailableMemory();
620   theInfo      = aGlCtx.MemoryInfo();
621   return !theInfo.IsEmpty();
622 }
623
624 // =======================================================================
625 // function : SetBuffersNoSwap
626 // purpose  :
627 // =======================================================================
628 void OpenGl_GraphicDriver::SetBuffersNoSwap (const Standard_Boolean theIsNoSwap)
629 {
630   myCaps->buffersNoSwap = theIsNoSwap;
631 }
632
633 // =======================================================================
634 // function : TextSize
635 // purpose  :
636 // =======================================================================
637 void OpenGl_GraphicDriver::TextSize (const Handle(Graphic3d_CView)& theView,
638                                      const Standard_CString         theText,
639                                      const Standard_ShortReal       theHeight,
640                                      Standard_ShortReal&            theWidth,
641                                      Standard_ShortReal&            theAscent,
642                                      Standard_ShortReal&            theDescent) const
643 {
644   const Handle(OpenGl_Context)& aCtx = GetSharedContext();
645   if (aCtx.IsNull())
646   {
647     return;
648   }
649
650   const Standard_ShortReal aHeight = (theHeight < 2.0f) ? DefaultTextHeight() : theHeight;
651   OpenGl_Aspects aTextAspect;
652   TCollection_ExtendedString anExtText = theText;
653   NCollection_String aText (anExtText.ToExtString());
654   OpenGl_Text::StringSize (aCtx, aText, aTextAspect, aHeight,
655                            theView->RenderingParams().Resolution, theView->RenderingParams().FontHinting,
656                            theWidth, theAscent, theDescent);
657 }
658
659 //=======================================================================
660 //function : InsertLayerBefore
661 //purpose  :
662 //=======================================================================
663 void OpenGl_GraphicDriver::InsertLayerBefore (const Graphic3d_ZLayerId theLayerId,
664                                               const Graphic3d_ZLayerSettings& theSettings,
665                                               const Graphic3d_ZLayerId theLayerAfter)
666 {
667   base_type::InsertLayerBefore (theLayerId, theSettings, theLayerAfter);
668
669   // Add layer to all views
670   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next())
671   {
672     aViewIt.Value()->InsertLayerBefore (theLayerId, theSettings, theLayerAfter);
673   }
674 }
675
676 //=======================================================================
677 //function : InsertLayerAfter
678 //purpose  :
679 //=======================================================================
680 void OpenGl_GraphicDriver::InsertLayerAfter (const Graphic3d_ZLayerId theNewLayerId,
681                                              const Graphic3d_ZLayerSettings& theSettings,
682                                              const Graphic3d_ZLayerId theLayerBefore)
683 {
684   base_type::InsertLayerAfter (theNewLayerId, theSettings, theLayerBefore);
685
686   // Add layer to all views
687   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next())
688   {
689     aViewIt.Value()->InsertLayerAfter (theNewLayerId, theSettings, theLayerBefore);
690   }
691 }
692
693 //=======================================================================
694 //function : RemoveZLayer
695 //purpose  :
696 //=======================================================================
697 void OpenGl_GraphicDriver::RemoveZLayer (const Graphic3d_ZLayerId theLayerId)
698 {
699   base_type::RemoveZLayer (theLayerId);
700
701   // Remove layer from all of the views
702   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next())
703   {
704     aViewIt.Value()->RemoveZLayer (theLayerId);
705   }
706
707   // Unset Z layer for all of the structures.
708   for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure); aStructIt.More(); aStructIt.Next())
709   {
710     OpenGl_Structure* aStruct = aStructIt.ChangeValue ();
711     if (aStruct->ZLayer() == theLayerId)
712       aStruct->SetZLayer (Graphic3d_ZLayerId_Default);
713   }
714 }
715
716 //=======================================================================
717 //function : SetZLayerSettings
718 //purpose  :
719 //=======================================================================
720 void OpenGl_GraphicDriver::SetZLayerSettings (const Graphic3d_ZLayerId theLayerId,
721                                               const Graphic3d_ZLayerSettings& theSettings)
722 {
723   base_type::SetZLayerSettings (theLayerId, theSettings);
724
725   // Change Z layer settings in all managed views
726   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next())
727   {
728     aViewIt.Value()->SetZLayerSettings (theLayerId, theSettings);
729   }
730 }
731
732 // =======================================================================
733 // function : Structure
734 // purpose  :
735 // =======================================================================
736 Handle(Graphic3d_CStructure) OpenGl_GraphicDriver::CreateStructure (const Handle(Graphic3d_StructureManager)& theManager)
737 {
738   Handle(OpenGl_Structure) aStructure = new OpenGl_Structure (theManager);
739   myMapOfStructure.Bind (aStructure->Id, aStructure.operator->());
740   return aStructure;
741 }
742
743 // =======================================================================
744 // function : Structure
745 // purpose  :
746 // =======================================================================
747 void OpenGl_GraphicDriver::RemoveStructure (Handle(Graphic3d_CStructure)& theCStructure)
748 {
749   OpenGl_Structure* aStructure = NULL;
750   if (!myMapOfStructure.Find (theCStructure->Id, aStructure))
751   {
752     return;
753   }
754
755   myMapOfStructure.UnBind (theCStructure->Id);
756   aStructure->Release (GetSharedContext());
757   theCStructure.Nullify();
758 }
759
760 // =======================================================================
761 // function : CreateView
762 // purpose  :
763 // =======================================================================
764 Handle(Graphic3d_CView) OpenGl_GraphicDriver::CreateView (const Handle(Graphic3d_StructureManager)& theMgr)
765 {
766   Handle(OpenGl_View) aView = new OpenGl_View (theMgr, this, myCaps, &myStateCounter);
767   myMapOfView.Add (aView);
768   for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (myLayers); aLayerIter.More(); aLayerIter.Next())
769   {
770     const Handle(Graphic3d_Layer)& aLayer = aLayerIter.Value();
771     aView->InsertLayerAfter (aLayer->LayerId(), aLayer->LayerSettings(), Graphic3d_ZLayerId_UNKNOWN);
772   }
773   return aView;
774 }
775
776 // =======================================================================
777 // function : RemoveView
778 // purpose  :
779 // =======================================================================
780 void OpenGl_GraphicDriver::RemoveView (const Handle(Graphic3d_CView)& theView)
781 {
782   Handle(OpenGl_Context) aCtx = GetSharedContext();
783   Handle(OpenGl_View) aView   = Handle(OpenGl_View)::DownCast (theView);
784   if (aView.IsNull())
785   {
786     return;
787   }
788
789   if (!myMapOfView.Remove (aView))
790   {
791     return;
792   }
793
794   Handle(OpenGl_Window) aWindow = aView->GlWindow();
795   if (!aWindow.IsNull()
796     && aWindow->GetGlContext()->MakeCurrent())
797   {
798     aCtx = aWindow->GetGlContext();
799   }
800   else
801   {
802     // try to hijack another context if any
803     const Handle(OpenGl_Context)& anOtherCtx = GetSharedContext();
804     if (!anOtherCtx.IsNull()
805       && anOtherCtx != aWindow->GetGlContext())
806     {
807       aCtx = anOtherCtx;
808       aCtx->MakeCurrent();
809     }
810   }
811
812   aView->ReleaseGlResources (aCtx);
813   if (myMapOfView.IsEmpty())
814   {
815     // The last view removed but some objects still present.
816     // Release GL resources now without object destruction.
817     for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
818          aStructIt.More (); aStructIt.Next())
819     {
820       OpenGl_Structure* aStruct = aStructIt.ChangeValue();
821       aStruct->ReleaseGlResources (aCtx);
822     }
823
824     if (!myMapOfStructure.IsEmpty())
825     {
826       aView->StructureManager()->SetDeviceLost();
827     }
828   }
829 }
830
831 // =======================================================================
832 // function : Window
833 // purpose  :
834 // =======================================================================
835 Handle(OpenGl_Window) OpenGl_GraphicDriver::CreateRenderWindow (const Handle(Aspect_Window)&  theWindow,
836                                                                 const Aspect_RenderingContext theContext)
837 {
838   Handle(OpenGl_Context) aShareCtx = GetSharedContext();
839   Handle(OpenGl_Window) aWindow = new OpenGl_Window (this, theWindow, theContext, myCaps, aShareCtx);
840   return aWindow;
841 }
842
843 //=======================================================================
844 //function : ViewExists
845 //purpose  :
846 //=======================================================================
847 Standard_Boolean OpenGl_GraphicDriver::ViewExists (const Handle(Aspect_Window)& AWindow, Handle(Graphic3d_CView)& theView)
848 {
849   Standard_Boolean isExist = Standard_False;
850
851   // Parse the list of views to find
852   // a view with the specified window
853
854 #if defined(_WIN32) && !defined(OCCT_UWP)
855   const Handle(WNT_Window) THEWindow = Handle(WNT_Window)::DownCast (AWindow);
856   Aspect_Handle TheSpecifiedWindowId = THEWindow->HWindow ();
857 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
858   const Handle(Cocoa_Window) THEWindow = Handle(Cocoa_Window)::DownCast (AWindow);
859   #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
860     UIView* TheSpecifiedWindowId = THEWindow->HView();
861   #else
862     NSView* TheSpecifiedWindowId = THEWindow->HView();
863   #endif
864 #elif defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(OCCT_UWP)
865   (void )AWindow;
866   int TheSpecifiedWindowId = -1;
867 #else
868   const Handle(Xw_Window) THEWindow = Handle(Xw_Window)::DownCast (AWindow);
869   int TheSpecifiedWindowId = int (THEWindow->XWindow ());
870 #endif
871
872   NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView);
873   for(; aViewIt.More(); aViewIt.Next())
874   {
875     const Handle(OpenGl_View)& aView = aViewIt.Value();
876     if (aView->IsDefined() && aView->IsActive())
877     {
878       const Handle(Aspect_Window) AspectWindow = aView->Window();
879
880 #if defined(_WIN32) && !defined(OCCT_UWP)
881       const Handle(WNT_Window) theWindow = Handle(WNT_Window)::DownCast (AspectWindow);
882       Aspect_Handle TheWindowIdOfView = theWindow->HWindow ();
883 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
884       const Handle(Cocoa_Window) theWindow = Handle(Cocoa_Window)::DownCast (AspectWindow);
885       #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
886         UIView* TheWindowIdOfView = theWindow->HView();
887       #else
888         NSView* TheWindowIdOfView = theWindow->HView();
889       #endif
890 #elif defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(OCCT_UWP)
891       int TheWindowIdOfView = 0;
892 #else
893       const Handle(Xw_Window) theWindow = Handle(Xw_Window)::DownCast (AspectWindow);
894       int TheWindowIdOfView = int (theWindow->XWindow ());
895 #endif  // WNT
896       // Comparaison on window IDs
897       if (TheWindowIdOfView == TheSpecifiedWindowId)
898       {
899         isExist = Standard_True;
900         theView = aView;
901       }
902     }
903   }
904
905   return isExist;
906 }
907
908 //=======================================================================
909 //function : setDeviceLost
910 //purpose  :
911 //=======================================================================
912 void OpenGl_GraphicDriver::setDeviceLost()
913 {
914   if (myMapOfStructure.IsEmpty())
915   {
916     return;
917   }
918
919   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView); aViewIter.More(); aViewIter.Next())
920   {
921     const Handle(OpenGl_View)& aView = aViewIter.Value();
922     if (aView->myWasRedrawnGL)
923     {
924       aView->StructureManager()->SetDeviceLost();
925     }
926   }
927 }