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