0024717: TKOpenGl - globally defined clipping planes blink when operating with view
[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                  theToStealActiveContext)
55 : Graphic3d_GraphicDriver (theDisp),
56 #if defined(HAVE_EGL) || defined(__ANDROID__)
57   myEglDisplay ((Aspect_Display )EGL_NO_DISPLAY),
58   myEglContext ((Aspect_RenderingContext )EGL_NO_CONTEXT),
59   myEglConfig  (NULL),
60 #endif
61   myCaps           (new OpenGl_Caps()),
62   myMapOfView      (1, NCollection_BaseAllocator::CommonBaseAllocator()),
63   myMapOfWS        (1, NCollection_BaseAllocator::CommonBaseAllocator()),
64   myMapOfStructure (1, NCollection_BaseAllocator::CommonBaseAllocator()),
65   myUserDrawCallback (NULL),
66   myTempText (new OpenGl_Text())
67 {
68 #if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
69   if (myDisplayConnection.IsNull())
70   {
71     //Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: cannot connect to X server!");
72     return;
73   }
74
75   Display* aDisplay = myDisplayConnection->GetDisplay();
76   Bool toSync = ::getenv ("CSF_GraphicSync") != NULL
77              || ::getenv ("CALL_SYNCHRO_X")  != NULL;
78   XSynchronize (aDisplay, toSync);
79
80 #if !defined(HAVE_EGL)
81   // does the server know about OpenGL & GLX?
82   int aDummy;
83   if (!XQueryExtension (aDisplay, "GLX", &aDummy, &aDummy, &aDummy))
84   {
85   #ifdef DEBUG
86     std::cerr << "This system doesn't appear to support OpenGL\n";
87   #endif
88   }
89 #endif
90 #endif
91
92 #if defined(HAVE_EGL) || defined(__ANDROID__)
93   if (theToStealActiveContext)
94   {
95     myEglDisplay = (Aspect_Display )eglGetCurrentDisplay();
96     myEglContext = (Aspect_RenderingContext )eglGetCurrentContext();
97     EGLSurface aEglSurf = eglGetCurrentSurface(EGL_DRAW);
98     if ((EGLDisplay )myEglDisplay == EGL_NO_DISPLAY
99      || (EGLContext )myEglContext == EGL_NO_CONTEXT)
100     {
101       Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: no active EGL context to steal!");
102       return;
103     }
104
105     TCollection_AsciiString anEglInfo = TCollection_AsciiString()
106       + "EGL info"
107       + "\n  Version:     " + eglQueryString ((EGLDisplay )myEglDisplay, EGL_VERSION)
108       + "\n  Vendor:      " + eglQueryString ((EGLDisplay )myEglDisplay, EGL_VENDOR)
109       + "\n  Client APIs: " + eglQueryString ((EGLDisplay )myEglDisplay, EGL_CLIENT_APIS)
110       + "\n  Extensions:  " + eglQueryString ((EGLDisplay )myEglDisplay, EGL_EXTENSIONS);
111     ::Message::DefaultMessenger()->Send (anEglInfo, Message_Info);
112
113     EGLint aCfgId = 0;
114     eglQuerySurface((EGLDisplay )myEglDisplay, aEglSurf, EGL_CONFIG_ID, &aCfgId);
115     const EGLint aConfigAttribs[] =
116     {
117       EGL_CONFIG_ID, aCfgId,
118       EGL_NONE
119     };
120
121     EGLint aNbConfigs = 0;
122     if (eglChooseConfig ((EGLDisplay )myEglDisplay, aConfigAttribs, &myEglConfig, 1, &aNbConfigs) != EGL_TRUE)
123     {
124       Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: EGL does not provide compatible configurations!");
125     }
126     return;
127   }
128
129 #if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
130   myEglDisplay = (Aspect_Display )eglGetDisplay (aDisplay);
131 #else
132   myEglDisplay = (Aspect_Display )eglGetDisplay (EGL_DEFAULT_DISPLAY);
133 #endif
134   if ((EGLDisplay )myEglDisplay == EGL_NO_DISPLAY)
135   {
136     Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: no EGL display!");
137     return;
138   }
139
140   EGLint aVerMajor = 0; EGLint aVerMinor = 0;
141   if (eglInitialize ((EGLDisplay )myEglDisplay, &aVerMajor, &aVerMinor) != EGL_TRUE)
142   {
143     Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: EGL display is unavailable!");
144     return;
145   }
146
147   TCollection_AsciiString anEglInfo = TCollection_AsciiString()
148     + "EGL info"
149     + "\n  Version:     " + aVerMajor + "." + aVerMinor + " (" + eglQueryString ((EGLDisplay )myEglDisplay, EGL_VERSION)
150     + "\n  Vendor:      " + eglQueryString ((EGLDisplay )myEglDisplay, EGL_VENDOR)
151     + "\n  Client APIs: " + eglQueryString ((EGLDisplay )myEglDisplay, EGL_CLIENT_APIS)
152     + "\n  Extensions:  " + eglQueryString ((EGLDisplay )myEglDisplay, EGL_EXTENSIONS);
153   ::Message::DefaultMessenger()->Send (anEglInfo, Message_Info);
154
155   const EGLint aConfigAttribs[] =
156   {
157     EGL_RED_SIZE,     8,
158     EGL_GREEN_SIZE,   8,
159     EGL_BLUE_SIZE,    8,
160     EGL_ALPHA_SIZE,   0,
161     EGL_DEPTH_SIZE,   24,
162     EGL_STENCIL_SIZE, 8,
163   #if defined(GL_ES_VERSION_2_0)
164     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
165   #else
166     EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
167   #endif
168     EGL_NONE
169   };
170
171   EGLint aNbConfigs = 0;
172   if (eglChooseConfig ((EGLDisplay )myEglDisplay, aConfigAttribs, &myEglConfig, 1, &aNbConfigs) != EGL_TRUE)
173   {
174     Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: EGL does not provide compatible configurations!");
175     return;
176   }
177
178 #if defined(GL_ES_VERSION_2_0)
179   if (eglBindAPI (EGL_OPENGL_ES_API) != EGL_TRUE)
180   {
181     Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: EGL does not provide OpenGL ES client!");
182     return;
183   }
184 #else
185   if (eglBindAPI (EGL_OPENGL_API) != EGL_TRUE)
186   {
187     Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: EGL does not provide OpenGL client!");
188     return;
189   }
190 #endif
191
192 #if defined(GL_ES_VERSION_2_0)
193   EGLint anEglCtxAttribs[] =
194   {
195     EGL_CONTEXT_CLIENT_VERSION, 2,
196     EGL_NONE
197   };
198 #else
199   EGLint* anEglCtxAttribs = NULL;
200 #endif
201
202   myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs);
203   if ((EGLContext )myEglContext == EGL_NO_CONTEXT)
204   {
205     Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: EGL is unable to create OpenGL context!");
206     return;
207   }
208   if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, (EGLContext )myEglContext) != EGL_TRUE)
209   {
210     Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: EGL is unable bind OpenGL context!");
211     return;
212   }
213 #else
214   // not yet implemented
215   (void )theToStealActiveContext;
216 #endif
217 }
218
219 // =======================================================================
220 // function : InquireLightLimit
221 // purpose  :
222 // =======================================================================
223 Standard_Integer OpenGl_GraphicDriver::InquireLightLimit()
224 {
225   return OpenGLMaxLights;
226 }
227
228 // =======================================================================
229 // function : InquireViewLimit
230 // purpose  :
231 // =======================================================================
232 Standard_Integer OpenGl_GraphicDriver::InquireViewLimit()
233 {
234   return 10000;
235 }
236
237 // =======================================================================
238 // function : InquirePlaneLimit
239 // purpose  :
240 // =======================================================================
241 Standard_Integer OpenGl_GraphicDriver::InquirePlaneLimit()
242 {
243   // NOTE the 2 first planes are reserved for ZClipping
244   const Handle(OpenGl_Context)& aCtx = GetSharedContext();
245   return aCtx.IsNull() ? 0 : Max (aCtx->MaxClipPlanes() - 2, 0);
246 }
247
248 // =======================================================================
249 // function : UserDrawCallback
250 // purpose  :
251 // =======================================================================
252 OpenGl_GraphicDriver::OpenGl_UserDrawCallback_t& OpenGl_GraphicDriver::UserDrawCallback()
253 {
254   return myUserDrawCallback;
255 }
256
257 // =======================================================================
258 // function : DefaultTextHeight
259 // purpose  :
260 // =======================================================================
261 Standard_ShortReal OpenGl_GraphicDriver::DefaultTextHeight() const
262 {
263   return 16.;
264 }
265
266 // =======================================================================
267 // function : EnableVBO
268 // purpose  :
269 // =======================================================================
270 void OpenGl_GraphicDriver::EnableVBO (const Standard_Boolean theToTurnOn)
271 {
272   myCaps->vboDisable = !theToTurnOn;
273 }
274
275 // =======================================================================
276 // function : GetSharedContext
277 // purpose  :
278 // =======================================================================
279 const Handle(OpenGl_Context)& OpenGl_GraphicDriver::GetSharedContext() const
280 {
281   if (myMapOfWS.IsEmpty())
282   {
283     return TheNullGlCtx;
284   }
285
286   NCollection_DataMap<Standard_Integer, Handle(OpenGl_Workspace)>::Iterator anIter (myMapOfWS);
287   return anIter.Value()->GetGlContext();
288 }
289
290 // =======================================================================
291 // function : MemoryInfo
292 // purpose  :
293 // =======================================================================
294 Standard_Boolean OpenGl_GraphicDriver::MemoryInfo (Standard_Size&           theFreeBytes,
295                                                    TCollection_AsciiString& theInfo) const
296 {
297   // this is extra work (for OpenGl_Context initialization)...
298   OpenGl_Context aGlCtx;
299   if (!aGlCtx.Init())
300   {
301     return Standard_False;
302   }
303   theFreeBytes = aGlCtx.AvailableMemory();
304   theInfo      = aGlCtx.MemoryInfo();
305   return !theInfo.IsEmpty();
306 }
307
308 // =======================================================================
309 // function : SetImmediateModeDrawToFront
310 // purpose  :
311 // =======================================================================
312 Standard_Boolean OpenGl_GraphicDriver::SetImmediateModeDrawToFront (const Graphic3d_CView& theCView,
313                                                                     const Standard_Boolean theDrawToFrontBuffer)
314 {
315   if (theCView.ViewId == -1)
316   {
317     return Standard_False;
318   }
319
320   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
321   if (aCView != NULL)
322   {
323     return aCView->WS->SetImmediateModeDrawToFront (theDrawToFrontBuffer);
324   }
325   return Standard_False;
326 }
327
328 // =======================================================================
329 // function : DisplayImmediateStructure
330 // purpose  :
331 // =======================================================================
332 void OpenGl_GraphicDriver::DisplayImmediateStructure (const Graphic3d_CView&      theCView,
333                                                       const Graphic3d_CStructure& theCStructure)
334 {
335   OpenGl_CView*     aCView     = (OpenGl_CView*     )theCView.ptrView;
336   OpenGl_Structure* aStructure = (OpenGl_Structure* )&theCStructure;
337   if (aCView == NULL)
338   {
339     return;
340   }
341
342   aCView->View->DisplayImmediateStructure (aStructure);
343 }
344
345 // =======================================================================
346 // function : EraseImmediateStructure
347 // purpose  :
348 // =======================================================================
349 void OpenGl_GraphicDriver::EraseImmediateStructure (const Graphic3d_CView&      theCView,
350                                                     const Graphic3d_CStructure& theCStructure)
351 {
352   OpenGl_CView*     aCView     = (OpenGl_CView*     )theCView.ptrView;
353   OpenGl_Structure* aStructure = (OpenGl_Structure* )&theCStructure;
354   if (aCView == NULL)
355   {
356     return;
357   }
358
359   aCView->View->EraseImmediateStructure (aStructure);
360 }
361
362
363 // =======================================================================
364 // function : Print
365 // purpose  :
366 // =======================================================================
367 Standard_Boolean OpenGl_GraphicDriver::Print (const Graphic3d_CView& theCView,
368                                               const Aspect_CLayer2d& theCUnderLayer,
369                                               const Aspect_CLayer2d& theCOverLayer,
370                                               const Aspect_Handle    thePrintDC,
371                                               const Standard_Boolean theToShowBackground,
372                                               const Standard_CString theFilename,
373                                               const Aspect_PrintAlgo thePrintAlgorithm,
374                                               const Standard_Real    theScaleFactor) const
375 {
376   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
377   if (aCView == NULL
378    || !myPrintContext.IsNull())
379   {
380     return Standard_False;
381   }
382
383   Standard_Boolean isPrinted = Standard_False;
384   myPrintContext = new OpenGl_PrinterContext();
385 #ifdef _WIN32
386   isPrinted = aCView->WS->Print (myPrintContext,
387                                  theCView,
388                                  theCUnderLayer,
389                                  theCOverLayer,
390                                  thePrintDC,
391                                  theToShowBackground,
392                                  theFilename,
393                                  thePrintAlgorithm,
394                                  theScaleFactor);
395 #else
396   Standard_NotImplemented::Raise ("OpenGl_GraphicDriver::Print is implemented only on Windows");
397 #endif
398   myPrintContext.Nullify();
399   return isPrinted;
400 }
401
402 // =======================================================================
403 // function : ZBufferTriedronSetup
404 // purpose  :
405 // =======================================================================
406 void OpenGl_GraphicDriver::ZBufferTriedronSetup (const Quantity_NameOfColor theXColor,
407                                                  const Quantity_NameOfColor theYColor,
408                                                  const Quantity_NameOfColor theZColor,
409                                                  const Standard_Real        theSizeRatio,
410                                                  const Standard_Real        theAxisDiametr,
411                                                  const Standard_Integer     theNbFacettes)
412 {
413   OpenGl_Trihedron::Setup (theXColor, theYColor, theZColor, theSizeRatio, theAxisDiametr, theNbFacettes);
414 }
415
416 // =======================================================================
417 // function : TriedronDisplay
418 // purpose  :
419 // =======================================================================
420 void OpenGl_GraphicDriver::TriedronDisplay (const Graphic3d_CView&              theCView,
421                                             const Aspect_TypeOfTriedronPosition thePosition,
422                                             const Quantity_NameOfColor          theColor,
423                                             const Standard_Real                 theScale,
424                                             const Standard_Boolean              theAsWireframe)
425 {
426   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
427   if (aCView != NULL)
428   {
429     aCView->View->TriedronDisplay (aCView->WS->GetGlContext(), thePosition, theColor, theScale, theAsWireframe);
430   }
431 }
432
433 // =======================================================================
434 // function : TriedronErase
435 // purpose  :
436 // =======================================================================
437 void OpenGl_GraphicDriver::TriedronErase (const Graphic3d_CView& theCView)
438 {
439   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
440   if (aCView != NULL)
441   {
442     aCView->View->TriedronErase (aCView->WS->GetGlContext());
443   }
444 }
445
446 // =======================================================================
447 // function : TriedronEcho
448 // purpose  :
449 // =======================================================================
450 void OpenGl_GraphicDriver::TriedronEcho (const Graphic3d_CView& ,
451                                          const Aspect_TypeOfTriedronEcho )
452 {
453   // do nothing
454 }
455
456 // =======================================================================
457 // function : Environment
458 // purpose  :
459 // =======================================================================
460 void OpenGl_GraphicDriver::Environment (const Graphic3d_CView& theCView)
461 {
462   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
463   if (aCView == NULL)
464   {
465     return;
466   }
467
468   aCView->View->SetTextureEnv    (aCView->WS->GetGlContext(), theCView.Context.TextureEnv);
469   aCView->View->SetSurfaceDetail ((Visual3d_TypeOfSurfaceDetail)theCView.Context.SurfaceDetail);
470 }
471
472 // =======================================================================
473 // function : BackgroundImage
474 // purpose  :
475 // =======================================================================
476 void OpenGl_GraphicDriver::BackgroundImage (const Standard_CString  theFileName,
477                                             const Graphic3d_CView&  theCView,
478                                             const Aspect_FillMethod theFillStyle)
479 {
480   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
481   if (aCView != NULL)
482   {
483     aCView->View->CreateBackgroundTexture (theFileName, theFillStyle);
484   }
485 }
486
487 // =======================================================================
488 // function : SetBgImageStyle
489 // purpose  :
490 // =======================================================================
491 void OpenGl_GraphicDriver::SetBgImageStyle (const Graphic3d_CView&  theCView,
492                                             const Aspect_FillMethod theFillStyle)
493 {
494   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
495   if (aCView != NULL)
496   {
497     aCView->View->SetBackgroundTextureStyle (theFillStyle);
498   }
499 }
500
501 // =======================================================================
502 // function : SetBgGradientStyle
503 // purpose  :
504 // =======================================================================
505 void OpenGl_GraphicDriver::SetBgGradientStyle (const Graphic3d_CView&          theCView,
506                                                const Aspect_GradientFillMethod theFillType)
507 {
508   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
509   if (aCView != NULL)
510   {
511     aCView->View->SetBackgroundGradientType (theFillType);
512   }
513 }
514
515 // =======================================================================
516 // function : GraduatedTrihedronDisplay
517 // purpose  :
518 // =======================================================================
519 void OpenGl_GraphicDriver::GraduatedTrihedronDisplay (const Graphic3d_CView&               theCView,
520                                                       const Graphic3d_CGraduatedTrihedron& theCubic)
521 {
522   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
523   if (aCView != NULL)
524   {
525     aCView->View->GraduatedTrihedronDisplay (aCView->WS->GetGlContext(), theCubic);
526   }
527 }
528
529 // =======================================================================
530 // function : GraduatedTrihedronErase
531 // purpose  :
532 // =======================================================================
533 void OpenGl_GraphicDriver::GraduatedTrihedronErase (const Graphic3d_CView& theCView)
534 {
535   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
536   if (aCView != NULL)
537   {
538     aCView->View->GraduatedTrihedronErase (aCView->WS->GetGlContext());
539   }
540 }
541
542 // =======================================================================
543 // function : GraduatedTrihedronMinMaxValues
544 // purpose  :
545 // =======================================================================
546 void OpenGl_GraphicDriver::GraduatedTrihedronMinMaxValues (const Standard_ShortReal theMinX,
547                                                            const Standard_ShortReal theMinY,
548                                                            const Standard_ShortReal theMinZ,
549                                                            const Standard_ShortReal theMaxX,
550                                                            const Standard_ShortReal theMaxY,
551                                                            const Standard_ShortReal theMaxZ)
552 {
553   OpenGl_GraduatedTrihedron::SetMinMax (theMinX, theMinY, theMinZ, theMaxX, theMaxY, theMaxZ);
554 }