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