X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=blobdiff_plain;f=src%2FOpenGl%2FOpenGl_Workspace.cxx;h=a0e76563af24887329482627b437a5c33fc5eb7e;hp=d5fb08fefc58d61e323f24c724d421b0c9f5285d;hb=1be4179947116e54658924f0149d3f35743a899a;hpb=68333c8f16e01c5252dbebd4c9fcd6680f3941ba diff --git a/src/OpenGl/OpenGl_Workspace.cxx b/src/OpenGl/OpenGl_Workspace.cxx index d5fb08fefc..a0e76563af 100644 --- a/src/OpenGl/OpenGl_Workspace.cxx +++ b/src/OpenGl/OpenGl_Workspace.cxx @@ -4,8 +4,8 @@ // // This file is part of Open CASCADE Technology software library. // -// This library is free software; you can redistribute it and / or modify it -// under the terms of the GNU Lesser General Public version 2.1 as published +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. @@ -13,49 +13,49 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -#ifdef HAVE_CONFIG_H - #include -#endif - -#include - -#include +#include +#include #include #include #include #include #include +#include #include +#include +#include +#include +#include #include #include -#include -#include +#include #include - -#if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE) - #include +#include + +IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,Standard_Transient) +IMPLEMENT_STANDARD_RTTIEXT(OpenGl_RaytraceFilter,OpenGl_RenderFilter) + +#ifdef HAVE_GL2PS + #include + /* OCC22216 NOTE: linker dependency can be switched off by undefining macro. + Pragma comment for gl2ps.lib is defined only here. */ + #ifdef _MSC_VER + #pragma comment( lib, "gl2ps.lib" ) + #endif #endif -IMPLEMENT_STANDARD_HANDLE(OpenGl_Workspace,OpenGl_Window) -IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,OpenGl_Window) - namespace { - static const TEL_COLOUR THE_WHITE_COLOR = { { 1.0f, 1.0f, 1.0f, 1.0f } }; - static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f); + static const OpenGl_Vec4 THE_WHITE_COLOR (1.0f, 1.0f, 1.0f, 1.0f); + static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f); static const OpenGl_AspectLine myDefaultAspectLine; static const OpenGl_AspectFace myDefaultAspectFace; static const OpenGl_AspectMarker myDefaultAspectMarker; static const OpenGl_AspectText myDefaultAspectText; - static const OpenGl_TextParam myDefaultTextParam = - { - 16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM - }; - static const OpenGl_Matrix myDefaultMatrix = { {{ 1.0F, 0.0F, 0.0F, 0.0F }, @@ -64,22 +64,22 @@ namespace { 0.0F, 0.0F, 0.0F, 1.0F }} }; -}; +} // ======================================================================= // function : Init // purpose : // ======================================================================= -void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp) +void OpenGl_Material::Init (const Graphic3d_MaterialAspect& theMat, + const Quantity_Color& theInteriorColor) { + const bool isPhysic = theMat.MaterialType (Graphic3d_MATERIAL_PHYSIC) == Standard_True; + // ambient component - if (theProp.color_mask & OPENGL_AMBIENT_MASK) + if (theMat.ReflectionMode (Graphic3d_TOR_AMBIENT)) { - const float* aSrcAmb = theProp.isphysic ? theProp.ambcol.rgb : theProp.matcol.rgb; - Ambient = OpenGl_Vec4 (aSrcAmb[0] * theProp.amb, - aSrcAmb[1] * theProp.amb, - aSrcAmb[2] * theProp.amb, - 1.0f); + const OpenGl_Vec3& aSrcAmb = isPhysic ? theMat.AmbientColor() : theInteriorColor; + Ambient = OpenGl_Vec4 (aSrcAmb * (float )theMat.Ambient(), 1.0f); } else { @@ -87,13 +87,10 @@ void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp) } // diffusion component - if (theProp.color_mask & OPENGL_DIFFUSE_MASK) + if (theMat.ReflectionMode (Graphic3d_TOR_DIFFUSE)) { - const float* aSrcDif = theProp.isphysic ? theProp.difcol.rgb : theProp.matcol.rgb; - Diffuse = OpenGl_Vec4 (aSrcDif[0] * theProp.diff, - aSrcDif[1] * theProp.diff, - aSrcDif[2] * theProp.diff, - 1.0f); + const OpenGl_Vec3& aSrcDif = isPhysic ? theMat.DiffuseColor() : theInteriorColor; + Diffuse = OpenGl_Vec4 (aSrcDif * (float )theMat.Diffuse(), 1.0f); } else { @@ -101,13 +98,10 @@ void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp) } // specular component - if (theProp.color_mask & OPENGL_SPECULAR_MASK) + if (theMat.ReflectionMode (Graphic3d_TOR_SPECULAR)) { - const float* aSrcSpe = theProp.isphysic ? theProp.speccol.rgb : THE_WHITE_COLOR.rgb; - Specular = OpenGl_Vec4 (aSrcSpe[0] * theProp.spec, - aSrcSpe[1] * theProp.spec, - aSrcSpe[2] * theProp.spec, - 1.0f); + const OpenGl_Vec3& aSrcSpe = isPhysic ? (const OpenGl_Vec3& )theMat.SpecularColor() : THE_WHITE_COLOR.rgb(); + Specular = OpenGl_Vec4 (aSrcSpe * (float )theMat.Specular(), 1.0f); } else { @@ -115,111 +109,74 @@ void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp) } // emission component - if (theProp.color_mask & OPENGL_EMISSIVE_MASK) + if (theMat.ReflectionMode (Graphic3d_TOR_EMISSION)) { - const float* aSrcEms = theProp.isphysic ? theProp.emscol.rgb : theProp.matcol.rgb; - Emission = OpenGl_Vec4 (aSrcEms[0] * theProp.emsv, - aSrcEms[1] * theProp.emsv, - aSrcEms[2] * theProp.emsv, - 1.0f); + const OpenGl_Vec3& aSrcEms = isPhysic ? theMat.EmissiveColor() : theInteriorColor; + Emission = OpenGl_Vec4 (aSrcEms * (float )theMat.Emissive(), 1.0f); } else { Emission = THE_BLACK_COLOR; } - ChangeShine() = theProp.shine; - ChangeTransparency() = theProp.trans; + ChangeShine() = 128.0f * float(theMat.Shininess()); + ChangeTransparency() = 1.0f - (float )theMat.Transparency(); } // ======================================================================= // function : OpenGl_Workspace // purpose : // ======================================================================= -OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_Display)& theDisplay, - const CALL_DEF_WINDOW& theCWindow, - Aspect_RenderingContext theGContext, - const Handle(OpenGl_Caps)& theCaps, - const Handle(OpenGl_Context)& theShareCtx) -: OpenGl_Window (theDisplay, theCWindow, theGContext, theCaps, theShareCtx), - NamedStatus (0), +OpenGl_Workspace::OpenGl_Workspace (OpenGl_View* theView, const Handle(OpenGl_Window)& theWindow) +: NamedStatus (0), HighlightColor (&THE_WHITE_COLOR), - // - myIsTransientOpen (Standard_False), - myRetainMode (Standard_False), - myTransientDrawToFront (Standard_True), - myUseTransparency (Standard_False), - myUseZBuffer (Standard_False), - myUseDepthTest (Standard_True), + myView (theView), + myWindow (theWindow), + myGlContext (!theWindow.IsNull() ? theWindow->GetGlContext() : NULL), + myUseZBuffer (Standard_True), + myUseDepthWrite (Standard_True), myUseGLLight (Standard_True), - myBackBufferRestored (Standard_False), // - AspectLine_set (&myDefaultAspectLine), - AspectLine_applied (NULL), - AspectFace_set (&myDefaultAspectFace), - AspectFace_applied (NULL), - AspectMarker_set (&myDefaultAspectMarker), - AspectMarker_applied (NULL), - AspectText_set (&myDefaultAspectText), - AspectText_applied (NULL), - TextParam_set (&myDefaultTextParam), - TextParam_applied (NULL), + myAspectLineSet (&myDefaultAspectLine), + myAspectFaceSet (&myDefaultAspectFace), + myAspectMarkerSet (&myDefaultAspectMarker), + myAspectTextSet (&myDefaultAspectText), + myAspectFaceAppliedWithHL (false), + // ViewMatrix_applied (&myDefaultMatrix), StructureMatrix_applied (&myDefaultMatrix), - myCullingMode (TelCullUndefined), - myModelViewMatrix (myDefaultMatrix), - PolygonOffset_applied (NULL) + myToAllowFaceCulling (false), + myToHighlight (false), + myModelViewMatrix (myDefaultMatrix) { - theDisplay->InitAttributes(); - - // General initialization of the context - - // Eviter d'avoir les faces mal orientees en noir. - // Pourrait etre utiliser pour detecter les problemes d'orientation - glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); - - // Optimisation pour le Fog et l'antialiasing - glHint (GL_FOG_HINT, GL_FASTEST); - glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST); - glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST); - glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST); - - // Polygon Offset - EnablePolygonOffset(); - -#ifdef HAVE_OPENCL + if (!myGlContext.IsNull() && myGlContext->MakeCurrent()) + { + myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - myComputeInitStatus = OpenGl_CLIS_NONE; + // General initialization of the context + #if !defined(GL_ES_VERSION_2_0) + if (myGlContext->core11 != NULL) + { + // Eviter d'avoir les faces mal orientees en noir. + // Pourrait etre utiliser pour detecter les problemes d'orientation + glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); - myViewModificationStatus = 0; - myLayersModificationStatus = 0; + // Optimisation pour le Fog et l'antialiasing + glHint (GL_FOG_HINT, GL_FASTEST); + glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST); + } - myIsRaytraceDataValid = Standard_False; - myToUpdateRaytraceData = Standard_False; + glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST); + glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST); + #endif + } -#endif -} + myDefaultCappingAlgoFilter = new OpenGl_CappingAlgoFilter(); -// ======================================================================= -// function : SetImmediateModeDrawToFront -// purpose : -// ======================================================================= -Standard_Boolean OpenGl_Workspace::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer) -{ - const Standard_Boolean aPrevMode = myTransientDrawToFront; - myTransientDrawToFront = theDrawToFrontBuffer; - return aPrevMode; -} - -// ======================================================================= -// function : ~OpenGl_Workspace -// purpose : -// ======================================================================= -OpenGl_Workspace::~OpenGl_Workspace() -{ -#ifdef HAVE_OPENCL - ReleaseOpenCL(); -#endif + myNoneCulling .Aspect()->SetSuppressBackFaces (false); + myNoneCulling .Aspect()->SetDrawEdges (false); + myFrontCulling.Aspect()->SetSuppressBackFaces (true); + myFrontCulling.Aspect()->SetDrawEdges (false); } // ======================================================================= @@ -228,8 +185,10 @@ OpenGl_Workspace::~OpenGl_Workspace() // ======================================================================= Standard_Boolean OpenGl_Workspace::Activate() { - if (!OpenGl_Window::Activate()) + if (myWindow.IsNull() || !myWindow->Activate()) + { return Standard_False; + } ViewMatrix_applied = &myDefaultMatrix; StructureMatrix_applied = &myDefaultMatrix; @@ -239,40 +198,32 @@ Standard_Boolean OpenGl_Workspace::Activate() return Standard_True; } -// ======================================================================= -// function : UseTransparency -// purpose : call_togl_transparency -// ======================================================================= -void OpenGl_Workspace::UseTransparency (const Standard_Boolean theFlag) -{ - myUseTransparency = theFlag; -} - //======================================================================= //function : ResetAppliedAspect //purpose : Sets default values of GL parameters in accordance with default aspects //======================================================================= void OpenGl_Workspace::ResetAppliedAspect() { + myGlContext->BindDefaultVao(); + NamedStatus = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0; HighlightColor = &THE_WHITE_COLOR; - AspectLine_set = &myDefaultAspectLine; - AspectLine_applied = NULL; - AspectFace_set = &myDefaultAspectFace; - AspectFace_applied = NULL; - AspectMarker_set = &myDefaultAspectMarker; - AspectMarker_applied = NULL; - AspectText_set = &myDefaultAspectText; - AspectText_applied = NULL; - TextParam_set = &myDefaultTextParam; - TextParam_applied = NULL; - PolygonOffset_applied = NULL; - myCullingMode = TelCullUndefined; - - AspectLine(Standard_True); - AspectFace(Standard_True); - AspectMarker(Standard_True); - AspectText(Standard_True); + myToAllowFaceCulling = false; + myAspectLineSet = &myDefaultAspectLine; + myAspectFaceSet = &myDefaultAspectFace; + myAspectFaceApplied.Nullify(); + myAspectMarkerSet = &myDefaultAspectMarker; + myAspectMarkerApplied.Nullify(); + myAspectTextSet = &myDefaultAspectText; + myPolygonOffsetApplied= Graphic3d_PolygonOffset(); + + ApplyAspectLine(); + ApplyAspectFace(); + ApplyAspectMarker(); + ApplyAspectText(); + + myGlContext->SetTypeOfLine (myDefaultAspectLine.Aspect()->Type()); + myGlContext->SetLineWidth (myDefaultAspectLine.Aspect()->Width()); } // ======================================================================= @@ -286,37 +237,58 @@ Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture() return myTextureBound; } + const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler(); + if (!aSampler.IsNull()) + { + aSampler->Unbind (*myGlContext); + } + +#if !defined(GL_ES_VERSION_2_0) // reset texture matrix because some code may expect it is identity - GLint aMatrixMode = GL_TEXTURE; - glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode); - glMatrixMode (GL_TEXTURE); - glLoadIdentity(); - glMatrixMode (aMatrixMode); + if (myGlContext->core11 != NULL) + { + GLint aMatrixMode = GL_TEXTURE; + glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode); + glMatrixMode (GL_TEXTURE); + glLoadIdentity(); + glMatrixMode (aMatrixMode); + } +#endif myTextureBound->Unbind (myGlContext); switch (myTextureBound->GetTarget()) { + #if !defined(GL_ES_VERSION_2_0) case GL_TEXTURE_1D: { - if (myTextureBound->GetParams()->GenMode() != GL_NONE) + if (myGlContext->core11 != NULL) { - glDisable (GL_TEXTURE_GEN_S); + if (myTextureBound->GetParams()->GenMode() != GL_NONE) + { + glDisable (GL_TEXTURE_GEN_S); + } + glDisable (GL_TEXTURE_1D); } - glDisable (GL_TEXTURE_1D); break; } + #endif case GL_TEXTURE_2D: { - if (myTextureBound->GetParams()->GenMode() != GL_NONE) + #if !defined(GL_ES_VERSION_2_0) + if (myGlContext->core11 != NULL) { - glDisable (GL_TEXTURE_GEN_S); - glDisable (GL_TEXTURE_GEN_T); - if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE) + if (myTextureBound->GetParams()->GenMode() != GL_NONE) { - glDisable (GL_POINT_SPRITE); + glDisable (GL_TEXTURE_GEN_S); + glDisable (GL_TEXTURE_GEN_T); + if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE) + { + glDisable (GL_POINT_SPRITE); + } } + glDisable (GL_TEXTURE_2D); } - glDisable (GL_TEXTURE_2D); + #endif break; } default: break; @@ -340,92 +312,110 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& return; } - GLint aMatrixMode = GL_TEXTURE; - glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode); - - // setup texture matrix - glMatrixMode (GL_TEXTURE); - glLoadIdentity(); - const Graphic3d_Vec2& aScale = aParams->Scale(); - const Graphic3d_Vec2& aTrans = aParams->Translation(); - glScalef ( aScale.x(), aScale.y(), 1.0f); - glTranslatef (-aTrans.x(), -aTrans.y(), 0.0f); - glRotatef (-aParams->Rotation(), 0.0f, 0.0f, 1.0f); - - // setup generation of texture coordinates - switch (aParams->GenMode()) +#if !defined(GL_ES_VERSION_2_0) + if (myGlContext->core11 != NULL) { - case Graphic3d_TOTM_OBJECT: + GLint anEnvMode = GL_MODULATE; // lighting mode + if (!aParams->IsModulate()) { - glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGenfv (GL_S, GL_OBJECT_PLANE, aParams->GenPlaneS().GetData()); - if (theTexture->GetTarget() != GL_TEXTURE_1D) + anEnvMode = GL_DECAL; + if (theTexture->GetFormat() == GL_ALPHA + || theTexture->GetFormat() == GL_LUMINANCE) { - glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGenfv (GL_T, GL_OBJECT_PLANE, aParams->GenPlaneT().GetData()); + anEnvMode = GL_REPLACE; } - break; } - case Graphic3d_TOTM_SPHERE: + + // setup generation of texture coordinates + switch (aParams->GenMode()) { - glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - if (theTexture->GetTarget() != GL_TEXTURE_1D) + case Graphic3d_TOTM_OBJECT: { - glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGenfv (GL_S, GL_OBJECT_PLANE, aParams->GenPlaneS().GetData()); + if (theTexture->GetTarget() != GL_TEXTURE_1D) + { + glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGenfv (GL_T, GL_OBJECT_PLANE, aParams->GenPlaneT().GetData()); + } + break; } - break; - } - case Graphic3d_TOTM_EYE: - { - glMatrixMode (GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); + case Graphic3d_TOTM_SPHERE: + { + glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + if (theTexture->GetTarget() != GL_TEXTURE_1D) + { + glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + } + break; + } + case Graphic3d_TOTM_EYE: + { + myGlContext->WorldViewState.Push(); - glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - glTexGenfv (GL_S, GL_EYE_PLANE, aParams->GenPlaneS().GetData()); + myGlContext->WorldViewState.SetIdentity(); + myGlContext->ApplyWorldViewMatrix(); - if (theTexture->GetTarget() != GL_TEXTURE_1D) - { - glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - glTexGenfv (GL_T, GL_EYE_PLANE, aParams->GenPlaneT().GetData()); + glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGenfv (GL_S, GL_EYE_PLANE, aParams->GenPlaneS().GetData()); + + if (theTexture->GetTarget() != GL_TEXTURE_1D) + { + glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGenfv (GL_T, GL_EYE_PLANE, aParams->GenPlaneT().GetData()); + } + + myGlContext->WorldViewState.Pop(); + + break; } - glPopMatrix(); - break; - } - case Graphic3d_TOTM_SPRITE: - { - if (GetGlContext()->core20 != NULL) + case Graphic3d_TOTM_SPRITE: { - glEnable (GL_POINT_SPRITE); - glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); - glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - GetGlContext()->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT); + if (myGlContext->core20fwd != NULL) + { + glEnable (GL_POINT_SPRITE); + glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); + anEnvMode = GL_REPLACE; + } + break; } - break; + case Graphic3d_TOTM_MANUAL: + default: break; } - case Graphic3d_TOTM_MANUAL: - default: break; - } - // setup lighting - if (aParams->GenMode() != Graphic3d_TOTM_SPRITE) - { - glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aParams->IsModulate() ? GL_MODULATE : GL_DECAL); + // setup lighting + glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode); } +#endif + + // get active sampler object to override default texture parameters + const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler(); // setup texture filtering and wrapping //if (theTexture->GetParams() != theParams) const GLenum aFilter = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR; - const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : GL_CLAMP; + const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp(); switch (theTexture->GetTarget()) { + #if !defined(GL_ES_VERSION_2_0) case GL_TEXTURE_1D: { - glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter); - glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter); - glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, aWrapMode); + if (aSampler.IsNull() || !aSampler->IsValid()) + { + glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter); + glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter); + glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, aWrapMode); + } + else + { + aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter); + aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter); + aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode); + } + break; } + #endif case GL_TEXTURE_2D: { GLenum aFilterMin = aFilter; @@ -445,37 +435,58 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& { // setup degree of anisotropy filter const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy(); + GLint aDegree; switch (aParams->AnisoFilter()) { case Graphic3d_LOTA_QUALITY: { - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aMaxDegree); + aDegree = aMaxDegree; break; } case Graphic3d_LOTA_MIDDLE: { - - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2)); + aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2); break; } case Graphic3d_LOTA_FAST: { - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2); + aDegree = 2; break; } case Graphic3d_LOTA_OFF: default: { - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + aDegree = 1; break; } } + + if (aSampler.IsNull() || !aSampler->IsValid()) + { + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree); + } + else + { + aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree); + } } } - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aWrapMode); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aWrapMode); + + if (aSampler.IsNull() || !aSampler->IsValid()) + { + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aWrapMode); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aWrapMode); + } + else + { + aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin); + aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter); + aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode); + aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T, aWrapMode); + } + break; } default: break; @@ -483,29 +494,38 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& switch (theTexture->GetTarget()) { + #if !defined(GL_ES_VERSION_2_0) case GL_TEXTURE_1D: { - if (aParams->GenMode() != Graphic3d_TOTM_MANUAL) + if (myGlContext->core11 != NULL) { - glEnable (GL_TEXTURE_GEN_S); + if (aParams->GenMode() != Graphic3d_TOTM_MANUAL) + { + glEnable (GL_TEXTURE_GEN_S); + } + glEnable (GL_TEXTURE_1D); } - glEnable (GL_TEXTURE_1D); break; } + #endif case GL_TEXTURE_2D: { - if (aParams->GenMode() != Graphic3d_TOTM_MANUAL) + #if !defined(GL_ES_VERSION_2_0) + if (myGlContext->core11 != NULL) { - glEnable (GL_TEXTURE_GEN_S); - glEnable (GL_TEXTURE_GEN_T); + if (aParams->GenMode() != Graphic3d_TOTM_MANUAL) + { + glEnable (GL_TEXTURE_GEN_S); + glEnable (GL_TEXTURE_GEN_T); + } + glEnable (GL_TEXTURE_2D); } - glEnable (GL_TEXTURE_2D); + #endif break; } default: break; } - glMatrixMode (aMatrixMode); // turn back active matrix theTexture->SetParams (aParams); } @@ -533,91 +553,666 @@ Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Text myTextureBound->Bind (myGlContext); setTextureParams (myTextureBound, theParams); + // If custom sampler object is available it will be + // used for overriding default texture parameters + const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler(); + + if (!aSampler.IsNull() && aSampler->IsValid()) + { + aSampler->Bind (*myGlContext); + } + return aPrevTexture; } // ======================================================================= -// function : Redraw +// function : updateMaterial // purpose : // ======================================================================= -void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView, - const Aspect_CLayer2d& theCUnderLayer, - const Aspect_CLayer2d& theCOverLayer) +void OpenGl_Workspace::updateMaterial (const int theFlag) { - if (!Activate()) + // Case of hidden line + if (myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE) { + // copy all values including line edge aspect + *myAspectFaceHl.Aspect().operator->() = *myAspectFaceSet->Aspect(); + myAspectFaceHl.SetAspectEdge (myAspectFaceSet->AspectEdge()); + myAspectFaceHl.Aspect()->SetInteriorColor (myView->BackgroundColor().GetRGB()); + myAspectFaceHl.SetNoLighting (true); + myAspectFaceSet = &myAspectFaceHl; return; } - // release pending GL resources - Handle(OpenGl_Context) aGlCtx = GetGlContext(); - aGlCtx->ReleaseDelayed(); + const Graphic3d_MaterialAspect* aSrcMat = &myAspectFaceSet->Aspect()->FrontMaterial(); + const Quantity_Color* aSrcIntColor = &myAspectFaceSet->Aspect()->InteriorColor(); + GLenum aFace = GL_FRONT_AND_BACK; + if (theFlag == TEL_BACK_MATERIAL) + { + aFace = GL_BACK; + aSrcMat = &myAspectFaceSet->Aspect()->BackMaterial(); + aSrcIntColor = &myAspectFaceSet->Aspect()->BackInteriorColor(); + } + else if (myAspectFaceSet->Aspect()->Distinguish() + && !(NamedStatus & OPENGL_NS_RESMAT)) + { + aFace = GL_FRONT; + } + + myMatTmp.Init (*aSrcMat, *aSrcIntColor); + if (myToHighlight) + { + myMatTmp.SetColor (*HighlightColor); + } + + // handling transparency + if (NamedStatus & OPENGL_NS_2NDPASSDO) + { + // second pass + myMatTmp.Diffuse.a() = aSrcMat->EnvReflexion(); + } + else + { + if (aSrcMat->EnvReflexion() != 0.0f) + { + // if the material reflects the environment scene, the second pass is needed + NamedStatus |= OPENGL_NS_2NDPASSNEED; + } + + const float aTransp = (float )aSrcMat->Transparency(); + if (aTransp != 0.0f) + { + // render transparent + myMatTmp.Diffuse.a() = 1.0f - aTransp; + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + if (myUseDepthWrite) + { + glDepthMask (GL_FALSE); + } + } + else + { + // render opaque + glBlendFunc (GL_ONE, GL_ZERO); + glDisable (GL_BLEND); + if (myUseDepthWrite) + { + glDepthMask (GL_TRUE); + } + } + } + + // do not update material properties in case of zero reflection mode, + // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway. + if (myAspectFaceSet->IsNoLighting()) + { + return; + } + + // reset material + if (NamedStatus & OPENGL_NS_RESMAT) + { + #if !defined(GL_ES_VERSION_2_0) + if (myGlContext->core11 != NULL) + { + myGlContext->core11->glMaterialfv (aFace, GL_AMBIENT, myMatTmp.Ambient.GetData()); + myGlContext->core11->glMaterialfv (aFace, GL_DIFFUSE, myMatTmp.Diffuse.GetData()); + myGlContext->core11->glMaterialfv (aFace, GL_SPECULAR, myMatTmp.Specular.GetData()); + myGlContext->core11->glMaterialfv (aFace, GL_EMISSION, myMatTmp.Emission.GetData()); + myGlContext->core11->glMaterialf (aFace, GL_SHININESS, myMatTmp.Shine()); + } + #endif + + if (theFlag == TEL_FRONT_MATERIAL) + { + myMatFront = myMatTmp; + myMatBack = myMatTmp; + } + else + { + myMatBack = myMatTmp; + } + + NamedStatus &= ~OPENGL_NS_RESMAT; + return; + } + + // reduce updates + OpenGl_Material& anOld = (theFlag == TEL_FRONT_MATERIAL) + ? myMatFront + : myMatBack; +#if !defined(GL_ES_VERSION_2_0) + if (myGlContext->core11 != NULL) + { + if (myMatTmp.Ambient.r() != anOld.Ambient.r() + || myMatTmp.Ambient.g() != anOld.Ambient.g() + || myMatTmp.Ambient.b() != anOld.Ambient.b()) + { + myGlContext->core11->glMaterialfv (aFace, GL_AMBIENT, myMatTmp.Ambient.GetData()); + } + if (myMatTmp.Diffuse.r() != anOld.Diffuse.r() + || myMatTmp.Diffuse.g() != anOld.Diffuse.g() + || myMatTmp.Diffuse.b() != anOld.Diffuse.b() + || fabs (myMatTmp.Diffuse.a() - anOld.Diffuse.a()) > 0.01f) + { + myGlContext->core11->glMaterialfv (aFace, GL_DIFFUSE, myMatTmp.Diffuse.GetData()); + } + if (myMatTmp.Specular.r() != anOld.Specular.r() + || myMatTmp.Specular.g() != anOld.Specular.g() + || myMatTmp.Specular.b() != anOld.Specular.b()) + { + myGlContext->core11->glMaterialfv (aFace, GL_SPECULAR, myMatTmp.Specular.GetData()); + } + if (myMatTmp.Emission.r() != anOld.Emission.r() + || myMatTmp.Emission.g() != anOld.Emission.g() + || myMatTmp.Emission.b() != anOld.Emission.b()) + { + myGlContext->core11->glMaterialfv (aFace, GL_EMISSION, myMatTmp.Emission.GetData()); + } + if (myMatTmp.Shine() != anOld.Shine()) + { + myGlContext->core11->glMaterialf (aFace, GL_SHININESS, myMatTmp.Shine()); + } + } +#endif + anOld = myMatTmp; + if (aFace == GL_FRONT_AND_BACK) + { + myMatBack = myMatTmp; + } +} + +// ======================================================================= +// function : SetAspectLine +// purpose : +// ======================================================================= +const OpenGl_AspectLine* OpenGl_Workspace::SetAspectLine (const OpenGl_AspectLine* theAspect) +{ + const OpenGl_AspectLine* aPrevAspectLine = myAspectLineSet; + myAspectLineSet = theAspect; + return aPrevAspectLine; +} + +// ======================================================================= +// function : SetAspectFace +// purpose : +// ======================================================================= +const OpenGl_AspectFace * OpenGl_Workspace::SetAspectFace (const OpenGl_AspectFace* theAspect) +{ + const OpenGl_AspectFace* aPrevAspectFace = myAspectFaceSet; + myAspectFaceSet = theAspect; + return aPrevAspectFace; +} + +// ======================================================================= +// function : SetAspectMarker +// purpose : +// ======================================================================= +const OpenGl_AspectMarker* OpenGl_Workspace::SetAspectMarker (const OpenGl_AspectMarker* theAspect) +{ + const OpenGl_AspectMarker* aPrevAspectMarker = myAspectMarkerSet; + myAspectMarkerSet = theAspect; + return aPrevAspectMarker; +} + +// ======================================================================= +// function : SetAspectText +// purpose : +// ======================================================================= +const OpenGl_AspectText * OpenGl_Workspace::SetAspectText (const OpenGl_AspectText* theAspect) +{ + const OpenGl_AspectText* aPrevAspectText = myAspectTextSet; + myAspectTextSet = theAspect; + return aPrevAspectText; +} + +// ======================================================================= +// function : ApplyAspectFace +// purpose : +// ======================================================================= +const OpenGl_AspectFace* OpenGl_Workspace::ApplyAspectFace() +{ + if (myView->BackfacingModel() == Graphic3d_TOBM_AUTOMATIC) + { + // manage back face culling mode, disable culling when clipping is enabled + bool toSuppressBackFaces = myToAllowFaceCulling + && myAspectFaceSet->Aspect()->ToSuppressBackFaces(); + if (toSuppressBackFaces) + { + if (myGlContext->Clipping().IsClippingOrCappingOn() + || myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH) + { + toSuppressBackFaces = false; + } + } + if (toSuppressBackFaces) + { + if (!(NamedStatus & OPENGL_NS_2NDPASSDO) + && (float )myAspectFaceSet->Aspect()->FrontMaterial().Transparency() != 0.0f) + { + // disable culling in case of translucent shading aspect + toSuppressBackFaces = false; + } + } + myGlContext->SetCullBackFaces (toSuppressBackFaces); + } - // cache render mode state - GLint aRendMode = GL_RENDER; - glGetIntegerv (GL_RENDER_MODE, &aRendMode); - aGlCtx->SetFeedback (aRendMode == GL_FEEDBACK); + if (myAspectFaceSet->Aspect() == myAspectFaceApplied + && myToHighlight == myAspectFaceAppliedWithHL) + { + return myAspectFaceSet; + } + myAspectFaceAppliedWithHL = myToHighlight; - Tint toSwap = (aRendMode == GL_RENDER); // swap buffers - GLint aViewPortBack[4]; - OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO; - if (aFrameBuffer != NULL) +#if !defined(GL_ES_VERSION_2_0) + const Aspect_InteriorStyle anIntstyle = myAspectFaceSet->Aspect()->InteriorStyle(); + if (myAspectFaceApplied.IsNull() + || myAspectFaceApplied->InteriorStyle() != anIntstyle) { - glGetIntegerv (GL_VIEWPORT, aViewPortBack); - aFrameBuffer->SetupViewport (aGlCtx); - aFrameBuffer->BindBuffer (aGlCtx); - toSwap = 0; // no need to swap buffers + switch (anIntstyle) + { + case Aspect_IS_EMPTY: + case Aspect_IS_HOLLOW: + { + myGlContext->SetPolygonMode (GL_LINE); + break; + } + case Aspect_IS_HATCH: + { + myGlContext->SetPolygonMode (GL_FILL); + myGlContext->SetPolygonHatchEnabled (true); + break; + } + case Aspect_IS_SOLID: + case Aspect_IS_HIDDENLINE: + { + myGlContext->SetPolygonMode (GL_FILL); + myGlContext->SetPolygonHatchEnabled (false); + break; + } + case Aspect_IS_POINT: + { + myGlContext->SetPolygonMode (GL_POINT); + break; + } + } } -#ifdef HAVE_OPENCL - if (!theCView.IsRaytracing || myComputeInitStatus == OpenGl_CLIS_FAIL) + if (anIntstyle == Aspect_IS_HATCH) { + myGlContext->SetPolygonHatchStyle (myAspectFaceSet->Aspect()->HatchStyle()); + } #endif - Redraw1 (theCView, theCUnderLayer, theCOverLayer, toSwap); - if (aFrameBuffer == NULL || !myTransientDrawToFront) + + // Aspect_POM_None means: do not change current settings + if ((myAspectFaceSet->Aspect()->PolygonOffset().Mode & Aspect_POM_None) != Aspect_POM_None) + { + if (myPolygonOffsetApplied.Mode != myAspectFaceSet->Aspect()->PolygonOffset().Mode + || myPolygonOffsetApplied.Factor != myAspectFaceSet->Aspect()->PolygonOffset().Factor + || myPolygonOffsetApplied.Units != myAspectFaceSet->Aspect()->PolygonOffset().Units) + { + SetPolygonOffset (myAspectFaceSet->Aspect()->PolygonOffset()); + } + } + + updateMaterial (TEL_FRONT_MATERIAL); + if (myAspectFaceSet->Aspect()->Distinguish()) + { + updateMaterial (TEL_BACK_MATERIAL); + } + + if (myAspectFaceSet->Aspect()->ToMapTexture()) + { + EnableTexture (myAspectFaceSet->TextureRes (myGlContext), + myAspectFaceSet->TextureParams()); + } + else + { + if (!myEnvironmentTexture.IsNull()) + { + EnableTexture (myEnvironmentTexture, + myEnvironmentTexture->GetParams()); + } + else { - RedrawImmediatMode(); + DisableTexture(); } + } - theCView.WasRedrawnGL = Standard_True; -#ifdef HAVE_OPENCL + myAspectFaceApplied = myAspectFaceSet->Aspect(); + return myAspectFaceSet; +} + +//======================================================================= +//function : SetPolygonOffset +//purpose : +//======================================================================= +void OpenGl_Workspace::SetPolygonOffset (const Graphic3d_PolygonOffset& theParams) +{ + myPolygonOffsetApplied = theParams; + + if ((theParams.Mode & Aspect_POM_Fill) == Aspect_POM_Fill) + { + glEnable (GL_POLYGON_OFFSET_FILL); } else { - int aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth; - int aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight; + glDisable (GL_POLYGON_OFFSET_FILL); + } - Raytrace (theCView, aSizeX, aSizeY, toSwap); +#if !defined(GL_ES_VERSION_2_0) + if ((theParams.Mode & Aspect_POM_Line) == Aspect_POM_Line) + { + glEnable (GL_POLYGON_OFFSET_LINE); + } + else + { + glDisable (GL_POLYGON_OFFSET_LINE); + } - theCView.WasRedrawnGL = Standard_False; + if ((theParams.Mode & Aspect_POM_Point) == Aspect_POM_Point) + { + glEnable (GL_POLYGON_OFFSET_POINT); + } + else + { + glDisable (GL_POLYGON_OFFSET_POINT); } #endif + glPolygonOffset (theParams.Factor, theParams.Units); +} - if (aFrameBuffer != NULL) +// ======================================================================= +// function : ApplyAspectMarker +// purpose : +// ======================================================================= +const OpenGl_AspectMarker* OpenGl_Workspace::ApplyAspectMarker() +{ + if (myAspectMarkerSet->Aspect() != myAspectMarkerApplied) { - aFrameBuffer->UnbindBuffer (aGlCtx); - // move back original viewport - glViewport (aViewPortBack[0], aViewPortBack[1], aViewPortBack[2], aViewPortBack[3]); + if (myAspectMarkerApplied.IsNull() + || (myAspectMarkerSet->Aspect()->Scale() != myAspectMarkerApplied->Scale())) + { + #if !defined(GL_ES_VERSION_2_0) + glPointSize (myAspectMarkerSet->Aspect()->Scale()); + #ifdef HAVE_GL2PS + gl2psPointSize (myAspectMarkerSet->Aspect()->Scale()); + #endif + #endif + } + myAspectMarkerApplied = myAspectMarkerSet->Aspect(); } + return myAspectMarkerSet; +} -#if (defined(_WIN32) || defined(__WIN32__)) && defined(HAVE_VIDEOCAPTURE) - if (OpenGl_AVIWriter_AllowWriting (theCView.DefWindow.XWindow)) +// ======================================================================= +// function : Width +// purpose : +// ======================================================================= +Standard_Integer OpenGl_Workspace::Width() const +{ + return !myView->GlWindow().IsNull() ? myView->GlWindow()->Width() : 0; +} + +// ======================================================================= +// function : Height +// purpose : +// ======================================================================= +Standard_Integer OpenGl_Workspace::Height() const +{ + return !myView->GlWindow().IsNull() ? myView->GlWindow()->Height() : 0; +} + +// ======================================================================= +// function : UseGLLight +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_Workspace::UseGLLight() const +{ + return myView->IsGLLightEnabled(); +} + +// ======================================================================= +// function : IsCullingEnabled +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_Workspace::IsCullingEnabled() const +{ + return myView->IsCullingEnabled(); +} + +// ======================================================================= +// function : FBOCreate +// purpose : +// ======================================================================= +Handle(OpenGl_FrameBuffer) OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth, + const Standard_Integer theHeight) +{ + // activate OpenGL context + if (!Activate()) + return Handle(OpenGl_FrameBuffer)(); + + DisableTexture(); + + // create the FBO + const Handle(OpenGl_Context)& aCtx = GetGlContext(); + Handle(OpenGl_FrameBuffer) aFrameBuffer = new OpenGl_FrameBuffer(); + if (!aFrameBuffer->Init (aCtx, theWidth, theHeight, GL_RGBA8, GL_DEPTH24_STENCIL8, 0)) + { + aFrameBuffer->Release (aCtx.operator->()); + return Handle(OpenGl_FrameBuffer)(); + } + return aFrameBuffer; +} + +// ======================================================================= +// function : FBORelease +// purpose : +// ======================================================================= +void OpenGl_Workspace::FBORelease (Handle(OpenGl_FrameBuffer)& theFbo) +{ + // activate OpenGL context + if (!Activate() + || theFbo.IsNull()) { - GLint params[4]; - glGetIntegerv (GL_VIEWPORT, params); - int nWidth = params[2] & ~0x7; - int nHeight = params[3] & ~0x7; + return; + } - const int nBitsPerPixel = 24; - GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8]; + theFbo->Release (GetGlContext().operator->()); + theFbo.Nullify(); +} - glPixelStorei (GL_PACK_ALIGNMENT, 1); - glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData); - OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel); - delete[] aDumpData; +inline bool getDataFormat (const Image_PixMap& theData, + GLenum& thePixelFormat, + GLenum& theDataType) +{ + thePixelFormat = GL_RGB; + theDataType = GL_UNSIGNED_BYTE; + switch (theData.Format()) + { + #if !defined(GL_ES_VERSION_2_0) + case Image_PixMap::ImgGray: + thePixelFormat = GL_DEPTH_COMPONENT; + theDataType = GL_UNSIGNED_BYTE; + return true; + case Image_PixMap::ImgGrayF: + thePixelFormat = GL_DEPTH_COMPONENT; + theDataType = GL_FLOAT; + return true; + case Image_PixMap::ImgBGR: + thePixelFormat = GL_BGR; + theDataType = GL_UNSIGNED_BYTE; + return true; + case Image_PixMap::ImgBGRA: + case Image_PixMap::ImgBGR32: + thePixelFormat = GL_BGRA; + theDataType = GL_UNSIGNED_BYTE; + return true; + case Image_PixMap::ImgBGRF: + thePixelFormat = GL_BGR; + theDataType = GL_FLOAT; + return true; + case Image_PixMap::ImgBGRAF: + thePixelFormat = GL_BGRA; + theDataType = GL_FLOAT; + return true; + #else + case Image_PixMap::ImgGray: + case Image_PixMap::ImgGrayF: + case Image_PixMap::ImgBGR: + case Image_PixMap::ImgBGRA: + case Image_PixMap::ImgBGR32: + case Image_PixMap::ImgBGRF: + case Image_PixMap::ImgBGRAF: + return false; + #endif + case Image_PixMap::ImgRGB: + thePixelFormat = GL_RGB; + theDataType = GL_UNSIGNED_BYTE; + return true; + case Image_PixMap::ImgRGBA: + case Image_PixMap::ImgRGB32: + thePixelFormat = GL_RGBA; + theDataType = GL_UNSIGNED_BYTE; + return true; + case Image_PixMap::ImgRGBF: + thePixelFormat = GL_RGB; + theDataType = GL_FLOAT; + return true; + case Image_PixMap::ImgRGBAF: + thePixelFormat = GL_RGBA; + theDataType = GL_FLOAT; + return true; + case Image_PixMap::ImgAlpha: + case Image_PixMap::ImgAlphaF: + return false; // GL_ALPHA is no more supported in core context + case Image_PixMap::ImgUNKNOWN: + return false; } + return false; +} + +// ======================================================================= +// function : getAligned +// purpose : +// ======================================================================= +inline Standard_Size getAligned (const Standard_Size theNumber, + const Standard_Size theAlignment) +{ + return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment; +} + +// ======================================================================= +// function : BufferDump +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_Workspace::BufferDump (const Handle(OpenGl_FrameBuffer)& theFbo, + Image_PixMap& theImage, + const Graphic3d_BufferType& theBufferType) +{ + GLenum aFormat, aType; + if (theImage.IsEmpty() + || !getDataFormat (theImage, aFormat, aType) + || !Activate()) + { + return Standard_False; + } +#if !defined(GL_ES_VERSION_2_0) + GLint aReadBufferPrev = GL_BACK; + if (theBufferType == Graphic3d_BT_Depth + && aFormat != GL_DEPTH_COMPONENT) + { + return Standard_False; + } +#else + (void )theBufferType; #endif - // reset render mode state - aGlCtx->SetFeedback (Standard_False); + // bind FBO if used + if (!theFbo.IsNull() && theFbo->IsValid()) + { + theFbo->BindBuffer (GetGlContext()); + } + else + { + #if !defined(GL_ES_VERSION_2_0) + glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev); + GLint aDrawBufferPrev = GL_BACK; + glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev); + glReadBuffer (aDrawBufferPrev); + #endif + } + + // setup alignment + const GLint anAligment = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL + glPixelStorei (GL_PACK_ALIGNMENT, anAligment); + bool isBatchCopy = !theImage.IsTopDown(); + + const GLint anExtraBytes = GLint(theImage.RowExtraBytes()); + GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes()); + Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment); + if (anExtraBytes < anAligment) + { + aPixelsWidth = 0; + } + else if (aSizeRowBytesEstim != theImage.SizeRowBytes()) + { + aPixelsWidth = 0; + isBatchCopy = false; + } +#if !defined(GL_ES_VERSION_2_0) + glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth); +#else + if (aPixelsWidth != 0) + { + isBatchCopy = false; + } +#endif + + if (!isBatchCopy) + { + // copy row by row + for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow) + { + // Image_PixMap rows indexation always starts from the upper corner + // while order in memory depends on the flag and processed by ChangeRow() method + glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow)); + } + } + else + { + glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData()); + } + + glPixelStorei (GL_PACK_ALIGNMENT, 1); +#if !defined(GL_ES_VERSION_2_0) + glPixelStorei (GL_PACK_ROW_LENGTH, 0); +#endif + + if (!theFbo.IsNull() && theFbo->IsValid()) + { + theFbo->UnbindBuffer (GetGlContext()); + } + else + { + #if !defined(GL_ES_VERSION_2_0) + glReadBuffer (aReadBufferPrev); + #endif + } + return Standard_True; +} + +// ======================================================================= +// function : CanRender +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement) +{ + Standard_Boolean aPrevFilterResult = Standard_True; + if (!myPrevRenderFilter.IsNull()) + { + aPrevFilterResult = myPrevRenderFilter->CanRender (theElement); + } + return aPrevFilterResult && + !OpenGl_Raytrace::IsRaytracedElement (theElement); }