0022627: Change OCCT memory management defaults
[occt.git] / src / OpenGl / OpenGl_GraphicDriver_7.cxx
1 // File:      OpenGl_GraphicDriver_7.cxx
2 // Created:   20 October 2011
3 // Author:    Sergey ZERCHANINOV
4 // Copyright: OPEN CASCADE 2011
5
6 #include <OpenGl_GraphicDriver.hxx>
7
8 #include <OpenGl_FrameBuffer.hxx>
9
10 #include <OpenGl_Structure.hxx>
11 #include <OpenGl_CView.hxx>
12 #include <OpenGl_Display.hxx>
13
14 /*----------------------------------------------------------------------*/
15
16 void OpenGl_GraphicDriver::ActivateView (const Graphic3d_CView& ACView)
17 {
18   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
19   if (aCView)
20     aCView->WS->SetActiveView(aCView->View);
21 }
22
23 void OpenGl_GraphicDriver::AntiAliasing (const Graphic3d_CView& ACView, const Standard_Boolean AFlag)
24 {
25   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
26   if (aCView)
27     aCView->View->SetAntiAliasing(AFlag);
28 }
29
30 void OpenGl_GraphicDriver::Background (const Graphic3d_CView& ACView)
31 {
32   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
33   if (aCView)
34   {
35     aCView->WS->SetBackgroundColor(ACView.DefWindow.Background.r,ACView.DefWindow.Background.g,ACView.DefWindow.Background.b);
36     aCView->WS->Invalidate();
37   }
38 }
39
40 void OpenGl_GraphicDriver::GradientBackground (const Graphic3d_CView& ACView,
41                                               const Quantity_Color& AColor1,
42                                               const Quantity_Color& AColor2,
43                                               const Aspect_GradientFillMethod AType)
44 {
45   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
46   if (aCView)
47   {
48     aCView->View->SetBackgroundGradient(AColor1,AColor2,AType);
49     aCView->WS->Invalidate();
50   }
51 }
52
53 void OpenGl_GraphicDriver::Blink (const Graphic3d_CStructure &, const Standard_Boolean)
54 {
55   // Do nothing
56 }
57
58 void OpenGl_GraphicDriver::BoundaryBox (const Graphic3d_CStructure& ACStructure, const Standard_Boolean Create)
59 {
60   OpenGl_Structure *astructure = (OpenGl_Structure *)ACStructure.ptrStructure;
61   if (!astructure)
62     return;
63
64   if ( Create )
65     astructure->SetHighlightBox(ACStructure.BoundBox);
66   else
67     astructure->ClearHighlightBox();
68 }
69
70 void OpenGl_GraphicDriver::HighlightColor (const Graphic3d_CStructure& ACStructure, const Standard_ShortReal R, const Standard_ShortReal G, const Standard_ShortReal B, const Standard_Boolean Create)
71 {
72   OpenGl_Structure *astructure = (OpenGl_Structure *)ACStructure.ptrStructure;
73   if (!astructure)
74     return;
75
76   if ( Create )
77     astructure->SetHighlightColor(R,G,B);
78   else
79     astructure->ClearHighlightColor();
80 }
81
82 void OpenGl_GraphicDriver::NameSetStructure (const Graphic3d_CStructure& ACStructure)
83 {
84   OpenGl_Structure *astructure = (OpenGl_Structure *)ACStructure.ptrStructure;
85   if (astructure)
86   {
87     Standard_Integer aStatus = 0;
88     if (ACStructure.highlight) aStatus |= OPENGL_NS_HIGHLIGHT;
89     if (!ACStructure.visible) aStatus |= OPENGL_NS_HIDE;
90     astructure->SetNamedStatus( aStatus );
91   }
92 }
93
94 void OpenGl_GraphicDriver::ClipLimit (const Graphic3d_CView& ACView, const Standard_Boolean AWait)
95 {
96   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
97   if (aCView)
98   {
99     aCView->View->SetClipLimit(ACView);
100     if (!AWait)
101     {
102       aCView->WS->Resize(ACView.DefWindow);
103       aCView->WS->Invalidate();
104     }
105   }
106 }
107
108 void OpenGl_GraphicDriver::DeactivateView (const Graphic3d_CView& ACView)
109 {
110   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
111   if (aCView)
112   {
113     const Handle(OpenGl_View) aDummyView;
114     aCView->WS->SetActiveView(aDummyView);
115   }
116 }
117
118 void OpenGl_GraphicDriver::DepthCueing (const Graphic3d_CView& ACView, const Standard_Boolean AFlag)
119 {
120   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
121   if (aCView)
122     aCView->View->SetFog(ACView, AFlag);
123 }
124
125 Standard_Boolean OpenGl_GraphicDriver::ProjectRaster (const Graphic3d_CView& ACView, const Standard_ShortReal AX, const Standard_ShortReal AY, const Standard_ShortReal AZ, Standard_Integer& AU, Standard_Integer& AV)
126 {
127   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
128   if (!aCView)
129     return Standard_False;
130
131   Standard_Integer aWidth = aCView->WS->Width();
132   Standard_Integer aHeight = aCView->WS->Height();
133   Standard_ShortReal xr, yr;
134   if (aCView->View->ProjectObjectToRaster(aWidth, aHeight, AX, AY, AZ, xr, yr))
135   {
136     AU = (Standard_Integer) xr;
137     AV = aHeight - (Standard_Integer) yr;
138     return Standard_True;
139   }
140
141   return Standard_False;
142 }
143
144 Standard_Boolean OpenGl_GraphicDriver::UnProjectRaster (const Graphic3d_CView& ACView, const Standard_Integer Axm, const Standard_Integer Aym, const Standard_Integer AXM, const Standard_Integer AYM, const Standard_Integer AU, const Standard_Integer AV, Standard_ShortReal& Ax, Standard_ShortReal& Ay, Standard_ShortReal& Az)
145 {
146   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
147   if (!aCView)
148     return Standard_False;
149
150   const Standard_Integer aWidth = aCView->WS->Width();
151   const Standard_Integer aHeight = aCView->WS->Height();
152
153   /*
154   Patched by P.Dolbey: the window pixel height decreased by one 
155   in order for yr to remain within valid coordinate range [0; Ym -1]
156   where Ym means window pixel height.
157   */
158   return aCView->View->ProjectRasterToObject( aWidth, aHeight, AU, (AYM-1)-Aym-AV, Ax, Ay, Az );
159 }
160
161 Standard_Boolean OpenGl_GraphicDriver::UnProjectRasterWithRay (const Graphic3d_CView& ACView, const Standard_Integer Axm, const Standard_Integer Aym, const Standard_Integer AXM, const Standard_Integer AYM, const Standard_Integer AU, const Standard_Integer AV, Standard_ShortReal& Ax, Standard_ShortReal& Ay, Standard_ShortReal& Az, Standard_ShortReal& Dx, Standard_ShortReal& Dy, Standard_ShortReal& Dz)
162 {
163   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
164   if (!aCView)
165     return Standard_False;
166
167   const Standard_Integer aWidth = aCView->WS->Width();
168   const Standard_Integer aHeight = aCView->WS->Height();
169
170   return aCView->View->ProjectRasterToObjectWithRay( aWidth, aHeight, AU, AYM-Aym-AV, Ax, Ay, Az, Dx, Dy, Dz );
171 }
172
173 void OpenGl_GraphicDriver::RatioWindow (const Graphic3d_CView& theCView)
174 {
175   const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
176   if (aCView != NULL)
177     aCView->WS->Resize (theCView.DefWindow);
178 }
179
180 void OpenGl_GraphicDriver::Redraw (const Graphic3d_CView& ACView, const Aspect_CLayer2d& ACUnderLayer, const Aspect_CLayer2d& ACOverLayer, const Standard_Integer x, const Standard_Integer y, const Standard_Integer width, const Standard_Integer height)
181 {
182   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
183   if (aCView)
184   {
185     /*if( width <= 0 || height <= 0  )
186       aCView->WS->Redraw(ACView, ACUnderLayer, ACOverLayer);
187     else
188       aCView->WS->RedrawArea(ACView, ACUnderLayer, ACOverLayer, x, y, width, height);*/
189     // Always do full redraw
190     aCView->WS->Redraw(ACView, ACUnderLayer, ACOverLayer);
191   }
192 }
193
194 Graphic3d_PtrFrameBuffer OpenGl_GraphicDriver::FBOCreate (const Graphic3d_CView& ACView, const Standard_Integer theWidth, const Standard_Integer theHeight)
195 {
196   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
197   if (aCView)
198     return aCView->WS->FBOCreate(theWidth, theHeight);
199   return (Graphic3d_PtrFrameBuffer)NULL;
200 }
201
202 Graphic3d_PtrFrameBuffer OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth, const Standard_Integer theHeight)
203 {
204   // activate OpenGL context
205   if (!Activate())
206     return NULL;
207
208   // create the FBO
209   OpenGl_FrameBuffer* aFrameBuffer = new OpenGl_FrameBuffer();
210   if (!aFrameBuffer->Init (GetGlContext(), theWidth, theHeight))
211   {
212     delete aFrameBuffer;
213     return NULL;
214   }
215   return (Graphic3d_PtrFrameBuffer )aFrameBuffer;
216 }
217
218 void OpenGl_GraphicDriver::FBORelease (const Graphic3d_CView& ACView, Graphic3d_PtrFrameBuffer& theFBOPtr)
219 {
220   if (theFBOPtr == NULL)
221     return;
222   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
223   if (aCView)
224   {
225     aCView->WS->FBORelease(theFBOPtr);
226     theFBOPtr = NULL;
227   }
228 }
229
230 void OpenGl_Workspace::FBORelease (Graphic3d_PtrFrameBuffer theFBOPtr)
231 {
232   // activate OpenGL context
233   if (!Activate())
234     return;
235
236   // release the object
237   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer*)theFBOPtr;
238   aFrameBuffer->Release (GetGlContext());
239   delete aFrameBuffer;
240 }
241
242 void OpenGl_GraphicDriver::FBOGetDimensions (const Graphic3d_CView& ,
243                                              const Graphic3d_PtrFrameBuffer theFBOPtr,
244                                              Standard_Integer& theWidth,    Standard_Integer& theHeight,
245                                              Standard_Integer& theWidthMax, Standard_Integer& theHeightMax)
246 {
247   if (theFBOPtr == NULL)
248   {
249     return;
250   }
251   const OpenGl_FrameBuffer* aFrameBuffer = (const OpenGl_FrameBuffer* )theFBOPtr;
252   theWidth  = aFrameBuffer->GetVPSizeX(); // current viewport size
253   theHeight = aFrameBuffer->GetVPSizeY();
254   theWidthMax  = aFrameBuffer->GetSizeX(); // texture size
255   theHeightMax = aFrameBuffer->GetSizeY();
256 }
257
258 void OpenGl_GraphicDriver::FBOChangeViewport (const Graphic3d_CView& ,
259                                               Graphic3d_PtrFrameBuffer& theFBOPtr,
260                                               const Standard_Integer theWidth, const Standard_Integer theHeight)
261 {
262   if (theFBOPtr == NULL)
263   {
264     return;
265   }
266   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theFBOPtr;
267   aFrameBuffer->ChangeViewport (theWidth, theHeight);
268 }
269
270 // OpenGL 1.2 stuff
271 #ifndef GL_BGR
272   #define GL_BGR  0x80E0
273 #endif
274 #ifndef GL_BGRA
275   #define GL_BGRA 0x80E1
276 #endif
277
278 static inline GLenum TFormatToGLEnum (const TRawBufferDataFormat theTFormat)
279 {
280   switch (theTFormat)
281   {
282     case TRGB:   return GL_RGB;
283     case TBGR:   return GL_BGR;
284     case TRGBA:  return GL_RGBA;
285     case TBGRA:  return GL_BGRA;
286     case TDepthComponent: return GL_DEPTH_COMPONENT;
287     case TRed:   return GL_RED;
288     case TGreen: return GL_GREEN;
289     case TBlue:  return GL_BLUE;
290     case TAlpha: return GL_ALPHA;
291     default:     return 0;
292   }
293 }
294
295 static inline GLenum TTypeToGLEnum (const TRawBufferDataType theTType)
296 {
297   switch (theTType)
298   {
299     case TUByte: return GL_UNSIGNED_BYTE;
300     case TFloat: return GL_FLOAT;
301     default:     return 0;
302   }
303 }
304
305 Standard_Boolean OpenGl_GraphicDriver::BufferDump (const Graphic3d_CView& ACView, Image_CRawBufferData& theBuffer)
306 {
307   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
308   if (aCView)
309     return aCView->WS->BufferDump((OpenGl_FrameBuffer *)ACView.ptrFBO,theBuffer);
310   return Standard_False;
311 }
312
313 Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer *theFBOPtr, Image_CRawBufferData& theBuffer)
314 {
315   GLenum aFormat = TFormatToGLEnum (theBuffer.format);
316   GLenum aType = TTypeToGLEnum (theBuffer.type);
317
318   // safe checks
319   if (aFormat == 0 || aType == 0 ||
320       theBuffer.widthPx == 0 || theBuffer.heightPx == 0 ||
321       theBuffer.dataPtr == NULL)
322   {
323     return Standard_False;
324   }
325
326   // activate OpenGL context
327   if (!Activate())
328     return Standard_False;
329
330   // bind FBO if used
331   OpenGl_FrameBuffer* aFrameBuffer = theFBOPtr;
332   GLint aReadBufferPrev = GL_BACK;
333   if (aFrameBuffer != NULL && aFrameBuffer->IsValid())
334   {
335     aFrameBuffer->BindBuffer (GetGlContext());
336   }
337   else
338   {
339     glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
340     GLint aDrawBufferPrev = GL_BACK;
341     glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
342     glReadBuffer (aDrawBufferPrev);
343   }
344
345   GLint anAlignBack = 1;
346   glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
347   if (theBuffer.rowAligmentBytes == 0)
348   {
349     theBuffer.rowAligmentBytes = 1;
350   }
351   glPixelStorei (GL_PACK_ALIGNMENT, theBuffer.rowAligmentBytes);
352
353   // read pixels
354   glReadPixels (0, 0, theBuffer.widthPx, theBuffer.heightPx, aFormat, aType, (GLvoid* )theBuffer.dataPtr);
355   glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack);
356
357   if (aFrameBuffer != NULL && aFrameBuffer->IsValid())
358   {
359     aFrameBuffer->UnbindBuffer (GetGlContext());
360   }
361   else
362   {
363     glReadBuffer (aReadBufferPrev);
364   }
365   return Standard_True;
366 }
367
368 void OpenGl_GraphicDriver::RemoveView (const Graphic3d_CView& ACView)
369 {
370   if (GetMapOfViews().IsBound (ACView.ViewId))
371     GetMapOfViews().UnBind (ACView.ViewId);
372
373   if (GetMapOfWorkspaces().IsBound (ACView.WsId))
374     GetMapOfWorkspaces().UnBind (ACView.WsId);
375
376   OpenGl_CView *aCView = (OpenGl_CView *)ACView.ptrView;
377   delete aCView;
378   ((Graphic3d_CView *)&ACView)->ptrView = NULL;
379 }
380
381 void OpenGl_GraphicDriver::SetLight (const Graphic3d_CView& ACView)
382 {
383   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
384   if (aCView)
385     aCView->View->SetLights(ACView.Context);
386 }
387
388 void OpenGl_GraphicDriver::SetPlane (const Graphic3d_CView& ACView)
389 {
390   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
391   if (aCView)
392     aCView->View->SetClippingPlanes(ACView.Context);
393 }
394
395 void OpenGl_GraphicDriver::SetVisualisation (const Graphic3d_CView& ACView)
396 {
397   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
398   if (aCView)
399   {
400     aCView->View->SetVisualisation(ACView.Context);
401     aCView->WS->UseZBuffer() = ( ACView.Context.Visualization == 0? (ACView.Context.ZBufferActivity == 1) : (ACView.Context.ZBufferActivity != 0) );
402   }
403 }
404
405 void OpenGl_GraphicDriver::TransformStructure (const Graphic3d_CStructure& ACStructure)
406 {
407   OpenGl_Structure *astructure = (OpenGl_Structure *)ACStructure.ptrStructure;
408   if (astructure)
409     astructure->SetTransformation(&(ACStructure.Transformation[0][0]));
410 }
411
412 void OpenGl_GraphicDriver::DegenerateStructure (const Graphic3d_CStructure& ACStructure)
413 {
414   OpenGl_Structure *astructure = (OpenGl_Structure *)ACStructure.ptrStructure;
415   if (astructure)
416     astructure->SetDegenerateModel( ACStructure.ContextFillArea.DegenerationMode, ACStructure.ContextFillArea.SkipRatio );
417 }
418
419 void OpenGl_GraphicDriver::Transparency (const Graphic3d_CView& ACView, const Standard_Boolean AFlag)
420 {
421   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
422   if (aCView)
423     aCView->WS->UseTransparency(AFlag);
424 }
425
426 void OpenGl_GraphicDriver::Update (const Graphic3d_CView& ACView, const Aspect_CLayer2d& ACUnderLayer, const Aspect_CLayer2d& ACOverLayer)
427 {
428   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
429   if (aCView)
430     aCView->WS->Update(ACView,ACUnderLayer,ACOverLayer);
431 }
432
433 Standard_Boolean OpenGl_GraphicDriver::View (Graphic3d_CView& ACView)
434 {
435   if (openglDisplay.IsNull())
436     return Standard_False;
437
438   if (GetMapOfViews().IsBound (ACView.ViewId))
439     GetMapOfViews().UnBind (ACView.ViewId);
440
441   if (GetMapOfWorkspaces().IsBound (ACView.WsId))
442     GetMapOfWorkspaces().UnBind (ACView.WsId);
443
444   Handle(OpenGl_Workspace) aWS = Handle(OpenGl_Workspace)::DownCast(openglDisplay->GetWindow( ACView.DefWindow.XWindow ));
445   if ( aWS.IsNull() )
446   {
447     aWS = new OpenGl_Workspace( openglDisplay, ACView.DefWindow, ACView.GContext );
448     openglDisplay->SetWindow( ACView.DefWindow.XWindow, aWS );
449   }
450
451   GetMapOfWorkspaces().Bind (ACView.WsId, aWS);
452
453   Handle(OpenGl_View) aView = new OpenGl_View( ACView.Context );
454   GetMapOfViews().Bind (ACView.ViewId, aView);
455
456   OpenGl_CView *aCView = new OpenGl_CView;
457   aCView->View = aView;
458   aCView->WS = aWS;
459   ACView.ptrView = aCView;
460
461   return Standard_True;
462 }
463
464 void OpenGl_GraphicDriver::ViewMapping (const Graphic3d_CView& ACView, const Standard_Boolean AWait)
465 {
466   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
467   if (aCView)
468   {
469     aCView->View->SetMapping(ACView);
470     if (!AWait)
471     {
472       aCView->WS->Resize(ACView.DefWindow);
473       aCView->WS->Invalidate();
474     }
475   }
476 }
477
478 void OpenGl_GraphicDriver::ViewOrientation (const Graphic3d_CView& ACView, const Standard_Boolean AWait)
479 {
480   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
481   if (aCView)
482   {
483     aCView->View->SetOrientation(ACView);
484     if (!AWait)
485     {
486       aCView->WS->Resize(ACView.DefWindow);
487       aCView->WS->Invalidate();
488     }
489   }
490 }
491
492 void OpenGl_GraphicDriver::SetBackFacingModel (const Graphic3d_CView& ACView)
493 {
494   const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
495   if (aCView)
496     aCView->View->SetBackfacing(ACView.Backfacing);
497 }
498
499 //=======================================================================
500 //function : AddZLayer
501 //purpose  : 
502 //=======================================================================
503
504 void OpenGl_GraphicDriver::AddZLayer (const Graphic3d_CView& theCView,
505                                       const Standard_Integer theLayerId)
506 {
507   const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
508   if (aCView)
509     aCView->View->AddZLayer (theLayerId);
510 }
511
512 //=======================================================================
513 //function : RemoveZLayer
514 //purpose  :
515 //=======================================================================
516
517 void OpenGl_GraphicDriver::RemoveZLayer (const Graphic3d_CView& theCView,
518                                          const Standard_Integer theLayerId)
519 {
520   const OpenGl_CView* aCView = (const OpenGl_CView *)theCView.ptrView;
521   if (aCView)
522     aCView->View->RemoveZLayer (theLayerId);
523 }