03f02a636e22f30ac35e37476c8f4984a4d9133d
[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
144 // =======================================================================
145 // function : ~OpenGl_GraphicDriver
146 // purpose  :
147 // =======================================================================
148 OpenGl_GraphicDriver::~OpenGl_GraphicDriver()
149 {
150   ReleaseContext();
151 }
152
153 // =======================================================================
154 // function : ReleaseContext
155 // purpose  :
156 // =======================================================================
157 void OpenGl_GraphicDriver::ReleaseContext()
158 {
159   Handle(OpenGl_Context) aCtxShared;
160   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView);
161        aViewIter.More(); aViewIter.Next())
162   {
163     const Handle(OpenGl_View)& aView = aViewIter.Value();
164     const Handle(OpenGl_Window)& aWindow = aView->GlWindow();
165     if (aWindow.IsNull())
166     {
167       continue;
168     }
169
170     const Handle(OpenGl_Context)& aCtx = aWindow->GetGlContext();
171     if (aCtx->MakeCurrent()
172      && aCtxShared.IsNull())
173     {
174       aCtxShared = aCtx;
175     }
176   }
177
178   if (!aCtxShared.IsNull())
179   {
180     aCtxShared->MakeCurrent();
181   }
182   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView);
183        aViewIter.More(); aViewIter.Next())
184   {
185     const Handle(OpenGl_View)& aView = aViewIter.Value();
186     aView->ReleaseGlResources (aCtxShared);
187   }
188
189   for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
190        aStructIt.More (); aStructIt.Next())
191   {
192     OpenGl_Structure* aStruct = aStructIt.ChangeValue();
193     aStruct->ReleaseGlResources (aCtxShared);
194   }
195
196   const bool isDeviceLost = !myMapOfStructure.IsEmpty();
197   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView);
198        aViewIter.More(); aViewIter.Next())
199   {
200     const Handle(OpenGl_View)& aView = aViewIter.Value();
201     if (isDeviceLost)
202     {
203       aView->StructureManager()->SetDeviceLost();
204     }
205
206     const Handle(OpenGl_Window)& aWindow = aView->GlWindow();
207     if (aWindow.IsNull())
208     {
209       continue;
210     }
211
212     aWindow->GetGlContext()->forcedRelease();
213   }
214
215 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
216   if (myIsOwnContext)
217   {
218     if (myEglContext != (Aspect_RenderingContext )EGL_NO_CONTEXT)
219     {
220       if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE)
221       {
222         ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, FAILED to release OpenGL context!", Message_Warning);
223       }
224       eglDestroyContext ((EGLDisplay )myEglDisplay, (EGLContext )myEglContext);
225     }
226
227     if (myEglDisplay != (Aspect_Display )EGL_NO_DISPLAY)
228     {
229       if (eglTerminate ((EGLDisplay )myEglDisplay) != EGL_TRUE)
230       {
231         ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, EGL, eglTerminate FAILED!", Message_Warning);
232       }
233     }
234   }
235
236   myEglDisplay = (Aspect_Display )EGL_NO_DISPLAY;
237   myEglContext = (Aspect_RenderingContext )EGL_NO_CONTEXT;
238   myEglConfig  = NULL;
239 #endif
240   myIsOwnContext = Standard_False;
241 }
242
243 // =======================================================================
244 // function : InitContext
245 // purpose  :
246 // =======================================================================
247 Standard_Boolean OpenGl_GraphicDriver::InitContext()
248 {
249   ReleaseContext();
250 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
251
252 #if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
253   if (myDisplayConnection.IsNull())
254   {
255     return Standard_False;
256   }
257   Display* aDisplay = myDisplayConnection->GetDisplay();
258   myEglDisplay = (Aspect_Display )eglGetDisplay (aDisplay);
259 #else
260   myEglDisplay = (Aspect_Display )eglGetDisplay (EGL_DEFAULT_DISPLAY);
261 #endif
262   if ((EGLDisplay )myEglDisplay == EGL_NO_DISPLAY)
263   {
264     ::Message::DefaultMessenger()->Send ("Error: no EGL display!", Message_Fail);
265     return Standard_False;
266   }
267
268   EGLint aVerMajor = 0; EGLint aVerMinor = 0;
269   if (eglInitialize ((EGLDisplay )myEglDisplay, &aVerMajor, &aVerMinor) != EGL_TRUE)
270   {
271     ::Message::DefaultMessenger()->Send ("Error: EGL display is unavailable!", Message_Fail);
272     return Standard_False;
273   }
274
275   myEglConfig = chooseEglSurfConfig ((EGLDisplay )myEglDisplay);
276   if (myEglConfig == NULL)
277   {
278     ::Message::DefaultMessenger()->Send ("Error: EGL does not provide compatible configurations!", Message_Fail);
279     return Standard_False;
280   }
281
282 #if defined(GL_ES_VERSION_2_0)
283   EGLint anEglCtxAttribs[] =
284   {
285     EGL_CONTEXT_CLIENT_VERSION, 2,
286     EGL_NONE
287   };
288   if (eglBindAPI (EGL_OPENGL_ES_API) != EGL_TRUE)
289   {
290     ::Message::DefaultMessenger()->Send ("Error: EGL does not provide OpenGL ES client!", Message_Fail);
291     return Standard_False;
292   }
293 #else
294   EGLint* anEglCtxAttribs = NULL;
295   if (eglBindAPI (EGL_OPENGL_API) != EGL_TRUE)
296   {
297     ::Message::DefaultMessenger()->Send ("Error: EGL does not provide OpenGL client!", Message_Fail);
298     return Standard_False;
299   }
300 #endif
301
302   myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs);
303   if ((EGLContext )myEglContext == EGL_NO_CONTEXT)
304   {
305     ::Message::DefaultMessenger()->Send ("Error: EGL is unable to create OpenGL context!", Message_Fail);
306     return Standard_False;
307   }
308   // eglMakeCurrent() fails or even crash with EGL_NO_SURFACE on some implementations
309   //if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, (EGLContext )myEglContext) != EGL_TRUE)
310   //{
311   //  ::Message::DefaultMessenger()->Send ("Error: EGL is unable bind OpenGL context!", Message_Fail);
312   //  return Standard_False;
313   //}
314 #endif
315   myIsOwnContext = Standard_True;
316   return Standard_True;
317 }
318
319 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
320 // =======================================================================
321 // function : InitEglContext
322 // purpose  :
323 // =======================================================================
324 Standard_Boolean OpenGl_GraphicDriver::InitEglContext (Aspect_Display          theEglDisplay,
325                                                        Aspect_RenderingContext theEglContext,
326                                                        void*                   theEglConfig)
327 {
328   ReleaseContext();
329 #if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
330   if (myDisplayConnection.IsNull())
331   {
332     return Standard_False;
333   }
334 #endif
335
336   if ((EGLDisplay )theEglDisplay == EGL_NO_DISPLAY
337    || (EGLContext )theEglContext == EGL_NO_CONTEXT)
338   {
339     return Standard_False;
340   }
341   myEglDisplay = theEglDisplay;
342   myEglContext = theEglContext;
343   myEglConfig  = theEglConfig;
344   if (theEglConfig == NULL)
345   {
346     myEglConfig = chooseEglSurfConfig ((EGLDisplay )myEglDisplay);
347     if (myEglConfig == NULL)
348     {
349       ::Message::DefaultMessenger()->Send ("Error: EGL does not provide compatible configurations!", Message_Fail);
350       return Standard_False;
351     }
352   }
353   return Standard_True;
354 }
355 #endif
356
357 // =======================================================================
358 // function : InquireLimit
359 // purpose  :
360 // =======================================================================
361 Standard_Integer OpenGl_GraphicDriver::InquireLimit (const Graphic3d_TypeOfLimit theType) const
362 {
363   const Handle(OpenGl_Context)& aCtx = GetSharedContext();
364   switch (theType)
365   {
366     case Graphic3d_TypeOfLimit_MaxNbLights:
367       return Graphic3d_ShaderProgram::THE_MAX_LIGHTS_DEFAULT;
368     case Graphic3d_TypeOfLimit_MaxNbClipPlanes:
369       return !aCtx.IsNull() ? aCtx->MaxClipPlanes() : 0;
370     case Graphic3d_TypeOfLimit_MaxNbViews:
371       return 10000;
372     case Graphic3d_TypeOfLimit_MaxTextureSize:
373       return !aCtx.IsNull() ? aCtx->MaxTextureSize() : 1024;
374     case Graphic3d_TypeOfLimit_MaxCombinedTextureUnits:
375       return !aCtx.IsNull() ? aCtx->MaxCombinedTextureUnits() : 1;
376     case Graphic3d_TypeOfLimit_MaxMsaa:
377       return !aCtx.IsNull() ? aCtx->MaxMsaaSamples() : 0;
378     case Graphic3d_TypeOfLimit_MaxViewDumpSizeX:
379       return !aCtx.IsNull() ? aCtx->MaxDumpSizeX() : 1024;
380     case Graphic3d_TypeOfLimit_MaxViewDumpSizeY:
381       return !aCtx.IsNull() ? aCtx->MaxDumpSizeY() : 1024;
382     case Graphic3d_TypeOfLimit_HasRayTracing:
383       return (!aCtx.IsNull() && aCtx->HasRayTracing()) ? 1 : 0;
384     case Graphic3d_TypeOfLimit_HasRayTracingTextures:
385       return (!aCtx.IsNull() && aCtx->HasRayTracingTextures()) ? 1 : 0;
386     case Graphic3d_TypeOfLimit_HasRayTracingAdaptiveSampling:
387       return (!aCtx.IsNull() && aCtx->HasRayTracingAdaptiveSampling()) ? 1 : 0;
388     case Graphic3d_TypeOfLimit_HasRayTracingAdaptiveSamplingAtomic:
389       return (!aCtx.IsNull() && aCtx->HasRayTracingAdaptiveSamplingAtomic()) ? 1 : 0;
390     case Graphic3d_TypeOfLimit_HasBlendedOit:
391       return (!aCtx.IsNull()
392             && aCtx->hasDrawBuffers != OpenGl_FeatureNotAvailable
393             && (aCtx->hasFloatBuffer != OpenGl_FeatureNotAvailable || aCtx->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable)) ? 1 : 0;
394     case Graphic3d_TypeOfLimit_HasBlendedOitMsaa:
395       return (!aCtx.IsNull()
396             && aCtx->hasSampleVariables != OpenGl_FeatureNotAvailable
397             && (InquireLimit (Graphic3d_TypeOfLimit_HasBlendedOit) == 1)) ? 1 : 0;
398     case Graphic3d_TypeOfLimit_HasFlatShading:
399       return !aCtx.IsNull() && aCtx->hasFlatShading != OpenGl_FeatureNotAvailable ? 1 : 0;
400     case Graphic3d_TypeOfLimit_IsWorkaroundFBO:
401       return !aCtx.IsNull() && aCtx->MaxTextureSize() != aCtx->MaxDumpSizeX() ? 1 : 0;
402     case Graphic3d_TypeOfLimit_HasMeshEdges:
403       return !aCtx.IsNull() && aCtx->hasGeometryStage != OpenGl_FeatureNotAvailable ? 1 : 0;
404     case Graphic3d_TypeOfLimit_NB:
405       return 0;
406   }
407   return 0;
408 }
409
410 // =======================================================================
411 // function : DefaultTextHeight
412 // purpose  :
413 // =======================================================================
414 Standard_ShortReal OpenGl_GraphicDriver::DefaultTextHeight() const
415 {
416   return 16.;
417 }
418
419 // =======================================================================
420 // function : EnableVBO
421 // purpose  :
422 // =======================================================================
423 void OpenGl_GraphicDriver::EnableVBO (const Standard_Boolean theToTurnOn)
424 {
425   myCaps->vboDisable = !theToTurnOn;
426 }
427
428 // =======================================================================
429 // function : GetSharedContext
430 // purpose  :
431 // =======================================================================
432 const Handle(OpenGl_Context)& OpenGl_GraphicDriver::GetSharedContext() const
433 {
434   if (myMapOfView.IsEmpty())
435   {
436     return TheNullGlCtx;
437   }
438
439   NCollection_Map<Handle(OpenGl_View)>::Iterator anIter (myMapOfView);
440   for (; anIter.More(); anIter.Next())
441   {
442     Handle(OpenGl_Window) aWindow = anIter.Value()->GlWindow();
443     if (aWindow.IsNull())
444     {
445       continue;
446     }
447
448     return aWindow->GetGlContext();
449   }
450
451   return TheNullGlCtx;
452 }
453
454 // =======================================================================
455 // function : MemoryInfo
456 // purpose  :
457 // =======================================================================
458 Standard_Boolean OpenGl_GraphicDriver::MemoryInfo (Standard_Size&           theFreeBytes,
459                                                    TCollection_AsciiString& theInfo) const
460 {
461   // this is extra work (for OpenGl_Context initialization)...
462   OpenGl_Context aGlCtx;
463   if (!aGlCtx.Init())
464   {
465     return Standard_False;
466   }
467   theFreeBytes = aGlCtx.AvailableMemory();
468   theInfo      = aGlCtx.MemoryInfo();
469   return !theInfo.IsEmpty();
470 }
471
472 // =======================================================================
473 // function : SetBuffersNoSwap
474 // purpose  :
475 // =======================================================================
476 void OpenGl_GraphicDriver::SetBuffersNoSwap (const Standard_Boolean theIsNoSwap)
477 {
478   myCaps->buffersNoSwap = theIsNoSwap;
479 }
480
481 // =======================================================================
482 // function : TextSize
483 // purpose  :
484 // =======================================================================
485 void OpenGl_GraphicDriver::TextSize (const Handle(Graphic3d_CView)& theView,
486                                      const Standard_CString         theText,
487                                      const Standard_ShortReal       theHeight,
488                                      Standard_ShortReal&            theWidth,
489                                      Standard_ShortReal&            theAscent,
490                                      Standard_ShortReal&            theDescent) const
491 {
492   const Handle(OpenGl_Context)& aCtx = GetSharedContext();
493   if (aCtx.IsNull())
494   {
495     return;
496   }
497
498   const Standard_ShortReal aHeight = (theHeight < 2.0f) ? DefaultTextHeight() : theHeight;
499   OpenGl_TextParam aTextParam;
500   aTextParam.Height = (int )aHeight;
501   OpenGl_Aspects aTextAspect;
502   TCollection_ExtendedString anExtText = theText;
503   NCollection_String aText (anExtText.ToExtString());
504   OpenGl_Text::StringSize(aCtx, aText, aTextAspect, aTextParam, theView->RenderingParams().Resolution, theWidth, theAscent, theDescent);
505 }
506
507 //=======================================================================
508 //function : AddZLayer
509 //purpose  :
510 //=======================================================================
511 void OpenGl_GraphicDriver::AddZLayer (const Graphic3d_ZLayerId theLayerId)
512 {
513   if (theLayerId < 1)
514   {
515     Standard_ASSERT_RAISE (theLayerId > 0,
516                            "OpenGl_GraphicDriver::AddZLayer, "
517                            "negative and zero IDs are reserved");
518   }
519
520   myLayerIds.Add (theLayerId);
521
522   // Default z-layer settings
523   myMapOfZLayerSettings.Bind (theLayerId, Graphic3d_ZLayerSettings());
524   addZLayerIndex (theLayerId);
525
526   // Add layer to all views
527   NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView);
528   for (; aViewIt.More(); aViewIt.Next())
529   {
530     aViewIt.Value()->AddZLayer (theLayerId);
531   }
532 }
533
534 //=======================================================================
535 //function : RemoveZLayer
536 //purpose  :
537 //=======================================================================
538 void OpenGl_GraphicDriver::RemoveZLayer (const Graphic3d_ZLayerId theLayerId)
539 {
540   Standard_ASSERT_RAISE (theLayerId > 0,
541                          "OpenGl_GraphicDriver::AddZLayer, "
542                          "negative and zero IDs are reserved"
543                          "and can not be removed");
544
545   Standard_ASSERT_RAISE (myLayerIds.Contains (theLayerId),
546                          "OpenGl_GraphicDriver::RemoveZLayer, "
547                          "Layer with theLayerId does not exist");
548
549   // Remove layer from all of the views
550   NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView);
551   for (; aViewIt.More(); aViewIt.Next())
552   {
553     aViewIt.Value()->RemoveZLayer (theLayerId);
554   }
555
556   // Unset Z layer for all of the structures.
557   NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
558   for( ; aStructIt.More (); aStructIt.Next ())
559   {
560     OpenGl_Structure* aStruct = aStructIt.ChangeValue ();
561     if (aStruct->ZLayer() == theLayerId)
562       aStruct->SetZLayer (Graphic3d_ZLayerId_Default);
563   }
564
565   // Remove index
566   for (TColStd_SequenceOfInteger::Iterator aLayerIt (myLayerSeq); aLayerIt.More(); aLayerIt.Next())
567   {
568     if (aLayerIt.Value() == theLayerId)
569     {
570       myLayerSeq.Remove (aLayerIt);
571       break;
572     }
573   }
574
575   myMapOfZLayerSettings.UnBind (theLayerId);
576   myLayerIds.Remove  (theLayerId);
577 }
578
579 //=======================================================================
580 //function : SetZLayerSettings
581 //purpose  :
582 //=======================================================================
583 void OpenGl_GraphicDriver::SetZLayerSettings (const Graphic3d_ZLayerId theLayerId,
584                                               const Graphic3d_ZLayerSettings& theSettings)
585 {
586   base_type::SetZLayerSettings (theLayerId, theSettings);
587
588   // Change Z layer settings in all managed views
589   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next())
590   {
591     aViewIt.Value()->SetZLayerSettings (theLayerId, theSettings);
592   }
593 }
594
595 // =======================================================================
596 // function : Structure
597 // purpose  :
598 // =======================================================================
599 Handle(Graphic3d_CStructure) OpenGl_GraphicDriver::CreateStructure (const Handle(Graphic3d_StructureManager)& theManager)
600 {
601   Handle(OpenGl_Structure) aStructure = new OpenGl_Structure (theManager);
602   myMapOfStructure.Bind (aStructure->Id, aStructure.operator->());
603   return aStructure;
604 }
605
606 // =======================================================================
607 // function : Structure
608 // purpose  :
609 // =======================================================================
610 void OpenGl_GraphicDriver::RemoveStructure (Handle(Graphic3d_CStructure)& theCStructure)
611 {
612   OpenGl_Structure* aStructure = NULL;
613   if (!myMapOfStructure.Find (theCStructure->Id, aStructure))
614   {
615     return;
616   }
617
618   myMapOfStructure.UnBind (theCStructure->Id);
619   aStructure->Release (GetSharedContext());
620   theCStructure.Nullify();
621 }
622
623 // =======================================================================
624 // function : View
625 // purpose  :
626 // =======================================================================
627 Handle(Graphic3d_CView) OpenGl_GraphicDriver::CreateView (const Handle(Graphic3d_StructureManager)& theMgr)
628 {
629   Handle(OpenGl_View) aView = new OpenGl_View (theMgr, this, myCaps, &myStateCounter);
630
631   myMapOfView.Add (aView);
632
633   for (TColStd_SequenceOfInteger::Iterator aLayerIt (myLayerSeq); aLayerIt.More(); aLayerIt.Next())
634   {
635     const Graphic3d_ZLayerId        aLayerID  = aLayerIt.Value();
636     const Graphic3d_ZLayerSettings& aSettings = myMapOfZLayerSettings.Find (aLayerID);
637     aView->AddZLayer         (aLayerID);
638     aView->SetZLayerSettings (aLayerID, aSettings);
639   }
640
641   return aView;
642 }
643
644 // =======================================================================
645 // function : RemoveView
646 // purpose  :
647 // =======================================================================
648 void OpenGl_GraphicDriver::RemoveView (const Handle(Graphic3d_CView)& theView)
649 {
650   Handle(OpenGl_Context) aCtx = GetSharedContext();
651   Handle(OpenGl_View) aView   = Handle(OpenGl_View)::DownCast (theView);
652   if (aView.IsNull())
653   {
654     return;
655   }
656
657   if (!myMapOfView.Remove (aView))
658   {
659     return;
660   }
661
662   Handle(OpenGl_Window) aWindow = aView->GlWindow();
663   if (!aWindow.IsNull()
664     && aWindow->GetGlContext()->MakeCurrent())
665   {
666     aCtx = aWindow->GetGlContext();
667   }
668   else
669   {
670     // try to hijack another context if any
671     const Handle(OpenGl_Context)& anOtherCtx = GetSharedContext();
672     if (!anOtherCtx.IsNull()
673       && anOtherCtx != aWindow->GetGlContext())
674     {
675       aCtx = anOtherCtx;
676       aCtx->MakeCurrent();
677     }
678   }
679
680   aView->ReleaseGlResources (aCtx);
681   if (myMapOfView.IsEmpty())
682   {
683     // The last view removed but some objects still present.
684     // Release GL resources now without object destruction.
685     for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
686          aStructIt.More (); aStructIt.Next())
687     {
688       OpenGl_Structure* aStruct = aStructIt.ChangeValue();
689       aStruct->ReleaseGlResources (aCtx);
690     }
691
692     if (!myMapOfStructure.IsEmpty())
693     {
694       aView->StructureManager()->SetDeviceLost();
695     }
696   }
697 }
698
699 // =======================================================================
700 // function : Window
701 // purpose  :
702 // =======================================================================
703 Handle(OpenGl_Window) OpenGl_GraphicDriver::CreateRenderWindow (const Handle(Aspect_Window)&  theWindow,
704                                                                 const Aspect_RenderingContext theContext)
705 {
706   Handle(OpenGl_Context) aShareCtx = GetSharedContext();
707   Handle(OpenGl_Window) aWindow = new OpenGl_Window (this, theWindow, theContext, myCaps, aShareCtx);
708   return aWindow;
709 }
710
711 //=======================================================================
712 //function : ViewExists
713 //purpose  :
714 //=======================================================================
715 Standard_Boolean OpenGl_GraphicDriver::ViewExists (const Handle(Aspect_Window)& AWindow, Handle(Graphic3d_CView)& theView)
716 {
717   Standard_Boolean isExist = Standard_False;
718
719   // Parse the list of views to find
720   // a view with the specified window
721
722 #if defined(_WIN32) && !defined(OCCT_UWP)
723   const Handle(WNT_Window) THEWindow = Handle(WNT_Window)::DownCast (AWindow);
724   Aspect_Handle TheSpecifiedWindowId = THEWindow->HWindow ();
725 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
726   const Handle(Cocoa_Window) THEWindow = Handle(Cocoa_Window)::DownCast (AWindow);
727   #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
728     UIView* TheSpecifiedWindowId = THEWindow->HView();
729   #else
730     NSView* TheSpecifiedWindowId = THEWindow->HView();
731   #endif
732 #elif defined(__ANDROID__) || defined(__QNX__) || defined(OCCT_UWP)
733   (void )AWindow;
734   int TheSpecifiedWindowId = -1;
735 #else
736   const Handle(Xw_Window) THEWindow = Handle(Xw_Window)::DownCast (AWindow);
737   int TheSpecifiedWindowId = int (THEWindow->XWindow ());
738 #endif
739
740   NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView);
741   for(; aViewIt.More(); aViewIt.Next())
742   {
743     const Handle(OpenGl_View)& aView = aViewIt.Value();
744     if (aView->IsDefined() && aView->IsActive())
745     {
746       const Handle(Aspect_Window) AspectWindow = aView->Window();
747
748 #if defined(_WIN32) && !defined(OCCT_UWP)
749       const Handle(WNT_Window) theWindow = Handle(WNT_Window)::DownCast (AspectWindow);
750       Aspect_Handle TheWindowIdOfView = theWindow->HWindow ();
751 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
752       const Handle(Cocoa_Window) theWindow = Handle(Cocoa_Window)::DownCast (AspectWindow);
753       #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
754         UIView* TheWindowIdOfView = theWindow->HView();
755       #else
756         NSView* TheWindowIdOfView = theWindow->HView();
757       #endif
758 #elif defined(__ANDROID__) || defined(__QNX__) || defined(OCCT_UWP)
759       int TheWindowIdOfView = 0;
760 #else
761       const Handle(Xw_Window) theWindow = Handle(Xw_Window)::DownCast (AspectWindow);
762       int TheWindowIdOfView = int (theWindow->XWindow ());
763 #endif  // WNT
764       // Comparaison on window IDs
765       if (TheWindowIdOfView == TheSpecifiedWindowId)
766       {
767         isExist = Standard_True;
768         theView = aView;
769       }
770     }
771   }
772
773   return isExist;
774 }
775
776 //=======================================================================
777 //function : setDeviceLost
778 //purpose  :
779 //=======================================================================
780 void OpenGl_GraphicDriver::setDeviceLost()
781 {
782   if (myMapOfStructure.IsEmpty())
783   {
784     return;
785   }
786
787   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView); aViewIter.More(); aViewIter.Next())
788   {
789     const Handle(OpenGl_View)& aView = aViewIter.Value();
790     if (aView->myWasRedrawnGL)
791     {
792       aView->StructureManager()->SetDeviceLost();
793     }
794   }
795 }