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