0024023: Revamp the OCCT Handle -- general
[occt.git] / src / OpenGl / OpenGl_Workspace.cxx
CommitLineData
b311480e 1// Created on: 2011-09-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.
b311480e 15
a577aaab 16#include <OpenGl_GlCore15.hxx>
b86bb3df 17#include <OpenGl_ArbFBO.hxx>
5f8b738e 18
2166f0fa
SK
19#include <InterfaceGraphic.hxx>
20
2166f0fa
SK
21#include <OpenGl_AspectLine.hxx>
22#include <OpenGl_AspectFace.hxx>
23#include <OpenGl_AspectMarker.hxx>
24#include <OpenGl_AspectText.hxx>
bf75be98 25#include <OpenGl_Context.hxx>
679ecdee 26#include <OpenGl_Element.hxx>
a174a3c5 27#include <OpenGl_FrameBuffer.hxx>
679ecdee 28#include <OpenGl_Structure.hxx>
25ef750e 29#include <OpenGl_Sampler.hxx>
b86bb3df 30#include <OpenGl_ShaderManager.hxx>
bf75be98 31#include <OpenGl_Texture.hxx>
c827ea3a 32#include <OpenGl_Utils.hxx>
e276548b 33#include <OpenGl_View.hxx>
a174a3c5 34#include <OpenGl_Workspace.hxx>
2166f0fa 35
bf75be98 36#include <Graphic3d_TextureParams.hxx>
c04c30b3 37#include <Graphic3d_GraphicDriver.hxx>
2166f0fa 38
58655684 39#if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
a174a3c5 40 #include <OpenGl_AVIWriter.hxx>
41#endif
42
2166f0fa
SK
43
44namespace
45{
0adbd30f 46 static const TEL_COLOUR THE_WHITE_COLOR = { { 1.0f, 1.0f, 1.0f, 1.0f } };
47 static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f);
2166f0fa
SK
48
49 static const OpenGl_AspectLine myDefaultAspectLine;
50 static const OpenGl_AspectFace myDefaultAspectFace;
51 static const OpenGl_AspectMarker myDefaultAspectMarker;
52 static const OpenGl_AspectText myDefaultAspectText;
53
54 static const OpenGl_TextParam myDefaultTextParam =
55 {
56 16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
57 };
58
59 static const OpenGl_Matrix myDefaultMatrix =
60 {
61 {{ 1.0F, 0.0F, 0.0F, 0.0F },
62 { 0.0F, 1.0F, 0.0F, 0.0F },
63 { 0.0F, 0.0F, 1.0F, 0.0F },
64 { 0.0F, 0.0F, 0.0F, 1.0F }}
65 };
bf75be98 66
2166f0fa
SK
67};
68
69// =======================================================================
0adbd30f 70// function : Init
71// purpose :
72// =======================================================================
73void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp)
74{
75 // ambient component
76 if (theProp.color_mask & OPENGL_AMBIENT_MASK)
77 {
78 const float* aSrcAmb = theProp.isphysic ? theProp.ambcol.rgb : theProp.matcol.rgb;
79 Ambient = OpenGl_Vec4 (aSrcAmb[0] * theProp.amb,
80 aSrcAmb[1] * theProp.amb,
81 aSrcAmb[2] * theProp.amb,
82 1.0f);
83 }
84 else
85 {
86 Ambient = THE_BLACK_COLOR;
87 }
88
89 // diffusion component
90 if (theProp.color_mask & OPENGL_DIFFUSE_MASK)
91 {
92 const float* aSrcDif = theProp.isphysic ? theProp.difcol.rgb : theProp.matcol.rgb;
93 Diffuse = OpenGl_Vec4 (aSrcDif[0] * theProp.diff,
94 aSrcDif[1] * theProp.diff,
95 aSrcDif[2] * theProp.diff,
96 1.0f);
97 }
98 else
99 {
100 Diffuse = THE_BLACK_COLOR;
101 }
102
103 // specular component
104 if (theProp.color_mask & OPENGL_SPECULAR_MASK)
105 {
106 const float* aSrcSpe = theProp.isphysic ? theProp.speccol.rgb : THE_WHITE_COLOR.rgb;
107 Specular = OpenGl_Vec4 (aSrcSpe[0] * theProp.spec,
108 aSrcSpe[1] * theProp.spec,
109 aSrcSpe[2] * theProp.spec,
110 1.0f);
111 }
112 else
113 {
114 Specular = THE_BLACK_COLOR;
115 }
116
117 // emission component
118 if (theProp.color_mask & OPENGL_EMISSIVE_MASK)
119 {
120 const float* aSrcEms = theProp.isphysic ? theProp.emscol.rgb : theProp.matcol.rgb;
121 Emission = OpenGl_Vec4 (aSrcEms[0] * theProp.emsv,
122 aSrcEms[1] * theProp.emsv,
123 aSrcEms[2] * theProp.emsv,
124 1.0f);
125 }
126 else
127 {
128 Emission = THE_BLACK_COLOR;
129 }
130
131 ChangeShine() = theProp.shine;
132 ChangeTransparency() = theProp.trans;
133}
134
135// =======================================================================
2166f0fa
SK
136// function : OpenGl_Workspace
137// purpose :
138// =======================================================================
25b97fac 139OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_GraphicDriver)& theDriver,
2166f0fa 140 const CALL_DEF_WINDOW& theCWindow,
5e27df78 141 Aspect_RenderingContext theGContext,
58655684 142 const Handle(OpenGl_Caps)& theCaps,
5e27df78 143 const Handle(OpenGl_Context)& theShareCtx)
25b97fac 144: OpenGl_Window (theDriver, theCWindow, theGContext, theCaps, theShareCtx),
a174a3c5 145 NamedStatus (0),
0adbd30f 146 HighlightColor (&THE_WHITE_COLOR),
a174a3c5 147 //
ee51a9fe 148 myHasFboBlit (Standard_True),
fc73a202 149 //
a272ed94 150 myViewId (-1),
73192b37 151 myAntiAliasingMode (3),
a174a3c5 152 myTransientDrawToFront (Standard_True),
679ecdee 153 myBackBufferRestored (Standard_False),
154 myIsImmediateDrawn (Standard_False),
eae454e3 155 myUseZBuffer (Standard_True),
156 myUseDepthWrite (Standard_True),
2166f0fa 157 myUseGLLight (Standard_True),
b7cd4ba7 158 myIsCullingEnabled (Standard_False),
a89742cf 159 myFrameCounter (0),
2166f0fa 160 //
2166f0fa
SK
161 AspectLine_set (&myDefaultAspectLine),
162 AspectLine_applied (NULL),
163 AspectFace_set (&myDefaultAspectFace),
164 AspectFace_applied (NULL),
165 AspectMarker_set (&myDefaultAspectMarker),
166 AspectMarker_applied (NULL),
167 AspectText_set (&myDefaultAspectText),
168 AspectText_applied (NULL),
169 TextParam_set (&myDefaultTextParam),
170 TextParam_applied (NULL),
171 ViewMatrix_applied (&myDefaultMatrix),
172 StructureMatrix_applied (&myDefaultMatrix),
3b1817a9 173 myCullingMode (TelCullUndefined),
0f8c0fb8 174 myModelViewMatrix (myDefaultMatrix),
550f3b8b 175 PolygonOffset_applied (THE_DEFAULT_POFFSET)
2166f0fa 176{
73192b37 177 myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
38a0206f 178 myMainSceneFbos[0] = new OpenGl_FrameBuffer();
179 myMainSceneFbos[1] = new OpenGl_FrameBuffer();
180 myImmediateSceneFbos[0] = new OpenGl_FrameBuffer();
181 myImmediateSceneFbos[1] = new OpenGl_FrameBuffer();
73192b37 182
183 if (!myGlContext->GetResource ("OpenGl_LineAttributes", myLineAttribs))
184 {
185 // share and register for release once the resource is no longer used
186 myLineAttribs = new OpenGl_LineAttributes();
187 myGlContext->ShareResource ("OpenGl_LineAttributes", myLineAttribs);
188 myLineAttribs->Init (myGlContext);
189 }
2166f0fa
SK
190
191 // General initialization of the context
192
ca3c13d1 193#if !defined(GL_ES_VERSION_2_0)
4e1523ef 194 if (myGlContext->core11 != NULL)
195 {
196 // Eviter d'avoir les faces mal orientees en noir.
197 // Pourrait etre utiliser pour detecter les problemes d'orientation
198 glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
199
200 // Optimisation pour le Fog et l'antialiasing
201 glHint (GL_FOG_HINT, GL_FASTEST);
202 glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST);
203 }
2166f0fa 204
2166f0fa
SK
205 glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST);
206 glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
ca3c13d1 207#endif
2166f0fa 208
73192b37 209 // AA mode
210 const char* anAaEnv = ::getenv ("CALL_OPENGL_ANTIALIASING_MODE");
211 if (anAaEnv != NULL)
212 {
213 int v;
214 if (sscanf (anAaEnv, "%d", &v) > 0) myAntiAliasingMode = v;
215 }
f8ae3605 216
217 myDefaultCappingAlgoFilter = new OpenGl_CappingAlgoFilter();
218 myNoneCulling.ChangeCullingMode() = TelCullNone;
219 myNoneCulling.ChangeEdge() = 0;
220 myFrontCulling.ChangeCullingMode() = TelCullBack;
221 myFrontCulling.ChangeEdge() = 0;
2166f0fa
SK
222}
223
224// =======================================================================
1981cb22 225// function : SetImmediateModeDrawToFront
226// purpose :
227// =======================================================================
228Standard_Boolean OpenGl_Workspace::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer)
229{
230 const Standard_Boolean aPrevMode = myTransientDrawToFront;
231 myTransientDrawToFront = theDrawToFrontBuffer;
232 return aPrevMode;
233}
234
38a0206f 235inline void nullifyGlResource (Handle(OpenGl_Resource)& theResource,
236 const Handle(OpenGl_Context)& theCtx)
237{
238 if (!theResource.IsNull())
239 {
240 theResource->Release (theCtx.operator->());
241 theResource.Nullify();
242 }
243}
244
1981cb22 245// =======================================================================
2166f0fa
SK
246// function : ~OpenGl_Workspace
247// purpose :
248// =======================================================================
249OpenGl_Workspace::~OpenGl_Workspace()
250{
73192b37 251 if (!myLineAttribs.IsNull())
252 {
253 myLineAttribs.Nullify();
254 myGlContext->ReleaseResource ("OpenGl_LineAttributes", Standard_True);
255 }
256
38a0206f 257 nullifyGlResource (myMainSceneFbos[0], myGlContext);
258 nullifyGlResource (myMainSceneFbos[1], myGlContext);
259 nullifyGlResource (myImmediateSceneFbos[0], myGlContext);
260 nullifyGlResource (myImmediateSceneFbos[1], myGlContext);
261
262 myFullScreenQuad.Release (myGlContext.operator->());
2166f0fa
SK
263}
264
265// =======================================================================
266// function : Activate
267// purpose :
268// =======================================================================
269Standard_Boolean OpenGl_Workspace::Activate()
270{
271 if (!OpenGl_Window::Activate())
272 return Standard_False;
273
2166f0fa
SK
274 ViewMatrix_applied = &myDefaultMatrix;
275 StructureMatrix_applied = &myDefaultMatrix;
26395493 276
277 ResetAppliedAspect();
278
279 return Standard_True;
2166f0fa
SK
280}
281
26395493 282//=======================================================================
283//function : ResetAppliedAspect
284//purpose : Sets default values of GL parameters in accordance with default aspects
285//=======================================================================
286void OpenGl_Workspace::ResetAppliedAspect()
287{
4e1523ef 288 myGlContext->BindDefaultVao();
289
bf75be98 290 NamedStatus = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0;
0adbd30f 291 HighlightColor = &THE_WHITE_COLOR;
26395493 292 AspectLine_set = &myDefaultAspectLine;
293 AspectLine_applied = NULL;
294 AspectFace_set = &myDefaultAspectFace;
295 AspectFace_applied = NULL;
296 AspectMarker_set = &myDefaultAspectMarker;
297 AspectMarker_applied = NULL;
298 AspectText_set = &myDefaultAspectText;
299 AspectText_applied = NULL;
300 TextParam_set = &myDefaultTextParam;
301 TextParam_applied = NULL;
550f3b8b 302 PolygonOffset_applied = THE_DEFAULT_POFFSET;
3b1817a9 303 myCullingMode = TelCullUndefined;
26395493 304
305 AspectLine(Standard_True);
306 AspectFace(Standard_True);
307 AspectMarker(Standard_True);
308 AspectText(Standard_True);
ac116c22 309
310 myGlContext->SetTypeOfLine (myDefaultAspectLine.Type());
311 myGlContext->SetLineWidth (myDefaultAspectLine.Width());
26395493 312}
bf75be98 313
314// =======================================================================
315// function : DisableTexture
316// purpose :
317// =======================================================================
318Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
319{
320 if (myTextureBound.IsNull())
321 {
322 return myTextureBound;
323 }
324
e3414ada 325 const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
326 if (!aSampler.IsNull())
327 {
328 aSampler->Unbind (*myGlContext);
329 }
330
ca3c13d1 331#if !defined(GL_ES_VERSION_2_0)
bf75be98 332 // reset texture matrix because some code may expect it is identity
4e1523ef 333 if (myGlContext->core11 != NULL)
334 {
335 GLint aMatrixMode = GL_TEXTURE;
336 glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
337 glMatrixMode (GL_TEXTURE);
338 glLoadIdentity();
339 glMatrixMode (aMatrixMode);
340 }
ca3c13d1 341#endif
bf75be98 342
343 myTextureBound->Unbind (myGlContext);
344 switch (myTextureBound->GetTarget())
345 {
ca3c13d1 346 #if !defined(GL_ES_VERSION_2_0)
bf75be98 347 case GL_TEXTURE_1D:
348 {
4e1523ef 349 if (myGlContext->core11 != NULL)
bf75be98 350 {
4e1523ef 351 if (myTextureBound->GetParams()->GenMode() != GL_NONE)
352 {
353 glDisable (GL_TEXTURE_GEN_S);
354 }
355 glDisable (GL_TEXTURE_1D);
bf75be98 356 }
bf75be98 357 break;
358 }
ca3c13d1 359 #endif
bf75be98 360 case GL_TEXTURE_2D:
361 {
ca3c13d1 362 #if !defined(GL_ES_VERSION_2_0)
4e1523ef 363 if (myGlContext->core11 != NULL)
bf75be98 364 {
4e1523ef 365 if (myTextureBound->GetParams()->GenMode() != GL_NONE)
a577aaab 366 {
4e1523ef 367 glDisable (GL_TEXTURE_GEN_S);
368 glDisable (GL_TEXTURE_GEN_T);
369 if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE)
370 {
371 glDisable (GL_POINT_SPRITE);
372 }
a577aaab 373 }
4e1523ef 374 glDisable (GL_TEXTURE_2D);
bf75be98 375 }
05e2200b 376 #endif
bf75be98 377 break;
378 }
379 default: break;
380 }
381
382 Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
383 myTextureBound.Nullify();
384 return aPrevTexture;
385}
386
387// =======================================================================
388// function : setTextureParams
389// purpose :
390// =======================================================================
391void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& theTexture,
392 const Handle(Graphic3d_TextureParams)& theParams)
393{
394 const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
395 if (aParams.IsNull())
396 {
397 return;
398 }
399
ca3c13d1 400#if !defined(GL_ES_VERSION_2_0)
bf75be98 401 GLint aMatrixMode = GL_TEXTURE;
4e1523ef 402 if (myGlContext->core11 != NULL)
403 {
404 glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
405
406 // setup texture matrix
407 glMatrixMode (GL_TEXTURE);
408 OpenGl_Mat4 aTextureMat;
409 const Graphic3d_Vec2& aScale = aParams->Scale();
410 const Graphic3d_Vec2& aTrans = aParams->Translation();
411 OpenGl_Utils::Scale (aTextureMat, aScale.x(), aScale.y(), 1.0f);
412 OpenGl_Utils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f);
413 OpenGl_Utils::Rotate (aTextureMat, -aParams->Rotation(), 0.0f, 0.0f, 1.0f);
414 glLoadMatrixf (aTextureMat);
415
416 GLint anEnvMode = GL_MODULATE; // lighting mode
417 if (!aParams->IsModulate())
076ca35c 418 {
4e1523ef 419 anEnvMode = GL_DECAL;
420 if (theTexture->GetFormat() == GL_ALPHA
421 || theTexture->GetFormat() == GL_LUMINANCE)
422 {
423 anEnvMode = GL_REPLACE;
424 }
076ca35c 425 }
076ca35c 426
4e1523ef 427 // setup generation of texture coordinates
428 switch (aParams->GenMode())
bf75be98 429 {
4e1523ef 430 case Graphic3d_TOTM_OBJECT:
bf75be98 431 {
4e1523ef 432 glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
433 glTexGenfv (GL_S, GL_OBJECT_PLANE, aParams->GenPlaneS().GetData());
434 if (theTexture->GetTarget() != GL_TEXTURE_1D)
435 {
436 glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
437 glTexGenfv (GL_T, GL_OBJECT_PLANE, aParams->GenPlaneT().GetData());
438 }
439 break;
bf75be98 440 }
4e1523ef 441 case Graphic3d_TOTM_SPHERE:
bf75be98 442 {
4e1523ef 443 glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
444 if (theTexture->GetTarget() != GL_TEXTURE_1D)
445 {
446 glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
447 }
448 break;
bf75be98 449 }
4e1523ef 450 case Graphic3d_TOTM_EYE:
451 {
452 myGlContext->WorldViewState.Push();
c827ea3a 453
4e1523ef 454 myGlContext->WorldViewState.SetIdentity();
455 myGlContext->ApplyWorldViewMatrix();
bf75be98 456
4e1523ef 457 glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
458 glTexGenfv (GL_S, GL_EYE_PLANE, aParams->GenPlaneS().GetData());
bf75be98 459
4e1523ef 460 if (theTexture->GetTarget() != GL_TEXTURE_1D)
461 {
462 glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
463 glTexGenfv (GL_T, GL_EYE_PLANE, aParams->GenPlaneT().GetData());
464 }
c827ea3a 465
4e1523ef 466 myGlContext->WorldViewState.Pop();
c827ea3a 467
4e1523ef 468 break;
469 }
470 case Graphic3d_TOTM_SPRITE:
a577aaab 471 {
4e1523ef 472 if (GetGlContext()->core20fwd != NULL)
473 {
474 glEnable (GL_POINT_SPRITE);
475 glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
476 anEnvMode = GL_REPLACE;
477 GetGlContext()->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
478 }
479 break;
a577aaab 480 }
4e1523ef 481 case Graphic3d_TOTM_MANUAL:
482 default: break;
a577aaab 483 }
bf75be98 484
4e1523ef 485 // setup lighting
486 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
487 }
ca3c13d1 488#endif
bf75be98 489
25ef750e 490 // get active sampler object to override default texture parameters
491 const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
492
bf75be98 493 // setup texture filtering and wrapping
494 //if (theTexture->GetParams() != theParams)
495 const GLenum aFilter = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
ca3c13d1 496 const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp();
bf75be98 497 switch (theTexture->GetTarget())
498 {
ca3c13d1 499 #if !defined(GL_ES_VERSION_2_0)
bf75be98 500 case GL_TEXTURE_1D:
501 {
25ef750e 502 if (aSampler.IsNull() || !aSampler->IsValid())
503 {
504 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
505 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
506 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, aWrapMode);
507 }
508 else
509 {
510 aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
511 aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter);
512 aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode);
513 }
514
bf75be98 515 break;
516 }
ca3c13d1 517 #endif
bf75be98 518 case GL_TEXTURE_2D:
519 {
520 GLenum aFilterMin = aFilter;
521 if (theTexture->HasMipmaps())
522 {
523 aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
524 if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
525 {
526 aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
527 }
528 else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
529 {
530 aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
531 }
532
533 if (myGlContext->extAnis)
534 {
535 // setup degree of anisotropy filter
536 const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
25ef750e 537 GLint aDegree;
bf75be98 538 switch (aParams->AnisoFilter())
539 {
540 case Graphic3d_LOTA_QUALITY:
541 {
25ef750e 542 aDegree = aMaxDegree;
bf75be98 543 break;
544 }
545 case Graphic3d_LOTA_MIDDLE:
546 {
25ef750e 547 aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
bf75be98 548 break;
549 }
550 case Graphic3d_LOTA_FAST:
551 {
25ef750e 552 aDegree = 2;
bf75be98 553 break;
554 }
555 case Graphic3d_LOTA_OFF:
556 default:
557 {
25ef750e 558 aDegree = 1;
bf75be98 559 break;
560 }
561 }
25ef750e 562
563 if (aSampler.IsNull() || !aSampler->IsValid())
564 {
565 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
566 }
567 else
568 {
569 aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
570 }
bf75be98 571 }
572 }
25ef750e 573
574 if (aSampler.IsNull() || !aSampler->IsValid())
575 {
576 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
577 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
578 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aWrapMode);
579 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aWrapMode);
580 }
581 else
582 {
583 aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin);
584 aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
585 aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode);
586 aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T, aWrapMode);
587 }
588
bf75be98 589 break;
590 }
591 default: break;
592 }
593
594 switch (theTexture->GetTarget())
595 {
ca3c13d1 596 #if !defined(GL_ES_VERSION_2_0)
bf75be98 597 case GL_TEXTURE_1D:
598 {
4e1523ef 599 if (myGlContext->core11 != NULL)
bf75be98 600 {
4e1523ef 601 if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
602 {
603 glEnable (GL_TEXTURE_GEN_S);
604 }
605 glEnable (GL_TEXTURE_1D);
bf75be98 606 }
bf75be98 607 break;
608 }
ca3c13d1 609 #endif
bf75be98 610 case GL_TEXTURE_2D:
611 {
ca3c13d1 612 #if !defined(GL_ES_VERSION_2_0)
4e1523ef 613 if (myGlContext->core11 != NULL)
bf75be98 614 {
4e1523ef 615 if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
616 {
617 glEnable (GL_TEXTURE_GEN_S);
618 glEnable (GL_TEXTURE_GEN_T);
619 }
620 glEnable (GL_TEXTURE_2D);
bf75be98 621 }
05e2200b 622 #endif
bf75be98 623 break;
624 }
625 default: break;
626 }
627
ca3c13d1 628#if !defined(GL_ES_VERSION_2_0)
4e1523ef 629 if (myGlContext->core11 != NULL)
630 {
631 glMatrixMode (aMatrixMode); // turn back active matrix
632 }
ca3c13d1 633#endif
bf75be98 634 theTexture->SetParams (aParams);
635}
636
637// =======================================================================
638// function : EnableTexture
639// purpose :
640// =======================================================================
641Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)& theTexture,
642 const Handle(Graphic3d_TextureParams)& theParams)
643{
644 if (theTexture.IsNull() || !theTexture->IsValid())
645 {
646 return DisableTexture();
647 }
648
bca1d6e2 649 if (myTextureBound == theTexture
650 && (theParams.IsNull() || theParams == theTexture->GetParams()))
bf75be98 651 {
bca1d6e2 652 // already bound
653 return myTextureBound;
bf75be98 654 }
655
656 Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
657 myTextureBound = theTexture;
658 myTextureBound->Bind (myGlContext);
659 setTextureParams (myTextureBound, theParams);
660
25ef750e 661 // If custom sampler object is available it will be
662 // used for overriding default texture parameters
663 const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
664
665 if (!aSampler.IsNull() && aSampler->IsValid())
666 {
667 aSampler->Bind (*myGlContext);
668 }
669
bf75be98 670 return aPrevTexture;
671}
a174a3c5 672
673// =======================================================================
38a0206f 674// function : bindDefaultFbo
675// purpose :
676// =======================================================================
677void OpenGl_Workspace::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo)
678{
679 OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid())
680 ? theCustomFbo
681 : (!myGlContext->DefaultFrameBuffer().IsNull()
682 && myGlContext->DefaultFrameBuffer()->IsValid()
683 ? myGlContext->DefaultFrameBuffer().operator->()
684 : NULL);
685 if (anFbo != NULL)
686 {
687 anFbo->BindBuffer (myGlContext);
688 }
689 else
690 {
691 #if !defined(GL_ES_VERSION_2_0)
692 myGlContext->SetReadDrawBuffer (GL_BACK);
693 #else
694 if (myGlContext->arbFBO != NULL)
695 {
696 myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
697 }
698 #endif
699 }
700 myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight);
701}
702
703// =======================================================================
704// function : blitBuffers
705// purpose :
706// =======================================================================
707bool OpenGl_Workspace::blitBuffers (OpenGl_FrameBuffer* theReadFbo,
708 OpenGl_FrameBuffer* theDrawFbo)
709{
710 if (theReadFbo == NULL)
711 {
712 return false;
713 }
f978241f 714 else if (theReadFbo == theDrawFbo)
715 {
716 return true;
717 }
38a0206f 718
719 // clear destination before blitting
720 if (theDrawFbo != NULL
721 && theDrawFbo->IsValid())
722 {
723 theDrawFbo->BindBuffer (myGlContext);
724 }
725 else
726 {
727 myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
728 }
729#if !defined(GL_ES_VERSION_2_0)
730 myGlContext->core20fwd->glClearDepth (1.0);
731#else
732 myGlContext->core20fwd->glClearDepthf (1.0f);
733#endif
734 myGlContext->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
735
736/*#if !defined(GL_ES_VERSION_2_0)
737 if (myGlContext->arbFBOBlit != NULL)
738 {
739 theReadFbo->BindReadBuffer (myGlContext);
740 if (theDrawFbo != NULL
741 && theDrawFbo->IsValid())
742 {
743 theDrawFbo->BindDrawBuffer (myGlContext);
744 }
745 else
746 {
747 myGlContext->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
748 }
749 // we don't copy stencil buffer here... does it matter for performance?
750 myGlContext->arbFBOBlit->glBlitFramebuffer (0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
751 0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
752 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
753
754 if (theDrawFbo != NULL
755 && theDrawFbo->IsValid())
756 {
757 theDrawFbo->BindBuffer (myGlContext);
758 }
759 else
760 {
761 myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
762 }
763 }
764 else
765#endif*/
766 {
767 myGlContext->core20fwd->glDepthFunc (GL_ALWAYS);
768 myGlContext->core20fwd->glDepthMask (GL_TRUE);
769 myGlContext->core20fwd->glEnable (GL_DEPTH_TEST);
770
771 DisableTexture();
772 if (!myFullScreenQuad.IsValid())
773 {
774 OpenGl_Vec4 aQuad[4] =
775 {
776 OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f),
777 OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 1.0f),
778 OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f),
779 OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 1.0f)
780 };
781 myFullScreenQuad.Init (myGlContext, 4, 4, aQuad[0].GetData());
782 }
783
784 const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager();
785 if (myFullScreenQuad.IsValid()
786 && aManager->BindFboBlitProgram())
787 {
788 theReadFbo->ColorTexture() ->Bind (myGlContext, GL_TEXTURE0 + 0);
789 theReadFbo->DepthStencilTexture()->Bind (myGlContext, GL_TEXTURE0 + 1);
fe3a29bc 790 myFullScreenQuad.BindVertexAttrib (myGlContext, Graphic3d_TOA_POS);
38a0206f 791
792 myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
793
fe3a29bc 794 myFullScreenQuad.UnbindVertexAttrib (myGlContext, Graphic3d_TOA_POS);
38a0206f 795 theReadFbo->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1);
796 theReadFbo->ColorTexture() ->Unbind (myGlContext, GL_TEXTURE0 + 0);
797 }
798 else
799 {
800 TCollection_ExtendedString aMsg = TCollection_ExtendedString()
801 + "Error! FBO blitting has failed";
802 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
803 GL_DEBUG_TYPE_ERROR_ARB,
804 0,
805 GL_DEBUG_SEVERITY_HIGH_ARB,
806 aMsg);
807 myHasFboBlit = Standard_False;
808 theReadFbo->Release (myGlContext.operator->());
809 return true;
810 }
811 }
812 return true;
813}
814
815// =======================================================================
816// function : drawStereoPair
817// purpose :
818// =======================================================================
f978241f 819void OpenGl_Workspace::drawStereoPair (const Graphic3d_CView& theCView)
38a0206f 820{
821 OpenGl_FrameBuffer* aPair[2] =
822 {
823 myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
824 myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
825 };
826 if (aPair[0] == NULL
f978241f 827 || aPair[1] == NULL
828 || !myTransientDrawToFront)
38a0206f 829 {
830 aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
831 aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL;
832 }
833
834 if (aPair[0] == NULL
835 || aPair[1] == NULL)
836 {
837 return;
838 }
839
f978241f 840 Standard_Boolean toReverse = theCView.RenderParams.ToReverseStereo;
841 const Standard_Boolean isOddY = (theCView.DefWindow.top + theCView.DefWindow.dy) % 2 == 1;
842 const Standard_Boolean isOddX = theCView.DefWindow.left % 2 == 1;
843 if (isOddY
844 && (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced
845 || theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
846 {
847 toReverse = !toReverse;
848 }
849 if (isOddX
850 && (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced
851 || theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
852 {
853 toReverse = !toReverse;
854 }
855
856 if (toReverse)
857 {
858 std::swap (aPair[0], aPair[1]);
859 }
860
38a0206f 861 myGlContext->core20fwd->glDepthFunc (GL_ALWAYS);
862 myGlContext->core20fwd->glDepthMask (GL_TRUE);
863 myGlContext->core20fwd->glEnable (GL_DEPTH_TEST);
864
865 DisableTexture();
866 if (!myFullScreenQuad.IsValid())
867 {
868 OpenGl_Vec4 aQuad[4] =
869 {
870 OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f),
871 OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 1.0f),
872 OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f),
873 OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 1.0f)
874 };
875 myFullScreenQuad.Init (myGlContext, 4, 4, aQuad[0].GetData());
876 }
877
878 const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager();
879 if (myFullScreenQuad.IsValid()
f978241f 880 && aManager->BindStereoProgram (theCView.RenderParams.StereoMode))
38a0206f 881 {
f978241f 882 if (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph)
883 {
884 OpenGl_Mat4 aFilterL, aFilterR;
885 aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
886 aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
887 switch (theCView.RenderParams.AnaglyphFilter)
888 {
889 case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple:
890 {
891 aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
892 aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
893 aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
894 break;
895 }
896 case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized:
897 {
898 aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f, 0.4710f, 0.16666667f, 0.0f));
899 aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f, -0.0484f, -0.0257f, 0.0f));
900 aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f, -0.0615f, 0.0128f, 0.0f));
901 aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
902 aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f));
903 aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f, 0.73333333f, 0.01111111f, 0.0f));
904 aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f, 1.29710000f, 0.0f));
905 aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
906 break;
907 }
908 case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple:
909 {
910 aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
911 aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
912 aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
913 break;
914 }
915 case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized:
916 {
917 aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f, 0.299f, 0.0f));
918 aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f, 0.908f, 0.068f, 0.0f));
919 aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f, 0.022f, 0.0f));
920 aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
921 aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f));
922 aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f, 0.062f, -0.017f, 0.0f));
923 aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f, 0.185f, 0.911f, 0.0f));
924 aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
925 break;
926 }
927 case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple:
928 {
929 aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
930 aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
931 aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
932 break;
933 }
934 case Graphic3d_RenderingParams::Anaglyph_UserDefined:
935 {
936 aFilterL = theCView.RenderParams.AnaglyphLeft;
937 aFilterR = theCView.RenderParams.AnaglyphRight;
938 break;
939 }
940 }
941 myGlContext->ActiveProgram()->SetUniform (myGlContext, "uMultL", aFilterL);
942 myGlContext->ActiveProgram()->SetUniform (myGlContext, "uMultR", aFilterR);
943 }
944
38a0206f 945 aPair[0]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 0);
946 aPair[1]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 1);
947 myFullScreenQuad.BindVertexAttrib (myGlContext, 0);
948
949 myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
950
951 myFullScreenQuad.UnbindVertexAttrib (myGlContext, 0);
952 aPair[1]->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1);
953 aPair[0]->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + 0);
954 }
955 else
956 {
957 TCollection_ExtendedString aMsg = TCollection_ExtendedString()
958 + "Error! Anaglyph has failed";
959 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
960 GL_DEBUG_TYPE_ERROR_ARB,
961 0,
962 GL_DEBUG_SEVERITY_HIGH_ARB,
963 aMsg);
964 }
965}
966
967// =======================================================================
a174a3c5 968// function : Redraw
969// purpose :
970// =======================================================================
971void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
972 const Aspect_CLayer2d& theCUnderLayer,
973 const Aspect_CLayer2d& theCOverLayer)
974{
975 if (!Activate())
976 {
977 return;
978 }
979
f978241f 980 if (mySwapInterval != myGlContext->caps->swapInterval)
981 {
982 mySwapInterval = myGlContext->caps->swapInterval;
983 myGlContext->SetSwapInterval (mySwapInterval);
984 }
985
a89742cf 986 ++myFrameCounter;
b7cd4ba7 987 myIsCullingEnabled = theCView.IsCullingEnabled;
f978241f 988 const Graphic3d_StereoMode aStereoMode = theCView.RenderParams.StereoMode;
989 const Handle(Graphic3d_Camera)& aCamera = myView->Camera();
990 Graphic3d_Camera::Projection aProjectType = aCamera->ProjectionType();
b7cd4ba7 991
a174a3c5 992 // release pending GL resources
ee51a9fe 993 myGlContext->ReleaseDelayed();
a174a3c5 994
b5ac8292 995 // fetch OpenGl context state
ee51a9fe 996 myGlContext->FetchState();
a174a3c5 997
a174a3c5 998 OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
ee51a9fe 999 bool toSwap = myGlContext->IsRender()
1000 && !myGlContext->caps->buffersNoSwap
1001 && aFrameBuffer == NULL;
a174a3c5 1002
b86bb3df 1003 Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth;
1004 Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight;
1005
38a0206f 1006 if ( aFrameBuffer == NULL
1007 && !myGlContext->DefaultFrameBuffer().IsNull()
1008 && myGlContext->DefaultFrameBuffer()->IsValid())
a2e4f780 1009 {
38a0206f 1010 aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->();
a2e4f780 1011 }
1012
ee51a9fe 1013 if (myHasFboBlit
f978241f 1014 && (myTransientDrawToFront || aProjectType == Graphic3d_Camera::Projection_Stereo))
b86bb3df 1015 {
38a0206f 1016 if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX
1017 || myMainSceneFbos[0]->GetVPSizeY() != aSizeY)
760c21c2 1018 {
ee51a9fe 1019 // prepare FBOs containing main scene
1020 // for further blitting and rendering immediate presentations on top
1021 if (myGlContext->core20fwd != NULL)
1022 {
38a0206f 1023 myMainSceneFbos[0]->Init (myGlContext, aSizeX, aSizeY);
ee51a9fe 1024 }
1025 }
b86bb3df 1026 }
ee51a9fe 1027 else
b86bb3df 1028 {
38a0206f 1029 myMainSceneFbos [0]->Release (myGlContext.operator->());
1030 myMainSceneFbos [1]->Release (myGlContext.operator->());
1031 myImmediateSceneFbos[0]->Release (myGlContext.operator->());
1032 myImmediateSceneFbos[1]->Release (myGlContext.operator->());
1033 myMainSceneFbos [0]->ChangeViewport (0, 0);
1034 myMainSceneFbos [1]->ChangeViewport (0, 0);
1035 myImmediateSceneFbos[0]->ChangeViewport (0, 0);
1036 myImmediateSceneFbos[1]->ChangeViewport (0, 0);
b86bb3df 1037 }
1038
f978241f 1039 if (aProjectType == Graphic3d_Camera::Projection_Stereo
1040 && myMainSceneFbos[0]->IsValid())
a89742cf 1041 {
f978241f 1042 myMainSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
1043 if (!myMainSceneFbos[1]->IsValid())
38a0206f 1044 {
f978241f 1045 // no enough memory?
38a0206f 1046 aProjectType = Graphic3d_Camera::Projection_Perspective;
1047 }
f978241f 1048 else if (!myTransientDrawToFront)
38a0206f 1049 {
f978241f 1050 //
1051 }
1052 else if (!myGlContext->HasStereoBuffers()
1053 || aStereoMode != Graphic3d_StereoMode_QuadBuffer)
1054 {
1055 myImmediateSceneFbos[0]->InitLazy (myGlContext, aSizeX, aSizeY);
1056 myImmediateSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
1057 if (!myImmediateSceneFbos[0]->IsValid()
1058 || !myImmediateSceneFbos[1]->IsValid())
38a0206f 1059 {
38a0206f 1060 aProjectType = Graphic3d_Camera::Projection_Perspective;
1061 }
38a0206f 1062 }
91c60b57 1063 }
e276548b 1064
38a0206f 1065 if (aProjectType == Graphic3d_Camera::Projection_Stereo)
91c60b57 1066 {
38a0206f 1067 OpenGl_FrameBuffer* aMainFbos[2] =
1068 {
1069 myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
1070 myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
1071 };
1072 OpenGl_FrameBuffer* anImmFbos[2] =
1073 {
1074 myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
1075 myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
1076 };
a174a3c5 1077
f978241f 1078 if (!myTransientDrawToFront)
1079 {
1080 anImmFbos[0] = aMainFbos[0];
1081 anImmFbos[1] = aMainFbos[1];
1082 }
1083 else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
1084 || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
1085 {
1086 anImmFbos[0] = NULL;
1087 anImmFbos[1] = NULL;
1088 }
1089
38a0206f 1090 #if !defined(GL_ES_VERSION_2_0)
f978241f 1091 myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
38a0206f 1092 #endif
1093 redraw1 (theCView, theCUnderLayer, theCOverLayer,
1094 aMainFbos[0], Graphic3d_Camera::Projection_MonoLeftEye);
1095 myBackBufferRestored = Standard_True;
1096 myIsImmediateDrawn = Standard_False;
1097 #if !defined(GL_ES_VERSION_2_0)
f978241f 1098 myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
38a0206f 1099 #endif
1100 if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aMainFbos[0], aProjectType, anImmFbos[0]))
1101 {
1102 toSwap = false;
1103 }
f978241f 1104 else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
1105 && toSwap)
1106 {
1107 myGlContext->SwapBuffers();
1108 }
38a0206f 1109
1110 #if !defined(GL_ES_VERSION_2_0)
f978241f 1111 myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
38a0206f 1112 #endif
1113 redraw1 (theCView, theCUnderLayer, theCOverLayer,
1114 aMainFbos[1], Graphic3d_Camera::Projection_MonoRightEye);
1115 myBackBufferRestored = Standard_True;
1116 myIsImmediateDrawn = Standard_False;
1117 if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aMainFbos[1], aProjectType, anImmFbos[1]))
1118 {
1119 toSwap = false;
1120 }
1121
1122 if (anImmFbos[0] != NULL)
1123 {
1124 bindDefaultFbo (aFrameBuffer);
f978241f 1125 drawStereoPair (theCView);
38a0206f 1126 }
1127 }
1128 else
a174a3c5 1129 {
38a0206f 1130 OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
1131 #if !defined(GL_ES_VERSION_2_0)
1132 if (aMainFbo == NULL
1133 && aFrameBuffer == NULL)
1134 {
1135 myGlContext->SetReadDrawBuffer (GL_BACK);
1136 }
1137 #endif
1138 redraw1 (theCView, theCUnderLayer, theCOverLayer,
1139 aMainFbo != NULL ? aMainFbo : aFrameBuffer, aProjectType);
1140 myBackBufferRestored = Standard_True;
1141 myIsImmediateDrawn = Standard_False;
1142 if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aMainFbo, aProjectType, aFrameBuffer))
1143 {
1144 toSwap = false;
1145 }
a174a3c5 1146 }
1147
679ecdee 1148#if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
a174a3c5 1149 if (OpenGl_AVIWriter_AllowWriting (theCView.DefWindow.XWindow))
1150 {
1151 GLint params[4];
1152 glGetIntegerv (GL_VIEWPORT, params);
1153 int nWidth = params[2] & ~0x7;
1154 int nHeight = params[3] & ~0x7;
1155
1156 const int nBitsPerPixel = 24;
1157 GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
1158
1159 glPixelStorei (GL_PACK_ALIGNMENT, 1);
1160 glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData);
1161 OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel);
1162 delete[] aDumpData;
1163 }
1164#endif
1165
38a0206f 1166 // bind default FBO
1167 bindDefaultFbo();
1168
ee51a9fe 1169 // Swap the buffers
1170 if (toSwap)
1171 {
1172 GetGlContext()->SwapBuffers();
38a0206f 1173 if (!myMainSceneFbos[0]->IsValid())
ee51a9fe 1174 {
1175 myBackBufferRestored = Standard_False;
1176 }
1177 }
1178 else
1179 {
1180 myGlContext->core11fwd->glFlush();
1181 }
1182
a174a3c5 1183 // reset render mode state
ee51a9fe 1184 myGlContext->FetchState();
a174a3c5 1185}
679ecdee 1186
1187// =======================================================================
1188// function : redraw1
1189// purpose :
1190// =======================================================================
38a0206f 1191void OpenGl_Workspace::redraw1 (const Graphic3d_CView& theCView,
1192 const Aspect_CLayer2d& theCUnderLayer,
1193 const Aspect_CLayer2d& theCOverLayer,
1194 OpenGl_FrameBuffer* theReadDrawFbo,
1195 const Graphic3d_Camera::Projection theProjection)
679ecdee 1196{
73192b37 1197 if (myView.IsNull())
679ecdee 1198 {
1199 return;
1200 }
1201
38a0206f 1202 if (theReadDrawFbo != NULL)
1203 {
1204 theReadDrawFbo->BindBuffer (myGlContext);
1205 theReadDrawFbo->SetupViewport (myGlContext);
1206 }
1207 else
1208 {
1209 myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight);
1210 }
1211
679ecdee 1212 // request reset of material
1213 NamedStatus |= OPENGL_NS_RESMAT;
1214
eae454e3 1215 myUseZBuffer = Standard_True;
1216 myUseDepthWrite = Standard_True;
1217 GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
1218 glDepthFunc (GL_LEQUAL);
1219 glDepthMask (GL_TRUE);
1220 glEnable (GL_DEPTH_TEST);
679ecdee 1221
eae454e3 1222#if !defined(GL_ES_VERSION_2_0)
1223 glClearDepth (1.0);
1224#else
1225 glClearDepthf (1.0f);
1226#endif
679ecdee 1227
91c60b57 1228 if (NamedStatus & OPENGL_NS_WHITEBACK)
679ecdee 1229 {
91c60b57 1230 // set background to white
1231 glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
679ecdee 1232 }
1233 else
1234 {
91c60b57 1235 glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f);
679ecdee 1236 }
91c60b57 1237
679ecdee 1238 glClear (toClear);
1239
1240 Handle(OpenGl_Workspace) aWS (this);
38a0206f 1241 myView->Render (myPrintContext, aWS, theReadDrawFbo, theProjection, theCView, theCUnderLayer, theCOverLayer, Standard_False);
679ecdee 1242}
1243
1244// =======================================================================
1245// function : copyBackToFront
1246// purpose :
1247// =======================================================================
1248void OpenGl_Workspace::copyBackToFront()
1249{
ca3c13d1 1250#if !defined(GL_ES_VERSION_2_0)
ca3c13d1 1251
c827ea3a 1252 OpenGl_Mat4 aProjectMat;
1253 OpenGl_Utils::Ortho2D<Standard_ShortReal> (aProjectMat,
1254 0.f, static_cast<GLfloat> (myWidth), 0.f, static_cast<GLfloat> (myHeight));
1255
1256 myGlContext->WorldViewState.Push();
1257 myGlContext->ProjectionState.Push();
1258
1259 myGlContext->WorldViewState.SetIdentity();
1260 myGlContext->ProjectionState.SetCurrent (aProjectMat);
1261
1262 myGlContext->ApplyProjectionMatrix();
1263 myGlContext->ApplyWorldViewMatrix();
679ecdee 1264
1265 DisableFeatures();
1266
38a0206f 1267 switch (myGlContext->DrawBuffer())
1268 {
1269 case GL_BACK_LEFT:
1270 {
1271 myGlContext->SetReadBuffer (GL_BACK_LEFT);
1272 myGlContext->SetDrawBuffer (GL_FRONT_LEFT);
1273 break;
1274 }
1275 case GL_BACK_RIGHT:
1276 {
1277 myGlContext->SetReadBuffer (GL_BACK_RIGHT);
1278 myGlContext->SetDrawBuffer (GL_FRONT_RIGHT);
1279 break;
1280 }
1281 default:
1282 {
1283 myGlContext->SetReadBuffer (GL_BACK);
1284 myGlContext->SetDrawBuffer (GL_FRONT);
1285 break;
1286 }
1287 }
679ecdee 1288
1289 glRasterPos2i (0, 0);
1290 glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_COLOR);
a1954302 1291 //glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH);
679ecdee 1292
1293 EnableFeatures();
1294
c827ea3a 1295 myGlContext->WorldViewState.Pop();
1296 myGlContext->ProjectionState.Pop();
1297 myGlContext->ApplyProjectionMatrix();
679ecdee 1298
38a0206f 1299 // read/write from front buffer now
1300 myGlContext->SetReadBuffer (myGlContext->DrawBuffer());
ca3c13d1 1301#endif
679ecdee 1302 myIsImmediateDrawn = Standard_False;
1303}
1304
1305// =======================================================================
1306// function : DisplayCallback
1307// purpose :
1308// =======================================================================
1309void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView,
1310 Standard_Integer theReason)
1311{
1312 if (theCView.GDisplayCB == NULL)
1313 {
1314 return;
1315 }
1316
1317 Aspect_GraphicCallbackStruct aCallData;
1318 aCallData.reason = theReason;
4e1523ef 1319 aCallData.glContext = myGlContext;
679ecdee 1320 aCallData.wsID = theCView.WsId;
1321 aCallData.viewID = theCView.ViewId;
4e1523ef 1322 aCallData.IsCoreProfile = (myGlContext->core11 == NULL);
679ecdee 1323 theCView.GDisplayCB (theCView.DefWindow.XWindow, theCView.GClientData, &aCallData);
1324}
1325
1326// =======================================================================
1327// function : RedrawImmediate
1328// purpose :
1329// =======================================================================
1330void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
1331 const Aspect_CLayer2d& theCUnderLayer,
ee51a9fe 1332 const Aspect_CLayer2d& theCOverLayer)
679ecdee 1333{
38a0206f 1334 const Handle(Graphic3d_Camera)& aCamera = myView->Camera();
1335 Graphic3d_Camera::Projection aProjectType = aCamera->ProjectionType();
1336 OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
1337 if ( aFrameBuffer == NULL
1338 && !myGlContext->DefaultFrameBuffer().IsNull()
1339 && myGlContext->DefaultFrameBuffer()->IsValid())
1340 {
1341 aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->();
1342 }
1343
f978241f 1344 const Graphic3d_StereoMode aStereoMode = theCView.RenderParams.StereoMode;
38a0206f 1345 if (aProjectType == Graphic3d_Camera::Projection_Stereo)
1346 {
1347 if (aFrameBuffer != NULL)
1348 {
1349 // implicitly switch to mono camera for image dump
1350 aProjectType = Graphic3d_Camera::Projection_Perspective;
1351 }
1352 else if (myMainSceneFbos[0]->IsValid()
1353 && !myMainSceneFbos[1]->IsValid())
1354 {
1355 aProjectType = Graphic3d_Camera::Projection_Perspective;
1356 }
1357 }
1358
ee51a9fe 1359 if (!myTransientDrawToFront
1360 || !myBackBufferRestored
38a0206f 1361 || (myGlContext->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid()))
679ecdee 1362 {
ee51a9fe 1363 Redraw (theCView, theCUnderLayer, theCOverLayer);
679ecdee 1364 return;
1365 }
ee51a9fe 1366 else if (!Activate())
679ecdee 1367 {
679ecdee 1368 return;
1369 }
1370
38a0206f 1371 bool toSwap = false;
1372 if (aProjectType == Graphic3d_Camera::Projection_Stereo)
1373 {
1374 OpenGl_FrameBuffer* aMainFbos[2] =
1375 {
1376 myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
1377 myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
1378 };
1379 OpenGl_FrameBuffer* anImmFbos[2] =
1380 {
1381 myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
1382 myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
1383 };
f978241f 1384 if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
1385 || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
1386 {
1387 anImmFbos[0] = NULL;
1388 anImmFbos[1] = NULL;
1389 }
38a0206f 1390
1391 if (myGlContext->arbFBO != NULL)
1392 {
1393 myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1394 }
1395 #if !defined(GL_ES_VERSION_2_0)
1396 if (anImmFbos[0] == NULL)
1397 {
f978241f 1398 myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
38a0206f 1399 }
1400 #endif
1401 toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer,
1402 aMainFbos[0],
1403 Graphic3d_Camera::Projection_MonoLeftEye,
1404 anImmFbos[0],
1405 Standard_True) || toSwap;
f978241f 1406 if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
1407 && toSwap
1408 && !myGlContext->caps->buffersNoSwap)
1409 {
1410 myGlContext->SwapBuffers();
1411 }
38a0206f 1412
1413 if (myGlContext->arbFBO != NULL)
1414 {
1415 myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1416 }
1417 #if !defined(GL_ES_VERSION_2_0)
1418 if (anImmFbos[1] == NULL)
1419 {
f978241f 1420 myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
38a0206f 1421 }
1422 #endif
1423 toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer,
1424 aMainFbos[1],
1425 Graphic3d_Camera::Projection_MonoRightEye,
1426 anImmFbos[1],
1427 Standard_True) || toSwap;
1428 if (anImmFbos[0] != NULL)
1429 {
1430 bindDefaultFbo (aFrameBuffer);
f978241f 1431 drawStereoPair (theCView);
38a0206f 1432 }
1433 }
1434 else
a2e4f780 1435 {
38a0206f 1436 OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
1437 #if !defined(GL_ES_VERSION_2_0)
1438 if (aMainFbo == NULL)
1439 {
1440 myGlContext->SetReadDrawBuffer (GL_BACK);
1441 }
1442 #endif
1443 toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer,
1444 aMainFbo,
1445 aProjectType,
1446 aFrameBuffer,
1447 Standard_True) || toSwap;
a2e4f780 1448 }
1449
38a0206f 1450 // bind default FBO
1451 bindDefaultFbo();
1452
1453 if (toSwap
ef0bfc15 1454 && !myGlContext->caps->buffersNoSwap)
b86bb3df 1455 {
ee51a9fe 1456 myGlContext->SwapBuffers();
1457 }
1458 else
1459 {
1460 myGlContext->core11fwd->glFlush();
ee51a9fe 1461 }
1462}
b86bb3df 1463
ee51a9fe 1464// =======================================================================
1465// function : redrawImmediate
1466// purpose :
1467// =======================================================================
1468bool OpenGl_Workspace::redrawImmediate (const Graphic3d_CView& theCView,
1469 const Aspect_CLayer2d& theCUnderLayer,
1470 const Aspect_CLayer2d& theCOverLayer,
38a0206f 1471 OpenGl_FrameBuffer* theReadFbo,
1472 const Graphic3d_Camera::Projection theProjection,
1473 OpenGl_FrameBuffer* theDrawFbo,
ee51a9fe 1474 const Standard_Boolean theIsPartialUpdate)
1475{
1476 GLboolean toCopyBackToFront = GL_FALSE;
1477 if (!myTransientDrawToFront)
1478 {
1479 myBackBufferRestored = Standard_False;
1480 }
38a0206f 1481 else if (theReadFbo != NULL
1482 && theReadFbo->IsValid()
ee51a9fe 1483 && myGlContext->IsRender())
1484 {
38a0206f 1485 if (!blitBuffers (theReadFbo, theDrawFbo))
b86bb3df 1486 {
38a0206f 1487 return true;
b86bb3df 1488 }
1489 }
38a0206f 1490 else if (theDrawFbo == NULL)
679ecdee 1491 {
ee51a9fe 1492 #if !defined(GL_ES_VERSION_2_0)
1493 myGlContext->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
1494 #endif
1495 if (toCopyBackToFront)
679ecdee 1496 {
ee51a9fe 1497 if (!myView->HasImmediateStructures()
1498 && !theIsPartialUpdate)
1499 {
1500 // prefer Swap Buffers within Redraw in compatibility mode (without FBO)
1501 return true;
1502 }
1503 copyBackToFront();
ee51a9fe 1504 }
1505 else
1506 {
1507 myBackBufferRestored = Standard_False;
679ecdee 1508 }
679ecdee 1509 }
1510 else
1511 {
1512 myBackBufferRestored = Standard_False;
1513 }
1514 myIsImmediateDrawn = Standard_True;
1515
679ecdee 1516 Handle(OpenGl_Workspace) aWS (this);
a1954302 1517
eae454e3 1518 myUseZBuffer = Standard_True;
1519 myUseDepthWrite = Standard_True;
1520 glDepthFunc (GL_LEQUAL);
1521 glDepthMask (GL_TRUE);
1522 glEnable (GL_DEPTH_TEST);
1523#if !defined(GL_ES_VERSION_2_0)
1524 glClearDepth (1.0);
1525#else
1526 glClearDepthf (1.0f);
1527#endif
a1954302 1528
38a0206f 1529 myView->Render (myPrintContext, aWS, theDrawFbo, theProjection,
1530 theCView, theCUnderLayer, theCOverLayer, Standard_True);
a1954302 1531 if (!myView->ImmediateStructures().IsEmpty())
1532 {
eae454e3 1533 myUseZBuffer = Standard_False;
a1954302 1534 glDisable (GL_DEPTH_TEST);
1535 }
9f112210 1536 for (OpenGl_IndexedMapOfStructure::Iterator anIter (myView->ImmediateStructures()); anIter.More(); anIter.Next())
679ecdee 1537 {
1538 const OpenGl_Structure* aStructure = anIter.Value();
a1954302 1539 if (!aStructure->IsVisible())
1540 {
1541 continue;
1542 }
1543
679ecdee 1544 aStructure->Render (aWS);
1545 }
1546
38a0206f 1547 return !toCopyBackToFront;
679ecdee 1548}
91c60b57 1549
91c60b57 1550
1551// =======================================================================
1552// function : CanRender
1553// purpose :
1554// =======================================================================
1555Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement)
1556{
1557 Standard_Boolean aPrevFilterResult = Standard_True;
1558 if (!myPrevRenderFilter.IsNull())
1559 {
1560 aPrevFilterResult = myPrevRenderFilter->CanRender (theElement);
1561 }
1562 return aPrevFilterResult &&
1563 !OpenGl_Raytrace::IsRaytracedElement (theElement);
1564}