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