0029570: Visualization, Graphic3d_Aspect - merge Graphic3d_Group aspects
[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_HasMeshEdges:
469       return !aCtx.IsNull() && aCtx->hasGeometryStage != OpenGl_FeatureNotAvailable ? 1 : 0;
470     case Graphic3d_TypeOfLimit_NB:
471       return 0;
472   }
473   return 0;
474 }
475
476 // =======================================================================
477 // function : DefaultTextHeight
478 // purpose  :
479 // =======================================================================
480 Standard_ShortReal OpenGl_GraphicDriver::DefaultTextHeight() const
481 {
482   return 16.;
483 }
484
485 // =======================================================================
486 // function : EnableVBO
487 // purpose  :
488 // =======================================================================
489 void OpenGl_GraphicDriver::EnableVBO (const Standard_Boolean theToTurnOn)
490 {
491   myCaps->vboDisable = !theToTurnOn;
492 }
493
494 // =======================================================================
495 // function : GetSharedContext
496 // purpose  :
497 // =======================================================================
498 const Handle(OpenGl_Context)& OpenGl_GraphicDriver::GetSharedContext() const
499 {
500   if (myMapOfView.IsEmpty())
501   {
502     return TheNullGlCtx;
503   }
504
505   NCollection_Map<Handle(OpenGl_View)>::Iterator anIter (myMapOfView);
506   for (; anIter.More(); anIter.Next())
507   {
508     Handle(OpenGl_Window) aWindow = anIter.Value()->GlWindow();
509     if (aWindow.IsNull())
510     {
511       continue;
512     }
513
514     return aWindow->GetGlContext();
515   }
516
517   return TheNullGlCtx;
518 }
519
520 // =======================================================================
521 // function : MemoryInfo
522 // purpose  :
523 // =======================================================================
524 Standard_Boolean OpenGl_GraphicDriver::MemoryInfo (Standard_Size&           theFreeBytes,
525                                                    TCollection_AsciiString& theInfo) const
526 {
527   // this is extra work (for OpenGl_Context initialization)...
528   OpenGl_Context aGlCtx;
529   if (!aGlCtx.Init())
530   {
531     return Standard_False;
532   }
533   theFreeBytes = aGlCtx.AvailableMemory();
534   theInfo      = aGlCtx.MemoryInfo();
535   return !theInfo.IsEmpty();
536 }
537
538 // =======================================================================
539 // function : SetBuffersNoSwap
540 // purpose  :
541 // =======================================================================
542 void OpenGl_GraphicDriver::SetBuffersNoSwap (const Standard_Boolean theIsNoSwap)
543 {
544   myCaps->buffersNoSwap = theIsNoSwap;
545 }
546
547 // =======================================================================
548 // function : TextSize
549 // purpose  :
550 // =======================================================================
551 void OpenGl_GraphicDriver::TextSize (const Handle(Graphic3d_CView)& theView,
552                                      const Standard_CString         theText,
553                                      const Standard_ShortReal       theHeight,
554                                      Standard_ShortReal&            theWidth,
555                                      Standard_ShortReal&            theAscent,
556                                      Standard_ShortReal&            theDescent) const
557 {
558   const Handle(OpenGl_Context)& aCtx = GetSharedContext();
559   if (aCtx.IsNull())
560   {
561     return;
562   }
563
564   const Standard_ShortReal aHeight = (theHeight < 2.0f) ? DefaultTextHeight() : theHeight;
565   OpenGl_TextParam aTextParam;
566   aTextParam.Height = (int )aHeight;
567   OpenGl_Aspects aTextAspect;
568   TCollection_ExtendedString anExtText = theText;
569   NCollection_String aText (anExtText.ToExtString());
570   OpenGl_Text::StringSize(aCtx, aText, aTextAspect, aTextParam, theView->RenderingParams().Resolution, theWidth, theAscent, theDescent);
571 }
572
573 //=======================================================================
574 //function : addZLayerIndex
575 //purpose  :
576 //=======================================================================
577 void OpenGl_GraphicDriver::addZLayerIndex (const Graphic3d_ZLayerId theLayerId)
578 {
579   // remove index
580   for (TColStd_SequenceOfInteger::Iterator aLayerIt (myLayerSeq); aLayerIt.More(); aLayerIt.Next())
581   {
582     if (aLayerIt.Value() == theLayerId)
583     {
584       myLayerSeq.Remove (aLayerIt);
585       break;
586     }
587   }
588
589   if (myMapOfZLayerSettings.Find (theLayerId).IsImmediate())
590   {
591     myLayerSeq.Append (theLayerId);
592     return;
593   }
594
595   for (TColStd_SequenceOfInteger::Iterator aLayerIt (myLayerSeq); aLayerIt.More(); aLayerIt.Next())
596   {
597     const Graphic3d_ZLayerSettings& aSettings = myMapOfZLayerSettings.Find (aLayerIt.Value());
598     if (aSettings.IsImmediate())
599     {
600       aLayerIt.Previous();
601       if (aLayerIt.More())
602       {
603         myLayerSeq.InsertAfter (aLayerIt, theLayerId);
604         return;
605       }
606
607       // first non-immediate layer
608       myLayerSeq.Prepend (theLayerId);
609       return;
610     }
611   }
612
613   // no immediate layers
614   myLayerSeq.Append (theLayerId);
615 }
616
617 //=======================================================================
618 //function : AddZLayer
619 //purpose  :
620 //=======================================================================
621 void OpenGl_GraphicDriver::AddZLayer (const Graphic3d_ZLayerId theLayerId)
622 {
623   if (theLayerId < 1)
624   {
625     Standard_ASSERT_RAISE (theLayerId > 0,
626                            "OpenGl_GraphicDriver::AddZLayer, "
627                            "negative and zero IDs are reserved");
628   }
629
630   myLayerIds.Add (theLayerId);
631
632   // Default z-layer settings
633   myMapOfZLayerSettings.Bind (theLayerId, Graphic3d_ZLayerSettings());
634   addZLayerIndex (theLayerId);
635
636   // Add layer to all views
637   NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView);
638   for (; aViewIt.More(); aViewIt.Next())
639   {
640     aViewIt.Value()->AddZLayer (theLayerId);
641   }
642 }
643
644 //=======================================================================
645 //function : RemoveZLayer
646 //purpose  :
647 //=======================================================================
648 void OpenGl_GraphicDriver::RemoveZLayer (const Graphic3d_ZLayerId theLayerId)
649 {
650   Standard_ASSERT_RAISE (theLayerId > 0,
651                          "OpenGl_GraphicDriver::AddZLayer, "
652                          "negative and zero IDs are reserved"
653                          "and can not be removed");
654
655   Standard_ASSERT_RAISE (myLayerIds.Contains (theLayerId),
656                          "OpenGl_GraphicDriver::RemoveZLayer, "
657                          "Layer with theLayerId does not exist");
658
659   // Remove layer from all of the views
660   NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView);
661   for (; aViewIt.More(); aViewIt.Next())
662   {
663     aViewIt.Value()->RemoveZLayer (theLayerId);
664   }
665
666   // Unset Z layer for all of the structures.
667   NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
668   for( ; aStructIt.More (); aStructIt.Next ())
669   {
670     OpenGl_Structure* aStruct = aStructIt.ChangeValue ();
671     if (aStruct->ZLayer() == theLayerId)
672       aStruct->SetZLayer (Graphic3d_ZLayerId_Default);
673   }
674
675   // Remove index
676   for (TColStd_SequenceOfInteger::Iterator aLayerIt (myLayerSeq); aLayerIt.More(); aLayerIt.Next())
677   {
678     if (aLayerIt.Value() == theLayerId)
679     {
680       myLayerSeq.Remove (aLayerIt);
681       break;
682     }
683   }
684
685   myMapOfZLayerSettings.UnBind (theLayerId);
686   myLayerIds.Remove  (theLayerId);
687 }
688
689 //=======================================================================
690 //function : ZLayers
691 //purpose  :
692 //=======================================================================
693 void OpenGl_GraphicDriver::ZLayers (TColStd_SequenceOfInteger& theLayerSeq) const
694 {
695   theLayerSeq.Assign (myLayerSeq);
696 }
697
698 //=======================================================================
699 //function : SetZLayerSettings
700 //purpose  :
701 //=======================================================================
702 void OpenGl_GraphicDriver::SetZLayerSettings (const Graphic3d_ZLayerId theLayerId,
703                                               const Graphic3d_ZLayerSettings& theSettings)
704 {
705   Graphic3d_ZLayerSettings* aSettings = myMapOfZLayerSettings.ChangeSeek (theLayerId);
706   if (aSettings != NULL)
707   {
708     const bool isChanged = (aSettings->IsImmediate() != theSettings.IsImmediate());
709     *aSettings = theSettings;
710     if (isChanged)
711     {
712       addZLayerIndex (theLayerId);
713     }
714   }
715   else
716   {
717     // abnormal case
718     myMapOfZLayerSettings.Bind (theLayerId, theSettings);
719     addZLayerIndex (theLayerId);
720   }
721
722   // Change Z layer settings in all managed views
723   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next())
724   {
725     aViewIt.Value()->SetZLayerSettings (theLayerId, theSettings);
726   }
727 }
728
729 //=======================================================================
730 //function : ZLayerSettings
731 //purpose  :
732 //=======================================================================
733 const Graphic3d_ZLayerSettings& OpenGl_GraphicDriver::ZLayerSettings (const Graphic3d_ZLayerId theLayerId) const
734 {
735   Standard_ASSERT_RAISE (myLayerIds.Contains (theLayerId),
736                          "OpenGl_GraphicDriver::ZLayerSettings, "
737                          "Layer with theLayerId does not exist");
738
739   return myMapOfZLayerSettings.Find (theLayerId);
740 }
741
742 // =======================================================================
743 // function : Structure
744 // purpose  :
745 // =======================================================================
746 Handle(Graphic3d_CStructure) OpenGl_GraphicDriver::CreateStructure (const Handle(Graphic3d_StructureManager)& theManager)
747 {
748   Handle(OpenGl_Structure) aStructure = new OpenGl_Structure (theManager);
749   myMapOfStructure.Bind (aStructure->Id, aStructure.operator->());
750   return aStructure;
751 }
752
753 // =======================================================================
754 // function : Structure
755 // purpose  :
756 // =======================================================================
757 void OpenGl_GraphicDriver::RemoveStructure (Handle(Graphic3d_CStructure)& theCStructure)
758 {
759   OpenGl_Structure* aStructure = NULL;
760   if (!myMapOfStructure.Find (theCStructure->Id, aStructure))
761   {
762     return;
763   }
764
765   myMapOfStructure.UnBind (theCStructure->Id);
766   aStructure->Release (GetSharedContext());
767   theCStructure.Nullify();
768 }
769
770 // =======================================================================
771 // function : View
772 // purpose  :
773 // =======================================================================
774 Handle(Graphic3d_CView) OpenGl_GraphicDriver::CreateView (const Handle(Graphic3d_StructureManager)& theMgr)
775 {
776   Handle(OpenGl_View) aView = new OpenGl_View (theMgr, this, myCaps, &myStateCounter);
777
778   myMapOfView.Add (aView);
779
780   for (TColStd_SequenceOfInteger::Iterator aLayerIt (myLayerSeq); aLayerIt.More(); aLayerIt.Next())
781   {
782     const Graphic3d_ZLayerId        aLayerID  = aLayerIt.Value();
783     const Graphic3d_ZLayerSettings& aSettings = myMapOfZLayerSettings.Find (aLayerID);
784     aView->AddZLayer         (aLayerID);
785     aView->SetZLayerSettings (aLayerID, aSettings);
786   }
787
788   return aView;
789 }
790
791 // =======================================================================
792 // function : RemoveView
793 // purpose  :
794 // =======================================================================
795 void OpenGl_GraphicDriver::RemoveView (const Handle(Graphic3d_CView)& theView)
796 {
797   Handle(OpenGl_Context) aCtx = GetSharedContext();
798   Handle(OpenGl_View) aView   = Handle(OpenGl_View)::DownCast (theView);
799   if (aView.IsNull())
800   {
801     return;
802   }
803
804   if (!myMapOfView.Remove (aView))
805   {
806     return;
807   }
808
809   Handle(OpenGl_Window) aWindow = aView->GlWindow();
810   if (!aWindow.IsNull()
811     && aWindow->GetGlContext()->MakeCurrent())
812   {
813     aCtx = aWindow->GetGlContext();
814   }
815   else
816   {
817     // try to hijack another context if any
818     const Handle(OpenGl_Context)& anOtherCtx = GetSharedContext();
819     if (!anOtherCtx.IsNull()
820       && anOtherCtx != aWindow->GetGlContext())
821     {
822       aCtx = anOtherCtx;
823       aCtx->MakeCurrent();
824     }
825   }
826
827   aView->ReleaseGlResources (aCtx);
828   if (myMapOfView.IsEmpty())
829   {
830     // The last view removed but some objects still present.
831     // Release GL resources now without object destruction.
832     for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
833          aStructIt.More (); aStructIt.Next())
834     {
835       OpenGl_Structure* aStruct = aStructIt.ChangeValue();
836       aStruct->ReleaseGlResources (aCtx);
837     }
838
839     if (!myMapOfStructure.IsEmpty())
840     {
841       aView->StructureManager()->SetDeviceLost();
842     }
843   }
844 }
845
846 // =======================================================================
847 // function : Window
848 // purpose  :
849 // =======================================================================
850 Handle(OpenGl_Window) OpenGl_GraphicDriver::CreateRenderWindow (const Handle(Aspect_Window)&  theWindow,
851                                                                 const Aspect_RenderingContext theContext)
852 {
853   Handle(OpenGl_Context) aShareCtx = GetSharedContext();
854   Handle(OpenGl_Window) aWindow = new OpenGl_Window (this, theWindow, theContext, myCaps, aShareCtx);
855   return aWindow;
856 }
857
858 //=======================================================================
859 //function : ViewExists
860 //purpose  :
861 //=======================================================================
862 Standard_Boolean OpenGl_GraphicDriver::ViewExists (const Handle(Aspect_Window)& AWindow, Handle(Graphic3d_CView)& theView)
863 {
864   Standard_Boolean isExist = Standard_False;
865
866   // Parse the list of views to find
867   // a view with the specified window
868
869 #if defined(_WIN32) && !defined(OCCT_UWP)
870   const Handle(WNT_Window) THEWindow = Handle(WNT_Window)::DownCast (AWindow);
871   Aspect_Handle TheSpecifiedWindowId = THEWindow->HWindow ();
872 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
873   const Handle(Cocoa_Window) THEWindow = Handle(Cocoa_Window)::DownCast (AWindow);
874   #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
875     UIView* TheSpecifiedWindowId = THEWindow->HView();
876   #else
877     NSView* TheSpecifiedWindowId = THEWindow->HView();
878   #endif
879 #elif defined(__ANDROID__) || defined(__QNX__) || defined(OCCT_UWP)
880   (void )AWindow;
881   int TheSpecifiedWindowId = -1;
882 #else
883   const Handle(Xw_Window) THEWindow = Handle(Xw_Window)::DownCast (AWindow);
884   int TheSpecifiedWindowId = int (THEWindow->XWindow ());
885 #endif
886
887   NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView);
888   for(; aViewIt.More(); aViewIt.Next())
889   {
890     const Handle(OpenGl_View)& aView = aViewIt.Value();
891     if (aView->IsDefined() && aView->IsActive())
892     {
893       const Handle(Aspect_Window) AspectWindow = aView->Window();
894
895 #if defined(_WIN32) && !defined(OCCT_UWP)
896       const Handle(WNT_Window) theWindow = Handle(WNT_Window)::DownCast (AspectWindow);
897       Aspect_Handle TheWindowIdOfView = theWindow->HWindow ();
898 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
899       const Handle(Cocoa_Window) theWindow = Handle(Cocoa_Window)::DownCast (AspectWindow);
900       #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
901         UIView* TheWindowIdOfView = theWindow->HView();
902       #else
903         NSView* TheWindowIdOfView = theWindow->HView();
904       #endif
905 #elif defined(__ANDROID__) || defined(__QNX__) || defined(OCCT_UWP)
906       int TheWindowIdOfView = 0;
907 #else
908       const Handle(Xw_Window) theWindow = Handle(Xw_Window)::DownCast (AspectWindow);
909       int TheWindowIdOfView = int (theWindow->XWindow ());
910 #endif  // WNT
911       // Comparaison on window IDs
912       if (TheWindowIdOfView == TheSpecifiedWindowId)
913       {
914         isExist = Standard_True;
915         theView = aView;
916       }
917     }
918   }
919
920   return isExist;
921 }
922
923 //=======================================================================
924 //function : setDeviceLost
925 //purpose  :
926 //=======================================================================
927 void OpenGl_GraphicDriver::setDeviceLost()
928 {
929   if (myMapOfStructure.IsEmpty())
930   {
931     return;
932   }
933
934   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView); aViewIter.More(); aViewIter.Next())
935   {
936     const Handle(OpenGl_View)& aView = aViewIter.Value();
937     if (aView->myWasRedrawnGL)
938     {
939       aView->StructureManager()->SetDeviceLost();
940     }
941   }
942 }