0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[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_Window.hxx>
29 #include <OpenGl_Workspace.hxx>
30
31 #include <Aspect_GraphicDeviceDefinitionError.hxx>
32 #include <Aspect_IdentDefinitionError.hxx>
33 #include <Graphic3d_StructureManager.hxx>
34 #include <Message_Messenger.hxx>
35 #include <OSD_Environment.hxx>
36 #include <Standard_NotImplemented.hxx>
37
38 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_GraphicDriver,Graphic3d_GraphicDriver)
39
40 #if defined(_WIN32)
41   #include <WNT_Window.hxx>
42 #elif defined(HAVE_XLIB)
43   #include <Xw_Window.hxx>
44 #elif defined(__APPLE__)
45   #include <Cocoa_Window.hxx>
46 #else
47   #include <Aspect_NeutralWindow.hxx>
48 #endif
49
50 #if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__) && (!defined(__APPLE__) || defined(HAVE_XLIB))
51   #include <X11/Xlib.h> // XOpenDisplay()
52   #include <GL/glx.h>
53 #endif
54
55 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
56   #include <EGL/egl.h>
57   #ifndef EGL_OPENGL_ES3_BIT
58     #define EGL_OPENGL_ES3_BIT 0x00000040
59   #endif
60 #endif
61
62 namespace
63 {
64   static const Handle(OpenGl_Context) TheNullGlCtx;
65
66 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
67   //! Wrapper over eglChooseConfig() called with preferred defaults.
68   static EGLConfig chooseEglSurfConfig (EGLDisplay theDisplay)
69   {
70     EGLint aConfigAttribs[] =
71     {
72       EGL_RED_SIZE,     8,
73       EGL_GREEN_SIZE,   8,
74       EGL_BLUE_SIZE,    8,
75       EGL_ALPHA_SIZE,   0,
76       EGL_DEPTH_SIZE,   24,
77       EGL_STENCIL_SIZE, 8,
78     #if defined(GL_ES_VERSION_2_0)
79       EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
80     #else
81       EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
82     #endif
83       EGL_NONE
84     };
85
86     EGLConfig aCfg = NULL;
87     EGLint aNbConfigs = 0;
88     for (Standard_Integer aGlesVer = 3; aGlesVer >= 2; --aGlesVer)
89     {
90     #if defined(GL_ES_VERSION_2_0)
91       aConfigAttribs[6 * 2 + 1] = aGlesVer == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
92     #else
93       if (aGlesVer == 2)
94       {
95         break;
96       }
97     #endif
98
99       if (eglChooseConfig (theDisplay, aConfigAttribs, &aCfg, 1, &aNbConfigs) == EGL_TRUE
100        && aCfg != NULL)
101       {
102         return aCfg;
103       }
104       eglGetError();
105
106       aConfigAttribs[4 * 2 + 1] = 16; // try config with smaller depth buffer
107       if (eglChooseConfig (theDisplay, aConfigAttribs, &aCfg, 1, &aNbConfigs) == EGL_TRUE
108        && aCfg != NULL)
109       {
110         return aCfg;
111       }
112       eglGetError();
113     }
114     return aCfg;
115   }
116 #elif defined(HAVE_XLIB)
117   //! Search for RGBA double-buffered visual with stencil buffer.
118   static int TheDoubleBuffVisual[] =
119   {
120     GLX_RGBA,
121     GLX_DEPTH_SIZE, 16,
122     GLX_STENCIL_SIZE, 1,
123     GLX_DOUBLEBUFFER,
124     None
125   };
126
127   //! Search for RGBA double-buffered visual with stencil buffer.
128   static int TheDoubleBuffFBConfig[] =
129   {
130     GLX_X_RENDERABLE,  True,
131     GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
132     GLX_RENDER_TYPE,   GLX_RGBA_BIT,
133     GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
134     GLX_DEPTH_SIZE,    16,
135     GLX_STENCIL_SIZE,  1,
136     GLX_DOUBLEBUFFER,  True,
137     None
138   };
139 #endif
140
141 }
142
143 // =======================================================================
144 // function : OpenGl_GraphicDriver
145 // purpose  :
146 // =======================================================================
147 OpenGl_GraphicDriver::OpenGl_GraphicDriver (const Handle(Aspect_DisplayConnection)& theDisp,
148                                             const Standard_Boolean                  theToInitialize)
149 : Graphic3d_GraphicDriver (theDisp),
150   myIsOwnContext (Standard_False),
151   myEglDisplay (NULL),
152   myEglContext (NULL),
153   myEglConfig  (NULL),
154   myCaps           (new OpenGl_Caps()),
155   myMapOfView      (1, NCollection_BaseAllocator::CommonBaseAllocator()),
156   myMapOfStructure (1, NCollection_BaseAllocator::CommonBaseAllocator())
157 {
158 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
159   myEglDisplay = (Aspect_Display )EGL_NO_DISPLAY;
160   myEglContext = (Aspect_RenderingContext )EGL_NO_CONTEXT;
161 #endif
162
163 #if defined(HAVE_XLIB)
164   if (myDisplayConnection.IsNull())
165   {
166     //throw Aspect_GraphicDeviceDefinitionError("OpenGl_GraphicDriver: cannot connect to X server!");
167     return;
168   }
169
170   Display* aDisplay = (Display* )myDisplayConnection->GetDisplayAspect();
171   Bool toSync = ::getenv ("CSF_GraphicSync") != NULL
172              || ::getenv ("CALL_SYNCHRO_X")  != NULL;
173   XSynchronize (aDisplay, toSync);
174 #endif
175   if (theToInitialize
176   && !InitContext())
177   {
178     throw Aspect_GraphicDeviceDefinitionError("OpenGl_GraphicDriver: default context can not be initialized!");
179   }
180 }
181
182 // =======================================================================
183 // function : ~OpenGl_GraphicDriver
184 // purpose  :
185 // =======================================================================
186 OpenGl_GraphicDriver::~OpenGl_GraphicDriver()
187 {
188   ReleaseContext();
189 }
190
191 // =======================================================================
192 // function : ReleaseContext
193 // purpose  :
194 // =======================================================================
195 void OpenGl_GraphicDriver::ReleaseContext()
196 {
197   Handle(OpenGl_Context) aCtxShared;
198   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView);
199        aViewIter.More(); aViewIter.Next())
200   {
201     const Handle(OpenGl_View)& aView = aViewIter.Value();
202     const Handle(OpenGl_Window)& aWindow = aView->GlWindow();
203     if (aWindow.IsNull())
204     {
205       continue;
206     }
207
208     const Handle(OpenGl_Context)& aCtx = aWindow->GetGlContext();
209     if (aCtx->MakeCurrent()
210      && aCtxShared.IsNull())
211     {
212       aCtxShared = aCtx;
213     }
214   }
215
216   if (!aCtxShared.IsNull())
217   {
218     aCtxShared->MakeCurrent();
219   }
220   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView);
221        aViewIter.More(); aViewIter.Next())
222   {
223     const Handle(OpenGl_View)& aView = aViewIter.Value();
224     aView->ReleaseGlResources (aCtxShared);
225   }
226
227   for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
228        aStructIt.More (); aStructIt.Next())
229   {
230     OpenGl_Structure* aStruct = aStructIt.ChangeValue();
231     aStruct->ReleaseGlResources (aCtxShared);
232   }
233
234   const bool isDeviceLost = !myMapOfStructure.IsEmpty();
235   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView);
236        aViewIter.More(); aViewIter.Next())
237   {
238     const Handle(OpenGl_View)& aView = aViewIter.Value();
239     if (isDeviceLost)
240     {
241       aView->StructureManager()->SetDeviceLost();
242     }
243
244     const Handle(OpenGl_Window)& aWindow = aView->GlWindow();
245     if (aWindow.IsNull())
246     {
247       continue;
248     }
249
250     aWindow->GetGlContext()->forcedRelease();
251   }
252
253 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
254   if (myIsOwnContext)
255   {
256     if (myEglContext != (Aspect_RenderingContext )EGL_NO_CONTEXT)
257     {
258       if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE)
259       {
260         ::Message::SendWarning ("OpenGl_GraphicDriver, FAILED to release OpenGL context");
261       }
262       eglDestroyContext ((EGLDisplay )myEglDisplay, (EGLContext )myEglContext);
263     }
264
265     if (myEglDisplay != (Aspect_Display )EGL_NO_DISPLAY)
266     {
267       if (eglTerminate ((EGLDisplay )myEglDisplay) != EGL_TRUE)
268       {
269         ::Message::SendWarning ("OpenGl_GraphicDriver, EGL, eglTerminate FAILED");
270       }
271     }
272   }
273
274   myEglDisplay = (Aspect_Display )EGL_NO_DISPLAY;
275   myEglContext = (Aspect_RenderingContext )EGL_NO_CONTEXT;
276   myEglConfig  = NULL;
277 #endif
278   myIsOwnContext = Standard_False;
279 }
280
281 // =======================================================================
282 // function : InitContext
283 // purpose  :
284 // =======================================================================
285 Standard_Boolean OpenGl_GraphicDriver::InitContext()
286 {
287   ReleaseContext();
288 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
289
290 #if defined(HAVE_XLIB)
291   if (myDisplayConnection.IsNull())
292   {
293     return Standard_False;
294   }
295   Display* aDisplay = (Display* )myDisplayConnection->GetDisplayAspect();
296   myEglDisplay = (Aspect_Display )eglGetDisplay (aDisplay);
297 #else
298   myEglDisplay = (Aspect_Display )eglGetDisplay (EGL_DEFAULT_DISPLAY);
299 #endif
300   if ((EGLDisplay )myEglDisplay == EGL_NO_DISPLAY)
301   {
302     ::Message::SendFail ("Error: no EGL display");
303     return Standard_False;
304   }
305
306   EGLint aVerMajor = 0; EGLint aVerMinor = 0;
307   if (eglInitialize ((EGLDisplay )myEglDisplay, &aVerMajor, &aVerMinor) != EGL_TRUE)
308   {
309     ::Message::SendFail ("Error: EGL display is unavailable");
310     return Standard_False;
311   }
312
313   myEglConfig = chooseEglSurfConfig ((EGLDisplay )myEglDisplay);
314   if (myEglConfig == NULL)
315   {
316     ::Message::SendFail ("Error: EGL does not provide compatible configurations");
317     return Standard_False;
318   }
319
320 #if defined(GL_ES_VERSION_2_0)
321   EGLint anEglCtxAttribs3[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE, EGL_NONE };
322   EGLint anEglCtxAttribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
323   if (eglBindAPI (EGL_OPENGL_ES_API) != EGL_TRUE)
324   {
325     ::Message::SendFail ("Error: EGL does not provide OpenGL ES client");
326     return Standard_False;
327   }
328   if (myCaps->contextMajorVersionUpper != 2)
329   {
330     myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs3);
331   }
332   if ((EGLContext )myEglContext == EGL_NO_CONTEXT)
333   {
334     myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs2);
335   }
336 #else
337   EGLint* anEglCtxAttribs = NULL;
338   if (eglBindAPI (EGL_OPENGL_API) != EGL_TRUE)
339   {
340     ::Message::SendFail ("Error: EGL does not provide OpenGL client");
341     return Standard_False;
342   }
343   myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs);
344 #endif
345
346   if ((EGLContext )myEglContext == EGL_NO_CONTEXT)
347   {
348     ::Message::SendFail ("Error: EGL is unable to create OpenGL context");
349     return Standard_False;
350   }
351   // eglMakeCurrent() fails or even crash with EGL_NO_SURFACE on some implementations
352   //if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, (EGLContext )myEglContext) != EGL_TRUE)
353   //{
354   //  ::Message::SendFail ("Error: EGL is unable bind OpenGL context");
355   //  return Standard_False;
356   //}
357 #endif
358   chooseVisualInfo();
359   myIsOwnContext = Standard_True;
360   return Standard_True;
361 }
362
363 // =======================================================================
364 // function : InitEglContext
365 // purpose  :
366 // =======================================================================
367 Standard_Boolean OpenGl_GraphicDriver::InitEglContext (Aspect_Display          theEglDisplay,
368                                                        Aspect_RenderingContext theEglContext,
369                                                        void*                   theEglConfig)
370 {
371   ReleaseContext();
372 #if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
373 #if defined(HAVE_XLIB)
374   if (myDisplayConnection.IsNull())
375   {
376     return Standard_False;
377   }
378 #endif
379
380   if ((EGLDisplay )theEglDisplay == EGL_NO_DISPLAY
381    || (EGLContext )theEglContext == EGL_NO_CONTEXT)
382   {
383     return Standard_False;
384   }
385   myEglDisplay = theEglDisplay;
386   myEglContext = theEglContext;
387   myEglConfig  = theEglConfig;
388   if (theEglConfig == NULL)
389   {
390     myEglConfig = chooseEglSurfConfig ((EGLDisplay )myEglDisplay);
391     if (myEglConfig == NULL)
392     {
393       ::Message::SendFail ("Error: EGL does not provide compatible configurations");
394       return Standard_False;
395     }
396   }
397   chooseVisualInfo();
398   return Standard_True;
399 #else
400   (void )theEglDisplay;
401   (void )theEglContext;
402   (void )theEglConfig;
403   throw Standard_NotImplemented ("OpenGl_GraphicDriver::InitEglContext() is not implemented");
404 #endif
405 }
406
407 // =======================================================================
408 // function : chooseVisualInfo
409 // purpose  :
410 // =======================================================================
411 void OpenGl_GraphicDriver::chooseVisualInfo()
412 {
413   if (myDisplayConnection.IsNull())
414   {
415     return;
416   }
417
418 #if defined(HAVE_XLIB)
419   Display* aDisp = (Display* )myDisplayConnection->GetDisplayAspect();
420
421   XVisualInfo* aVisInfo = NULL;
422   Aspect_FBConfig anFBConfig = NULL;
423 #if defined(HAVE_EGL) || defined(HAVE_GLES2)
424   XVisualInfo aVisInfoTmp;
425   memset (&aVisInfoTmp, 0, sizeof(aVisInfoTmp));
426   aVisInfoTmp.screen = DefaultScreen (aDisp);
427   if (myEglDisplay != EGL_NO_DISPLAY
428    && myEglConfig != NULL
429    && eglGetConfigAttrib ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NATIVE_VISUAL_ID, (EGLint* )&aVisInfoTmp.visualid) == EGL_TRUE)
430   {
431     int aNbVisuals = 0;
432     aVisInfo = XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfoTmp, &aNbVisuals);
433   }
434 #else
435   int aScreen = DefaultScreen(aDisp);
436   int aDummy = 0;
437   if (!XQueryExtension (aDisp, "GLX", &aDummy, &aDummy, &aDummy)
438    || !glXQueryExtension (aDisp, &aDummy, &aDummy))
439   {
440     Message::SendFail ("Error: OpenGl_GraphicDriver, GLX extension is unavailable");
441   }
442
443   // FBConfigs were added in GLX version 1.3
444   int aGlxMajor = 0, aGlxMinor = 0;
445   const bool hasFBCfg = glXQueryVersion (aDisp, &aGlxMajor, &aGlxMinor)
446                      && ((aGlxMajor == 1 && aGlxMinor >= 3) || (aGlxMajor > 1));
447   if (hasFBCfg)
448   {
449     int aFBCount = 0;
450     GLXFBConfig* aFBCfgList = NULL;
451     if (hasFBCfg)
452     {
453       aFBCfgList = glXChooseFBConfig (aDisp, aScreen, TheDoubleBuffFBConfig, &aFBCount);
454     }
455     if(aFBCfgList != NULL
456     && aFBCount >= 1)
457     {
458       anFBConfig = aFBCfgList[0];
459       aVisInfo   = glXGetVisualFromFBConfig (aDisp, anFBConfig);
460
461       /*int aDepthSize = 0, aStencilSize = 0;
462       glXGetFBConfigAttrib (aDisp, anFBConfig, GLX_DEPTH_SIZE, &aDepthSize);
463       glXGetFBConfigAttrib (aDisp, anFBConfig, GLX_STENCIL_SIZE, &aStencilSize);
464       Message::SendInfo() << "GLX FBConfig:"
465                           << "\n  DepthSize= " << aDepthSize
466                           << "\n  StencilSize= " << aStencilSize;*/
467     }
468     XFree (aFBCfgList);
469   }
470
471   if (aVisInfo == NULL)
472   {
473     aVisInfo = glXChooseVisual (aDisp, aScreen, TheDoubleBuffVisual);
474   }
475 #endif
476   if (aVisInfo != NULL)
477   {
478     myDisplayConnection->SetDefaultVisualInfo ((Aspect_XVisualInfo* )aVisInfo, anFBConfig);
479   }
480   else
481   {
482     Message::SendWarning ("OpenGl_GraphicDriver, couldn't find compatible Visual (RGBA, double-buffered)");
483   }
484 #endif
485 }
486
487 // =======================================================================
488 // function : InquireLimit
489 // purpose  :
490 // =======================================================================
491 Standard_Integer OpenGl_GraphicDriver::InquireLimit (const Graphic3d_TypeOfLimit theType) const
492 {
493   const Handle(OpenGl_Context)& aCtx = GetSharedContext();
494   switch (theType)
495   {
496     case Graphic3d_TypeOfLimit_MaxNbLights:
497       return Graphic3d_ShaderProgram::THE_MAX_LIGHTS_DEFAULT;
498     case Graphic3d_TypeOfLimit_MaxNbClipPlanes:
499       return !aCtx.IsNull() ? aCtx->MaxClipPlanes() : 0;
500     case Graphic3d_TypeOfLimit_MaxNbViews:
501       return 10000;
502     case Graphic3d_TypeOfLimit_MaxTextureSize:
503       return !aCtx.IsNull() ? aCtx->MaxTextureSize() : 1024;
504     case Graphic3d_TypeOfLimit_MaxCombinedTextureUnits:
505       return !aCtx.IsNull() ? aCtx->MaxCombinedTextureUnits() : 1;
506     case Graphic3d_TypeOfLimit_MaxMsaa:
507       return !aCtx.IsNull() ? aCtx->MaxMsaaSamples() : 0;
508     case Graphic3d_TypeOfLimit_MaxViewDumpSizeX:
509       return !aCtx.IsNull() ? aCtx->MaxDumpSizeX() : 1024;
510     case Graphic3d_TypeOfLimit_MaxViewDumpSizeY:
511       return !aCtx.IsNull() ? aCtx->MaxDumpSizeY() : 1024;
512     case Graphic3d_TypeOfLimit_HasPBR:
513       return (!aCtx.IsNull() && aCtx->HasPBR()) ? 1 : 0;
514     case Graphic3d_TypeOfLimit_HasRayTracing:
515       return (!aCtx.IsNull() && aCtx->HasRayTracing()) ? 1 : 0;
516     case Graphic3d_TypeOfLimit_HasRayTracingTextures:
517       return (!aCtx.IsNull() && aCtx->HasRayTracingTextures()) ? 1 : 0;
518     case Graphic3d_TypeOfLimit_HasRayTracingAdaptiveSampling:
519       return (!aCtx.IsNull() && aCtx->HasRayTracingAdaptiveSampling()) ? 1 : 0;
520     case Graphic3d_TypeOfLimit_HasRayTracingAdaptiveSamplingAtomic:
521       return (!aCtx.IsNull() && aCtx->HasRayTracingAdaptiveSamplingAtomic()) ? 1 : 0;
522     case Graphic3d_TypeOfLimit_HasSRGB:
523       return (!aCtx.IsNull() && aCtx->HasSRGB()) ? 1 : 0;
524     case Graphic3d_TypeOfLimit_HasBlendedOit:
525       return (!aCtx.IsNull()
526             && aCtx->hasDrawBuffers != OpenGl_FeatureNotAvailable
527             && (aCtx->hasFloatBuffer != OpenGl_FeatureNotAvailable || aCtx->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable)) ? 1 : 0;
528     case Graphic3d_TypeOfLimit_HasBlendedOitMsaa:
529       return (!aCtx.IsNull()
530             && aCtx->hasSampleVariables != OpenGl_FeatureNotAvailable
531             && (InquireLimit (Graphic3d_TypeOfLimit_HasBlendedOit) == 1)) ? 1 : 0;
532     case Graphic3d_TypeOfLimit_HasFlatShading:
533       return !aCtx.IsNull() && aCtx->hasFlatShading != OpenGl_FeatureNotAvailable ? 1 : 0;
534     case Graphic3d_TypeOfLimit_IsWorkaroundFBO:
535       return !aCtx.IsNull() && aCtx->MaxTextureSize() != aCtx->MaxDumpSizeX() ? 1 : 0;
536     case Graphic3d_TypeOfLimit_HasMeshEdges:
537       return !aCtx.IsNull() && aCtx->hasGeometryStage != OpenGl_FeatureNotAvailable ? 1 : 0;
538     case Graphic3d_TypeOfLimit_NB:
539       return 0;
540   }
541   return 0;
542 }
543
544 // =======================================================================
545 // function : DefaultTextHeight
546 // purpose  :
547 // =======================================================================
548 Standard_ShortReal OpenGl_GraphicDriver::DefaultTextHeight() const
549 {
550   return 16.;
551 }
552
553 // =======================================================================
554 // function : EnableVBO
555 // purpose  :
556 // =======================================================================
557 void OpenGl_GraphicDriver::EnableVBO (const Standard_Boolean theToTurnOn)
558 {
559   myCaps->vboDisable = !theToTurnOn;
560 }
561
562 // =======================================================================
563 // function : IsVerticalSync
564 // purpose  :
565 // =======================================================================
566 bool OpenGl_GraphicDriver::IsVerticalSync() const
567 {
568   return myCaps->swapInterval == 1;
569 }
570
571 // =======================================================================
572 // function : SetVerticalSync
573 // purpose  :
574 // =======================================================================
575 void OpenGl_GraphicDriver::SetVerticalSync (bool theToEnable)
576 {
577   myCaps->swapInterval = theToEnable ? 1 : 0;
578 }
579
580 // =======================================================================
581 // function : GetSharedContext
582 // purpose  :
583 // =======================================================================
584 const Handle(OpenGl_Context)& OpenGl_GraphicDriver::GetSharedContext (bool theBound) const
585 {
586   if (myMapOfView.IsEmpty())
587   {
588     return TheNullGlCtx;
589   }
590
591   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView); aViewIter.More(); aViewIter.Next())
592   {
593     if (const Handle(OpenGl_Window)& aWindow = aViewIter.Value()->GlWindow())
594     {
595       if (!theBound)
596       {
597         return aWindow->GetGlContext();
598       }
599       else if (aWindow->GetGlContext()->IsCurrent())
600       {
601         return aWindow->GetGlContext();
602       }
603     }
604   }
605
606   return TheNullGlCtx;
607 }
608
609 // =======================================================================
610 // function : MemoryInfo
611 // purpose  :
612 // =======================================================================
613 Standard_Boolean OpenGl_GraphicDriver::MemoryInfo (Standard_Size&           theFreeBytes,
614                                                    TCollection_AsciiString& theInfo) const
615 {
616   // this is extra work (for OpenGl_Context initialization)...
617   OpenGl_Context aGlCtx;
618   if (!aGlCtx.Init())
619   {
620     return Standard_False;
621   }
622   theFreeBytes = aGlCtx.AvailableMemory();
623   theInfo      = aGlCtx.MemoryInfo();
624   return !theInfo.IsEmpty();
625 }
626
627 // =======================================================================
628 // function : SetBuffersNoSwap
629 // purpose  :
630 // =======================================================================
631 void OpenGl_GraphicDriver::SetBuffersNoSwap (const Standard_Boolean theIsNoSwap)
632 {
633   myCaps->buffersNoSwap = theIsNoSwap;
634 }
635
636 // =======================================================================
637 // function : TextSize
638 // purpose  :
639 // =======================================================================
640 void OpenGl_GraphicDriver::TextSize (const Handle(Graphic3d_CView)& theView,
641                                      const Standard_CString         theText,
642                                      const Standard_ShortReal       theHeight,
643                                      Standard_ShortReal&            theWidth,
644                                      Standard_ShortReal&            theAscent,
645                                      Standard_ShortReal&            theDescent) const
646 {
647   const Handle(OpenGl_Context)& aCtx = GetSharedContext();
648   if (aCtx.IsNull())
649   {
650     return;
651   }
652
653   const Standard_ShortReal aHeight = (theHeight < 2.0f) ? DefaultTextHeight() : theHeight;
654   OpenGl_Aspects aTextAspect;
655   TCollection_ExtendedString anExtText = theText;
656   NCollection_String aText (anExtText.ToExtString());
657   OpenGl_Text::StringSize (aCtx, aText, aTextAspect, aHeight,
658                            theView->RenderingParams().Resolution, theView->RenderingParams().FontHinting,
659                            theWidth, theAscent, theDescent);
660 }
661
662 //=======================================================================
663 //function : InsertLayerBefore
664 //purpose  :
665 //=======================================================================
666 void OpenGl_GraphicDriver::InsertLayerBefore (const Graphic3d_ZLayerId theLayerId,
667                                               const Graphic3d_ZLayerSettings& theSettings,
668                                               const Graphic3d_ZLayerId theLayerAfter)
669 {
670   base_type::InsertLayerBefore (theLayerId, theSettings, theLayerAfter);
671
672   // Add layer to all views
673   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next())
674   {
675     aViewIt.Value()->InsertLayerBefore (theLayerId, theSettings, theLayerAfter);
676   }
677 }
678
679 //=======================================================================
680 //function : InsertLayerAfter
681 //purpose  :
682 //=======================================================================
683 void OpenGl_GraphicDriver::InsertLayerAfter (const Graphic3d_ZLayerId theNewLayerId,
684                                              const Graphic3d_ZLayerSettings& theSettings,
685                                              const Graphic3d_ZLayerId theLayerBefore)
686 {
687   base_type::InsertLayerAfter (theNewLayerId, theSettings, theLayerBefore);
688
689   // Add layer to all views
690   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next())
691   {
692     aViewIt.Value()->InsertLayerAfter (theNewLayerId, theSettings, theLayerBefore);
693   }
694 }
695
696 //=======================================================================
697 //function : RemoveZLayer
698 //purpose  :
699 //=======================================================================
700 void OpenGl_GraphicDriver::RemoveZLayer (const Graphic3d_ZLayerId theLayerId)
701 {
702   base_type::RemoveZLayer (theLayerId);
703
704   // Remove layer from all of the views
705   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next())
706   {
707     aViewIt.Value()->RemoveZLayer (theLayerId);
708   }
709
710   // Unset Z layer for all of the structures.
711   for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure); aStructIt.More(); aStructIt.Next())
712   {
713     OpenGl_Structure* aStruct = aStructIt.ChangeValue ();
714     if (aStruct->ZLayer() == theLayerId)
715       aStruct->SetZLayer (Graphic3d_ZLayerId_Default);
716   }
717 }
718
719 //=======================================================================
720 //function : SetZLayerSettings
721 //purpose  :
722 //=======================================================================
723 void OpenGl_GraphicDriver::SetZLayerSettings (const Graphic3d_ZLayerId theLayerId,
724                                               const Graphic3d_ZLayerSettings& theSettings)
725 {
726   base_type::SetZLayerSettings (theLayerId, theSettings);
727
728   // Change Z layer settings in all managed views
729   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next())
730   {
731     aViewIt.Value()->SetZLayerSettings (theLayerId, theSettings);
732   }
733 }
734
735 // =======================================================================
736 // function : Structure
737 // purpose  :
738 // =======================================================================
739 Handle(Graphic3d_CStructure) OpenGl_GraphicDriver::CreateStructure (const Handle(Graphic3d_StructureManager)& theManager)
740 {
741   Handle(OpenGl_Structure) aStructure = new OpenGl_Structure (theManager);
742   myMapOfStructure.Bind (aStructure->Id, aStructure.operator->());
743   return aStructure;
744 }
745
746 // =======================================================================
747 // function : Structure
748 // purpose  :
749 // =======================================================================
750 void OpenGl_GraphicDriver::RemoveStructure (Handle(Graphic3d_CStructure)& theCStructure)
751 {
752   OpenGl_Structure* aStructure = NULL;
753   if (!myMapOfStructure.Find (theCStructure->Id, aStructure))
754   {
755     return;
756   }
757
758   myMapOfStructure.UnBind (theCStructure->Id);
759   aStructure->Release (GetSharedContext());
760   theCStructure.Nullify();
761 }
762
763 // =======================================================================
764 // function : CreateView
765 // purpose  :
766 // =======================================================================
767 Handle(Graphic3d_CView) OpenGl_GraphicDriver::CreateView (const Handle(Graphic3d_StructureManager)& theMgr)
768 {
769   Handle(OpenGl_View) aView = new OpenGl_View (theMgr, this, myCaps, &myStateCounter);
770   myMapOfView.Add (aView);
771   for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (myLayers); aLayerIter.More(); aLayerIter.Next())
772   {
773     const Handle(Graphic3d_Layer)& aLayer = aLayerIter.Value();
774     aView->InsertLayerAfter (aLayer->LayerId(), aLayer->LayerSettings(), Graphic3d_ZLayerId_UNKNOWN);
775   }
776   return aView;
777 }
778
779 // =======================================================================
780 // function : RemoveView
781 // purpose  :
782 // =======================================================================
783 void OpenGl_GraphicDriver::RemoveView (const Handle(Graphic3d_CView)& theView)
784 {
785   Handle(OpenGl_Context) aCtx = GetSharedContext();
786   Handle(OpenGl_View) aView   = Handle(OpenGl_View)::DownCast (theView);
787   if (aView.IsNull())
788   {
789     return;
790   }
791
792   if (!myMapOfView.Remove (aView))
793   {
794     return;
795   }
796
797   Handle(OpenGl_Window) aWindow = aView->GlWindow();
798   if (!aWindow.IsNull()
799     && aWindow->GetGlContext()->MakeCurrent())
800   {
801     aCtx = aWindow->GetGlContext();
802   }
803   else
804   {
805     // try to hijack another context if any
806     const Handle(OpenGl_Context)& anOtherCtx = GetSharedContext();
807     if (!anOtherCtx.IsNull()
808       && anOtherCtx != aWindow->GetGlContext())
809     {
810       aCtx = anOtherCtx;
811       aCtx->MakeCurrent();
812     }
813   }
814
815   aView->ReleaseGlResources (aCtx);
816   if (myMapOfView.IsEmpty())
817   {
818     // The last view removed but some objects still present.
819     // Release GL resources now without object destruction.
820     for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
821          aStructIt.More (); aStructIt.Next())
822     {
823       OpenGl_Structure* aStruct = aStructIt.ChangeValue();
824       aStruct->ReleaseGlResources (aCtx);
825     }
826
827     if (!myMapOfStructure.IsEmpty())
828     {
829       aView->StructureManager()->SetDeviceLost();
830     }
831   }
832 }
833
834 // =======================================================================
835 // function : Window
836 // purpose  :
837 // =======================================================================
838 Handle(OpenGl_Window) OpenGl_GraphicDriver::CreateRenderWindow (const Handle(Aspect_Window)&  theWindow,
839                                                                 const Aspect_RenderingContext theContext)
840 {
841   Handle(OpenGl_Context) aShareCtx = GetSharedContext();
842   Handle(OpenGl_Window) aWindow = new OpenGl_Window (this, theWindow, theContext, myCaps, aShareCtx);
843   return aWindow;
844 }
845
846 //=======================================================================
847 //function : ViewExists
848 //purpose  :
849 //=======================================================================
850 Standard_Boolean OpenGl_GraphicDriver::ViewExists (const Handle(Aspect_Window)& theWindow,
851                                                    Handle(Graphic3d_CView)& theView)
852 {
853   // Parse the list of views to find a view with the specified window
854   const Aspect_Drawable aNativeHandle = theWindow->NativeHandle();
855   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next())
856   {
857     const Handle(OpenGl_View)& aView = aViewIt.Value();
858     if (!aView->IsDefined()
859      || !aView->IsActive())
860     {
861       continue;
862     }
863
864     const Handle(Aspect_Window) anAspectWindow = aView->Window();
865     const Aspect_Drawable aViewNativeHandle = anAspectWindow->NativeHandle();
866     if (aViewNativeHandle == aNativeHandle)
867     {
868       theView = aView;
869       return true;
870     }
871   }
872
873   return false;
874 }
875
876 //=======================================================================
877 //function : setDeviceLost
878 //purpose  :
879 //=======================================================================
880 void OpenGl_GraphicDriver::setDeviceLost()
881 {
882   if (myMapOfStructure.IsEmpty())
883   {
884     return;
885   }
886
887   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView); aViewIter.More(); aViewIter.Next())
888   {
889     const Handle(OpenGl_View)& aView = aViewIter.Value();
890     if (aView->myWasRedrawnGL)
891     {
892       aView->StructureManager()->SetDeviceLost();
893     }
894   }
895 }