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