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