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