0024732: OpenGl_Context - retrieve functions up to GL4.4
[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
2166f0fa
SK
129Graphic3d_PtrFrameBuffer OpenGl_GraphicDriver::FBOCreate (const Graphic3d_CView& ACView, const Standard_Integer theWidth, const Standard_Integer theHeight)
130{
131 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
132 if (aCView)
133 return aCView->WS->FBOCreate(theWidth, theHeight);
134 return (Graphic3d_PtrFrameBuffer)NULL;
7fd59977 135}
136
fd4a6963 137Graphic3d_PtrFrameBuffer OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth,
138 const Standard_Integer theHeight)
2166f0fa 139{
7fd59977 140 // activate OpenGL context
2166f0fa 141 if (!Activate())
7fd59977 142 return NULL;
2166f0fa 143
7fd59977 144 // create the FBO
fd4a6963 145 const Handle(OpenGl_Context)& aCtx = GetGlContext();
7fd59977 146 OpenGl_FrameBuffer* aFrameBuffer = new OpenGl_FrameBuffer();
fd4a6963 147 if (!aFrameBuffer->Init (aCtx, theWidth, theHeight))
7fd59977 148 {
fd4a6963 149 aFrameBuffer->Release (aCtx.operator->());
7fd59977 150 delete aFrameBuffer;
151 return NULL;
152 }
153 return (Graphic3d_PtrFrameBuffer )aFrameBuffer;
154}
155
2166f0fa 156void OpenGl_GraphicDriver::FBORelease (const Graphic3d_CView& ACView, Graphic3d_PtrFrameBuffer& theFBOPtr)
7fd59977 157{
158 if (theFBOPtr == NULL)
7fd59977 159 return;
2166f0fa
SK
160 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
161 if (aCView)
162 {
163 aCView->WS->FBORelease(theFBOPtr);
164 theFBOPtr = NULL;
7fd59977 165 }
2166f0fa
SK
166}
167
168void OpenGl_Workspace::FBORelease (Graphic3d_PtrFrameBuffer theFBOPtr)
169{
7fd59977 170 // activate OpenGL context
fd4a6963 171 if (!Activate()
172 || theFBOPtr == NULL)
173 {
7fd59977 174 return;
fd4a6963 175 }
2166f0fa 176
7fd59977 177 // release the object
2166f0fa 178 OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer*)theFBOPtr;
fd4a6963 179 if (aFrameBuffer != NULL)
180 {
181 aFrameBuffer->Release (GetGlContext().operator->());
182 }
7fd59977 183 delete aFrameBuffer;
7fd59977 184}
185
186void OpenGl_GraphicDriver::FBOGetDimensions (const Graphic3d_CView& ,
187 const Graphic3d_PtrFrameBuffer theFBOPtr,
188 Standard_Integer& theWidth, Standard_Integer& theHeight,
189 Standard_Integer& theWidthMax, Standard_Integer& theHeightMax)
190{
191 if (theFBOPtr == NULL)
192 {
193 return;
194 }
195 const OpenGl_FrameBuffer* aFrameBuffer = (const OpenGl_FrameBuffer* )theFBOPtr;
196 theWidth = aFrameBuffer->GetVPSizeX(); // current viewport size
197 theHeight = aFrameBuffer->GetVPSizeY();
198 theWidthMax = aFrameBuffer->GetSizeX(); // texture size
199 theHeightMax = aFrameBuffer->GetSizeY();
200}
201
202void OpenGl_GraphicDriver::FBOChangeViewport (const Graphic3d_CView& ,
203 Graphic3d_PtrFrameBuffer& theFBOPtr,
204 const Standard_Integer theWidth, const Standard_Integer theHeight)
205{
206 if (theFBOPtr == NULL)
207 {
208 return;
209 }
210 OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theFBOPtr;
211 aFrameBuffer->ChangeViewport (theWidth, theHeight);
212}
213
692613e5 214inline bool getDataFormat (const Image_PixMap& theData,
215 GLenum& thePixelFormat,
216 GLenum& theDataType)
7fd59977 217{
692613e5 218 thePixelFormat = GL_RGB;
219 theDataType = GL_UNSIGNED_BYTE;
220 switch (theData.Format())
7fd59977 221 {
692613e5 222 case Image_PixMap::ImgGray:
223 thePixelFormat = GL_DEPTH_COMPONENT;
224 theDataType = GL_UNSIGNED_BYTE;
225 return true;
226 case Image_PixMap::ImgRGB:
227 thePixelFormat = GL_RGB;
228 theDataType = GL_UNSIGNED_BYTE;
229 return true;
230 case Image_PixMap::ImgBGR:
231 thePixelFormat = GL_BGR;
232 theDataType = GL_UNSIGNED_BYTE;
233 return true;
234 case Image_PixMap::ImgRGBA:
235 case Image_PixMap::ImgRGB32:
236 thePixelFormat = GL_RGBA;
237 theDataType = GL_UNSIGNED_BYTE;
238 return true;
239 case Image_PixMap::ImgBGRA:
240 case Image_PixMap::ImgBGR32:
241 thePixelFormat = GL_BGRA;
242 theDataType = GL_UNSIGNED_BYTE;
243 return true;
244 case Image_PixMap::ImgGrayF:
245 thePixelFormat = GL_DEPTH_COMPONENT;
246 theDataType = GL_FLOAT;
247 return true;
248 case Image_PixMap::ImgRGBF:
249 thePixelFormat = GL_RGB;
250 theDataType = GL_FLOAT;
251 return true;
252 case Image_PixMap::ImgBGRF:
253 thePixelFormat = GL_BGR;
254 theDataType = GL_FLOAT;
255 return true;
256 case Image_PixMap::ImgRGBAF:
257 thePixelFormat = GL_RGBA;
258 theDataType = GL_FLOAT;
259 return true;
260 case Image_PixMap::ImgBGRAF:
261 thePixelFormat = GL_BGRA;
262 theDataType = GL_FLOAT;
263 return true;
264 default:
265 return false;
7fd59977 266 }
267}
268
692613e5 269Standard_Boolean OpenGl_GraphicDriver::BufferDump (const Graphic3d_CView& theCView,
270 Image_PixMap& theImage,
271 const Graphic3d_BufferType& theBufferType)
7fd59977 272{
692613e5 273 const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
274 return (aCView != NULL) && aCView->WS->BufferDump ((OpenGl_FrameBuffer* )theCView.ptrFBO, theImage, theBufferType);
2166f0fa
SK
275}
276
692613e5 277Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer* theFBOPtr,
278 Image_PixMap& theImage,
279 const Graphic3d_BufferType& theBufferType)
7fd59977 280{
692613e5 281 GLenum aFormat, aType;
282 if (theImage.IsEmpty()
283 || !getDataFormat (theImage, aFormat, aType)
284 || ((theBufferType == Graphic3d_BT_Depth) && (aFormat != GL_DEPTH_COMPONENT))
285 || !Activate())
7fd59977 286 {
287 return Standard_False;
288 }
289
7fd59977 290 // bind FBO if used
7fd59977 291 GLint aReadBufferPrev = GL_BACK;
692613e5 292 if (theFBOPtr != NULL && theFBOPtr->IsValid())
7fd59977 293 {
692613e5 294 theFBOPtr->BindBuffer (GetGlContext());
7fd59977 295 }
296 else
297 {
298 glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
299 GLint aDrawBufferPrev = GL_BACK;
300 glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
301 glReadBuffer (aDrawBufferPrev);
302 }
303
74706083 304 // setup alignment
305 const GLint anExtraBytes = (GLint )theImage.RowExtraBytes();
306 const GLint anAligment = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
692613e5 307 glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
308
74706083 309 const GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
310 glPixelStorei (GL_PACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
311
312 if (theImage.IsTopDown())
692613e5 313 {
314 // copy row by row
315 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
316 {
74706083 317 // Image_PixMap rows indexation always starts from the upper corner
318 // while order in memory depends on the flag and processed by ChangeRow() method
319 glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
692613e5 320 }
321 }
322 else
7fd59977 323 {
692613e5 324 glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
7fd59977 325 }
7fd59977 326
74706083 327 glPixelStorei (GL_PACK_ALIGNMENT, 1);
328 glPixelStorei (GL_PACK_ROW_LENGTH, 0);
7fd59977 329
692613e5 330 if (theFBOPtr != NULL && theFBOPtr->IsValid())
7fd59977 331 {
692613e5 332 theFBOPtr->UnbindBuffer (GetGlContext());
7fd59977 333 }
334 else
335 {
336 glReadBuffer (aReadBufferPrev);
337 }
338 return Standard_True;
339}
340
dd8a4ce9 341void OpenGl_GraphicDriver::RemoveView (const Graphic3d_CView& theCView)
2166f0fa 342{
fd4a6963 343 Handle(OpenGl_Context) aCtx = GetSharedContext();
344 Handle(OpenGl_View) aView;
345 Handle(OpenGl_Workspace) aWindow;
346 if (myMapOfWS.Find (theCView.WsId, aWindow))
347 {
dd8a4ce9 348 myMapOfWS.UnBind (theCView.WsId);
fd4a6963 349 }
350 if (!aWindow.IsNull())
351 {
352 if (aWindow->GetGlContext()->MakeCurrent())
353 {
354 aCtx = aWindow->GetGlContext();
355 }
356 else
357 {
358 // try to hijack another context if any
359 const Handle(OpenGl_Context)& anOtherCtx = GetSharedContext();
360 if (!anOtherCtx.IsNull()
361 && anOtherCtx != aWindow->GetGlContext())
362 {
363 aCtx = anOtherCtx;
364 aCtx->MakeCurrent();
365 }
366 }
367 }
368 if (myMapOfView.Find (theCView.ViewId, aView))
369 {
370 aView->ReleaseGlResources (aCtx);
371 myMapOfView.UnBind (theCView.ViewId);
372 }
7fd59977 373
fd4a6963 374 if (myMapOfWS.IsEmpty())
dd8a4ce9 375 {
376 // The last view removed but some objects still present.
377 // Release GL resources now without object destruction.
378 for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
379 aStructIt.More (); aStructIt.Next())
380 {
381 OpenGl_Structure* aStruct = aStructIt.ChangeValue();
fd4a6963 382 aStruct->ReleaseGlResources (aCtx);
dd8a4ce9 383 }
fd4a6963 384 myTempText->Release (aCtx);
385 myGlDisplay->ReleaseAttributes (aCtx.operator->());
386 myDeviceLostFlag = !myMapOfStructure.IsEmpty();
dd8a4ce9 387 }
388
bf75be98 389 OpenGl_CView* aCView = (OpenGl_CView* )theCView.ptrView;
2166f0fa 390 delete aCView;
dd8a4ce9 391 ((Graphic3d_CView *)&theCView)->ptrView = NULL;
fd4a6963 392
393 aCtx.Nullify();
394 aView.Nullify();
395 aWindow.Nullify();
7fd59977 396}
397
2166f0fa
SK
398void OpenGl_GraphicDriver::SetLight (const Graphic3d_CView& ACView)
399{
400 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
401 if (aCView)
402 aCView->View->SetLights(ACView.Context);
7fd59977 403}
404
4269bd1b 405void OpenGl_GraphicDriver::SetClipPlanes (const Graphic3d_CView& theCView)
2166f0fa 406{
4269bd1b 407 const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
2166f0fa 408 if (aCView)
4269bd1b 409 {
410 aCView->View->SetClipPlanes (theCView.Context.ClipPlanes);
411 }
412}
413
b5ac8292 414//=======================================================================
415//function : SetCamera
416//purpose :
417//=======================================================================
418void OpenGl_GraphicDriver::SetCamera (const Graphic3d_CView& theCView)
419{
420 const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
421 if (aCView)
422 {
423 aCView->View->SetCamera (theCView.Context.Camera);
424 }
425}
426
2166f0fa
SK
427void OpenGl_GraphicDriver::SetVisualisation (const Graphic3d_CView& ACView)
428{
429 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
430 if (aCView)
431 {
432 aCView->View->SetVisualisation(ACView.Context);
433 aCView->WS->UseZBuffer() = ( ACView.Context.Visualization == 0? (ACView.Context.ZBufferActivity == 1) : (ACView.Context.ZBufferActivity != 0) );
7fd59977 434 }
7fd59977 435}
436
2166f0fa
SK
437void OpenGl_GraphicDriver::Transparency (const Graphic3d_CView& ACView, const Standard_Boolean AFlag)
438{
439 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
440 if (aCView)
441 aCView->WS->UseTransparency(AFlag);
442}
7fd59977 443
2166f0fa
SK
444void OpenGl_GraphicDriver::Update (const Graphic3d_CView& ACView, const Aspect_CLayer2d& ACUnderLayer, const Aspect_CLayer2d& ACOverLayer)
445{
446 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
447 if (aCView)
448 aCView->WS->Update(ACView,ACUnderLayer,ACOverLayer);
449}
7fd59977 450
5e27df78 451Standard_Boolean OpenGl_GraphicDriver::View (Graphic3d_CView& theCView)
2166f0fa 452{
fd4a6963 453 if (myGlDisplay.IsNull()
454 || myMapOfView.IsBound (theCView.ViewId)
455 || myMapOfWS .IsBound (theCView.WsId))
2166f0fa 456 {
fd4a6963 457 return Standard_False;
7fd59977 458 }
459
fd4a6963 460 Handle(OpenGl_Context) aShareCtx = GetSharedContext();
461 Handle(OpenGl_Workspace) aWS = new OpenGl_Workspace (myGlDisplay, theCView.DefWindow, theCView.GContext, myCaps, aShareCtx);
392ac980 462 Handle(OpenGl_View) aView = new OpenGl_View (theCView.Context, &myStateCounter);
fd4a6963 463 myMapOfWS .Bind (theCView.WsId, aWS);
5e27df78 464 myMapOfView.Bind (theCView.ViewId, aView);
7fd59977 465
5e27df78 466 OpenGl_CView* aCView = new OpenGl_CView();
2166f0fa 467 aCView->View = aView;
fd4a6963 468 aCView->WS = aWS;
5e27df78 469 theCView.ptrView = aCView;
7fd59977 470
2166f0fa
SK
471 return Standard_True;
472}
7fd59977 473
2166f0fa
SK
474void OpenGl_GraphicDriver::SetBackFacingModel (const Graphic3d_CView& ACView)
475{
476 const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
477 if (aCView)
478 aCView->View->SetBackfacing(ACView.Backfacing);
479}
59f45b7c 480
481//=======================================================================
482//function : AddZLayer
bf75be98 483//purpose :
59f45b7c 484//=======================================================================
485
486void OpenGl_GraphicDriver::AddZLayer (const Graphic3d_CView& theCView,
487 const Standard_Integer theLayerId)
488{
489 const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView;
490 if (aCView)
491 aCView->View->AddZLayer (theLayerId);
492}
493
494//=======================================================================
495//function : RemoveZLayer
496//purpose :
497//=======================================================================
498
499void OpenGl_GraphicDriver::RemoveZLayer (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->RemoveZLayer (theLayerId);
505}