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__)
44 static const Handle(OpenGl_Context) TheNullGlCtx;
47 // =======================================================================
48 // function : OpenGl_GraphicDriver
50 // =======================================================================
51 OpenGl_GraphicDriver::OpenGl_GraphicDriver (const Handle(Aspect_DisplayConnection)& theDisp,
52 const Standard_Boolean theToInitialize)
53 : Graphic3d_GraphicDriver (theDisp),
54 myIsOwnContext (Standard_False),
55 #if defined(HAVE_EGL) || defined(__ANDROID__)
56 myEglDisplay ((Aspect_Display )EGL_NO_DISPLAY),
57 myEglContext ((Aspect_RenderingContext )EGL_NO_CONTEXT),
60 myCaps (new OpenGl_Caps()),
61 myMapOfView (1, NCollection_BaseAllocator::CommonBaseAllocator()),
62 myMapOfWS (1, NCollection_BaseAllocator::CommonBaseAllocator()),
63 myMapOfStructure (1, NCollection_BaseAllocator::CommonBaseAllocator()),
64 myUserDrawCallback (NULL)
66 #if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
67 if (myDisplayConnection.IsNull())
69 //Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: cannot connect to X server!");
73 Display* aDisplay = myDisplayConnection->GetDisplay();
74 Bool toSync = ::getenv ("CSF_GraphicSync") != NULL
75 || ::getenv ("CALL_SYNCHRO_X") != NULL;
76 XSynchronize (aDisplay, toSync);
78 #if !defined(HAVE_EGL)
79 // does the server know about OpenGL & GLX?
81 if (!XQueryExtension (aDisplay, "GLX", &aDummy, &aDummy, &aDummy))
83 ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, this system doesn't appear to support OpenGL!", Message_Warning);
90 Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: default context can not be initialized!");
94 // =======================================================================
95 // function : ~OpenGl_GraphicDriver
97 // =======================================================================
98 OpenGl_GraphicDriver::~OpenGl_GraphicDriver()
103 // =======================================================================
104 // function : ReleaseContext
106 // =======================================================================
107 void OpenGl_GraphicDriver::ReleaseContext()
109 Handle(OpenGl_Context) aCtxShared;
110 for (NCollection_Map<Handle(OpenGl_Workspace)>::Iterator aWindowIter (myMapOfWS);
111 aWindowIter.More(); aWindowIter.Next())
113 const Handle(OpenGl_Workspace)& aWindow = aWindowIter.ChangeValue();
114 const Handle(OpenGl_Context)& aCtx = aWindow->GetGlContext();
115 if (aCtx->MakeCurrent()
116 && aCtxShared.IsNull())
122 if (!aCtxShared.IsNull())
124 aCtxShared->MakeCurrent();
126 for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView);
127 aViewIter.More(); aViewIter.Next())
129 const Handle(OpenGl_View)& aView = aViewIter.ChangeValue();
130 aView->ReleaseGlResources (aCtxShared);
133 for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
134 aStructIt.More (); aStructIt.Next())
136 OpenGl_Structure* aStruct = aStructIt.ChangeValue();
137 aStruct->ReleaseGlResources (aCtxShared);
139 myDeviceLostFlag = myDeviceLostFlag || !myMapOfStructure.IsEmpty();
141 for (NCollection_Map<Handle(OpenGl_Workspace)>::Iterator aWindowIter (myMapOfWS);
142 aWindowIter.More(); aWindowIter.Next())
144 const Handle(OpenGl_Workspace)& aWindow = aWindowIter.ChangeValue();
145 const Handle(OpenGl_Context)& aCtx = aWindow->GetGlContext();
146 aCtx->forcedRelease();
149 #if defined(HAVE_EGL) || defined(__ANDROID__)
152 if (myEglContext != (Aspect_RenderingContext )EGL_NO_CONTEXT)
154 if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE)
156 ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, FAILED to release OpenGL context!", Message_Warning);
158 eglDestroyContext ((EGLDisplay )myEglDisplay, (EGLContext )myEglContext);
161 if (myEglDisplay != (Aspect_Display )EGL_NO_DISPLAY)
163 if (eglTerminate ((EGLDisplay )myEglDisplay) != EGL_TRUE)
165 ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, EGL, eglTerminate FAILED!", Message_Warning);
170 myEglDisplay = (Aspect_Display )EGL_NO_DISPLAY;
171 myEglContext = (Aspect_RenderingContext )EGL_NO_CONTEXT;
174 myIsOwnContext = Standard_False;
177 // =======================================================================
178 // function : InitContext
180 // =======================================================================
181 Standard_Boolean OpenGl_GraphicDriver::InitContext()
184 #if defined(HAVE_EGL) || defined(__ANDROID__)
186 #if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
187 if (myDisplayConnection.IsNull())
189 return Standard_False;
191 Display* aDisplay = myDisplayConnection->GetDisplay();
192 myEglDisplay = (Aspect_Display )eglGetDisplay (aDisplay);
194 myEglDisplay = (Aspect_Display )eglGetDisplay (EGL_DEFAULT_DISPLAY);
196 if ((EGLDisplay )myEglDisplay == EGL_NO_DISPLAY)
198 ::Message::DefaultMessenger()->Send ("Error: no EGL display!", Message_Fail);
199 return Standard_False;
202 EGLint aVerMajor = 0; EGLint aVerMinor = 0;
203 if (eglInitialize ((EGLDisplay )myEglDisplay, &aVerMajor, &aVerMinor) != EGL_TRUE)
205 ::Message::DefaultMessenger()->Send ("Error: EGL display is unavailable!", Message_Fail);
206 return Standard_False;
209 EGLint aConfigAttribs[] =
217 #if defined(GL_ES_VERSION_2_0)
218 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
220 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
225 EGLint aNbConfigs = 0;
226 if (eglChooseConfig ((EGLDisplay )myEglDisplay, aConfigAttribs, &myEglConfig, 1, &aNbConfigs) != EGL_TRUE
227 || myEglConfig == NULL)
230 aConfigAttribs[4 * 2 + 1] = 16; // try config with smaller depth buffer
231 if (eglChooseConfig ((EGLDisplay )myEglDisplay, aConfigAttribs, &myEglConfig, 1, &aNbConfigs) != EGL_TRUE
232 || myEglConfig == NULL)
234 ::Message::DefaultMessenger()->Send ("Error: EGL does not provide compatible configurations!", Message_Fail);
235 return Standard_False;
239 #if defined(GL_ES_VERSION_2_0)
240 EGLint anEglCtxAttribs[] =
242 EGL_CONTEXT_CLIENT_VERSION, 2,
245 if (eglBindAPI (EGL_OPENGL_ES_API) != EGL_TRUE)
247 ::Message::DefaultMessenger()->Send ("Error: EGL does not provide OpenGL ES client!", Message_Fail);
248 return Standard_False;
251 EGLint* anEglCtxAttribs = NULL;
252 if (eglBindAPI (EGL_OPENGL_API) != EGL_TRUE)
254 ::Message::DefaultMessenger()->Send ("Error: EGL does not provide OpenGL client!", Message_Fail);
255 return Standard_False;
259 myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs);
260 if ((EGLContext )myEglContext == EGL_NO_CONTEXT)
262 ::Message::DefaultMessenger()->Send ("Error: EGL is unable to create OpenGL context!", Message_Fail);
263 return Standard_False;
265 if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, (EGLContext )myEglContext) != EGL_TRUE)
267 ::Message::DefaultMessenger()->Send ("Error: EGL is unable bind OpenGL context!", Message_Fail);
268 return Standard_False;
271 myIsOwnContext = Standard_True;
272 return Standard_True;
275 #if defined(HAVE_EGL) || defined(__ANDROID__)
276 // =======================================================================
277 // function : InitEglContext
279 // =======================================================================
280 Standard_Boolean OpenGl_GraphicDriver::InitEglContext (Aspect_Display theEglDisplay,
281 Aspect_RenderingContext theEglContext,
285 #if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
286 if (myDisplayConnection.IsNull())
288 return Standard_False;
292 if ((EGLDisplay )theEglDisplay == EGL_NO_DISPLAY
293 || (EGLContext )theEglContext == EGL_NO_CONTEXT
294 || theEglConfig == NULL)
296 return Standard_False;
298 myEglDisplay = theEglDisplay;
299 myEglContext = theEglContext;
300 myEglConfig = theEglConfig;
301 return Standard_True;
305 // =======================================================================
306 // function : InquireLightLimit
308 // =======================================================================
309 Standard_Integer OpenGl_GraphicDriver::InquireLightLimit()
311 return OpenGLMaxLights;
314 // =======================================================================
315 // function : InquireViewLimit
317 // =======================================================================
318 Standard_Integer OpenGl_GraphicDriver::InquireViewLimit()
323 // =======================================================================
324 // function : InquirePlaneLimit
326 // =======================================================================
327 Standard_Integer OpenGl_GraphicDriver::InquirePlaneLimit()
329 // NOTE the 2 first planes are reserved for ZClipping
330 const Handle(OpenGl_Context)& aCtx = GetSharedContext();
331 return aCtx.IsNull() ? 0 : Max (aCtx->MaxClipPlanes() - 2, 0);
334 // =======================================================================
335 // function : UserDrawCallback
337 // =======================================================================
338 OpenGl_GraphicDriver::OpenGl_UserDrawCallback_t& OpenGl_GraphicDriver::UserDrawCallback()
340 return myUserDrawCallback;
343 // =======================================================================
344 // function : DefaultTextHeight
346 // =======================================================================
347 Standard_ShortReal OpenGl_GraphicDriver::DefaultTextHeight() const
352 // =======================================================================
353 // function : EnableVBO
355 // =======================================================================
356 void OpenGl_GraphicDriver::EnableVBO (const Standard_Boolean theToTurnOn)
358 myCaps->vboDisable = !theToTurnOn;
361 // =======================================================================
362 // function : GetSharedContext
364 // =======================================================================
365 const Handle(OpenGl_Context)& OpenGl_GraphicDriver::GetSharedContext() const
367 if (myMapOfWS.IsEmpty())
372 NCollection_Map<Handle(OpenGl_Workspace)>::Iterator anIter (myMapOfWS);
373 return anIter.Value()->GetGlContext();
376 // =======================================================================
377 // function : MemoryInfo
379 // =======================================================================
380 Standard_Boolean OpenGl_GraphicDriver::MemoryInfo (Standard_Size& theFreeBytes,
381 TCollection_AsciiString& theInfo) const
383 // this is extra work (for OpenGl_Context initialization)...
384 OpenGl_Context aGlCtx;
387 return Standard_False;
389 theFreeBytes = aGlCtx.AvailableMemory();
390 theInfo = aGlCtx.MemoryInfo();
391 return !theInfo.IsEmpty();
394 // =======================================================================
395 // function : SetImmediateModeDrawToFront
397 // =======================================================================
398 Standard_Boolean OpenGl_GraphicDriver::SetImmediateModeDrawToFront (const Graphic3d_CView& theCView,
399 const Standard_Boolean theDrawToFrontBuffer)
401 if (theCView.ViewId == -1)
403 return Standard_False;
406 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
409 return aCView->WS->SetImmediateModeDrawToFront (theDrawToFrontBuffer);
411 return Standard_False;
414 // =======================================================================
417 // =======================================================================
418 Standard_Boolean OpenGl_GraphicDriver::Print (const Graphic3d_CView& theCView,
419 const Aspect_Handle thePrintDC,
420 const Standard_Boolean theToShowBackground,
421 const Standard_CString theFilename,
422 const Aspect_PrintAlgo thePrintAlgorithm,
423 const Standard_Real theScaleFactor) const
425 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
427 || !myPrintContext.IsNull())
429 return Standard_False;
432 Standard_Boolean isPrinted = Standard_False;
433 myPrintContext = new OpenGl_PrinterContext();
435 isPrinted = aCView->WS->Print (myPrintContext,
443 Standard_NotImplemented::Raise ("OpenGl_GraphicDriver::Print is implemented only on Windows");
445 myPrintContext.Nullify();
449 // =======================================================================
450 // function : ZBufferTriedronSetup
452 // =======================================================================
453 void OpenGl_GraphicDriver::ZBufferTriedronSetup (const Graphic3d_CView& theCView,
454 const Quantity_NameOfColor theXColor,
455 const Quantity_NameOfColor theYColor,
456 const Quantity_NameOfColor theZColor,
457 const Standard_Real theSizeRatio,
458 const Standard_Real theAxisDiametr,
459 const Standard_Integer theNbFacets)
461 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
467 OpenGl_Trihedron& aTrih = aCView->View->ChangeTrihedron();
468 aTrih.SetArrowsColors (theXColor, theYColor, theZColor);
469 aTrih.SetSizeRatio (theSizeRatio);
470 aTrih.SetNbFacets (theNbFacets);
471 aTrih.SetArrowDiameter (theAxisDiametr);
474 // =======================================================================
475 // function : TriedronDisplay
477 // =======================================================================
478 void OpenGl_GraphicDriver::TriedronDisplay (const Graphic3d_CView& theCView,
479 const Aspect_TypeOfTriedronPosition thePosition,
480 const Quantity_NameOfColor theColor,
481 const Standard_Real theScale,
482 const Standard_Boolean theAsWireframe)
484 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
487 aCView->View->TriedronDisplay (thePosition, theColor, theScale, theAsWireframe);
491 // =======================================================================
492 // function : TriedronErase
494 // =======================================================================
495 void OpenGl_GraphicDriver::TriedronErase (const Graphic3d_CView& theCView)
497 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
500 aCView->View->TriedronErase (aCView->WS->GetGlContext());
504 // =======================================================================
505 // function : TriedronEcho
507 // =======================================================================
508 void OpenGl_GraphicDriver::TriedronEcho (const Graphic3d_CView& ,
509 const Aspect_TypeOfTriedronEcho )
514 // =======================================================================
515 // function : Environment
517 // =======================================================================
518 void OpenGl_GraphicDriver::Environment (const Graphic3d_CView& theCView)
520 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
526 aCView->View->SetTextureEnv (aCView->WS->GetGlContext(), theCView.Context.TextureEnv);
527 aCView->View->SetSurfaceDetail ((Visual3d_TypeOfSurfaceDetail)theCView.Context.SurfaceDetail);
530 // =======================================================================
531 // function : BackgroundImage
533 // =======================================================================
534 void OpenGl_GraphicDriver::BackgroundImage (const Standard_CString theFileName,
535 const Graphic3d_CView& theCView,
536 const Aspect_FillMethod theFillStyle)
538 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
541 aCView->View->CreateBackgroundTexture (theFileName, theFillStyle);
545 // =======================================================================
546 // function : SetBgImageStyle
548 // =======================================================================
549 void OpenGl_GraphicDriver::SetBgImageStyle (const Graphic3d_CView& theCView,
550 const Aspect_FillMethod theFillStyle)
552 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
555 aCView->View->SetBackgroundTextureStyle (theFillStyle);
559 // =======================================================================
560 // function : SetBgGradientStyle
562 // =======================================================================
563 void OpenGl_GraphicDriver::SetBgGradientStyle (const Graphic3d_CView& theCView,
564 const Aspect_GradientFillMethod theFillType)
566 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
569 aCView->View->SetBackgroundGradientType (theFillType);
573 // =======================================================================
574 // function : GraduatedTrihedronDisplay
576 // =======================================================================
577 void OpenGl_GraphicDriver::GraduatedTrihedronDisplay (const Graphic3d_CView& theCView,
578 const Graphic3d_GraduatedTrihedron& theCubic)
580 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
583 aCView->View->GraduatedTrihedronDisplay (aCView->WS->GetGlContext(), theCubic);
587 // =======================================================================
588 // function : GraduatedTrihedronErase
590 // =======================================================================
591 void OpenGl_GraphicDriver::GraduatedTrihedronErase (const Graphic3d_CView& theCView)
593 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
596 aCView->View->GraduatedTrihedronErase (aCView->WS->GetGlContext());
600 // =======================================================================
601 // function : GraduatedTrihedronMinMaxValues
603 // =======================================================================
604 void OpenGl_GraphicDriver::GraduatedTrihedronMinMaxValues (const Graphic3d_CView& theView,
605 const Graphic3d_Vec3 theMin,
606 const Graphic3d_Vec3 theMax)
608 const OpenGl_CView* aCView = (const OpenGl_CView* )theView.ptrView;
611 aCView->View->ChangeGraduatedTrihedron().SetMinMax (theMin, theMax);
615 // =======================================================================
616 // function : SetBuffersNoSwap
618 // =======================================================================
619 void OpenGl_GraphicDriver::SetBuffersNoSwap (const Standard_Boolean theIsNoSwap)
621 myCaps->buffersNoSwap = theIsNoSwap;
624 // =======================================================================
625 // function : TextSize
627 // =======================================================================
628 void OpenGl_GraphicDriver::TextSize (const Standard_CString theText,
629 const Standard_ShortReal theHeight,
630 Standard_ShortReal& theWidth,
631 Standard_ShortReal& theAscent,
632 Standard_ShortReal& theDescent) const
634 const Handle(OpenGl_Context)& aCtx = GetSharedContext();
640 const Standard_ShortReal aHeight = (theHeight < 2.0f) ? DefaultTextHeight() : theHeight;
641 OpenGl_TextParam aTextParam;
642 aTextParam.Height = (int )aHeight;
643 OpenGl_AspectText aTextAspect;
644 CALL_DEF_CONTEXTTEXT aDefaultContextText =
651 { 1.F, 1.F, 1.F }, //Color
652 (int)Aspect_TOST_NORMAL, //Style
653 (int)Aspect_TODT_NORMAL, //DisplayType
654 { 1.F, 1.F, 1.F }, //ColorSubTitle
657 (int)Font_FA_Regular //TextFontAspect
659 aTextAspect.SetAspect(aDefaultContextText);
660 TCollection_ExtendedString anExtText = theText;
661 NCollection_String aText = (Standard_Utf16Char* )anExtText.ToExtString();
662 OpenGl_Text::StringSize (aCtx, aText, aTextAspect, aTextParam, theWidth, theAscent, theDescent);