1 // Created on: 2011-10-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2013 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_GraphicDriver.hxx>
17 #include <OpenGl_Context.hxx>
18 #include <OpenGl_Flipper.hxx>
19 #include <OpenGl_GraduatedTrihedron.hxx>
20 #include <OpenGl_Group.hxx>
21 #include <OpenGl_CView.hxx>
22 #include <OpenGl_View.hxx>
23 #include <OpenGl_StencilTest.hxx>
24 #include <OpenGl_Text.hxx>
25 #include <OpenGl_Trihedron.hxx>
26 #include <OpenGl_Workspace.hxx>
28 #include <Aspect_GraphicDeviceDefinitionError.hxx>
29 #include <Message_Messenger.hxx>
30 #include <OSD_Environment.hxx>
31 #include <Standard_NotImplemented.hxx>
33 #if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
34 #include <X11/Xlib.h> // XOpenDisplay()
37 #if defined(HAVE_EGL) || defined(__ANDROID__)
41 IMPLEMENT_STANDARD_HANDLE(OpenGl_GraphicDriver,Graphic3d_GraphicDriver)
42 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_GraphicDriver,Graphic3d_GraphicDriver)
46 static const Handle(OpenGl_Context) TheNullGlCtx;
49 // =======================================================================
50 // function : OpenGl_GraphicDriver
52 // =======================================================================
53 OpenGl_GraphicDriver::OpenGl_GraphicDriver (const Handle(Aspect_DisplayConnection)& theDisp,
54 const Standard_Boolean theToInitialize)
55 : Graphic3d_GraphicDriver (theDisp),
56 myIsOwnContext (Standard_False),
57 #if defined(HAVE_EGL) || defined(__ANDROID__)
58 myEglDisplay ((Aspect_Display )EGL_NO_DISPLAY),
59 myEglContext ((Aspect_RenderingContext )EGL_NO_CONTEXT),
62 myCaps (new OpenGl_Caps()),
63 myMapOfView (1, NCollection_BaseAllocator::CommonBaseAllocator()),
64 myMapOfWS (1, NCollection_BaseAllocator::CommonBaseAllocator()),
65 myMapOfStructure (1, NCollection_BaseAllocator::CommonBaseAllocator()),
66 myUserDrawCallback (NULL),
67 myTempText (new OpenGl_Text())
69 #if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
70 if (myDisplayConnection.IsNull())
72 //Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: cannot connect to X server!");
76 Display* aDisplay = myDisplayConnection->GetDisplay();
77 Bool toSync = ::getenv ("CSF_GraphicSync") != NULL
78 || ::getenv ("CALL_SYNCHRO_X") != NULL;
79 XSynchronize (aDisplay, toSync);
81 #if !defined(HAVE_EGL)
82 // does the server know about OpenGL & GLX?
84 if (!XQueryExtension (aDisplay, "GLX", &aDummy, &aDummy, &aDummy))
86 ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, this system doesn't appear to support OpenGL!", Message_Warning);
93 Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: default context can not be initialized!");
97 // =======================================================================
98 // function : ~OpenGl_GraphicDriver
100 // =======================================================================
101 OpenGl_GraphicDriver::~OpenGl_GraphicDriver()
106 // =======================================================================
107 // function : ReleaseContext
109 // =======================================================================
110 void OpenGl_GraphicDriver::ReleaseContext()
112 Handle(OpenGl_Context) aCtxShared;
113 for (NCollection_Map<Handle(OpenGl_Workspace)>::Iterator aWindowIter (myMapOfWS);
114 aWindowIter.More(); aWindowIter.Next())
116 const Handle(OpenGl_Workspace)& aWindow = aWindowIter.ChangeValue();
117 const Handle(OpenGl_Context)& aCtx = aWindow->GetGlContext();
118 if (aCtx->MakeCurrent()
119 && aCtxShared.IsNull())
125 if (!aCtxShared.IsNull())
127 aCtxShared->MakeCurrent();
129 for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView);
130 aViewIter.More(); aViewIter.Next())
132 const Handle(OpenGl_View)& aView = aViewIter.ChangeValue();
133 aView->ReleaseGlResources (aCtxShared);
136 for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
137 aStructIt.More (); aStructIt.Next())
139 OpenGl_Structure* aStruct = aStructIt.ChangeValue();
140 aStruct->ReleaseGlResources (aCtxShared);
142 myTempText->Release (aCtxShared.operator->());
143 myDeviceLostFlag = myDeviceLostFlag || !myMapOfStructure.IsEmpty();
145 for (NCollection_Map<Handle(OpenGl_Workspace)>::Iterator aWindowIter (myMapOfWS);
146 aWindowIter.More(); aWindowIter.Next())
148 const Handle(OpenGl_Workspace)& aWindow = aWindowIter.ChangeValue();
149 const Handle(OpenGl_Context)& aCtx = aWindow->GetGlContext();
150 aCtx->forcedRelease();
153 #if defined(HAVE_EGL) || defined(__ANDROID__)
156 if (myEglContext != (Aspect_RenderingContext )EGL_NO_CONTEXT)
158 if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE)
160 ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, FAILED to release OpenGL context!", Message_Warning);
162 eglDestroyContext ((EGLDisplay )myEglDisplay, (EGLContext )myEglContext);
165 if (myEglDisplay != (Aspect_Display )EGL_NO_DISPLAY)
167 if (eglTerminate ((EGLDisplay )myEglDisplay) != EGL_TRUE)
169 ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, EGL, eglTerminate FAILED!", Message_Warning);
174 myEglDisplay = (Aspect_Display )EGL_NO_DISPLAY;
175 myEglContext = (Aspect_RenderingContext )EGL_NO_CONTEXT;
178 myIsOwnContext = Standard_False;
181 // =======================================================================
182 // function : InitContext
184 // =======================================================================
185 Standard_Boolean OpenGl_GraphicDriver::InitContext()
188 #if defined(HAVE_EGL) || defined(__ANDROID__)
190 #if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
191 if (myDisplayConnection.IsNull())
193 return Standard_False;
195 Display* aDisplay = myDisplayConnection->GetDisplay();
196 myEglDisplay = (Aspect_Display )eglGetDisplay (aDisplay);
198 myEglDisplay = (Aspect_Display )eglGetDisplay (EGL_DEFAULT_DISPLAY);
200 if ((EGLDisplay )myEglDisplay == EGL_NO_DISPLAY)
202 ::Message::DefaultMessenger()->Send ("Error: no EGL display!", Message_Fail);
203 return Standard_False;
206 EGLint aVerMajor = 0; EGLint aVerMinor = 0;
207 if (eglInitialize ((EGLDisplay )myEglDisplay, &aVerMajor, &aVerMinor) != EGL_TRUE)
209 ::Message::DefaultMessenger()->Send ("Error: EGL display is unavailable!", Message_Fail);
210 return Standard_False;
213 EGLint aConfigAttribs[] =
221 #if defined(GL_ES_VERSION_2_0)
222 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
224 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
229 EGLint aNbConfigs = 0;
230 if (eglChooseConfig ((EGLDisplay )myEglDisplay, aConfigAttribs, &myEglConfig, 1, &aNbConfigs) != EGL_TRUE
231 || myEglConfig == NULL)
234 aConfigAttribs[4 * 2 + 1] = 16; // try config with smaller depth buffer
235 if (eglChooseConfig ((EGLDisplay )myEglDisplay, aConfigAttribs, &myEglConfig, 1, &aNbConfigs) != EGL_TRUE
236 || myEglConfig == NULL)
238 ::Message::DefaultMessenger()->Send ("Error: EGL does not provide compatible configurations!", Message_Fail);
239 return Standard_False;
243 #if defined(GL_ES_VERSION_2_0)
244 EGLint anEglCtxAttribs[] =
246 EGL_CONTEXT_CLIENT_VERSION, 2,
249 if (eglBindAPI (EGL_OPENGL_ES_API) != EGL_TRUE)
251 ::Message::DefaultMessenger()->Send ("Error: EGL does not provide OpenGL ES client!", Message_Fail);
252 return Standard_False;
255 EGLint* anEglCtxAttribs = NULL;
256 if (eglBindAPI (EGL_OPENGL_API) != EGL_TRUE)
258 ::Message::DefaultMessenger()->Send ("Error: EGL does not provide OpenGL client!", Message_Fail);
259 return Standard_False;
263 myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs);
264 if ((EGLContext )myEglContext == EGL_NO_CONTEXT)
266 ::Message::DefaultMessenger()->Send ("Error: EGL is unable to create OpenGL context!", Message_Fail);
267 return Standard_False;
269 if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, (EGLContext )myEglContext) != EGL_TRUE)
271 ::Message::DefaultMessenger()->Send ("Error: EGL is unable bind OpenGL context!", Message_Fail);
272 return Standard_False;
275 myIsOwnContext = Standard_True;
276 return Standard_True;
279 #if defined(HAVE_EGL) || defined(__ANDROID__)
280 // =======================================================================
281 // function : InitEglContext
283 // =======================================================================
284 Standard_Boolean OpenGl_GraphicDriver::InitEglContext (Aspect_Display theEglDisplay,
285 Aspect_RenderingContext theEglContext,
289 #if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
290 if (myDisplayConnection.IsNull())
292 return Standard_False;
296 if ((EGLDisplay )theEglDisplay == EGL_NO_DISPLAY
297 || (EGLContext )theEglContext == EGL_NO_CONTEXT
298 || theEglConfig == NULL)
300 return Standard_False;
302 myEglDisplay = theEglDisplay;
303 myEglContext = theEglContext;
304 myEglConfig = theEglConfig;
305 return Standard_True;
309 // =======================================================================
310 // function : InquireLightLimit
312 // =======================================================================
313 Standard_Integer OpenGl_GraphicDriver::InquireLightLimit()
315 return OpenGLMaxLights;
318 // =======================================================================
319 // function : InquireViewLimit
321 // =======================================================================
322 Standard_Integer OpenGl_GraphicDriver::InquireViewLimit()
327 // =======================================================================
328 // function : InquirePlaneLimit
330 // =======================================================================
331 Standard_Integer OpenGl_GraphicDriver::InquirePlaneLimit()
333 // NOTE the 2 first planes are reserved for ZClipping
334 const Handle(OpenGl_Context)& aCtx = GetSharedContext();
335 return aCtx.IsNull() ? 0 : Max (aCtx->MaxClipPlanes() - 2, 0);
338 // =======================================================================
339 // function : UserDrawCallback
341 // =======================================================================
342 OpenGl_GraphicDriver::OpenGl_UserDrawCallback_t& OpenGl_GraphicDriver::UserDrawCallback()
344 return myUserDrawCallback;
347 // =======================================================================
348 // function : DefaultTextHeight
350 // =======================================================================
351 Standard_ShortReal OpenGl_GraphicDriver::DefaultTextHeight() const
356 // =======================================================================
357 // function : EnableVBO
359 // =======================================================================
360 void OpenGl_GraphicDriver::EnableVBO (const Standard_Boolean theToTurnOn)
362 myCaps->vboDisable = !theToTurnOn;
365 // =======================================================================
366 // function : GetSharedContext
368 // =======================================================================
369 const Handle(OpenGl_Context)& OpenGl_GraphicDriver::GetSharedContext() const
371 if (myMapOfWS.IsEmpty())
376 NCollection_Map<Handle(OpenGl_Workspace)>::Iterator anIter (myMapOfWS);
377 return anIter.Value()->GetGlContext();
380 // =======================================================================
381 // function : MemoryInfo
383 // =======================================================================
384 Standard_Boolean OpenGl_GraphicDriver::MemoryInfo (Standard_Size& theFreeBytes,
385 TCollection_AsciiString& theInfo) const
387 // this is extra work (for OpenGl_Context initialization)...
388 OpenGl_Context aGlCtx;
391 return Standard_False;
393 theFreeBytes = aGlCtx.AvailableMemory();
394 theInfo = aGlCtx.MemoryInfo();
395 return !theInfo.IsEmpty();
398 // =======================================================================
399 // function : SetImmediateModeDrawToFront
401 // =======================================================================
402 Standard_Boolean OpenGl_GraphicDriver::SetImmediateModeDrawToFront (const Graphic3d_CView& theCView,
403 const Standard_Boolean theDrawToFrontBuffer)
405 if (theCView.ViewId == -1)
407 return Standard_False;
410 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
413 return aCView->WS->SetImmediateModeDrawToFront (theDrawToFrontBuffer);
415 return Standard_False;
418 // =======================================================================
419 // function : DisplayImmediateStructure
421 // =======================================================================
422 void OpenGl_GraphicDriver::DisplayImmediateStructure (const Graphic3d_CView& theCView,
423 const Handle(Graphic3d_Structure)& theStructure)
425 OpenGl_CView* aCView = (OpenGl_CView* )theCView.ptrView;
431 aCView->View->DisplayImmediateStructure (theStructure);
434 // =======================================================================
435 // function : EraseImmediateStructure
437 // =======================================================================
438 void OpenGl_GraphicDriver::EraseImmediateStructure (const Graphic3d_CView& theCView,
439 const Graphic3d_CStructure& theCStructure)
441 OpenGl_CView* aCView = (OpenGl_CView* )theCView.ptrView;
442 OpenGl_Structure* aStructure = (OpenGl_Structure* )&theCStructure;
448 aCView->View->EraseImmediateStructure (aStructure);
452 // =======================================================================
455 // =======================================================================
456 Standard_Boolean OpenGl_GraphicDriver::Print (const Graphic3d_CView& theCView,
457 const Aspect_CLayer2d& theCUnderLayer,
458 const Aspect_CLayer2d& theCOverLayer,
459 const Aspect_Handle thePrintDC,
460 const Standard_Boolean theToShowBackground,
461 const Standard_CString theFilename,
462 const Aspect_PrintAlgo thePrintAlgorithm,
463 const Standard_Real theScaleFactor) const
465 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
467 || !myPrintContext.IsNull())
469 return Standard_False;
472 Standard_Boolean isPrinted = Standard_False;
473 myPrintContext = new OpenGl_PrinterContext();
475 isPrinted = aCView->WS->Print (myPrintContext,
485 Standard_NotImplemented::Raise ("OpenGl_GraphicDriver::Print is implemented only on Windows");
487 myPrintContext.Nullify();
491 // =======================================================================
492 // function : ZBufferTriedronSetup
494 // =======================================================================
495 void OpenGl_GraphicDriver::ZBufferTriedronSetup (const Graphic3d_CView& theCView,
496 const Quantity_NameOfColor theXColor,
497 const Quantity_NameOfColor theYColor,
498 const Quantity_NameOfColor theZColor,
499 const Standard_Real theSizeRatio,
500 const Standard_Real theAxisDiametr,
501 const Standard_Integer theNbFacets)
503 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
509 OpenGl_Trihedron& aTrih = aCView->View->ChangeTrihedron();
510 aTrih.SetArrowsColors (theXColor, theYColor, theZColor);
511 aTrih.SetSizeRatio (theSizeRatio);
512 aTrih.SetNbFacets (theNbFacets);
513 aTrih.SetArrowDiameter (theAxisDiametr);
516 // =======================================================================
517 // function : TriedronDisplay
519 // =======================================================================
520 void OpenGl_GraphicDriver::TriedronDisplay (const Graphic3d_CView& theCView,
521 const Aspect_TypeOfTriedronPosition thePosition,
522 const Quantity_NameOfColor theColor,
523 const Standard_Real theScale,
524 const Standard_Boolean theAsWireframe)
526 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
529 aCView->View->TriedronDisplay (thePosition, theColor, theScale, theAsWireframe);
533 // =======================================================================
534 // function : TriedronErase
536 // =======================================================================
537 void OpenGl_GraphicDriver::TriedronErase (const Graphic3d_CView& theCView)
539 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
542 aCView->View->TriedronErase (aCView->WS->GetGlContext());
546 // =======================================================================
547 // function : TriedronEcho
549 // =======================================================================
550 void OpenGl_GraphicDriver::TriedronEcho (const Graphic3d_CView& ,
551 const Aspect_TypeOfTriedronEcho )
556 // =======================================================================
557 // function : Environment
559 // =======================================================================
560 void OpenGl_GraphicDriver::Environment (const Graphic3d_CView& theCView)
562 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
568 aCView->View->SetTextureEnv (aCView->WS->GetGlContext(), theCView.Context.TextureEnv);
569 aCView->View->SetSurfaceDetail ((Visual3d_TypeOfSurfaceDetail)theCView.Context.SurfaceDetail);
572 // =======================================================================
573 // function : BackgroundImage
575 // =======================================================================
576 void OpenGl_GraphicDriver::BackgroundImage (const Standard_CString theFileName,
577 const Graphic3d_CView& theCView,
578 const Aspect_FillMethod theFillStyle)
580 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
583 aCView->View->CreateBackgroundTexture (theFileName, theFillStyle);
587 // =======================================================================
588 // function : SetBgImageStyle
590 // =======================================================================
591 void OpenGl_GraphicDriver::SetBgImageStyle (const Graphic3d_CView& theCView,
592 const Aspect_FillMethod theFillStyle)
594 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
597 aCView->View->SetBackgroundTextureStyle (theFillStyle);
601 // =======================================================================
602 // function : SetBgGradientStyle
604 // =======================================================================
605 void OpenGl_GraphicDriver::SetBgGradientStyle (const Graphic3d_CView& theCView,
606 const Aspect_GradientFillMethod theFillType)
608 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
611 aCView->View->SetBackgroundGradientType (theFillType);
615 // =======================================================================
616 // function : GraduatedTrihedronDisplay
618 // =======================================================================
619 void OpenGl_GraphicDriver::GraduatedTrihedronDisplay (const Graphic3d_CView& theCView,
620 const Graphic3d_GraduatedTrihedron& theCubic)
622 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
625 aCView->View->GraduatedTrihedronDisplay (aCView->WS->GetGlContext(), theCubic);
629 // =======================================================================
630 // function : GraduatedTrihedronErase
632 // =======================================================================
633 void OpenGl_GraphicDriver::GraduatedTrihedronErase (const Graphic3d_CView& theCView)
635 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
638 aCView->View->GraduatedTrihedronErase (aCView->WS->GetGlContext());
642 // =======================================================================
643 // function : GraduatedTrihedronMinMaxValues
645 // =======================================================================
646 void OpenGl_GraphicDriver::GraduatedTrihedronMinMaxValues (const Graphic3d_CView& theView,
647 const Graphic3d_Vec3 theMin,
648 const Graphic3d_Vec3 theMax)
650 const OpenGl_CView* aCView = (const OpenGl_CView* )theView.ptrView;
653 aCView->View->ChangeGraduatedTrihedron().SetMinMax (theMin, theMax);