0026128: Visualization, TKOpenGl - fix misprint in external GLX context initialization
[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 #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>
27
28 #include <Aspect_GraphicDeviceDefinitionError.hxx>
29 #include <Message_Messenger.hxx>
30 #include <OSD_Environment.hxx>
31 #include <Standard_NotImplemented.hxx>
32
33 #if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
34   #include <X11/Xlib.h> // XOpenDisplay()
35 #endif
36
37 #if defined(HAVE_EGL) || defined(__ANDROID__)
38   #include <EGL/egl.h>
39 #endif
40
41 IMPLEMENT_STANDARD_HANDLE(OpenGl_GraphicDriver,Graphic3d_GraphicDriver)
42 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_GraphicDriver,Graphic3d_GraphicDriver)
43
44 namespace
45 {
46   static const Handle(OpenGl_Context) TheNullGlCtx;
47 }
48
49 // =======================================================================
50 // function : OpenGl_GraphicDriver
51 // purpose  :
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),
60   myEglConfig  (NULL),
61 #endif
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())
68 {
69 #if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
70   if (myDisplayConnection.IsNull())
71   {
72     //Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: cannot connect to X server!");
73     return;
74   }
75
76   Display* aDisplay = myDisplayConnection->GetDisplay();
77   Bool toSync = ::getenv ("CSF_GraphicSync") != NULL
78              || ::getenv ("CALL_SYNCHRO_X")  != NULL;
79   XSynchronize (aDisplay, toSync);
80
81 #if !defined(HAVE_EGL)
82   // does the server know about OpenGL & GLX?
83   int aDummy;
84   if (!XQueryExtension (aDisplay, "GLX", &aDummy, &aDummy, &aDummy))
85   {
86     ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, this system doesn't appear to support OpenGL!", Message_Warning);
87   }
88 #endif
89 #endif
90   if (theToInitialize
91   && !InitContext())
92   {
93     Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: default context can not be initialized!");
94   }
95 }
96
97 // =======================================================================
98 // function : ~OpenGl_GraphicDriver
99 // purpose  :
100 // =======================================================================
101 OpenGl_GraphicDriver::~OpenGl_GraphicDriver()
102 {
103   ReleaseContext();
104 }
105
106 // =======================================================================
107 // function : ReleaseContext
108 // purpose  :
109 // =======================================================================
110 void OpenGl_GraphicDriver::ReleaseContext()
111 {
112   Handle(OpenGl_Context) aCtxShared;
113   for (NCollection_Map<Handle(OpenGl_Workspace)>::Iterator aWindowIter (myMapOfWS);
114        aWindowIter.More(); aWindowIter.Next())
115   {
116     const Handle(OpenGl_Workspace)& aWindow = aWindowIter.ChangeValue();
117     const Handle(OpenGl_Context)&   aCtx    = aWindow->GetGlContext();
118     if (aCtx->MakeCurrent()
119      && aCtxShared.IsNull())
120     {
121       aCtxShared = aCtx;
122     }
123   }
124
125   if (!aCtxShared.IsNull())
126   {
127     aCtxShared->MakeCurrent();
128   }
129   for (NCollection_Map<Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView);
130        aViewIter.More(); aViewIter.Next())
131   {
132     const Handle(OpenGl_View)& aView = aViewIter.ChangeValue();
133     aView->ReleaseGlResources (aCtxShared);
134   }
135
136   for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
137        aStructIt.More (); aStructIt.Next())
138   {
139     OpenGl_Structure* aStruct = aStructIt.ChangeValue();
140     aStruct->ReleaseGlResources (aCtxShared);
141   }
142   myTempText->Release (aCtxShared.operator->());
143   myDeviceLostFlag = myDeviceLostFlag || !myMapOfStructure.IsEmpty();
144
145   for (NCollection_Map<Handle(OpenGl_Workspace)>::Iterator aWindowIter (myMapOfWS);
146        aWindowIter.More(); aWindowIter.Next())
147   {
148     const Handle(OpenGl_Workspace)& aWindow = aWindowIter.ChangeValue();
149     const Handle(OpenGl_Context)&   aCtx    = aWindow->GetGlContext();
150     aCtx->forcedRelease();
151   }
152
153 #if defined(HAVE_EGL) || defined(__ANDROID__)
154   if (myIsOwnContext)
155   {
156     if (myEglContext != (Aspect_RenderingContext )EGL_NO_CONTEXT)
157     {
158       if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE)
159       {
160         ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, FAILED to release OpenGL context!", Message_Warning);
161       }
162       eglDestroyContext ((EGLDisplay )myEglDisplay, (EGLContext )myEglContext);
163     }
164
165     if (myEglDisplay != (Aspect_Display )EGL_NO_DISPLAY)
166     {
167       if (eglTerminate ((EGLDisplay )myEglDisplay) != EGL_TRUE)
168       {
169         ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, EGL, eglTerminate FAILED!", Message_Warning);
170       }
171     }
172   }
173
174   myEglDisplay = (Aspect_Display )EGL_NO_DISPLAY;
175   myEglContext = (Aspect_RenderingContext )EGL_NO_CONTEXT;
176   myEglConfig  = NULL;
177 #endif
178   myIsOwnContext = Standard_False;
179 }
180
181 // =======================================================================
182 // function : InitContext
183 // purpose  :
184 // =======================================================================
185 Standard_Boolean OpenGl_GraphicDriver::InitContext()
186 {
187   ReleaseContext();
188 #if defined(HAVE_EGL) || defined(__ANDROID__)
189
190 #if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
191   if (myDisplayConnection.IsNull())
192   {
193     return Standard_False;
194   }
195   Display* aDisplay = myDisplayConnection->GetDisplay();
196   myEglDisplay = (Aspect_Display )eglGetDisplay (aDisplay);
197 #else
198   myEglDisplay = (Aspect_Display )eglGetDisplay (EGL_DEFAULT_DISPLAY);
199 #endif
200   if ((EGLDisplay )myEglDisplay == EGL_NO_DISPLAY)
201   {
202     ::Message::DefaultMessenger()->Send ("Error: no EGL display!", Message_Fail);
203     return Standard_False;
204   }
205
206   EGLint aVerMajor = 0; EGLint aVerMinor = 0;
207   if (eglInitialize ((EGLDisplay )myEglDisplay, &aVerMajor, &aVerMinor) != EGL_TRUE)
208   {
209     ::Message::DefaultMessenger()->Send ("Error: EGL display is unavailable!", Message_Fail);
210     return Standard_False;
211   }
212
213   EGLint aConfigAttribs[] =
214   {
215     EGL_RED_SIZE,     8,
216     EGL_GREEN_SIZE,   8,
217     EGL_BLUE_SIZE,    8,
218     EGL_ALPHA_SIZE,   0,
219     EGL_DEPTH_SIZE,   24,
220     EGL_STENCIL_SIZE, 8,
221   #if defined(GL_ES_VERSION_2_0)
222     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
223   #else
224     EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
225   #endif
226     EGL_NONE
227   };
228
229   EGLint aNbConfigs = 0;
230   if (eglChooseConfig ((EGLDisplay )myEglDisplay, aConfigAttribs, &myEglConfig, 1, &aNbConfigs) != EGL_TRUE
231    || myEglConfig == NULL)
232   {
233     eglGetError();
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)
237     {
238       ::Message::DefaultMessenger()->Send ("Error: EGL does not provide compatible configurations!", Message_Fail);
239       return Standard_False;
240     }
241   }
242
243 #if defined(GL_ES_VERSION_2_0)
244   EGLint anEglCtxAttribs[] =
245   {
246     EGL_CONTEXT_CLIENT_VERSION, 2,
247     EGL_NONE
248   };
249   if (eglBindAPI (EGL_OPENGL_ES_API) != EGL_TRUE)
250   {
251     ::Message::DefaultMessenger()->Send ("Error: EGL does not provide OpenGL ES client!", Message_Fail);
252     return Standard_False;
253   }
254 #else
255   EGLint* anEglCtxAttribs = NULL;
256   if (eglBindAPI (EGL_OPENGL_API) != EGL_TRUE)
257   {
258     ::Message::DefaultMessenger()->Send ("Error: EGL does not provide OpenGL client!", Message_Fail);
259     return Standard_False;
260   }
261 #endif
262
263   myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs);
264   if ((EGLContext )myEglContext == EGL_NO_CONTEXT)
265   {
266     ::Message::DefaultMessenger()->Send ("Error: EGL is unable to create OpenGL context!", Message_Fail);
267     return Standard_False;
268   }
269   if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, (EGLContext )myEglContext) != EGL_TRUE)
270   {
271     ::Message::DefaultMessenger()->Send ("Error: EGL is unable bind OpenGL context!", Message_Fail);
272     return Standard_False;
273   }
274 #endif
275   myIsOwnContext = Standard_True;
276   return Standard_True;
277 }
278
279 #if defined(HAVE_EGL) || defined(__ANDROID__)
280 // =======================================================================
281 // function : InitEglContext
282 // purpose  :
283 // =======================================================================
284 Standard_Boolean OpenGl_GraphicDriver::InitEglContext (Aspect_Display          theEglDisplay,
285                                                        Aspect_RenderingContext theEglContext,
286                                                        void*                   theEglConfig)
287 {
288   ReleaseContext();
289 #if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
290   if (myDisplayConnection.IsNull())
291   {
292     return Standard_False;
293   }
294 #endif
295
296   if ((EGLDisplay )theEglDisplay == EGL_NO_DISPLAY
297    || (EGLContext )theEglContext == EGL_NO_CONTEXT
298    || theEglConfig == NULL)
299   {
300     return Standard_False;
301   }
302   myEglDisplay = theEglDisplay;
303   myEglContext = theEglContext;
304   myEglConfig  = theEglConfig;
305   return Standard_True;
306 }
307 #endif
308
309 // =======================================================================
310 // function : InquireLightLimit
311 // purpose  :
312 // =======================================================================
313 Standard_Integer OpenGl_GraphicDriver::InquireLightLimit()
314 {
315   return OpenGLMaxLights;
316 }
317
318 // =======================================================================
319 // function : InquireViewLimit
320 // purpose  :
321 // =======================================================================
322 Standard_Integer OpenGl_GraphicDriver::InquireViewLimit()
323 {
324   return 10000;
325 }
326
327 // =======================================================================
328 // function : InquirePlaneLimit
329 // purpose  :
330 // =======================================================================
331 Standard_Integer OpenGl_GraphicDriver::InquirePlaneLimit()
332 {
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);
336 }
337
338 // =======================================================================
339 // function : UserDrawCallback
340 // purpose  :
341 // =======================================================================
342 OpenGl_GraphicDriver::OpenGl_UserDrawCallback_t& OpenGl_GraphicDriver::UserDrawCallback()
343 {
344   return myUserDrawCallback;
345 }
346
347 // =======================================================================
348 // function : DefaultTextHeight
349 // purpose  :
350 // =======================================================================
351 Standard_ShortReal OpenGl_GraphicDriver::DefaultTextHeight() const
352 {
353   return 16.;
354 }
355
356 // =======================================================================
357 // function : EnableVBO
358 // purpose  :
359 // =======================================================================
360 void OpenGl_GraphicDriver::EnableVBO (const Standard_Boolean theToTurnOn)
361 {
362   myCaps->vboDisable = !theToTurnOn;
363 }
364
365 // =======================================================================
366 // function : GetSharedContext
367 // purpose  :
368 // =======================================================================
369 const Handle(OpenGl_Context)& OpenGl_GraphicDriver::GetSharedContext() const
370 {
371   if (myMapOfWS.IsEmpty())
372   {
373     return TheNullGlCtx;
374   }
375
376   NCollection_Map<Handle(OpenGl_Workspace)>::Iterator anIter (myMapOfWS);
377   return anIter.Value()->GetGlContext();
378 }
379
380 // =======================================================================
381 // function : MemoryInfo
382 // purpose  :
383 // =======================================================================
384 Standard_Boolean OpenGl_GraphicDriver::MemoryInfo (Standard_Size&           theFreeBytes,
385                                                    TCollection_AsciiString& theInfo) const
386 {
387   // this is extra work (for OpenGl_Context initialization)...
388   OpenGl_Context aGlCtx;
389   if (!aGlCtx.Init())
390   {
391     return Standard_False;
392   }
393   theFreeBytes = aGlCtx.AvailableMemory();
394   theInfo      = aGlCtx.MemoryInfo();
395   return !theInfo.IsEmpty();
396 }
397
398 // =======================================================================
399 // function : SetImmediateModeDrawToFront
400 // purpose  :
401 // =======================================================================
402 Standard_Boolean OpenGl_GraphicDriver::SetImmediateModeDrawToFront (const Graphic3d_CView& theCView,
403                                                                     const Standard_Boolean theDrawToFrontBuffer)
404 {
405   if (theCView.ViewId == -1)
406   {
407     return Standard_False;
408   }
409
410   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
411   if (aCView != NULL)
412   {
413     return aCView->WS->SetImmediateModeDrawToFront (theDrawToFrontBuffer);
414   }
415   return Standard_False;
416 }
417
418 // =======================================================================
419 // function : DisplayImmediateStructure
420 // purpose  :
421 // =======================================================================
422 void OpenGl_GraphicDriver::DisplayImmediateStructure (const Graphic3d_CView&             theCView,
423                                                       const Handle(Graphic3d_Structure)& theStructure)
424 {
425   OpenGl_CView* aCView = (OpenGl_CView* )theCView.ptrView;
426   if (aCView == NULL)
427   {
428     return;
429   }
430
431   aCView->View->DisplayImmediateStructure (theStructure);
432 }
433
434 // =======================================================================
435 // function : EraseImmediateStructure
436 // purpose  :
437 // =======================================================================
438 void OpenGl_GraphicDriver::EraseImmediateStructure (const Graphic3d_CView&      theCView,
439                                                     const Graphic3d_CStructure& theCStructure)
440 {
441   OpenGl_CView*     aCView     = (OpenGl_CView*     )theCView.ptrView;
442   OpenGl_Structure* aStructure = (OpenGl_Structure* )&theCStructure;
443   if (aCView == NULL)
444   {
445     return;
446   }
447
448   aCView->View->EraseImmediateStructure (aStructure);
449 }
450
451
452 // =======================================================================
453 // function : Print
454 // purpose  :
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
464 {
465   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
466   if (aCView == NULL
467    || !myPrintContext.IsNull())
468   {
469     return Standard_False;
470   }
471
472   Standard_Boolean isPrinted = Standard_False;
473   myPrintContext = new OpenGl_PrinterContext();
474 #ifdef _WIN32
475   isPrinted = aCView->WS->Print (myPrintContext,
476                                  theCView,
477                                  theCUnderLayer,
478                                  theCOverLayer,
479                                  thePrintDC,
480                                  theToShowBackground,
481                                  theFilename,
482                                  thePrintAlgorithm,
483                                  theScaleFactor);
484 #else
485   Standard_NotImplemented::Raise ("OpenGl_GraphicDriver::Print is implemented only on Windows");
486 #endif
487   myPrintContext.Nullify();
488   return isPrinted;
489 }
490
491 // =======================================================================
492 // function : ZBufferTriedronSetup
493 // purpose  :
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)
502 {
503   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
504   if (aCView == NULL)
505   {
506     return;
507   }
508
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);
514 }
515
516 // =======================================================================
517 // function : TriedronDisplay
518 // purpose  :
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)
525 {
526   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
527   if (aCView != NULL)
528   {
529     aCView->View->TriedronDisplay (thePosition, theColor, theScale, theAsWireframe);
530   }
531 }
532
533 // =======================================================================
534 // function : TriedronErase
535 // purpose  :
536 // =======================================================================
537 void OpenGl_GraphicDriver::TriedronErase (const Graphic3d_CView& theCView)
538 {
539   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
540   if (aCView != NULL)
541   {
542     aCView->View->TriedronErase (aCView->WS->GetGlContext());
543   }
544 }
545
546 // =======================================================================
547 // function : TriedronEcho
548 // purpose  :
549 // =======================================================================
550 void OpenGl_GraphicDriver::TriedronEcho (const Graphic3d_CView& ,
551                                          const Aspect_TypeOfTriedronEcho )
552 {
553   // do nothing
554 }
555
556 // =======================================================================
557 // function : Environment
558 // purpose  :
559 // =======================================================================
560 void OpenGl_GraphicDriver::Environment (const Graphic3d_CView& theCView)
561 {
562   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
563   if (aCView == NULL)
564   {
565     return;
566   }
567
568   aCView->View->SetTextureEnv    (aCView->WS->GetGlContext(), theCView.Context.TextureEnv);
569   aCView->View->SetSurfaceDetail ((Visual3d_TypeOfSurfaceDetail)theCView.Context.SurfaceDetail);
570 }
571
572 // =======================================================================
573 // function : BackgroundImage
574 // purpose  :
575 // =======================================================================
576 void OpenGl_GraphicDriver::BackgroundImage (const Standard_CString  theFileName,
577                                             const Graphic3d_CView&  theCView,
578                                             const Aspect_FillMethod theFillStyle)
579 {
580   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
581   if (aCView != NULL)
582   {
583     aCView->View->CreateBackgroundTexture (theFileName, theFillStyle);
584   }
585 }
586
587 // =======================================================================
588 // function : SetBgImageStyle
589 // purpose  :
590 // =======================================================================
591 void OpenGl_GraphicDriver::SetBgImageStyle (const Graphic3d_CView&  theCView,
592                                             const Aspect_FillMethod theFillStyle)
593 {
594   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
595   if (aCView != NULL)
596   {
597     aCView->View->SetBackgroundTextureStyle (theFillStyle);
598   }
599 }
600
601 // =======================================================================
602 // function : SetBgGradientStyle
603 // purpose  :
604 // =======================================================================
605 void OpenGl_GraphicDriver::SetBgGradientStyle (const Graphic3d_CView&          theCView,
606                                                const Aspect_GradientFillMethod theFillType)
607 {
608   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
609   if (aCView != NULL)
610   {
611     aCView->View->SetBackgroundGradientType (theFillType);
612   }
613 }
614
615 // =======================================================================
616 // function : GraduatedTrihedronDisplay
617 // purpose  :
618 // =======================================================================
619 void OpenGl_GraphicDriver::GraduatedTrihedronDisplay (const Graphic3d_CView&               theCView,
620                                                       const Graphic3d_GraduatedTrihedron& theCubic)
621 {
622   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
623   if (aCView != NULL)
624   {
625     aCView->View->GraduatedTrihedronDisplay (aCView->WS->GetGlContext(), theCubic);
626   }
627 }
628
629 // =======================================================================
630 // function : GraduatedTrihedronErase
631 // purpose  :
632 // =======================================================================
633 void OpenGl_GraphicDriver::GraduatedTrihedronErase (const Graphic3d_CView& theCView)
634 {
635   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
636   if (aCView != NULL)
637   {
638     aCView->View->GraduatedTrihedronErase (aCView->WS->GetGlContext());
639   }
640 }
641
642 // =======================================================================
643 // function : GraduatedTrihedronMinMaxValues
644 // purpose  :
645 // =======================================================================
646 void OpenGl_GraphicDriver::GraduatedTrihedronMinMaxValues (const Graphic3d_CView& theView,
647                                                            const Graphic3d_Vec3   theMin,
648                                                            const Graphic3d_Vec3   theMax)
649 {
650   const OpenGl_CView* aCView = (const OpenGl_CView* )theView.ptrView;
651   if (aCView != NULL)
652   {
653     aCView->View->ChangeGraduatedTrihedron().SetMinMax (theMin, theMax);
654   }
655 }