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