0025540: Visualization - discretization of the circle differs in shaded and wireframe...
[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>
2166f0fa 37
58655684 38#if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
a174a3c5 39 #include <OpenGl_AVIWriter.hxx>
40#endif
41
2166f0fa
SK
42IMPLEMENT_STANDARD_HANDLE(OpenGl_Workspace,OpenGl_Window)
43IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,OpenGl_Window)
44
45namespace
46{
0adbd30f 47 static const TEL_COLOUR THE_WHITE_COLOR = { { 1.0f, 1.0f, 1.0f, 1.0f } };
48 static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f);
2166f0fa
SK
49
50 static const OpenGl_AspectLine myDefaultAspectLine;
51 static const OpenGl_AspectFace myDefaultAspectFace;
52 static const OpenGl_AspectMarker myDefaultAspectMarker;
53 static const OpenGl_AspectText myDefaultAspectText;
54
55 static const OpenGl_TextParam myDefaultTextParam =
56 {
57 16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
58 };
59
60 static const OpenGl_Matrix myDefaultMatrix =
61 {
62 {{ 1.0F, 0.0F, 0.0F, 0.0F },
63 { 0.0F, 1.0F, 0.0F, 0.0F },
64 { 0.0F, 0.0F, 1.0F, 0.0F },
65 { 0.0F, 0.0F, 0.0F, 1.0F }}
66 };
bf75be98 67
2166f0fa
SK
68};
69
0adbd30f 70// =======================================================================
71// function : Init
72// purpose :
73// =======================================================================
74void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp)
75{
76 // ambient component
77 if (theProp.color_mask & OPENGL_AMBIENT_MASK)
78 {
79 const float* aSrcAmb = theProp.isphysic ? theProp.ambcol.rgb : theProp.matcol.rgb;
80 Ambient = OpenGl_Vec4 (aSrcAmb[0] * theProp.amb,
81 aSrcAmb[1] * theProp.amb,
82 aSrcAmb[2] * theProp.amb,
83 1.0f);
84 }
85 else
86 {
87 Ambient = THE_BLACK_COLOR;
88 }
89
90 // diffusion component
91 if (theProp.color_mask & OPENGL_DIFFUSE_MASK)
92 {
93 const float* aSrcDif = theProp.isphysic ? theProp.difcol.rgb : theProp.matcol.rgb;
94 Diffuse = OpenGl_Vec4 (aSrcDif[0] * theProp.diff,
95 aSrcDif[1] * theProp.diff,
96 aSrcDif[2] * theProp.diff,
97 1.0f);
98 }
99 else
100 {
101 Diffuse = THE_BLACK_COLOR;
102 }
103
104 // specular component
105 if (theProp.color_mask & OPENGL_SPECULAR_MASK)
106 {
107 const float* aSrcSpe = theProp.isphysic ? theProp.speccol.rgb : THE_WHITE_COLOR.rgb;
108 Specular = OpenGl_Vec4 (aSrcSpe[0] * theProp.spec,
109 aSrcSpe[1] * theProp.spec,
110 aSrcSpe[2] * theProp.spec,
111 1.0f);
112 }
113 else
114 {
115 Specular = THE_BLACK_COLOR;
116 }
117
118 // emission component
119 if (theProp.color_mask & OPENGL_EMISSIVE_MASK)
120 {
121 const float* aSrcEms = theProp.isphysic ? theProp.emscol.rgb : theProp.matcol.rgb;
122 Emission = OpenGl_Vec4 (aSrcEms[0] * theProp.emsv,
123 aSrcEms[1] * theProp.emsv,
124 aSrcEms[2] * theProp.emsv,
125 1.0f);
126 }
127 else
128 {
129 Emission = THE_BLACK_COLOR;
130 }
131
132 ChangeShine() = theProp.shine;
133 ChangeTransparency() = theProp.trans;
134}
135
2166f0fa
SK
136// =======================================================================
137// function : OpenGl_Workspace
138// purpose :
139// =======================================================================
25b97fac 140OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_GraphicDriver)& theDriver,
2166f0fa 141 const CALL_DEF_WINDOW& theCWindow,
5e27df78 142 Aspect_RenderingContext theGContext,
58655684 143 const Handle(OpenGl_Caps)& theCaps,
5e27df78 144 const Handle(OpenGl_Context)& theShareCtx)
25b97fac 145: OpenGl_Window (theDriver, theCWindow, theGContext, theCaps, theShareCtx),
a174a3c5 146 NamedStatus (0),
0adbd30f 147 HighlightColor (&THE_WHITE_COLOR),
a174a3c5 148 //
fc73a202 149 myComputeInitStatus (OpenGl_RT_NONE),
150 myIsRaytraceDataValid (Standard_False),
25ef750e 151 myIsRaytraceWarnTextures (Standard_False),
fc73a202 152 myViewModificationStatus (0),
153 myLayersModificationStatus (0),
154 //
a89742cf 155 myRaytraceFilter (new OpenGl_RaytraceFilter()),
156 myToRedrawGL (Standard_True),
a272ed94 157 myViewId (-1),
73192b37 158 myAntiAliasingMode (3),
a174a3c5 159 myTransientDrawToFront (Standard_True),
679ecdee 160 myBackBufferRestored (Standard_False),
161 myIsImmediateDrawn (Standard_False),
2166f0fa
SK
162 myUseZBuffer (Standard_False),
163 myUseDepthTest (Standard_True),
164 myUseGLLight (Standard_True),
b7cd4ba7 165 myIsCullingEnabled (Standard_False),
a89742cf 166 myFrameCounter (0),
2166f0fa 167 //
2166f0fa
SK
168 AspectLine_set (&myDefaultAspectLine),
169 AspectLine_applied (NULL),
170 AspectFace_set (&myDefaultAspectFace),
171 AspectFace_applied (NULL),
172 AspectMarker_set (&myDefaultAspectMarker),
173 AspectMarker_applied (NULL),
174 AspectText_set (&myDefaultAspectText),
175 AspectText_applied (NULL),
176 TextParam_set (&myDefaultTextParam),
177 TextParam_applied (NULL),
178 ViewMatrix_applied (&myDefaultMatrix),
179 StructureMatrix_applied (&myDefaultMatrix),
3b1817a9 180 myCullingMode (TelCullUndefined),
0f8c0fb8 181 myModelViewMatrix (myDefaultMatrix),
550f3b8b 182 PolygonOffset_applied (THE_DEFAULT_POFFSET)
2166f0fa 183{
73192b37 184 myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
b86bb3df 185 myResultFBO = new OpenGl_FrameBuffer();
73192b37 186
187 if (!myGlContext->GetResource ("OpenGl_LineAttributes", myLineAttribs))
188 {
189 // share and register for release once the resource is no longer used
190 myLineAttribs = new OpenGl_LineAttributes();
191 myGlContext->ShareResource ("OpenGl_LineAttributes", myLineAttribs);
192 myLineAttribs->Init (myGlContext);
193 }
2166f0fa
SK
194
195 // General initialization of the context
196
ca3c13d1 197#if !defined(GL_ES_VERSION_2_0)
2166f0fa
SK
198 // Eviter d'avoir les faces mal orientees en noir.
199 // Pourrait etre utiliser pour detecter les problemes d'orientation
bf75be98 200 glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
2166f0fa
SK
201
202 // Optimisation pour le Fog et l'antialiasing
203 glHint (GL_FOG_HINT, GL_FASTEST);
204 glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST);
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 }
2166f0fa
SK
216}
217
1981cb22 218// =======================================================================
219// function : SetImmediateModeDrawToFront
220// purpose :
221// =======================================================================
222Standard_Boolean OpenGl_Workspace::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer)
223{
224 const Standard_Boolean aPrevMode = myTransientDrawToFront;
225 myTransientDrawToFront = theDrawToFrontBuffer;
226 return aPrevMode;
227}
228
2166f0fa
SK
229// =======================================================================
230// function : ~OpenGl_Workspace
231// purpose :
232// =======================================================================
233OpenGl_Workspace::~OpenGl_Workspace()
234{
73192b37 235 if (!myLineAttribs.IsNull())
236 {
237 myLineAttribs.Nullify();
238 myGlContext->ReleaseResource ("OpenGl_LineAttributes", Standard_True);
239 }
240
b86bb3df 241 if (!myResultFBO.IsNull())
242 {
243 myResultFBO->Release (myGlContext.operator->());
244 myResultFBO.Nullify();
245 }
246 if (myFullScreenQuad.IsValid())
247 {
248 myFullScreenQuad.Release (myGlContext.operator->());
249 }
250
fc73a202 251 ReleaseRaytraceResources();
2166f0fa
SK
252}
253
254// =======================================================================
255// function : Activate
256// purpose :
257// =======================================================================
258Standard_Boolean OpenGl_Workspace::Activate()
259{
260 if (!OpenGl_Window::Activate())
261 return Standard_False;
262
2166f0fa
SK
263 ViewMatrix_applied = &myDefaultMatrix;
264 StructureMatrix_applied = &myDefaultMatrix;
26395493 265
266 ResetAppliedAspect();
267
268 return Standard_True;
2166f0fa
SK
269}
270
26395493 271//=======================================================================
272//function : ResetAppliedAspect
273//purpose : Sets default values of GL parameters in accordance with default aspects
274//=======================================================================
275void OpenGl_Workspace::ResetAppliedAspect()
276{
bf75be98 277 NamedStatus = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0;
0adbd30f 278 HighlightColor = &THE_WHITE_COLOR;
26395493 279 AspectLine_set = &myDefaultAspectLine;
280 AspectLine_applied = NULL;
281 AspectFace_set = &myDefaultAspectFace;
282 AspectFace_applied = NULL;
283 AspectMarker_set = &myDefaultAspectMarker;
284 AspectMarker_applied = NULL;
285 AspectText_set = &myDefaultAspectText;
286 AspectText_applied = NULL;
287 TextParam_set = &myDefaultTextParam;
288 TextParam_applied = NULL;
550f3b8b 289 PolygonOffset_applied = THE_DEFAULT_POFFSET;
3b1817a9 290 myCullingMode = TelCullUndefined;
26395493 291
292 AspectLine(Standard_True);
293 AspectFace(Standard_True);
294 AspectMarker(Standard_True);
295 AspectText(Standard_True);
296}
bf75be98 297
298// =======================================================================
299// function : DisableTexture
300// purpose :
301// =======================================================================
302Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
303{
304 if (myTextureBound.IsNull())
305 {
306 return myTextureBound;
307 }
308
e3414ada 309 const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
310 if (!aSampler.IsNull())
311 {
312 aSampler->Unbind (*myGlContext);
313 }
314
ca3c13d1 315#if !defined(GL_ES_VERSION_2_0)
bf75be98 316 // reset texture matrix because some code may expect it is identity
317 GLint aMatrixMode = GL_TEXTURE;
318 glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
319 glMatrixMode (GL_TEXTURE);
320 glLoadIdentity();
321 glMatrixMode (aMatrixMode);
ca3c13d1 322#endif
bf75be98 323
324 myTextureBound->Unbind (myGlContext);
325 switch (myTextureBound->GetTarget())
326 {
ca3c13d1 327 #if !defined(GL_ES_VERSION_2_0)
bf75be98 328 case GL_TEXTURE_1D:
329 {
ca3c13d1 330
bf75be98 331 if (myTextureBound->GetParams()->GenMode() != GL_NONE)
332 {
333 glDisable (GL_TEXTURE_GEN_S);
334 }
335 glDisable (GL_TEXTURE_1D);
336 break;
337 }
ca3c13d1 338 #endif
bf75be98 339 case GL_TEXTURE_2D:
340 {
ca3c13d1 341 #if !defined(GL_ES_VERSION_2_0)
bf75be98 342 if (myTextureBound->GetParams()->GenMode() != GL_NONE)
343 {
344 glDisable (GL_TEXTURE_GEN_S);
345 glDisable (GL_TEXTURE_GEN_T);
a577aaab 346 if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE)
347 {
348 glDisable (GL_POINT_SPRITE);
349 }
bf75be98 350 }
351 glDisable (GL_TEXTURE_2D);
05e2200b 352 #endif
bf75be98 353 break;
354 }
355 default: break;
356 }
357
358 Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
359 myTextureBound.Nullify();
360 return aPrevTexture;
361}
362
363// =======================================================================
364// function : setTextureParams
365// purpose :
366// =======================================================================
367void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& theTexture,
368 const Handle(Graphic3d_TextureParams)& theParams)
369{
370 const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
371 if (aParams.IsNull())
372 {
373 return;
374 }
375
ca3c13d1 376#if !defined(GL_ES_VERSION_2_0)
bf75be98 377 GLint aMatrixMode = GL_TEXTURE;
378 glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
379
380 // setup texture matrix
381 glMatrixMode (GL_TEXTURE);
c827ea3a 382 OpenGl_Mat4 aTextureMat;
bf75be98 383 const Graphic3d_Vec2& aScale = aParams->Scale();
384 const Graphic3d_Vec2& aTrans = aParams->Translation();
c827ea3a 385 OpenGl_Utils::Scale (aTextureMat, aScale.x(), aScale.y(), 1.0f);
386 OpenGl_Utils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f);
387 OpenGl_Utils::Rotate (aTextureMat, -aParams->Rotation(), 0.0f, 0.0f, 1.0f);
388 glLoadMatrixf (aTextureMat);
bf75be98 389
076ca35c 390 GLint anEnvMode = GL_MODULATE; // lighting mode
391 if (!aParams->IsModulate())
392 {
393 anEnvMode = GL_DECAL;
394 if (theTexture->GetFormat() == GL_ALPHA
395 || theTexture->GetFormat() == GL_LUMINANCE)
396 {
397 anEnvMode = GL_REPLACE;
398 }
399 }
400
bf75be98 401 // setup generation of texture coordinates
402 switch (aParams->GenMode())
403 {
404 case Graphic3d_TOTM_OBJECT:
405 {
406 glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
407 glTexGenfv (GL_S, GL_OBJECT_PLANE, aParams->GenPlaneS().GetData());
408 if (theTexture->GetTarget() != GL_TEXTURE_1D)
409 {
410 glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
411 glTexGenfv (GL_T, GL_OBJECT_PLANE, aParams->GenPlaneT().GetData());
412 }
413 break;
414 }
415 case Graphic3d_TOTM_SPHERE:
416 {
417 glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
418 if (theTexture->GetTarget() != GL_TEXTURE_1D)
419 {
420 glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
421 }
422 break;
423 }
424 case Graphic3d_TOTM_EYE:
425 {
c827ea3a 426 myGlContext->WorldViewState.Push();
427
428 myGlContext->WorldViewState.SetIdentity();
429 myGlContext->ApplyWorldViewMatrix();
bf75be98 430
431 glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
432 glTexGenfv (GL_S, GL_EYE_PLANE, aParams->GenPlaneS().GetData());
433
434 if (theTexture->GetTarget() != GL_TEXTURE_1D)
435 {
436 glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
437 glTexGenfv (GL_T, GL_EYE_PLANE, aParams->GenPlaneT().GetData());
438 }
c827ea3a 439
440 myGlContext->WorldViewState.Pop();
441
bf75be98 442 break;
443 }
a577aaab 444 case Graphic3d_TOTM_SPRITE:
445 {
446 if (GetGlContext()->core20 != NULL)
447 {
448 glEnable (GL_POINT_SPRITE);
449 glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
076ca35c 450 anEnvMode = GL_REPLACE;
a577aaab 451 GetGlContext()->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
452 }
453 break;
454 }
bf75be98 455 case Graphic3d_TOTM_MANUAL:
456 default: break;
457 }
458
459 // setup lighting
076ca35c 460 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
ca3c13d1 461#endif
bf75be98 462
25ef750e 463 // get active sampler object to override default texture parameters
464 const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
465
bf75be98 466 // setup texture filtering and wrapping
467 //if (theTexture->GetParams() != theParams)
468 const GLenum aFilter = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
ca3c13d1 469 const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp();
bf75be98 470 switch (theTexture->GetTarget())
471 {
ca3c13d1 472 #if !defined(GL_ES_VERSION_2_0)
bf75be98 473 case GL_TEXTURE_1D:
474 {
25ef750e 475 if (aSampler.IsNull() || !aSampler->IsValid())
476 {
477 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
478 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
479 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, aWrapMode);
480 }
481 else
482 {
483 aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
484 aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter);
485 aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode);
486 }
487
bf75be98 488 break;
489 }
ca3c13d1 490 #endif
bf75be98 491 case GL_TEXTURE_2D:
492 {
493 GLenum aFilterMin = aFilter;
494 if (theTexture->HasMipmaps())
495 {
496 aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
497 if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
498 {
499 aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
500 }
501 else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
502 {
503 aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
504 }
505
506 if (myGlContext->extAnis)
507 {
508 // setup degree of anisotropy filter
509 const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
25ef750e 510 GLint aDegree;
bf75be98 511 switch (aParams->AnisoFilter())
512 {
513 case Graphic3d_LOTA_QUALITY:
514 {
25ef750e 515 aDegree = aMaxDegree;
bf75be98 516 break;
517 }
518 case Graphic3d_LOTA_MIDDLE:
519 {
25ef750e 520 aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
bf75be98 521 break;
522 }
523 case Graphic3d_LOTA_FAST:
524 {
25ef750e 525 aDegree = 2;
bf75be98 526 break;
527 }
528 case Graphic3d_LOTA_OFF:
529 default:
530 {
25ef750e 531 aDegree = 1;
bf75be98 532 break;
533 }
534 }
25ef750e 535
536 if (aSampler.IsNull() || !aSampler->IsValid())
537 {
538 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
539 }
540 else
541 {
542 aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
543 }
bf75be98 544 }
545 }
25ef750e 546
547 if (aSampler.IsNull() || !aSampler->IsValid())
548 {
549 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
550 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
551 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aWrapMode);
552 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aWrapMode);
553 }
554 else
555 {
556 aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin);
557 aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
558 aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode);
559 aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T, aWrapMode);
560 }
561
bf75be98 562 break;
563 }
564 default: break;
565 }
566
567 switch (theTexture->GetTarget())
568 {
ca3c13d1 569 #if !defined(GL_ES_VERSION_2_0)
bf75be98 570 case GL_TEXTURE_1D:
571 {
572 if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
573 {
574 glEnable (GL_TEXTURE_GEN_S);
575 }
576 glEnable (GL_TEXTURE_1D);
577 break;
578 }
ca3c13d1 579 #endif
bf75be98 580 case GL_TEXTURE_2D:
581 {
ca3c13d1 582 #if !defined(GL_ES_VERSION_2_0)
bf75be98 583 if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
584 {
585 glEnable (GL_TEXTURE_GEN_S);
586 glEnable (GL_TEXTURE_GEN_T);
587 }
588 glEnable (GL_TEXTURE_2D);
05e2200b 589 #endif
bf75be98 590 break;
591 }
592 default: break;
593 }
594
ca3c13d1 595#if !defined(GL_ES_VERSION_2_0)
bf75be98 596 glMatrixMode (aMatrixMode); // turn back active matrix
ca3c13d1 597#endif
bf75be98 598 theTexture->SetParams (aParams);
599}
600
601// =======================================================================
602// function : EnableTexture
603// purpose :
604// =======================================================================
605Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)& theTexture,
606 const Handle(Graphic3d_TextureParams)& theParams)
607{
608 if (theTexture.IsNull() || !theTexture->IsValid())
609 {
610 return DisableTexture();
611 }
612
bca1d6e2 613 if (myTextureBound == theTexture
614 && (theParams.IsNull() || theParams == theTexture->GetParams()))
bf75be98 615 {
bca1d6e2 616 // already bound
617 return myTextureBound;
bf75be98 618 }
619
620 Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
621 myTextureBound = theTexture;
622 myTextureBound->Bind (myGlContext);
623 setTextureParams (myTextureBound, theParams);
624
25ef750e 625 // If custom sampler object is available it will be
626 // used for overriding default texture parameters
627 const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
628
629 if (!aSampler.IsNull() && aSampler->IsValid())
630 {
631 aSampler->Bind (*myGlContext);
632 }
633
bf75be98 634 return aPrevTexture;
635}
a174a3c5 636
637// =======================================================================
638// function : Redraw
639// purpose :
640// =======================================================================
641void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
642 const Aspect_CLayer2d& theCUnderLayer,
643 const Aspect_CLayer2d& theCOverLayer)
644{
645 if (!Activate())
646 {
647 return;
648 }
649
a89742cf 650 ++myFrameCounter;
b7cd4ba7 651 myIsCullingEnabled = theCView.IsCullingEnabled;
652
a174a3c5 653 // release pending GL resources
654 Handle(OpenGl_Context) aGlCtx = GetGlContext();
655 aGlCtx->ReleaseDelayed();
656
b5ac8292 657 // fetch OpenGl context state
658 aGlCtx->FetchState();
a174a3c5 659
25b97fac 660 Tint toSwap = (aGlCtx->IsRender() && !aGlCtx->caps->buffersNoSwap) ? 1 : 0; // swap buffers
a174a3c5 661 OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
662 if (aFrameBuffer != NULL)
663 {
fd4a6963 664 aFrameBuffer->SetupViewport (aGlCtx);
a174a3c5 665 toSwap = 0; // no need to swap buffers
666 }
e3573bb9 667 else
668 {
669 aGlCtx->core11fwd->glViewport (0, 0, myWidth, myHeight);
670 }
a174a3c5 671
b86bb3df 672 Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth;
673 Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight;
674
675 if (myResultFBO->GetVPSizeX() != aSizeX
676 || myResultFBO->GetVPSizeY() != aSizeY)
677 {
760c21c2 678 // prepare FBOs containing main scene
679 // for further blitting and rendering immediate presentations on top
680 if (aGlCtx->core20fwd != NULL)
681 {
682 myResultFBO->Init (aGlCtx, aSizeX, aSizeY);
683 }
b86bb3df 684 }
685 if (myResultFBO->IsValid())
686 {
687 myResultFBO->SetupViewport (aGlCtx);
688 }
689
690 const Standard_Boolean isImmediate = myView->HasImmediateStructures()
691 || myResultFBO->IsValid();
692
a89742cf 693 myToRedrawGL = Standard_True;
694 if (theCView.RenderParams.Method == Graphic3d_RM_RAYTRACING
695 && myComputeInitStatus != OpenGl_RT_FAIL)
e276548b 696 {
a89742cf 697 if (UpdateRaytraceGeometry (OpenGl_GUM_CHECK) && myIsRaytraceDataValid)
698 {
699 myToRedrawGL = Standard_False;
700
701 // Only non-raytracable structures should be rendered in OpenGL mode.
702 Handle(OpenGl_RenderFilter) aRenderFilter = GetRenderFilter();
703 myRaytraceFilter->SetPrevRenderFilter (aRenderFilter);
704 SetRenderFilter (myRaytraceFilter);
705
a89742cf 706 if (myOpenGlFBO.IsNull())
707 {
708 myOpenGlFBO = new OpenGl_FrameBuffer();
709 }
710 if (myOpenGlFBO->GetVPSizeX() != aSizeX
711 || myOpenGlFBO->GetVPSizeY() != aSizeY)
712 {
713 myOpenGlFBO->Init (aGlCtx, aSizeX, aSizeY);
714 }
715
716 // OverLayer and UnderLayer shouldn't be drawn by OpenGL.
717 // They will be drawn during ray-tracing.
718 Aspect_CLayer2d anEmptyCLayer;
719 anEmptyCLayer.ptrLayer = NULL;
720
721 myOpenGlFBO->BindBuffer (aGlCtx);
722 redraw1 (theCView, anEmptyCLayer, anEmptyCLayer, 0);
723 myOpenGlFBO->UnbindBuffer (aGlCtx);
724
a89742cf 725 Raytrace (theCView, aSizeX, aSizeY, isImmediate ? 0 : toSwap,
b86bb3df 726 theCOverLayer, theCUnderLayer,
727 myResultFBO->IsValid() ? myResultFBO.operator->() : aFrameBuffer);
a89742cf 728
729 if (isImmediate)
730 {
b86bb3df 731 RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True, aFrameBuffer);
a89742cf 732 }
733
734 SetRenderFilter (aRenderFilter);
735
736 theCView.WasRedrawnGL = Standard_False;
737 }
738 }
739
740 if (myToRedrawGL)
741 {
742 // draw entire frame using normal OpenGL pipeline
b86bb3df 743 if (myResultFBO->IsValid())
744 {
745 myResultFBO->BindBuffer (aGlCtx);
746 }
747 else if (aFrameBuffer != NULL)
a89742cf 748 {
749 aFrameBuffer->BindBuffer (aGlCtx);
750 }
751
679ecdee 752 redraw1 (theCView, theCUnderLayer, theCOverLayer, isImmediate ? 0 : toSwap);
753 if (isImmediate)
e276548b 754 {
b86bb3df 755 RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True, aFrameBuffer);
e276548b 756 }
757
758 theCView.WasRedrawnGL = Standard_True;
e276548b 759 }
a174a3c5 760
761 if (aFrameBuffer != NULL)
762 {
763 aFrameBuffer->UnbindBuffer (aGlCtx);
764 // move back original viewport
e3573bb9 765 aGlCtx->core11fwd->glViewport (0, 0, myWidth, myHeight);
a174a3c5 766 }
767
679ecdee 768#if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
a174a3c5 769 if (OpenGl_AVIWriter_AllowWriting (theCView.DefWindow.XWindow))
770 {
771 GLint params[4];
772 glGetIntegerv (GL_VIEWPORT, params);
773 int nWidth = params[2] & ~0x7;
774 int nHeight = params[3] & ~0x7;
775
776 const int nBitsPerPixel = 24;
777 GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
778
779 glPixelStorei (GL_PACK_ALIGNMENT, 1);
780 glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData);
781 OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel);
782 delete[] aDumpData;
783 }
784#endif
785
786 // reset render mode state
b5ac8292 787 aGlCtx->FetchState();
a174a3c5 788}
679ecdee 789
790// =======================================================================
791// function : redraw1
792// purpose :
793// =======================================================================
794void OpenGl_Workspace::redraw1 (const Graphic3d_CView& theCView,
795 const Aspect_CLayer2d& theCUnderLayer,
796 const Aspect_CLayer2d& theCOverLayer,
797 const int theToSwap)
798{
73192b37 799 if (myView.IsNull())
679ecdee 800 {
801 return;
802 }
803
804 // request reset of material
805 NamedStatus |= OPENGL_NS_RESMAT;
806
679ecdee 807 GLbitfield toClear = GL_COLOR_BUFFER_BIT;
808 if (myUseZBuffer)
809 {
810 glDepthFunc (GL_LEQUAL);
811 glDepthMask (GL_TRUE);
812 if (myUseDepthTest)
813 {
814 glEnable (GL_DEPTH_TEST);
815 }
816 else
817 {
818 glDisable (GL_DEPTH_TEST);
819 }
820
ca3c13d1 821 #if !defined(GL_ES_VERSION_2_0)
679ecdee 822 glClearDepth (1.0);
ca3c13d1 823 #else
824 glClearDepthf (1.0f);
825 #endif
679ecdee 826 toClear |= GL_DEPTH_BUFFER_BIT;
827 }
828 else
829 {
830 glDisable (GL_DEPTH_TEST);
831 }
832
a89742cf 833 if (!ToRedrawGL())
679ecdee 834 {
a89742cf 835 // set background to black
836 glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
837 toClear |= GL_DEPTH_BUFFER_BIT; //
679ecdee 838 }
839 else
840 {
a89742cf 841 if (NamedStatus & OPENGL_NS_WHITEBACK)
842 {
843 // set background to white
844 glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
845 toClear |= GL_DEPTH_BUFFER_BIT;
846 }
847 else
848 {
849 glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f);
850 }
679ecdee 851 }
852 glClear (toClear);
853
854 Handle(OpenGl_Workspace) aWS (this);
a1954302 855 myView->Render (myPrintContext, aWS, theCView, theCUnderLayer, theCOverLayer, Standard_False);
679ecdee 856
857 // swap the buffers
858 if (theToSwap)
859 {
860 GetGlContext()->SwapBuffers();
861 myBackBufferRestored = Standard_False;
862 myIsImmediateDrawn = Standard_False;
863 }
864 else
865 {
a89742cf 866 glFlush(); //
867 myBackBufferRestored = Standard_True;//
868 myIsImmediateDrawn = Standard_False;//
679ecdee 869 }
870}
871
872// =======================================================================
873// function : copyBackToFront
874// purpose :
875// =======================================================================
876void OpenGl_Workspace::copyBackToFront()
877{
ca3c13d1 878#if !defined(GL_ES_VERSION_2_0)
ca3c13d1 879
c827ea3a 880 OpenGl_Mat4 aProjectMat;
881 OpenGl_Utils::Ortho2D<Standard_ShortReal> (aProjectMat,
882 0.f, static_cast<GLfloat> (myWidth), 0.f, static_cast<GLfloat> (myHeight));
883
884 myGlContext->WorldViewState.Push();
885 myGlContext->ProjectionState.Push();
886
887 myGlContext->WorldViewState.SetIdentity();
888 myGlContext->ProjectionState.SetCurrent (aProjectMat);
889
890 myGlContext->ApplyProjectionMatrix();
891 myGlContext->ApplyWorldViewMatrix();
679ecdee 892
893 DisableFeatures();
894
895 glDrawBuffer (GL_FRONT);
896 glReadBuffer (GL_BACK);
897
898 glRasterPos2i (0, 0);
899 glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_COLOR);
a1954302 900 //glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH);
679ecdee 901
902 EnableFeatures();
903
c827ea3a 904 myGlContext->WorldViewState.Pop();
905 myGlContext->ProjectionState.Pop();
906 myGlContext->ApplyProjectionMatrix();
679ecdee 907 glDrawBuffer (GL_BACK);
908
ca3c13d1 909#endif
679ecdee 910 myIsImmediateDrawn = Standard_False;
911}
912
913// =======================================================================
914// function : DisplayCallback
915// purpose :
916// =======================================================================
917void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView,
918 Standard_Integer theReason)
919{
920 if (theCView.GDisplayCB == NULL)
921 {
922 return;
923 }
924
925 Aspect_GraphicCallbackStruct aCallData;
926 aCallData.reason = theReason;
927 aCallData.glContext = GetGlContext();
928 aCallData.wsID = theCView.WsId;
929 aCallData.viewID = theCView.ViewId;
930 theCView.GDisplayCB (theCView.DefWindow.XWindow, theCView.GClientData, &aCallData);
931}
932
933// =======================================================================
934// function : RedrawImmediate
935// purpose :
936// =======================================================================
937void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
938 const Aspect_CLayer2d& theCUnderLayer,
939 const Aspect_CLayer2d& theCOverLayer,
b86bb3df 940 const Standard_Boolean theToForce,
941 OpenGl_FrameBuffer* theTargetFBO)
679ecdee 942{
943 if (!Activate())
944 {
945 return;
946 }
947
948 GLboolean isDoubleBuffer = GL_FALSE;
ca3c13d1 949#if !defined(GL_ES_VERSION_2_0)
679ecdee 950 glGetBooleanv (GL_DOUBLEBUFFER, &isDoubleBuffer);
ca3c13d1 951#endif
b86bb3df 952 if (!myView->HasImmediateStructures()
953 && !myResultFBO->IsValid())
679ecdee 954 {
955 if (theToForce
956 || !myIsImmediateDrawn)
957 {
958 myIsImmediateDrawn = Standard_False;
959 return;
960 }
961
962 if (myBackBufferRestored
963 && isDoubleBuffer)
964 {
965 copyBackToFront();
65812bd0 966 glFlush();
679ecdee 967 }
968 else
969 {
970 Redraw (theCView, theCUnderLayer, theCOverLayer);
971 }
972 return;
973 }
974
b86bb3df 975 if (myResultFBO->IsValid()
976 && myGlContext->IsRender())
977 {
978 if (!myBackBufferRestored)
979 {
980 Redraw (theCView, theCUnderLayer, theCOverLayer);
981 return;
982 }
983
984 // clear destination before blitting
985 if (theTargetFBO != NULL)
986 {
987 theTargetFBO->BindBuffer (myGlContext);
988 }
989 else
990 {
991 myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
992 }
993 #if !defined(GL_ES_VERSION_2_0)
994 myGlContext->core20fwd->glClearDepth (1.0);
995 #else
996 myGlContext->core20fwd->glClearDepthf (1.0f);
997 #endif
998 myGlContext->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
999
1000 /*#if !defined(GL_ES_VERSION_2_0)
1001 if (myGlContext->arbFBOBlit != NULL)
1002 {
1003 myResultFBO->BindReadBuffer (myGlContext);
1004 if (theTargetFBO != NULL)
1005 {
1006 theTargetFBO->BindDrawBuffer (myGlContext);
1007 }
1008 else
1009 {
1010 myGlContext->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1011 }
1012 // we don't copy stencil buffer here... does it matter for performance?
1013 myGlContext->arbFBOBlit->glBlitFramebuffer (0, 0, myResultFBO->GetVPSizeX(), myResultFBO->GetVPSizeY(),
1014 0, 0, myResultFBO->GetVPSizeX(), myResultFBO->GetVPSizeY(),
1015 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
1016
1017 if (theTargetFBO != NULL)
1018 {
1019 theTargetFBO->BindBuffer (myGlContext);
1020 }
1021 else
1022 {
1023 myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1024 }
1025 }
1026 else
1027 #endif*/
1028 {
1029 myGlContext->core20fwd->glDepthFunc (GL_ALWAYS);
1030 myGlContext->core20fwd->glDepthMask (GL_TRUE);
1031 myGlContext->core20fwd->glEnable (GL_DEPTH_TEST);
1032
1033 DisableTexture();
1034 if (!myFullScreenQuad.IsValid())
1035 {
1036 OpenGl_Vec4 aQuad[4] =
1037 {
1038 OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f),
1039 OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 1.0f),
1040 OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f),
1041 OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 1.0f)
1042 };
1043 myFullScreenQuad.Init (myGlContext, 4, 4, aQuad[0].GetData());
1044 }
1045
1046 const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager();
1047 if (myFullScreenQuad.IsValid()
1048 && aManager->BindFboBlitProgram())
1049 {
1050 myResultFBO->ColorTexture() ->Bind (myGlContext, GL_TEXTURE0 + 0);
1051 myResultFBO->DepthStencilTexture()->Bind (myGlContext, GL_TEXTURE0 + 1);
1052 myFullScreenQuad.BindVertexAttrib (myGlContext, 0);
1053
1054 myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1055
1056 myFullScreenQuad.UnbindVertexAttrib (myGlContext, 0);
1057 myResultFBO->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1);
1058 myResultFBO->ColorTexture() ->Unbind (myGlContext, GL_TEXTURE0 + 0);
1059 }
1060 }
1061 }
1062 else if (isDoubleBuffer && myTransientDrawToFront)
679ecdee 1063 {
1064 if (!myBackBufferRestored)
1065 {
1066 Redraw (theCView, theCUnderLayer, theCOverLayer);
1067 return;
1068 }
1069 copyBackToFront();
1070 MakeFrontBufCurrent();
1071 }
1072 else
1073 {
1074 myBackBufferRestored = Standard_False;
1075 }
1076 myIsImmediateDrawn = Standard_True;
1077
679ecdee 1078 Handle(OpenGl_Workspace) aWS (this);
a1954302 1079
1080 if (myUseZBuffer)
1081 {
1082 glDepthFunc (GL_LEQUAL);
1083 glDepthMask (GL_TRUE);
1084 if (myUseDepthTest)
1085 {
1086 glEnable (GL_DEPTH_TEST);
1087 }
1088 else
1089 {
1090 glDisable (GL_DEPTH_TEST);
1091 }
1092
1093 #if !defined(GL_ES_VERSION_2_0)
1094 glClearDepth (1.0);
1095 #else
1096 glClearDepthf (1.0f);
1097 #endif
1098 }
1099 else
1100 {
1101 glDisable (GL_DEPTH_TEST);
1102 }
1103
1104 myView->Render (myPrintContext, aWS, theCView, theCUnderLayer, theCOverLayer, Standard_True);
1105 if (!myView->ImmediateStructures().IsEmpty())
1106 {
1107 glDisable (GL_DEPTH_TEST);
1108 }
679ecdee 1109 for (OpenGl_SequenceOfStructure::Iterator anIter (myView->ImmediateStructures());
1110 anIter.More(); anIter.Next())
1111 {
1112 const OpenGl_Structure* aStructure = anIter.Value();
a1954302 1113 if (!aStructure->IsVisible())
1114 {
1115 continue;
1116 }
1117
679ecdee 1118 aStructure->Render (aWS);
1119 }
1120
b86bb3df 1121 if (myResultFBO->IsValid())
1122 {
1123 if (theTargetFBO == NULL
1124 && myGlContext->IsRender()
1125 && !myGlContext->caps->buffersNoSwap)
1126 {
1127 myGlContext->SwapBuffers();
1128 }
1129 }
1130 else if (isDoubleBuffer && myTransientDrawToFront)
679ecdee 1131 {
1132 glFlush();
1133 MakeBackBufCurrent();
1134 }
1135}