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