1 // Created on: 2011-10-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_GraphicDriver.hxx>
18 #include <OpenGl_FrameBuffer.hxx>
20 #include <OpenGl_Structure.hxx>
21 #include <OpenGl_CView.hxx>
22 #include <OpenGl_Text.hxx>
24 /*----------------------------------------------------------------------*/
26 void OpenGl_GraphicDriver::ActivateView (const Graphic3d_CView& ACView)
28 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
30 aCView->WS->SetActiveView(aCView->View);
33 void OpenGl_GraphicDriver::AntiAliasing (const Graphic3d_CView& ACView, const Standard_Boolean AFlag)
35 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
37 aCView->View->SetAntiAliasing(AFlag);
40 void OpenGl_GraphicDriver::Background (const Graphic3d_CView& ACView)
42 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
45 aCView->WS->SetBackgroundColor(ACView.DefWindow.Background.r,ACView.DefWindow.Background.g,ACView.DefWindow.Background.b);
49 void OpenGl_GraphicDriver::GradientBackground (const Graphic3d_CView& ACView,
50 const Quantity_Color& AColor1,
51 const Quantity_Color& AColor2,
52 const Aspect_GradientFillMethod AType)
54 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
57 aCView->View->SetBackgroundGradient(AColor1,AColor2,AType);
61 void OpenGl_GraphicDriver::ClipLimit (const Graphic3d_CView& ACView, const Standard_Boolean AWait)
63 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
66 aCView->View->SetClipLimit(ACView);
69 aCView->WS->Resize(ACView.DefWindow);
74 void OpenGl_GraphicDriver::DeactivateView (const Graphic3d_CView& ACView)
76 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
79 const Handle(OpenGl_View) aDummyView;
80 aCView->WS->SetActiveView(aDummyView);
84 void OpenGl_GraphicDriver::DepthCueing (const Graphic3d_CView& ACView, const Standard_Boolean AFlag)
86 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
88 aCView->View->SetFog(ACView, AFlag);
91 void OpenGl_GraphicDriver::RatioWindow (const Graphic3d_CView& theCView)
93 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
95 aCView->WS->Resize (theCView.DefWindow);
98 void OpenGl_GraphicDriver::Redraw (const Graphic3d_CView& ACView,
99 const Aspect_CLayer2d& ACUnderLayer,
100 const Aspect_CLayer2d& ACOverLayer,
101 const Standard_Integer /*x*/,
102 const Standard_Integer /*y*/,
103 const Standard_Integer /*width*/,
104 const Standard_Integer /*height*/)
106 if (ACView.RenderParams.Method == Graphic3d_RM_RAYTRACING
107 && !myCaps->vboDisable
108 && !myCaps->keepArrayData)
110 if (ACView.WasRedrawnGL)
112 myDeviceLostFlag = Standard_True;
115 myCaps->keepArrayData = Standard_True;
118 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
121 /*if( width <= 0 || height <= 0 )
122 aCView->WS->Redraw(ACView, ACUnderLayer, ACOverLayer);
124 aCView->WS->RedrawArea(ACView, ACUnderLayer, ACOverLayer, x, y, width, height);*/
125 // Always do full redraw
126 aCView->WS->Redraw(ACView, ACUnderLayer, ACOverLayer);
130 void OpenGl_GraphicDriver::RedrawImmediate (const Graphic3d_CView& theCView,
131 const Aspect_CLayer2d& theCUnderLayer,
132 const Aspect_CLayer2d& theCOverLayer)
134 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
137 aCView->WS->RedrawImmediate (theCView, theCUnderLayer, theCOverLayer);
141 void OpenGl_GraphicDriver::Invalidate (const Graphic3d_CView& theCView)
143 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
146 aCView->WS->Invalidate (theCView);
150 Graphic3d_PtrFrameBuffer OpenGl_GraphicDriver::FBOCreate (const Graphic3d_CView& ACView, const Standard_Integer theWidth, const Standard_Integer theHeight)
152 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
154 return aCView->WS->FBOCreate(theWidth, theHeight);
155 return (Graphic3d_PtrFrameBuffer)NULL;
158 Graphic3d_PtrFrameBuffer OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth,
159 const Standard_Integer theHeight)
161 // activate OpenGL context
166 const Handle(OpenGl_Context)& aCtx = GetGlContext();
167 OpenGl_FrameBuffer* aFrameBuffer = new OpenGl_FrameBuffer();
168 if (!aFrameBuffer->Init (aCtx, theWidth, theHeight))
170 aFrameBuffer->Release (aCtx.operator->());
174 return (Graphic3d_PtrFrameBuffer )aFrameBuffer;
177 void OpenGl_GraphicDriver::FBORelease (const Graphic3d_CView& ACView, Graphic3d_PtrFrameBuffer& theFBOPtr)
179 if (theFBOPtr == NULL)
181 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
184 aCView->WS->FBORelease(theFBOPtr);
189 void OpenGl_Workspace::FBORelease (Graphic3d_PtrFrameBuffer theFBOPtr)
191 // activate OpenGL context
193 || theFBOPtr == NULL)
198 // release the object
199 OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer*)theFBOPtr;
200 if (aFrameBuffer != NULL)
202 aFrameBuffer->Release (GetGlContext().operator->());
207 void OpenGl_GraphicDriver::FBOGetDimensions (const Graphic3d_CView& ,
208 const Graphic3d_PtrFrameBuffer theFBOPtr,
209 Standard_Integer& theWidth, Standard_Integer& theHeight,
210 Standard_Integer& theWidthMax, Standard_Integer& theHeightMax)
212 if (theFBOPtr == NULL)
216 const OpenGl_FrameBuffer* aFrameBuffer = (const OpenGl_FrameBuffer* )theFBOPtr;
217 theWidth = aFrameBuffer->GetVPSizeX(); // current viewport size
218 theHeight = aFrameBuffer->GetVPSizeY();
219 theWidthMax = aFrameBuffer->GetSizeX(); // texture size
220 theHeightMax = aFrameBuffer->GetSizeY();
223 void OpenGl_GraphicDriver::FBOChangeViewport (const Graphic3d_CView& ,
224 Graphic3d_PtrFrameBuffer& theFBOPtr,
225 const Standard_Integer theWidth, const Standard_Integer theHeight)
227 if (theFBOPtr == NULL)
231 OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theFBOPtr;
232 aFrameBuffer->ChangeViewport (theWidth, theHeight);
235 inline bool getDataFormat (const Image_PixMap& theData,
236 GLenum& thePixelFormat,
239 thePixelFormat = GL_RGB;
240 theDataType = GL_UNSIGNED_BYTE;
241 switch (theData.Format())
243 #if !defined(GL_ES_VERSION_2_0)
244 case Image_PixMap::ImgGray:
245 thePixelFormat = GL_DEPTH_COMPONENT;
246 theDataType = GL_UNSIGNED_BYTE;
248 case Image_PixMap::ImgGrayF:
249 thePixelFormat = GL_DEPTH_COMPONENT;
250 theDataType = GL_FLOAT;
252 case Image_PixMap::ImgBGR:
253 thePixelFormat = GL_BGR;
254 theDataType = GL_UNSIGNED_BYTE;
256 case Image_PixMap::ImgBGRA:
257 case Image_PixMap::ImgBGR32:
258 thePixelFormat = GL_BGRA;
259 theDataType = GL_UNSIGNED_BYTE;
261 case Image_PixMap::ImgBGRF:
262 thePixelFormat = GL_BGR;
263 theDataType = GL_FLOAT;
265 case Image_PixMap::ImgBGRAF:
266 thePixelFormat = GL_BGRA;
267 theDataType = GL_FLOAT;
270 case Image_PixMap::ImgRGB:
271 thePixelFormat = GL_RGB;
272 theDataType = GL_UNSIGNED_BYTE;
274 case Image_PixMap::ImgRGBA:
275 case Image_PixMap::ImgRGB32:
276 thePixelFormat = GL_RGBA;
277 theDataType = GL_UNSIGNED_BYTE;
279 case Image_PixMap::ImgRGBF:
280 thePixelFormat = GL_RGB;
281 theDataType = GL_FLOAT;
283 case Image_PixMap::ImgRGBAF:
284 thePixelFormat = GL_RGBA;
285 theDataType = GL_FLOAT;
292 Standard_Boolean OpenGl_GraphicDriver::BufferDump (const Graphic3d_CView& theCView,
293 Image_PixMap& theImage,
294 const Graphic3d_BufferType& theBufferType)
296 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
297 return (aCView != NULL) && aCView->WS->BufferDump ((OpenGl_FrameBuffer* )theCView.ptrFBO, theImage, theBufferType);
300 Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer* theFBOPtr,
301 Image_PixMap& theImage,
302 const Graphic3d_BufferType& theBufferType)
304 GLenum aFormat, aType;
305 if (theImage.IsEmpty()
306 || !getDataFormat (theImage, aFormat, aType)
309 return Standard_False;
311 #if !defined(GL_ES_VERSION_2_0)
312 GLint aReadBufferPrev = GL_BACK;
313 if (theBufferType == Graphic3d_BT_Depth
314 && aFormat != GL_DEPTH_COMPONENT)
316 return Standard_False;
321 if (theFBOPtr != NULL && theFBOPtr->IsValid())
323 theFBOPtr->BindBuffer (GetGlContext());
327 #if !defined(GL_ES_VERSION_2_0)
328 glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
329 GLint aDrawBufferPrev = GL_BACK;
330 glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
331 glReadBuffer (aDrawBufferPrev);
336 const GLint anAligment = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
337 glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
339 #if !defined(GL_ES_VERSION_2_0)
340 const GLint anExtraBytes = (GLint )theImage.RowExtraBytes();
341 const GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
342 glPixelStorei (GL_PACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
345 if (theImage.IsTopDown())
348 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
350 // Image_PixMap rows indexation always starts from the upper corner
351 // while order in memory depends on the flag and processed by ChangeRow() method
352 glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
357 glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
360 glPixelStorei (GL_PACK_ALIGNMENT, 1);
361 #if !defined(GL_ES_VERSION_2_0)
362 glPixelStorei (GL_PACK_ROW_LENGTH, 0);
365 if (theFBOPtr != NULL && theFBOPtr->IsValid())
367 theFBOPtr->UnbindBuffer (GetGlContext());
371 #if !defined(GL_ES_VERSION_2_0)
372 glReadBuffer (aReadBufferPrev);
375 return Standard_True;
378 void OpenGl_GraphicDriver::RemoveView (const Graphic3d_CView& theCView)
380 Handle(OpenGl_Context) aCtx = GetSharedContext();
381 Handle(OpenGl_View) aView;
382 Handle(OpenGl_Workspace) aWindow;
383 if (myMapOfWS.Find (theCView.WsId, aWindow))
385 myMapOfWS.UnBind (theCView.WsId);
387 if (!aWindow.IsNull())
389 if (aWindow->GetGlContext()->MakeCurrent())
391 aCtx = aWindow->GetGlContext();
395 // try to hijack another context if any
396 const Handle(OpenGl_Context)& anOtherCtx = GetSharedContext();
397 if (!anOtherCtx.IsNull()
398 && anOtherCtx != aWindow->GetGlContext())
405 if (myMapOfView.Find (theCView.ViewId, aView))
407 aView->ReleaseGlResources (aCtx);
408 myMapOfView.UnBind (theCView.ViewId);
411 if (myMapOfWS.IsEmpty())
413 // The last view removed but some objects still present.
414 // Release GL resources now without object destruction.
415 for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
416 aStructIt.More (); aStructIt.Next())
418 OpenGl_Structure* aStruct = aStructIt.ChangeValue();
419 aStruct->ReleaseGlResources (aCtx);
421 myTempText->Release (aCtx.operator->());
422 myDeviceLostFlag = !myMapOfStructure.IsEmpty();
425 OpenGl_CView* aCView = (OpenGl_CView* )theCView.ptrView;
427 ((Graphic3d_CView *)&theCView)->ptrView = NULL;
434 void OpenGl_GraphicDriver::SetLight (const Graphic3d_CView& ACView)
436 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
438 aCView->View->SetLights(ACView.Context);
441 void OpenGl_GraphicDriver::SetClipPlanes (const Graphic3d_CView& theCView)
443 const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
446 aCView->View->SetClipPlanes (theCView.Context.ClipPlanes);
450 //=======================================================================
451 //function : SetCamera
453 //=======================================================================
454 void OpenGl_GraphicDriver::SetCamera (const Graphic3d_CView& theCView)
456 const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
459 aCView->View->SetCamera (theCView.Context.Camera);
463 void OpenGl_GraphicDriver::SetVisualisation (const Graphic3d_CView& ACView)
465 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
468 aCView->View->SetVisualisation(ACView.Context);
469 aCView->WS->UseZBuffer() = ( ACView.Context.Visualization == 0? (ACView.Context.ZBufferActivity == 1) : (ACView.Context.ZBufferActivity != 0) );
473 void OpenGl_GraphicDriver::Transparency (const Graphic3d_CView& ACView, const Standard_Boolean AFlag)
475 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
477 aCView->WS->UseTransparency(AFlag);
480 // =======================================================================
481 // function : InvalidateBVHData
483 // =======================================================================
484 void OpenGl_GraphicDriver::InvalidateBVHData (Graphic3d_CView& theCView, const Standard_Integer theLayerId)
486 OpenGl_CView *aCView = (OpenGl_CView *)theCView.ptrView;
489 aCView->View->InvalidateBVHData (theLayerId);
493 Standard_Boolean OpenGl_GraphicDriver::View (Graphic3d_CView& theCView)
495 Handle(OpenGl_Context) aShareCtx = GetSharedContext();
496 if (myMapOfView.IsBound (theCView.ViewId))
498 OpenGl_CView* aCView = (OpenGl_CView* )theCView.ptrView;
499 if (!myMapOfWS.IsBound (theCView.WsId)
502 return Standard_False;
505 Handle(OpenGl_Workspace) aWS = new OpenGl_Workspace (this, theCView.DefWindow, theCView.GContext, myCaps, aShareCtx);
507 aWS->SetActiveView (aCView->View);
509 myMapOfWS.UnBind (theCView.WsId);
510 myMapOfWS.Bind (theCView.WsId, aWS);
511 return Standard_True;
514 Handle(OpenGl_Workspace) aWS = new OpenGl_Workspace (this, theCView.DefWindow, theCView.GContext, myCaps, aShareCtx);
515 Handle(OpenGl_View) aView = new OpenGl_View (theCView.Context, &myStateCounter);
516 myMapOfWS .Bind (theCView.WsId, aWS);
517 myMapOfView.Bind (theCView.ViewId, aView);
519 OpenGl_CView* aCView = new OpenGl_CView();
520 aCView->View = aView;
522 theCView.ptrView = aCView;
523 aWS->SetActiveView (aCView->View);
525 return Standard_True;
528 void OpenGl_GraphicDriver::SetBackFacingModel (const Graphic3d_CView& ACView)
530 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
532 aCView->View->SetBackfacing(ACView.Backfacing);
535 //=======================================================================
536 //function : AddZLayer
538 //=======================================================================
540 void OpenGl_GraphicDriver::AddZLayer (const Graphic3d_CView& theCView,
541 const Standard_Integer theLayerId)
543 const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
545 aCView->View->AddZLayer (theLayerId);
548 //=======================================================================
549 //function : RemoveZLayer
551 //=======================================================================
552 void OpenGl_GraphicDriver::RemoveZLayer (const Graphic3d_CView& theCView,
553 const Standard_Integer theLayerId)
555 const OpenGl_CView* aCView = (const OpenGl_CView *)theCView.ptrView;
557 aCView->View->RemoveZLayer (theLayerId);
560 //=======================================================================
561 //function : SetZLayerSettings
563 //=======================================================================
564 Standard_EXPORT void OpenGl_GraphicDriver::SetZLayerSettings (const Graphic3d_CView& theCView,
565 const Standard_Integer theLayerId,
566 const Graphic3d_ZLayerSettings& theSettings)
568 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
570 aCView->View->SetZLayerSettings (theLayerId, theSettings);