0024776: Visualization - inherit OpenGl_View from Graphic3d_CView
[occt.git] / src / OpenGl / OpenGl_GraphicDriver_7.cxx
1 // Created on: 2011-10-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 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
18 #include <OpenGl_FrameBuffer.hxx>
19
20 #include <OpenGl_Structure.hxx>
21 #include <OpenGl_CView.hxx>
22 #include <OpenGl_Text.hxx>
23
24 /*----------------------------------------------------------------------*/
25
26 void OpenGl_GraphicDriver::ActivateView (const Graphic3d_CView& ACView)
27 {
28   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
29   if (aCView)
30     aCView->WS->SetActiveView(aCView->View, ACView.ViewId);
31 }
32
33 void OpenGl_GraphicDriver::AntiAliasing (const Graphic3d_CView& ACView, const Standard_Boolean AFlag)
34 {
35   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
36   if (aCView)
37     aCView->View->SetAntiAliasing(AFlag);
38 }
39
40 void OpenGl_GraphicDriver::Background (const Graphic3d_CView& ACView)
41 {
42   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
43   if (aCView)
44   {
45     aCView->WS->SetBackgroundColor(ACView.DefWindow.Background.r,ACView.DefWindow.Background.g,ACView.DefWindow.Background.b);
46   }
47 }
48
49 void OpenGl_GraphicDriver::GradientBackground (const Graphic3d_CView& ACView,
50                                               const Quantity_Color& AColor1,
51                                               const Quantity_Color& AColor2,
52                                               const Aspect_GradientFillMethod AType)
53 {
54   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
55   if (aCView)
56   {
57     aCView->View->SetBackgroundGradient(AColor1,AColor2,AType);
58   }
59 }
60
61 void OpenGl_GraphicDriver::ClipLimit (const Graphic3d_CView& ACView, const Standard_Boolean AWait)
62 {
63   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
64   if (aCView)
65   {
66     aCView->View->SetClipLimit(ACView);
67     if (!AWait)
68     {
69       aCView->WS->Resize(ACView.DefWindow);
70     }
71   }
72 }
73
74 void OpenGl_GraphicDriver::DeactivateView (const Graphic3d_CView& ACView)
75 {
76   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
77   if (aCView)
78   {
79     const Handle(OpenGl_View) aDummyView;
80     aCView->WS->SetActiveView (aDummyView, -1);
81   }
82 }
83
84 void OpenGl_GraphicDriver::DepthCueing (const Graphic3d_CView& ACView, const Standard_Boolean AFlag)
85 {
86   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
87   if (aCView)
88     aCView->View->SetFog(ACView, AFlag);
89 }
90
91 void OpenGl_GraphicDriver::RatioWindow (const Graphic3d_CView& theCView)
92 {
93   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
94   if (aCView != NULL)
95     aCView->WS->Resize (theCView.DefWindow);
96 }
97
98 void OpenGl_GraphicDriver::Redraw (const Graphic3d_CView& ACView,
99                                    const Standard_Integer /*x*/,
100                                    const Standard_Integer /*y*/,
101                                    const Standard_Integer /*width*/,
102                                    const Standard_Integer /*height*/)
103 {
104   if (ACView.RenderParams.Method == Graphic3d_RM_RAYTRACING
105   && !myCaps->vboDisable
106   && !myCaps->keepArrayData)
107   {
108     if (ACView.WasRedrawnGL)
109     {
110       myDeviceLostFlag = Standard_True;
111     }
112
113     myCaps->keepArrayData = Standard_True;
114   }
115
116   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
117   if (aCView)
118   {
119     /*if( width <= 0 || height <= 0  )
120       aCView->WS->Redraw(ACView, ACUnderLayer, ACOverLayer);
121     else
122       aCView->WS->RedrawArea(ACView, ACUnderLayer, ACOverLayer, x, y, width, height);*/
123     // Always do full redraw
124     aCView->WS->Redraw(ACView);
125   }
126 }
127
128 void OpenGl_GraphicDriver::RedrawImmediate (const Graphic3d_CView& theCView)
129 {
130   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
131   if (aCView != NULL)
132   {
133     aCView->WS->RedrawImmediate (theCView);
134   }
135 }
136
137 void OpenGl_GraphicDriver::Invalidate (const Graphic3d_CView& theCView)
138 {
139   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
140   if (aCView != NULL)
141   {
142     aCView->WS->Invalidate();
143   }
144 }
145
146 Standard_Boolean OpenGl_GraphicDriver::IsInvalidated (const Graphic3d_CView& theCView) const
147 {
148   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
149   return aCView == NULL
150       || aCView->WS->IsInvalidated();
151 }
152
153 Graphic3d_PtrFrameBuffer OpenGl_GraphicDriver::FBOCreate (const Graphic3d_CView& ACView, const Standard_Integer theWidth, const Standard_Integer theHeight)
154 {
155   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
156   if (aCView)
157     return aCView->WS->FBOCreate(theWidth, theHeight);
158   return (Graphic3d_PtrFrameBuffer)NULL;
159 }
160
161 Graphic3d_PtrFrameBuffer OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth,
162                                                       const Standard_Integer theHeight)
163 {
164   // activate OpenGL context
165   if (!Activate())
166     return NULL;
167
168   // create the FBO
169   const Handle(OpenGl_Context)& aCtx = GetGlContext();
170   OpenGl_FrameBuffer* aFrameBuffer = new OpenGl_FrameBuffer();
171   if (!aFrameBuffer->Init (aCtx, theWidth, theHeight))
172   {
173     aFrameBuffer->Release (aCtx.operator->());
174     delete aFrameBuffer;
175     return NULL;
176   }
177   return (Graphic3d_PtrFrameBuffer )aFrameBuffer;
178 }
179
180 void OpenGl_GraphicDriver::FBORelease (const Graphic3d_CView& ACView, Graphic3d_PtrFrameBuffer& theFBOPtr)
181 {
182   if (theFBOPtr == NULL)
183     return;
184   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
185   if (aCView)
186   {
187     aCView->WS->FBORelease(theFBOPtr);
188     theFBOPtr = NULL;
189   }
190 }
191
192 void OpenGl_Workspace::FBORelease (Graphic3d_PtrFrameBuffer theFBOPtr)
193 {
194   // activate OpenGL context
195   if (!Activate()
196    || theFBOPtr == NULL)
197   {
198     return;
199   }
200
201   // release the object
202   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer*)theFBOPtr;
203   if (aFrameBuffer != NULL)
204   {
205     aFrameBuffer->Release (GetGlContext().operator->());
206   }
207   delete aFrameBuffer;
208 }
209
210 void OpenGl_GraphicDriver::FBOGetDimensions (const Graphic3d_CView& ,
211                                              const Graphic3d_PtrFrameBuffer theFBOPtr,
212                                              Standard_Integer& theWidth,    Standard_Integer& theHeight,
213                                              Standard_Integer& theWidthMax, Standard_Integer& theHeightMax)
214 {
215   if (theFBOPtr == NULL)
216   {
217     return;
218   }
219   const OpenGl_FrameBuffer* aFrameBuffer = (const OpenGl_FrameBuffer* )theFBOPtr;
220   theWidth  = aFrameBuffer->GetVPSizeX(); // current viewport size
221   theHeight = aFrameBuffer->GetVPSizeY();
222   theWidthMax  = aFrameBuffer->GetSizeX(); // texture size
223   theHeightMax = aFrameBuffer->GetSizeY();
224 }
225
226 void OpenGl_GraphicDriver::FBOChangeViewport (const Graphic3d_CView& ,
227                                               Graphic3d_PtrFrameBuffer& theFBOPtr,
228                                               const Standard_Integer theWidth, const Standard_Integer theHeight)
229 {
230   if (theFBOPtr == NULL)
231   {
232     return;
233   }
234   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theFBOPtr;
235   aFrameBuffer->ChangeViewport (theWidth, theHeight);
236 }
237
238 inline bool getDataFormat (const Image_PixMap& theData,
239                            GLenum&             thePixelFormat,
240                            GLenum&             theDataType)
241 {
242   thePixelFormat = GL_RGB;
243   theDataType    = GL_UNSIGNED_BYTE;
244   switch (theData.Format())
245   {
246   #if !defined(GL_ES_VERSION_2_0)
247     case Image_PixMap::ImgGray:
248       thePixelFormat = GL_DEPTH_COMPONENT;
249       theDataType    = GL_UNSIGNED_BYTE;
250       return true;
251     case Image_PixMap::ImgGrayF:
252       thePixelFormat = GL_DEPTH_COMPONENT;
253       theDataType    = GL_FLOAT;
254       return true;
255     case Image_PixMap::ImgBGR:
256       thePixelFormat = GL_BGR;
257       theDataType    = GL_UNSIGNED_BYTE;
258       return true;
259     case Image_PixMap::ImgBGRA:
260     case Image_PixMap::ImgBGR32:
261       thePixelFormat = GL_BGRA;
262       theDataType    = GL_UNSIGNED_BYTE;
263       return true;
264     case Image_PixMap::ImgBGRF:
265       thePixelFormat = GL_BGR;
266       theDataType    = GL_FLOAT;
267       return true;
268     case Image_PixMap::ImgBGRAF:
269       thePixelFormat = GL_BGRA;
270       theDataType    = GL_FLOAT;
271       return true;
272   #else
273     case Image_PixMap::ImgGray:
274     case Image_PixMap::ImgGrayF:
275     case Image_PixMap::ImgBGR:
276     case Image_PixMap::ImgBGRA:
277     case Image_PixMap::ImgBGR32:
278     case Image_PixMap::ImgBGRF:
279     case Image_PixMap::ImgBGRAF:
280       return false;
281   #endif
282     case Image_PixMap::ImgRGB:
283       thePixelFormat = GL_RGB;
284       theDataType    = GL_UNSIGNED_BYTE;
285       return true;
286     case Image_PixMap::ImgRGBA:
287     case Image_PixMap::ImgRGB32:
288       thePixelFormat = GL_RGBA;
289       theDataType    = GL_UNSIGNED_BYTE;
290       return true;
291     case Image_PixMap::ImgRGBF:
292       thePixelFormat = GL_RGB;
293       theDataType    = GL_FLOAT;
294       return true;
295     case Image_PixMap::ImgRGBAF:
296       thePixelFormat = GL_RGBA;
297       theDataType    = GL_FLOAT;
298       return true;
299     case Image_PixMap::ImgAlpha:
300     case Image_PixMap::ImgAlphaF:
301       return false; // GL_ALPHA is no more supported in core context
302     case Image_PixMap::ImgUNKNOWN:
303       return false;
304   }
305   return false;
306 }
307
308 Standard_Boolean OpenGl_GraphicDriver::BufferDump (const Graphic3d_CView&      theCView,
309                                                    Image_PixMap&               theImage,
310                                                    const Graphic3d_BufferType& theBufferType)
311 {
312   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
313   return (aCView != NULL) && aCView->WS->BufferDump ((OpenGl_FrameBuffer* )theCView.ptrFBO, theImage, theBufferType);
314 }
315
316 //! Compute aligned number greater or equal to specified one
317 inline Standard_Size getAligned (const Standard_Size theNumber,
318                                  const Standard_Size theAlignment)
319 {
320   return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment;
321 }
322
323 Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer*         theFBOPtr,
324                                                Image_PixMap&               theImage,
325                                                const Graphic3d_BufferType& theBufferType)
326 {
327   GLenum aFormat, aType;
328   if (theImage.IsEmpty()
329    || !getDataFormat (theImage, aFormat, aType)
330    || !Activate())
331   {
332     return Standard_False;
333   }
334 #if !defined(GL_ES_VERSION_2_0)
335   GLint aReadBufferPrev = GL_BACK;
336   if (theBufferType == Graphic3d_BT_Depth
337    && aFormat != GL_DEPTH_COMPONENT)
338   {
339     return Standard_False;
340   }
341 #endif
342
343   // bind FBO if used
344   if (theFBOPtr != NULL && theFBOPtr->IsValid())
345   {
346     theFBOPtr->BindBuffer (GetGlContext());
347   }
348   else
349   {
350   #if !defined(GL_ES_VERSION_2_0)
351     glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
352     GLint aDrawBufferPrev = GL_BACK;
353     glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
354     glReadBuffer (aDrawBufferPrev);
355   #endif
356   }
357
358   // setup alignment
359   const GLint anAligment   = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
360   glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
361   bool isBatchCopy = !theImage.IsTopDown();
362
363   const GLint   anExtraBytes       = GLint(theImage.RowExtraBytes());
364   GLint         aPixelsWidth       = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
365   Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment);
366   if (anExtraBytes < anAligment)
367   {
368     aPixelsWidth = 0;
369   }
370   else if (aSizeRowBytesEstim != theImage.SizeRowBytes())
371   {
372     aPixelsWidth = 0;
373     isBatchCopy  = false;
374   }
375 #if !defined(GL_ES_VERSION_2_0)
376   glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth);
377 #else
378   if (aPixelsWidth != 0)
379   {
380     isBatchCopy = false;
381   }
382 #endif
383
384   if (!isBatchCopy)
385   {
386     // copy row by row
387     for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
388     {
389       // Image_PixMap rows indexation always starts from the upper corner
390       // while order in memory depends on the flag and processed by ChangeRow() method
391       glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
392     }
393   }
394   else
395   {
396     glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
397   }
398
399   glPixelStorei (GL_PACK_ALIGNMENT,  1);
400 #if !defined(GL_ES_VERSION_2_0)
401   glPixelStorei (GL_PACK_ROW_LENGTH, 0);
402 #endif
403
404   if (theFBOPtr != NULL && theFBOPtr->IsValid())
405   {
406     theFBOPtr->UnbindBuffer (GetGlContext());
407   }
408   else
409   {
410   #if !defined(GL_ES_VERSION_2_0)
411     glReadBuffer (aReadBufferPrev);
412   #endif
413   }
414   return Standard_True;
415 }
416
417 void OpenGl_GraphicDriver::RemoveView (const Graphic3d_CView& theCView)
418 {
419   Handle(OpenGl_Context) aCtx   = GetSharedContext();
420   OpenGl_CView*          aCView = (OpenGl_CView* )theCView.ptrView;
421   if (aCView == NULL
422    || aCView->View.IsNull()
423    || aCView->WS.IsNull())
424   {
425     return;
426   }
427
428   Handle(OpenGl_View)      aView   = aCView->View;
429   Handle(OpenGl_Workspace) aWindow = aCView->WS;
430   if (!myMapOfWS  .Remove (aWindow)
431    || !myMapOfView.Remove (aView))
432   {
433     return;
434   }
435
436   if (aWindow->GetGlContext()->MakeCurrent())
437   {
438     aCtx = aWindow->GetGlContext();
439   }
440   else
441   {
442     // try to hijack another context if any
443     const Handle(OpenGl_Context)& anOtherCtx = GetSharedContext();
444     if (!anOtherCtx.IsNull()
445       && anOtherCtx != aWindow->GetGlContext())
446     {
447       aCtx = anOtherCtx;
448       aCtx->MakeCurrent();
449     }
450   }
451
452   aView->ReleaseGlResources (aCtx);
453   if (myMapOfWS.IsEmpty())
454   {
455     // The last view removed but some objects still present.
456     // Release GL resources now without object destruction.
457     for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
458          aStructIt.More (); aStructIt.Next())
459     {
460       OpenGl_Structure* aStruct = aStructIt.ChangeValue();
461       aStruct->ReleaseGlResources (aCtx);
462     }
463     myDeviceLostFlag = !myMapOfStructure.IsEmpty();
464   }
465
466   delete aCView;
467   ((Graphic3d_CView *)&theCView)->ptrView = NULL;
468
469   aCtx.Nullify();
470   aView.Nullify();
471   aWindow.Nullify();
472 }
473
474 void OpenGl_GraphicDriver::SetLight (const Graphic3d_CView& ACView)
475 {
476   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
477   if (aCView)
478     aCView->View->SetLights(ACView.Context);
479 }
480
481 void OpenGl_GraphicDriver::SetClipPlanes (const Graphic3d_CView& theCView)
482 {
483   const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
484   if (aCView)
485   {
486     aCView->View->SetClipPlanes (theCView.Context.ClipPlanes);
487   }
488 }
489
490 //=======================================================================
491 //function : SetCamera
492 //purpose  :
493 //=======================================================================
494 void OpenGl_GraphicDriver::SetCamera (const Graphic3d_CView& theCView)
495 {
496   const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
497   if (aCView)
498   {
499     aCView->View->SetCamera (theCView.Context.Camera);
500   }
501 }
502
503 void OpenGl_GraphicDriver::SetVisualisation (const Graphic3d_CView& ACView)
504 {
505   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
506   if (aCView)
507   {
508     aCView->View->SetVisualisation(ACView.Context);
509   }
510 }
511
512 // =======================================================================
513 // function : InvalidateBVHData
514 // purpose  :
515 // =======================================================================
516 void OpenGl_GraphicDriver::InvalidateBVHData (Graphic3d_CView& theCView, const Standard_Integer theLayerId)
517 {
518   OpenGl_CView *aCView = (OpenGl_CView *)theCView.ptrView;
519   if(aCView)
520   {
521     aCView->View->InvalidateBVHData (theLayerId);
522   }
523 }
524
525 Standard_Boolean OpenGl_GraphicDriver::View (Graphic3d_CView& theCView)
526 {
527   Handle(OpenGl_Context) aShareCtx = GetSharedContext();
528   OpenGl_CView*          aCView = (OpenGl_CView* )theCView.ptrView;
529   if (aCView != NULL
530    && myMapOfView.Contains (aCView->View))
531   {
532     Handle(OpenGl_Workspace) anOldWS = aCView->WS;
533     Handle(OpenGl_Workspace) aWS     = new OpenGl_Workspace (this, theCView.DefWindow, theCView.GContext, myCaps, aShareCtx);
534     aCView->WS = aWS;
535     aWS->SetActiveView (aCView->View, theCView.ViewId);
536
537     myMapOfWS.Remove (anOldWS);
538     myMapOfWS.Add    (aWS);
539     return Standard_True;
540   }
541
542   Handle(OpenGl_Workspace) aWS       = new OpenGl_Workspace (this, theCView.DefWindow, theCView.GContext, myCaps, aShareCtx);
543   Handle(OpenGl_View)      aView     = new OpenGl_View (theCView.Context, &myStateCounter);
544   myMapOfWS  .Add (aWS);
545   myMapOfView.Add (aView);
546
547   aCView = new OpenGl_CView();
548   aCView->View = aView;
549   aCView->WS   = aWS;
550   theCView.ptrView = aCView;
551   aWS->SetActiveView (aCView->View, theCView.ViewId);
552
553   return Standard_True;
554 }
555
556 void OpenGl_GraphicDriver::SetBackFacingModel (const Graphic3d_CView& ACView)
557 {
558   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
559   if (aCView)
560     aCView->View->SetBackfacing(ACView.Backfacing);
561 }
562
563 //=======================================================================
564 //function : AddZLayer
565 //purpose  :
566 //=======================================================================
567
568 void OpenGl_GraphicDriver::AddZLayer (const Graphic3d_CView&   theCView,
569                                       const Graphic3d_ZLayerId theLayerId)
570 {
571   const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
572   if (aCView)
573     aCView->View->AddZLayer (theLayerId);
574 }
575
576 //=======================================================================
577 //function : RemoveZLayer
578 //purpose  :
579 //=======================================================================
580 void OpenGl_GraphicDriver::RemoveZLayer (const Graphic3d_CView&   theCView,
581                                          const Graphic3d_ZLayerId theLayerId)
582 {
583   const OpenGl_CView* aCView = (const OpenGl_CView *)theCView.ptrView;
584   if (aCView)
585     aCView->View->RemoveZLayer (theLayerId);
586 }
587
588 //=======================================================================
589 //function : SetZLayerSettings
590 //purpose  :
591 //=======================================================================
592 Standard_EXPORT void OpenGl_GraphicDriver::SetZLayerSettings (const Graphic3d_CView&          theCView,
593                                                               const Graphic3d_ZLayerId        theLayerId,
594                                                               const Graphic3d_ZLayerSettings& theSettings)
595 {
596   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
597   if (aCView)
598     aCView->View->SetZLayerSettings (theLayerId, theSettings);
599 }