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