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