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