0024590: Crash when processing OpenGl_BndBoxPrs objects
[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
8 // under the terms of the GNU Lesser General Public 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 #ifdef HAVE_CONFIG_H
17   #include <config.h>
18 #endif
19
20 #include <OpenGl_GraphicDriver.hxx>
21 #include <OpenGl_Context.hxx>
22 #include <OpenGl_Flipper.hxx>
23 #include <OpenGl_GraduatedTrihedron.hxx>
24 #include <OpenGl_Group.hxx>
25 #include <OpenGl_CView.hxx>
26 #include <OpenGl_View.hxx>
27 #include <OpenGl_StencilTest.hxx>
28 #include <OpenGl_Text.hxx>
29 #include <OpenGl_Trihedron.hxx>
30 #include <OpenGl_Workspace.hxx>
31
32 #include <Standard_NotImplemented.hxx>
33
34 IMPLEMENT_STANDARD_HANDLE(OpenGl_GraphicDriver,Graphic3d_GraphicDriver)
35 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_GraphicDriver,Graphic3d_GraphicDriver)
36
37 namespace
38 {
39   static const Handle(OpenGl_Context) TheNullGlCtx;
40 };
41
42 // Pour eviter de "mangler" MetaGraphicDriverFactory, le nom de la
43 // fonction qui cree un Graphic3d_GraphicDriver.
44 // En effet, ce nom est recherche par la methode DlSymb de la
45 // classe OSD_SharedLibrary dans la methode SetGraphicDriver de la
46 // classe Graphic3d_GraphicDevice
47 extern "C" {
48 #if defined(_MSC_VER) // disable MS VC++ warning on C-style function returning C++ object
49   #pragma warning(push)
50   #pragma warning(disable:4190)
51 #endif
52   Standard_EXPORT Handle(Graphic3d_GraphicDriver) MetaGraphicDriverFactory (const Standard_CString theShrName)
53   {
54     Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (theShrName);
55     return aDriver;
56   }
57 #if defined(_MSC_VER)
58   #pragma warning(pop)
59 #endif
60 }
61
62 // =======================================================================
63 // function : OpenGl_GraphicDriver
64 // purpose  :
65 // =======================================================================
66 OpenGl_GraphicDriver::OpenGl_GraphicDriver (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
67 : Graphic3d_GraphicDriver ("TKOpenGl"),
68   myCaps           (new OpenGl_Caps()),
69   myMapOfView      (1, NCollection_BaseAllocator::CommonBaseAllocator()),
70   myMapOfWS        (1, NCollection_BaseAllocator::CommonBaseAllocator()),
71   myMapOfStructure (1, NCollection_BaseAllocator::CommonBaseAllocator()),
72   myUserDrawCallback (NULL),
73   myTempText (new OpenGl_Text())
74 {
75   Begin (theDisplayConnection);
76 }
77
78 // =======================================================================
79 // function : OpenGl_GraphicDriver
80 // purpose  :
81 // =======================================================================
82 OpenGl_GraphicDriver::OpenGl_GraphicDriver (const Standard_CString theShrName)
83 : Graphic3d_GraphicDriver (theShrName),
84   myCaps           (new OpenGl_Caps()),
85   myMapOfView      (1, NCollection_BaseAllocator::CommonBaseAllocator()),
86   myMapOfWS        (1, NCollection_BaseAllocator::CommonBaseAllocator()),
87   myMapOfStructure (1, NCollection_BaseAllocator::CommonBaseAllocator()),
88   myUserDrawCallback (NULL),
89   myTempText (new OpenGl_Text())
90 {
91   //
92 }
93
94 // =======================================================================
95 // function : UserDrawCallback
96 // purpose  :
97 // =======================================================================
98 OpenGl_GraphicDriver::OpenGl_UserDrawCallback_t& OpenGl_GraphicDriver::UserDrawCallback()
99 {
100   return myUserDrawCallback;
101 }
102
103 // =======================================================================
104 // function : DefaultTextHeight
105 // purpose  :
106 // =======================================================================
107 Standard_ShortReal OpenGl_GraphicDriver::DefaultTextHeight() const
108 {
109   return 16.;
110 }
111
112 // =======================================================================
113 // function : EnableVBO
114 // purpose  :
115 // =======================================================================
116 void OpenGl_GraphicDriver::EnableVBO (const Standard_Boolean theToTurnOn)
117 {
118   myCaps->vboDisable = !theToTurnOn;
119 }
120
121 // =======================================================================
122 // function : GetSharedContext
123 // purpose  :
124 // =======================================================================
125 const Handle(OpenGl_Context)& OpenGl_GraphicDriver::GetSharedContext() const
126 {
127   if (myMapOfWS.IsEmpty())
128   {
129     return TheNullGlCtx;
130   }
131
132   NCollection_DataMap<Standard_Integer, Handle(OpenGl_Workspace)>::Iterator anIter (myMapOfWS);
133   return anIter.Value()->GetGlContext();
134 }
135
136 // =======================================================================
137 // function : MemoryInfo
138 // purpose  :
139 // =======================================================================
140 Standard_Boolean OpenGl_GraphicDriver::MemoryInfo (Standard_Size&           theFreeBytes,
141                                                    TCollection_AsciiString& theInfo) const
142 {
143   // this is extra work (for OpenGl_Context initialization)...
144   OpenGl_Context aGlCtx;
145   if (!aGlCtx.Init())
146   {
147     return Standard_False;
148   }
149   theFreeBytes = aGlCtx.AvailableMemory();
150   theInfo      = aGlCtx.MemoryInfo();
151   return !theInfo.IsEmpty();
152 }
153
154 // =======================================================================
155 // function : SetImmediateModeDrawToFront
156 // purpose  :
157 // =======================================================================
158 Standard_Boolean OpenGl_GraphicDriver::SetImmediateModeDrawToFront (const Graphic3d_CView& theCView,
159                                                                     const Standard_Boolean theDrawToFrontBuffer)
160 {
161   if (theCView.ViewId == -1)
162   {
163     return Standard_False;
164   }
165
166   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
167   if (aCView != NULL)
168   {
169     return aCView->WS->SetImmediateModeDrawToFront (theDrawToFrontBuffer);
170   }
171   return Standard_False;
172 }
173
174 // =======================================================================
175 // function : GetOpenClDeviceInfo
176 // purpose  : Returns information about device used for computations
177 // =======================================================================
178 #ifndef HAVE_OPENCL
179
180 Standard_Boolean OpenGl_GraphicDriver::GetOpenClDeviceInfo (const Graphic3d_CView&,
181   NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString>&)
182 {
183   return Standard_False;
184 }
185
186 #else
187
188 Standard_Boolean OpenGl_GraphicDriver::GetOpenClDeviceInfo (const Graphic3d_CView& theCView,
189   NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString>& theInfo)
190 {
191
192   if (theCView.ViewId == -1 || theCView.ptrView == NULL)
193   {
194     return Standard_False;
195   }
196
197   return reinterpret_cast<const OpenGl_CView*> (theCView.ptrView)->WS->GetOpenClDeviceInfo (theInfo);
198 }
199
200 #endif
201
202 // =======================================================================
203 // function : BeginAddMode
204 // purpose  :
205 // =======================================================================
206 Standard_Boolean OpenGl_GraphicDriver::BeginAddMode (const Graphic3d_CView& theCView)
207 {
208   if (theCView.ViewId == -1)
209   {
210     return Standard_False;
211   }
212
213   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
214   if (aCView != NULL && aCView->WS->BeginAddMode())
215   {
216     myImmediateWS = aCView->WS;
217     return Standard_True;
218   }
219
220   return Standard_False;
221 }
222
223 // =======================================================================
224 // function : EndAddMode
225 // purpose  :
226 // =======================================================================
227 void OpenGl_GraphicDriver::EndAddMode()
228 {
229   if (!myImmediateWS.IsNull())
230   {
231     myImmediateWS->EndAddMode();
232     myImmediateWS.Nullify();
233   }
234 }
235
236 // =======================================================================
237 // function : BeginImmediatMode
238 // purpose  :
239 // =======================================================================
240 Standard_Boolean OpenGl_GraphicDriver::BeginImmediatMode (const Graphic3d_CView& theCView,
241                                                           const Aspect_CLayer2d& /*theCUnderLayer*/,
242                                                           const Aspect_CLayer2d& /*theCOverLayer*/,
243                                                           const Standard_Boolean theDoubleBuffer,
244                                                           const Standard_Boolean theRetainMode)
245 {
246   if (theCView.ViewId == -1)
247   {
248     return Standard_False;
249   }
250
251   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
252   if (aCView != NULL && aCView->WS->BeginImmediatMode (theCView, theDoubleBuffer, theRetainMode))
253   {
254     myImmediateWS = aCView->WS;
255     return Standard_True;
256   }
257
258   return Standard_False;
259 }
260
261 // =======================================================================
262 // function : ClearImmediatMode
263 // purpose  :
264 // =======================================================================
265 void OpenGl_GraphicDriver::ClearImmediatMode (const Graphic3d_CView& theCView,
266                                               const Standard_Boolean theToFlush)
267 {
268   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
269   if (aCView != NULL)
270   {
271     aCView->WS->ClearImmediatMode (theCView, theToFlush);
272   }
273 }
274
275 // =======================================================================
276 // function : DrawStructure
277 // purpose  :
278 // =======================================================================
279 void OpenGl_GraphicDriver::DrawStructure (const Graphic3d_CStructure& theCStructure)
280 {
281   OpenGl_Structure* aStructure = (OpenGl_Structure* )theCStructure.ptrStructure;
282   if (aStructure == NULL)
283   {
284     return;
285   }
286
287   if (!myImmediateWS.IsNull())
288   {
289     myImmediateWS->DrawStructure (aStructure);
290   }
291 }
292
293 // =======================================================================
294 // function : EndImmediatMode
295 // purpose  :
296 // =======================================================================
297 void OpenGl_GraphicDriver::EndImmediatMode (const Standard_Integer )
298 {
299   if (!myImmediateWS.IsNull())
300   {
301     myImmediateWS->EndImmediatMode();
302     myImmediateWS.Nullify();
303   }
304 }
305
306 // =======================================================================
307 // function : Print
308 // purpose  :
309 // =======================================================================
310 Standard_Boolean OpenGl_GraphicDriver::Print (const Graphic3d_CView& theCView,
311                                               const Aspect_CLayer2d& theCUnderLayer,
312                                               const Aspect_CLayer2d& theCOverLayer,
313                                               const Aspect_Handle    thePrintDC,
314                                               const Standard_Boolean theToShowBackground,
315                                               const Standard_CString theFilename,
316                                               const Aspect_PrintAlgo thePrintAlgorithm,
317                                               const Standard_Real    theScaleFactor) const
318 {
319   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
320   if (aCView == NULL
321    || !myPrintContext.IsNull())
322   {
323     return Standard_False;
324   }
325
326   Standard_Boolean isPrinted = Standard_False;
327   myPrintContext = new OpenGl_PrinterContext();
328 #ifdef _WIN32
329   isPrinted = aCView->WS->Print (myPrintContext,
330                                  theCView,
331                                  theCUnderLayer,
332                                  theCOverLayer,
333                                  thePrintDC,
334                                  theToShowBackground,
335                                  theFilename,
336                                  thePrintAlgorithm,
337                                  theScaleFactor);
338 #else
339   Standard_NotImplemented::Raise ("OpenGl_GraphicDriver::Print is implemented only on Windows");
340 #endif
341   myPrintContext.Nullify();
342   return isPrinted;
343 }
344
345 void OpenGl_GraphicDriver::SetStencilTestOptions (const Graphic3d_CGroup& theCGroup,
346                                                   const Standard_Boolean theIsEnabled)
347 {
348   OpenGl_StencilTest* aStencilTest = new OpenGl_StencilTest();
349   aStencilTest->SetOptions (theIsEnabled);
350   ((OpenGl_Group* )theCGroup.ptrGroup)->AddElement (aStencilTest);
351 }
352
353 // =======================================================================
354 // function : Text
355 // purpose  :
356 // =======================================================================
357 void OpenGl_GraphicDriver::Text (const Graphic3d_CGroup&                 theCGroup,
358                                  const TCollection_ExtendedString&       theText,
359                                  const Graphic3d_Vertex&                 thePoint,
360                                  const Standard_Real                     theHeight,
361                                  const Quantity_PlaneAngle               /*theAngle*/,
362                                  const Graphic3d_TextPath                /*theTp*/,
363                                  const Graphic3d_HorizontalTextAlignment theHta,
364                                  const Graphic3d_VerticalTextAlignment   theVta,
365                                  const Standard_Boolean                  /*theToEvalMinMax*/)
366 {
367   if (theCGroup.ptrGroup == NULL)
368   {
369     return;
370   }
371
372   OpenGl_TextParam aParams;
373   aParams.Height = int ((theHeight < 2.0) ? DefaultTextHeight() : theHeight);
374   aParams.HAlign = theHta;
375   aParams.VAlign = theVta;
376   const OpenGl_Vec3 aPoint (thePoint.X(), thePoint.Y(), thePoint.Z());
377   OpenGl_Text* aText = new OpenGl_Text (theText, aPoint, aParams);
378   ((OpenGl_Group* )theCGroup.ptrGroup)->AddElement (aText);
379 }
380
381 // =======================================================================
382 // function : Text
383 // purpose  : Wrapper CString -> TCollection_ExtendedString
384 // =======================================================================
385 void OpenGl_GraphicDriver::Text (const Graphic3d_CGroup&                 theCGroup,
386                                  const Standard_CString                  theText,
387                                  const Graphic3d_Vertex&                 thePoint,
388                                  const Standard_Real                     theHeight,
389                                  const Quantity_PlaneAngle               theAngle,
390                                  const Graphic3d_TextPath                theTp,
391                                  const Graphic3d_HorizontalTextAlignment theHta,
392                                  const Graphic3d_VerticalTextAlignment   theVta,
393                                  const Standard_Boolean                  theToEvalMinMax)
394 {
395   OpenGl_GraphicDriver::Text (theCGroup, TCollection_ExtendedString (theText),
396                               thePoint, theHeight, theAngle, theTp, theHta, theVta, theToEvalMinMax);
397 }
398
399 // =======================================================================
400 // function : Text
401 // purpose  : Wrapper CString -> TCollection_ExtendedString
402 // =======================================================================
403 void OpenGl_GraphicDriver::Text (const Graphic3d_CGroup& theCGroup,
404                                  const Standard_CString  theText,
405                                  const Graphic3d_Vertex& thePoint,
406                                  const Standard_Real     theHeight,
407                                  const Standard_Boolean  theToEvalMinMax)
408 {
409   OpenGl_GraphicDriver::Text (theCGroup, TCollection_ExtendedString (theText), thePoint, theHeight, theToEvalMinMax);
410 }
411
412 // =======================================================================
413 // function : Text
414 // purpose  : Wrapper with default values
415 // =======================================================================
416 void OpenGl_GraphicDriver::Text (const Graphic3d_CGroup&           theCGroup,
417                                  const TCollection_ExtendedString& theText,
418                                  const Graphic3d_Vertex&           thePoint,
419                                  const Standard_Real               theHeight,
420                                  const Standard_Boolean            theToEvalMinMax)
421 {
422   OpenGl_GraphicDriver::Text (theCGroup,
423                               theText, thePoint, theHeight, 0.0,
424                               Graphic3d_TP_RIGHT, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM,
425                               theToEvalMinMax);
426 }
427
428 // =======================================================================
429 // function : ZBufferTriedronSetup
430 // purpose  :
431 // =======================================================================
432 void OpenGl_GraphicDriver::ZBufferTriedronSetup (const Quantity_NameOfColor theXColor,
433                                                  const Quantity_NameOfColor theYColor,
434                                                  const Quantity_NameOfColor theZColor,
435                                                  const Standard_Real        theSizeRatio,
436                                                  const Standard_Real        theAxisDiametr,
437                                                  const Standard_Integer     theNbFacettes)
438 {
439   OpenGl_Trihedron::Setup (theXColor, theYColor, theZColor, theSizeRatio, theAxisDiametr, theNbFacettes);
440 }
441
442 // =======================================================================
443 // function : TriedronDisplay
444 // purpose  :
445 // =======================================================================
446 void OpenGl_GraphicDriver::TriedronDisplay (const Graphic3d_CView&              theCView,
447                                             const Aspect_TypeOfTriedronPosition thePosition,
448                                             const Quantity_NameOfColor          theColor,
449                                             const Standard_Real                 theScale,
450                                             const Standard_Boolean              theAsWireframe)
451 {
452   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
453   if (aCView != NULL)
454   {
455     aCView->View->TriedronDisplay (aCView->WS->GetGlContext(), thePosition, theColor, theScale, theAsWireframe);
456   }
457 }
458
459 // =======================================================================
460 // function : TriedronErase
461 // purpose  :
462 // =======================================================================
463 void OpenGl_GraphicDriver::TriedronErase (const Graphic3d_CView& theCView)
464 {
465   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
466   if (aCView != NULL)
467   {
468     aCView->View->TriedronErase (aCView->WS->GetGlContext());
469   }
470 }
471
472 // =======================================================================
473 // function : TriedronEcho
474 // purpose  :
475 // =======================================================================
476 void OpenGl_GraphicDriver::TriedronEcho (const Graphic3d_CView& ,
477                                          const Aspect_TypeOfTriedronEcho )
478 {
479   // do nothing
480 }
481
482 // =======================================================================
483 // function : Environment
484 // purpose  :
485 // =======================================================================
486 void OpenGl_GraphicDriver::Environment (const Graphic3d_CView& theCView)
487 {
488   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
489   if (aCView == NULL)
490   {
491     return;
492   }
493
494   aCView->View->SetTextureEnv    (aCView->WS->GetGlContext(), theCView.Context.TextureEnv);
495   aCView->View->SetSurfaceDetail ((Visual3d_TypeOfSurfaceDetail)theCView.Context.SurfaceDetail);
496 }
497
498 // =======================================================================
499 // function : BackgroundImage
500 // purpose  :
501 // =======================================================================
502 void OpenGl_GraphicDriver::BackgroundImage (const Standard_CString  theFileName,
503                                             const Graphic3d_CView&  theCView,
504                                             const Aspect_FillMethod theFillStyle)
505 {
506   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
507   if (aCView != NULL)
508   {
509     aCView->View->CreateBackgroundTexture (theFileName, theFillStyle);
510   }
511 }
512
513 // =======================================================================
514 // function : SetBgImageStyle
515 // purpose  :
516 // =======================================================================
517 void OpenGl_GraphicDriver::SetBgImageStyle (const Graphic3d_CView&  theCView,
518                                             const Aspect_FillMethod theFillStyle)
519 {
520   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
521   if (aCView != NULL)
522   {
523     aCView->View->SetBackgroundTextureStyle (theFillStyle);
524   }
525 }
526
527 // =======================================================================
528 // function : SetBgGradientStyle
529 // purpose  :
530 // =======================================================================
531 void OpenGl_GraphicDriver::SetBgGradientStyle (const Graphic3d_CView&          theCView,
532                                                const Aspect_GradientFillMethod theFillType)
533 {
534   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
535   if (aCView != NULL)
536   {
537     aCView->View->SetBackgroundGradientType (theFillType);
538   }
539 }
540
541 // =======================================================================
542 // function : GraduatedTrihedronDisplay
543 // purpose  :
544 // =======================================================================
545 void OpenGl_GraphicDriver::GraduatedTrihedronDisplay (const Graphic3d_CView&               theCView,
546                                                       const Graphic3d_CGraduatedTrihedron& theCubic)
547 {
548   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
549   if (aCView != NULL)
550   {
551     aCView->View->GraduatedTrihedronDisplay (aCView->WS->GetGlContext(), theCubic);
552   }
553 }
554
555 // =======================================================================
556 // function : GraduatedTrihedronErase
557 // purpose  :
558 // =======================================================================
559 void OpenGl_GraphicDriver::GraduatedTrihedronErase (const Graphic3d_CView& theCView)
560 {
561   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
562   if (aCView != NULL)
563   {
564     aCView->View->GraduatedTrihedronErase (aCView->WS->GetGlContext());
565   }
566 }
567
568 // =======================================================================
569 // function : GraduatedTrihedronMinMaxValues
570 // purpose  :
571 // =======================================================================
572 void OpenGl_GraphicDriver::GraduatedTrihedronMinMaxValues (const Standard_ShortReal theMinX,
573                                                            const Standard_ShortReal theMinY,
574                                                            const Standard_ShortReal theMinZ,
575                                                            const Standard_ShortReal theMaxX,
576                                                            const Standard_ShortReal theMaxY,
577                                                            const Standard_ShortReal theMaxZ)
578 {
579   OpenGl_GraduatedTrihedron::SetMinMax (theMinX, theMinY, theMinZ, theMaxX, theMaxY, theMaxZ);
580 }
581
582 // =======================================================================
583 // function : SetFlippingOptions
584 // purpose  : Enable or disable flipping option for the given group
585 // =======================================================================
586 void OpenGl_GraphicDriver::SetFlippingOptions (const Graphic3d_CGroup& theCGroup,
587                                                const Standard_Boolean  theIsEnabled,
588                                                const gp_Ax2&           theRefPlane)
589 {
590   OpenGl_Flipper* aFlipper = new OpenGl_Flipper (theRefPlane);
591   aFlipper->SetOptions (theIsEnabled);
592   ((OpenGl_Group* )theCGroup.ptrGroup)->AddElement (aFlipper);
593 }