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