0024887: Visualization - revise and extend Raytracing controls
[occt.git] / src / OpenGl / OpenGl_GraphicDriver_7.cxx
CommitLineData
b311480e 1// Created on: 2011-10-20
2// Created by: Sergey ZERCHANINOV
973c2be1 3// Copyright (c) 2011-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 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
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
7fd59977 15
2166f0fa 16#include <OpenGl_GraphicDriver.hxx>
7fd59977 17
7fd59977 18#include <OpenGl_FrameBuffer.hxx>
19
2166f0fa
SK
20#include <OpenGl_Structure.hxx>
21#include <OpenGl_CView.hxx>
eb4320f2 22#include <OpenGl_Text.hxx>
7fd59977 23
2166f0fa 24/*----------------------------------------------------------------------*/
7fd59977 25
2166f0fa
SK
26void OpenGl_GraphicDriver::ActivateView (const Graphic3d_CView& ACView)
27{
28 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
29 if (aCView)
30 aCView->WS->SetActiveView(aCView->View);
7fd59977 31}
32
2166f0fa
SK
33void OpenGl_GraphicDriver::AntiAliasing (const Graphic3d_CView& ACView, const Standard_Boolean AFlag)
34{
35 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
36 if (aCView)
37 aCView->View->SetAntiAliasing(AFlag);
7fd59977 38}
39
2166f0fa
SK
40void OpenGl_GraphicDriver::Background (const Graphic3d_CView& ACView)
41{
42 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
43 if (aCView)
44 {
45 aCView->WS->SetBackgroundColor(ACView.DefWindow.Background.r,ACView.DefWindow.Background.g,ACView.DefWindow.Background.b);
7fd59977 46 }
7fd59977 47}
48
2166f0fa 49void OpenGl_GraphicDriver::GradientBackground (const Graphic3d_CView& ACView,
7fd59977 50 const Quantity_Color& AColor1,
51 const Quantity_Color& AColor2,
2166f0fa
SK
52 const Aspect_GradientFillMethod AType)
53{
54 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
55 if (aCView)
56 {
57 aCView->View->SetBackgroundGradient(AColor1,AColor2,AType);
7fd59977 58 }
7fd59977 59}
60
2166f0fa
SK
61void OpenGl_GraphicDriver::ClipLimit (const Graphic3d_CView& ACView, const Standard_Boolean AWait)
62{
63 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
64 if (aCView)
65 {
66 aCView->View->SetClipLimit(ACView);
529afc1a 67 if (!AWait)
2166f0fa
SK
68 {
69 aCView->WS->Resize(ACView.DefWindow);
2166f0fa 70 }
7fd59977 71 }
7fd59977 72}
73
2166f0fa
SK
74void OpenGl_GraphicDriver::DeactivateView (const Graphic3d_CView& ACView)
75{
76 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
77 if (aCView)
78 {
79 const Handle(OpenGl_View) aDummyView;
80 aCView->WS->SetActiveView(aDummyView);
7fd59977 81 }
7fd59977 82}
83
2166f0fa
SK
84void OpenGl_GraphicDriver::DepthCueing (const Graphic3d_CView& ACView, const Standard_Boolean AFlag)
85{
86 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
87 if (aCView)
88 aCView->View->SetFog(ACView, AFlag);
7fd59977 89}
90
529afc1a 91void OpenGl_GraphicDriver::RatioWindow (const Graphic3d_CView& theCView)
2166f0fa 92{
529afc1a
K
93 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
94 if (aCView != NULL)
95 aCView->WS->Resize (theCView.DefWindow);
2166f0fa 96}
7fd59977 97
35e08fe8 98void 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*/)
2166f0fa 105{
bc8c79bb 106 if (!myCaps->vboDisable && ACView.RenderParams.Method == Graphic3d_RM_RAYTRACING)
e276548b 107 {
108 if (ACView.WasRedrawnGL)
109 {
110 myDeviceLostFlag = Standard_True;
111 }
112
113 myCaps->keepArrayData = Standard_True;
114 }
115
2166f0fa
SK
116 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
117 if (aCView)
118 {
119 /*if( width <= 0 || height <= 0 )
120 aCView->WS->Redraw(ACView, ACUnderLayer, ACOverLayer);
121 else
122 aCView->WS->RedrawArea(ACView, ACUnderLayer, ACOverLayer, x, y, width, height);*/
123 // Always do full redraw
124 aCView->WS->Redraw(ACView, ACUnderLayer, ACOverLayer);
7fd59977 125 }
7fd59977 126}
127
679ecdee 128void OpenGl_GraphicDriver::RedrawImmediate (const Graphic3d_CView& theCView,
129 const Aspect_CLayer2d& theCUnderLayer,
130 const Aspect_CLayer2d& theCOverLayer)
131{
132 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
133 if (aCView != NULL)
134 {
135 aCView->WS->RedrawImmediate (theCView, theCUnderLayer, theCOverLayer);
136 }
137}
138
139void OpenGl_GraphicDriver::Invalidate (const Graphic3d_CView& theCView)
140{
141 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
142 if (aCView != NULL)
143 {
144 aCView->WS->Invalidate (theCView);
145 }
146}
147
2166f0fa
SK
148Graphic3d_PtrFrameBuffer OpenGl_GraphicDriver::FBOCreate (const Graphic3d_CView& ACView, const Standard_Integer theWidth, const Standard_Integer theHeight)
149{
150 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
151 if (aCView)
152 return aCView->WS->FBOCreate(theWidth, theHeight);
153 return (Graphic3d_PtrFrameBuffer)NULL;
7fd59977 154}
155
fd4a6963 156Graphic3d_PtrFrameBuffer OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth,
157 const Standard_Integer theHeight)
2166f0fa 158{
7fd59977 159 // activate OpenGL context
2166f0fa 160 if (!Activate())
7fd59977 161 return NULL;
2166f0fa 162
7fd59977 163 // create the FBO
fd4a6963 164 const Handle(OpenGl_Context)& aCtx = GetGlContext();
7fd59977 165 OpenGl_FrameBuffer* aFrameBuffer = new OpenGl_FrameBuffer();
fd4a6963 166 if (!aFrameBuffer->Init (aCtx, theWidth, theHeight))
7fd59977 167 {
fd4a6963 168 aFrameBuffer->Release (aCtx.operator->());
7fd59977 169 delete aFrameBuffer;
170 return NULL;
171 }
172 return (Graphic3d_PtrFrameBuffer )aFrameBuffer;
173}
174
2166f0fa 175void OpenGl_GraphicDriver::FBORelease (const Graphic3d_CView& ACView, Graphic3d_PtrFrameBuffer& theFBOPtr)
7fd59977 176{
177 if (theFBOPtr == NULL)
7fd59977 178 return;
2166f0fa
SK
179 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
180 if (aCView)
181 {
182 aCView->WS->FBORelease(theFBOPtr);
183 theFBOPtr = NULL;
7fd59977 184 }
2166f0fa
SK
185}
186
187void OpenGl_Workspace::FBORelease (Graphic3d_PtrFrameBuffer theFBOPtr)
188{
7fd59977 189 // activate OpenGL context
fd4a6963 190 if (!Activate()
191 || theFBOPtr == NULL)
192 {
7fd59977 193 return;
fd4a6963 194 }
2166f0fa 195
7fd59977 196 // release the object
2166f0fa 197 OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer*)theFBOPtr;
fd4a6963 198 if (aFrameBuffer != NULL)
199 {
200 aFrameBuffer->Release (GetGlContext().operator->());
201 }
7fd59977 202 delete aFrameBuffer;
7fd59977 203}
204
205void OpenGl_GraphicDriver::FBOGetDimensions (const Graphic3d_CView& ,
206 const Graphic3d_PtrFrameBuffer theFBOPtr,
207 Standard_Integer& theWidth, Standard_Integer& theHeight,
208 Standard_Integer& theWidthMax, Standard_Integer& theHeightMax)
209{
210 if (theFBOPtr == NULL)
211 {
212 return;
213 }
214 const OpenGl_FrameBuffer* aFrameBuffer = (const OpenGl_FrameBuffer* )theFBOPtr;
215 theWidth = aFrameBuffer->GetVPSizeX(); // current viewport size
216 theHeight = aFrameBuffer->GetVPSizeY();
217 theWidthMax = aFrameBuffer->GetSizeX(); // texture size
218 theHeightMax = aFrameBuffer->GetSizeY();
219}
220
221void OpenGl_GraphicDriver::FBOChangeViewport (const Graphic3d_CView& ,
222 Graphic3d_PtrFrameBuffer& theFBOPtr,
223 const Standard_Integer theWidth, const Standard_Integer theHeight)
224{
225 if (theFBOPtr == NULL)
226 {
227 return;
228 }
229 OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theFBOPtr;
230 aFrameBuffer->ChangeViewport (theWidth, theHeight);
231}
232
692613e5 233inline bool getDataFormat (const Image_PixMap& theData,
234 GLenum& thePixelFormat,
235 GLenum& theDataType)
7fd59977 236{
692613e5 237 thePixelFormat = GL_RGB;
238 theDataType = GL_UNSIGNED_BYTE;
239 switch (theData.Format())
7fd59977 240 {
692613e5 241 case Image_PixMap::ImgGray:
242 thePixelFormat = GL_DEPTH_COMPONENT;
243 theDataType = GL_UNSIGNED_BYTE;
244 return true;
245 case Image_PixMap::ImgRGB:
246 thePixelFormat = GL_RGB;
247 theDataType = GL_UNSIGNED_BYTE;
248 return true;
249 case Image_PixMap::ImgBGR:
250 thePixelFormat = GL_BGR;
251 theDataType = GL_UNSIGNED_BYTE;
252 return true;
253 case Image_PixMap::ImgRGBA:
254 case Image_PixMap::ImgRGB32:
255 thePixelFormat = GL_RGBA;
256 theDataType = GL_UNSIGNED_BYTE;
257 return true;
258 case Image_PixMap::ImgBGRA:
259 case Image_PixMap::ImgBGR32:
260 thePixelFormat = GL_BGRA;
261 theDataType = GL_UNSIGNED_BYTE;
262 return true;
263 case Image_PixMap::ImgGrayF:
264 thePixelFormat = GL_DEPTH_COMPONENT;
265 theDataType = GL_FLOAT;
266 return true;
267 case Image_PixMap::ImgRGBF:
268 thePixelFormat = GL_RGB;
269 theDataType = GL_FLOAT;
270 return true;
271 case Image_PixMap::ImgBGRF:
272 thePixelFormat = GL_BGR;
273 theDataType = GL_FLOAT;
274 return true;
275 case Image_PixMap::ImgRGBAF:
276 thePixelFormat = GL_RGBA;
277 theDataType = GL_FLOAT;
278 return true;
279 case Image_PixMap::ImgBGRAF:
280 thePixelFormat = GL_BGRA;
281 theDataType = GL_FLOAT;
282 return true;
283 default:
284 return false;
7fd59977 285 }
286}
287
692613e5 288Standard_Boolean OpenGl_GraphicDriver::BufferDump (const Graphic3d_CView& theCView,
289 Image_PixMap& theImage,
290 const Graphic3d_BufferType& theBufferType)
7fd59977 291{
692613e5 292 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
293 return (aCView != NULL) && aCView->WS->BufferDump ((OpenGl_FrameBuffer* )theCView.ptrFBO, theImage, theBufferType);
2166f0fa
SK
294}
295
692613e5 296Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer* theFBOPtr,
297 Image_PixMap& theImage,
298 const Graphic3d_BufferType& theBufferType)
7fd59977 299{
692613e5 300 GLenum aFormat, aType;
301 if (theImage.IsEmpty()
302 || !getDataFormat (theImage, aFormat, aType)
303 || ((theBufferType == Graphic3d_BT_Depth) && (aFormat != GL_DEPTH_COMPONENT))
304 || !Activate())
7fd59977 305 {
306 return Standard_False;
307 }
308
7fd59977 309 // bind FBO if used
7fd59977 310 GLint aReadBufferPrev = GL_BACK;
692613e5 311 if (theFBOPtr != NULL && theFBOPtr->IsValid())
7fd59977 312 {
692613e5 313 theFBOPtr->BindBuffer (GetGlContext());
7fd59977 314 }
315 else
316 {
317 glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
318 GLint aDrawBufferPrev = GL_BACK;
319 glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
320 glReadBuffer (aDrawBufferPrev);
321 }
322
74706083 323 // setup alignment
324 const GLint anExtraBytes = (GLint )theImage.RowExtraBytes();
325 const GLint anAligment = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
692613e5 326 glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
327
74706083 328 const GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
329 glPixelStorei (GL_PACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
330
331 if (theImage.IsTopDown())
692613e5 332 {
333 // copy row by row
334 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
335 {
74706083 336 // Image_PixMap rows indexation always starts from the upper corner
337 // while order in memory depends on the flag and processed by ChangeRow() method
338 glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
692613e5 339 }
340 }
341 else
7fd59977 342 {
692613e5 343 glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
7fd59977 344 }
7fd59977 345
74706083 346 glPixelStorei (GL_PACK_ALIGNMENT, 1);
347 glPixelStorei (GL_PACK_ROW_LENGTH, 0);
7fd59977 348
692613e5 349 if (theFBOPtr != NULL && theFBOPtr->IsValid())
7fd59977 350 {
692613e5 351 theFBOPtr->UnbindBuffer (GetGlContext());
7fd59977 352 }
353 else
354 {
355 glReadBuffer (aReadBufferPrev);
356 }
357 return Standard_True;
358}
359
dd8a4ce9 360void OpenGl_GraphicDriver::RemoveView (const Graphic3d_CView& theCView)
2166f0fa 361{
fd4a6963 362 Handle(OpenGl_Context) aCtx = GetSharedContext();
363 Handle(OpenGl_View) aView;
364 Handle(OpenGl_Workspace) aWindow;
365 if (myMapOfWS.Find (theCView.WsId, aWindow))
366 {
dd8a4ce9 367 myMapOfWS.UnBind (theCView.WsId);
fd4a6963 368 }
369 if (!aWindow.IsNull())
370 {
371 if (aWindow->GetGlContext()->MakeCurrent())
372 {
373 aCtx = aWindow->GetGlContext();
374 }
375 else
376 {
377 // try to hijack another context if any
378 const Handle(OpenGl_Context)& anOtherCtx = GetSharedContext();
379 if (!anOtherCtx.IsNull()
380 && anOtherCtx != aWindow->GetGlContext())
381 {
382 aCtx = anOtherCtx;
383 aCtx->MakeCurrent();
384 }
385 }
386 }
387 if (myMapOfView.Find (theCView.ViewId, aView))
388 {
389 aView->ReleaseGlResources (aCtx);
390 myMapOfView.UnBind (theCView.ViewId);
391 }
7fd59977 392
fd4a6963 393 if (myMapOfWS.IsEmpty())
dd8a4ce9 394 {
395 // The last view removed but some objects still present.
396 // Release GL resources now without object destruction.
397 for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
398 aStructIt.More (); aStructIt.Next())
399 {
400 OpenGl_Structure* aStruct = aStructIt.ChangeValue();
fd4a6963 401 aStruct->ReleaseGlResources (aCtx);
dd8a4ce9 402 }
fd4a6963 403 myTempText->Release (aCtx);
fd4a6963 404 myDeviceLostFlag = !myMapOfStructure.IsEmpty();
dd8a4ce9 405 }
406
bf75be98 407 OpenGl_CView* aCView = (OpenGl_CView* )theCView.ptrView;
2166f0fa 408 delete aCView;
dd8a4ce9 409 ((Graphic3d_CView *)&theCView)->ptrView = NULL;
fd4a6963 410
411 aCtx.Nullify();
412 aView.Nullify();
413 aWindow.Nullify();
7fd59977 414}
415
2166f0fa
SK
416void OpenGl_GraphicDriver::SetLight (const Graphic3d_CView& ACView)
417{
418 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
419 if (aCView)
420 aCView->View->SetLights(ACView.Context);
7fd59977 421}
422
4269bd1b 423void OpenGl_GraphicDriver::SetClipPlanes (const Graphic3d_CView& theCView)
2166f0fa 424{
4269bd1b 425 const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
2166f0fa 426 if (aCView)
4269bd1b 427 {
428 aCView->View->SetClipPlanes (theCView.Context.ClipPlanes);
429 }
430}
431
b5ac8292 432//=======================================================================
433//function : SetCamera
434//purpose :
435//=======================================================================
436void OpenGl_GraphicDriver::SetCamera (const Graphic3d_CView& theCView)
437{
438 const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
439 if (aCView)
440 {
441 aCView->View->SetCamera (theCView.Context.Camera);
442 }
443}
444
2166f0fa
SK
445void OpenGl_GraphicDriver::SetVisualisation (const Graphic3d_CView& ACView)
446{
447 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
448 if (aCView)
449 {
450 aCView->View->SetVisualisation(ACView.Context);
451 aCView->WS->UseZBuffer() = ( ACView.Context.Visualization == 0? (ACView.Context.ZBufferActivity == 1) : (ACView.Context.ZBufferActivity != 0) );
7fd59977 452 }
7fd59977 453}
454
2166f0fa
SK
455void OpenGl_GraphicDriver::Transparency (const Graphic3d_CView& ACView, const Standard_Boolean AFlag)
456{
457 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
458 if (aCView)
459 aCView->WS->UseTransparency(AFlag);
460}
7fd59977 461
5e27df78 462Standard_Boolean OpenGl_GraphicDriver::View (Graphic3d_CView& theCView)
2166f0fa 463{
73192b37 464 if (myMapOfView.IsBound (theCView.ViewId)
fd4a6963 465 || myMapOfWS .IsBound (theCView.WsId))
2166f0fa 466 {
fd4a6963 467 return Standard_False;
7fd59977 468 }
469
fd4a6963 470 Handle(OpenGl_Context) aShareCtx = GetSharedContext();
73192b37 471 Handle(OpenGl_Workspace) aWS = new OpenGl_Workspace (myDisplayConnection, theCView.DefWindow, theCView.GContext, myCaps, aShareCtx);
392ac980 472 Handle(OpenGl_View) aView = new OpenGl_View (theCView.Context, &myStateCounter);
fd4a6963 473 myMapOfWS .Bind (theCView.WsId, aWS);
5e27df78 474 myMapOfView.Bind (theCView.ViewId, aView);
7fd59977 475
5e27df78 476 OpenGl_CView* aCView = new OpenGl_CView();
2166f0fa 477 aCView->View = aView;
fd4a6963 478 aCView->WS = aWS;
5e27df78 479 theCView.ptrView = aCView;
7fd59977 480
2166f0fa
SK
481 return Standard_True;
482}
7fd59977 483
2166f0fa
SK
484void OpenGl_GraphicDriver::SetBackFacingModel (const Graphic3d_CView& ACView)
485{
486 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
487 if (aCView)
488 aCView->View->SetBackfacing(ACView.Backfacing);
489}
59f45b7c 490
491//=======================================================================
492//function : AddZLayer
bf75be98 493//purpose :
59f45b7c 494//=======================================================================
495
496void OpenGl_GraphicDriver::AddZLayer (const Graphic3d_CView& theCView,
497 const Standard_Integer theLayerId)
498{
499 const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
500 if (aCView)
501 aCView->View->AddZLayer (theLayerId);
502}
503
504//=======================================================================
505//function : RemoveZLayer
506//purpose :
507//=======================================================================
59f45b7c 508void OpenGl_GraphicDriver::RemoveZLayer (const Graphic3d_CView& theCView,
509 const Standard_Integer theLayerId)
510{
511 const OpenGl_CView* aCView = (const OpenGl_CView *)theCView.ptrView;
512 if (aCView)
513 aCView->View->RemoveZLayer (theLayerId);
514}
c5751993 515
516//=======================================================================
517//function : SetZLayerSettings
518//purpose :
519//=======================================================================
520Standard_EXPORT void OpenGl_GraphicDriver::SetZLayerSettings (const Graphic3d_CView& theCView,
521 const Standard_Integer theLayerId,
522 const Graphic3d_ZLayerSettings& theSettings)
523{
524 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
525 if (aCView)
526 aCView->View->SetZLayerSettings (theLayerId, theSettings);
527}