From: kgv Date: Sun, 16 Feb 2020 12:04:17 +0000 (+0300) Subject: 0031315: Visualization - marker texture is lost after multi-textured object X-Git-Tag: V7_5_0_beta~273 X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff_plain;h=d850414af1f2f72ea7bac6856c6fd984c0d3c92b 0031315: Visualization - marker texture is lost after multi-textured object OpenGl_Context::BindTextures() now iterates over pair of texture sets considering inconsistent texture unit ranges. --- diff --git a/src/Graphic3d/Graphic3d_TextureSet.hxx b/src/Graphic3d/Graphic3d_TextureSet.hxx index 7b0d5bc5dc..0f554ac233 100644 --- a/src/Graphic3d/Graphic3d_TextureSet.hxx +++ b/src/Graphic3d/Graphic3d_TextureSet.hxx @@ -18,6 +18,7 @@ #include //! Class holding array of textures to be mapped as a set. +//! Textures should be defined in ascending order of texture units within the set. class Graphic3d_TextureSet : public Standard_Transient { DEFINE_STANDARD_RTTIEXT(Graphic3d_TextureSet, Standard_Transient) diff --git a/src/OpenGl/FILES b/src/OpenGl/FILES index bc44d75e51..c170d39f5e 100755 --- a/src/OpenGl/FILES +++ b/src/OpenGl/FILES @@ -56,6 +56,7 @@ OpenGl_TextureFormat.cxx OpenGl_TextureFormat.hxx OpenGl_TextureSet.cxx OpenGl_TextureSet.hxx +OpenGl_TextureSetPairIterator.hxx OpenGl_Resource.hxx OpenGl_Resource.cxx OpenGl_NamedResource.hxx diff --git a/src/OpenGl/OpenGl_AspectsTextureSet.cxx b/src/OpenGl/OpenGl_AspectsTextureSet.cxx index 150361b30d..e1876f2c9b 100644 --- a/src/OpenGl/OpenGl_AspectsTextureSet.cxx +++ b/src/OpenGl/OpenGl_AspectsTextureSet.cxx @@ -195,6 +195,7 @@ void OpenGl_AspectsTextureSet::build (const Handle(OpenGl_Context)& theCtx, Standard_Integer& aTextureSetBits = myTextures[0]->ChangeTextureSetBits(); aTextureSetBits = Graphic3d_TextureSetBits_NONE; + Standard_Integer aPrevTextureUnit = -1; if (theAspect->ToMapTexture()) { Graphic3d_TextureSet::Iterator aTextureIter (aNewTextureSet); @@ -212,6 +213,11 @@ void OpenGl_AspectsTextureSet::build (const Handle(OpenGl_Context)& theCtx, if (aResource->Init(theCtx, aTexture)) { aResIter0.ChangeUnit() = aResource->Sampler()->Parameters()->TextureUnit(); + if (aResIter0.Unit() < aPrevTextureUnit) + { + throw Standard_ProgramError("Graphic3d_TextureMap defines texture units in non-ascending order"); + } + aPrevTextureUnit = aResIter0.Unit(); aResource->Sampler()->SetParameters(aTexture->GetParams()); aResource->SetRevision (aTexture->Revision()); } @@ -262,6 +268,11 @@ void OpenGl_AspectsTextureSet::build (const Handle(OpenGl_Context)& theCtx, // update occupation of texture units const Graphic3d_TextureUnit aTexUnit = aResource->Sampler()->Parameters()->TextureUnit(); aResIter0.ChangeUnit() = aTexUnit; + if (aResIter0.Unit() < aPrevTextureUnit) + { + throw Standard_ProgramError("Graphic3d_TextureMap defines texture units in non-ascending order"); + } + aPrevTextureUnit = aResIter0.Unit(); if (aTexUnit >= Graphic3d_TextureUnit_0 && aTexUnit <= Graphic3d_TextureUnit_5) { aTextureSetBits |= (1 << int(aTexUnit)); diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index c2818ed519..86b763bf78 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -3428,93 +3429,56 @@ Handle(OpenGl_TextureSet) OpenGl_Context::BindTextures (const Handle(OpenGl_Text if (myActiveTextures != theTextures) { Handle(OpenGl_Context) aThisCtx (this); - OpenGl_TextureSet::Iterator aTextureIterOld (myActiveTextures), aTextureIterNew (theTextures); - for (;;) + for (OpenGl_TextureSetPairIterator aSlotIter (myActiveTextures, theTextures); aSlotIter.More(); aSlotIter.Next()) { - if (!aTextureIterNew.More()) + const Graphic3d_TextureUnit aTexUnit = aSlotIter.Unit(); + const OpenGl_Texture* aTextureOld = aSlotIter.Texture1(); + const OpenGl_Texture* aTextureNew = aSlotIter.Texture2(); + if (aTextureNew == aTextureOld) { - for (; aTextureIterOld.More(); aTextureIterOld.Next()) - { - if (const Handle(OpenGl_Texture)& aTextureOld = aTextureIterOld.Value()) - { - aTextureOld->Unbind (aThisCtx, aTextureIterOld.Unit()); - #if !defined(GL_ES_VERSION_2_0) - if (core11 != NULL) - { - OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters()); - } - #endif - } - } - break; + continue; } - const Handle(OpenGl_Texture)& aTextureNew = aTextureIterNew.Value(); - if (aTextureIterOld.More()) + if (aTextureNew != NULL + && aTextureNew->IsValid()) { - const Handle(OpenGl_Texture)& aTextureOld = aTextureIterOld.Value(); - if (aTextureNew == aTextureOld - && aTextureIterNew.Unit() == aTextureIterOld.Unit()) + if (aTexUnit >= myMaxTexCombined) { - aTextureIterNew.Next(); - aTextureIterOld.Next(); + PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString("Texture unit ") + aTexUnit + " for " + aTextureNew->ResourceId() + " exceeds hardware limit " + myMaxTexCombined); continue; } - else if (aTextureNew.IsNull() - || !aTextureNew->IsValid()) + + aTextureNew->Bind (aThisCtx, aTexUnit); + if (aTextureNew->Sampler()->ToUpdateParameters()) { - if (!aTextureOld.IsNull()) + if (aTextureNew->Sampler()->IsImmutable()) { - aTextureOld->Unbind (aThisCtx, aTextureIterOld.Unit()); - #if !defined(GL_ES_VERSION_2_0) - if (core11 != NULL) - { - OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters()); - } - #endif + aTextureNew->Sampler()->Init (aThisCtx, *aTextureNew); + } + else + { + OpenGl_Sampler::applySamplerParams (aThisCtx, aTextureNew->Sampler()->Parameters(), aTextureNew->Sampler().get(), aTextureNew->GetTarget(), aTextureNew->HasMipmaps()); } - - aTextureIterNew.Next(); - aTextureIterOld.Next(); - continue; - } - - aTextureIterOld.Next(); - } - if (aTextureNew.IsNull()) - { - aTextureIterNew.Next(); - continue; - } - - const Graphic3d_TextureUnit aTexUnit = aTextureIterNew.Unit(); - if (aTexUnit >= myMaxTexCombined) - { - PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, - TCollection_AsciiString("Texture unit ") + aTexUnit + " for " + aTextureNew->ResourceId() + " exceeds hardware limit " + myMaxTexCombined); - aTextureIterNew.Next(); - continue; - } - - aTextureNew->Bind (aThisCtx, aTexUnit); - if (aTextureNew->Sampler()->ToUpdateParameters()) - { - if (aTextureNew->Sampler()->IsImmutable()) - { - aTextureNew->Sampler()->Init (aThisCtx, *aTextureNew); } - else + #if !defined(GL_ES_VERSION_2_0) + if (core11 != NULL) { - OpenGl_Sampler::applySamplerParams (aThisCtx, aTextureNew->Sampler()->Parameters(), aTextureNew->Sampler().get(), aTextureNew->GetTarget(), aTextureNew->HasMipmaps()); + OpenGl_Sampler::applyGlobalTextureParams (aThisCtx, *aTextureNew, aTextureNew->Sampler()->Parameters()); } + #endif } - #if !defined(GL_ES_VERSION_2_0) - if (core11 != NULL) + else if (aTextureOld != NULL + && aTextureOld->IsValid()) { - OpenGl_Sampler::applyGlobalTextureParams (aThisCtx, *aTextureNew, aTextureNew->Sampler()->Parameters()); + aTextureOld->Unbind (aThisCtx, aTexUnit); + #if !defined(GL_ES_VERSION_2_0) + if (core11 != NULL) + { + OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters()); + } + #endif } - #endif - aTextureIterNew.Next(); } myActiveTextures = theTextures; } diff --git a/src/OpenGl/OpenGl_TextureSet.hxx b/src/OpenGl/OpenGl_TextureSet.hxx index e2ce50c5af..b22c1d0b99 100644 --- a/src/OpenGl/OpenGl_TextureSet.hxx +++ b/src/OpenGl/OpenGl_TextureSet.hxx @@ -20,6 +20,7 @@ class OpenGl_Texture; //! Class holding array of textures to be mapped as a set. +//! Textures should be defined in ascending order of texture units within the set. class OpenGl_TextureSet : public Standard_Transient { DEFINE_STANDARD_RTTIEXT(OpenGl_TextureSet, Standard_Transient) @@ -99,12 +100,18 @@ public: //! Return the first texture. Handle(OpenGl_Texture)& ChangeFirst() { return myTextures.ChangeFirst().Texture; } + //! Return the first texture unit. + Graphic3d_TextureUnit FirstUnit() const { return myTextures.First().Unit; } + //! Return the last texture. const Handle(OpenGl_Texture)& Last() const { return myTextures.Last().Texture; } //! Return the last texture. Handle(OpenGl_Texture)& ChangeLast() { return myTextures.ChangeLast().Texture; } + //! Return the last texture unit. + Graphic3d_TextureUnit LastUnit() const { return myTextures.Last().Unit; } + //! Return the last texture unit. Graphic3d_TextureUnit& ChangeLastUnit() { return myTextures.ChangeLast().Unit; } diff --git a/src/OpenGl/OpenGl_TextureSetPairIterator.hxx b/src/OpenGl/OpenGl_TextureSetPairIterator.hxx new file mode 100644 index 0000000000..8cc10b6b5c --- /dev/null +++ b/src/OpenGl/OpenGl_TextureSetPairIterator.hxx @@ -0,0 +1,104 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// 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 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. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _OpenGl_TextureSetPairIterator_Header +#define _OpenGl_TextureSetPairIterator_Header + +#include + +//! Class for iterating pair of texture sets through each defined texture slot. +//! Note that iterator considers texture slots being in ascending order within OpenGl_TextureSet. +class OpenGl_TextureSetPairIterator +{ +public: + + //! Constructor. + OpenGl_TextureSetPairIterator (const Handle(OpenGl_TextureSet)& theSet1, + const Handle(OpenGl_TextureSet)& theSet2) + : myIter1 (theSet1), + myIter2 (theSet2), + myTexture1 (NULL), + myTexture2 (NULL), + myUnitLower (IntegerLast()), + myUnitUpper (IntegerFirst()), + myUnitCurrent (0) + { + if (!theSet1.IsNull() + && !theSet1->IsEmpty()) + { + myUnitLower = Min (myUnitLower, theSet1->FirstUnit()); + myUnitUpper = Max (myUnitUpper, theSet1->LastUnit()); + } + if (!theSet2.IsNull() + && !theSet2->IsEmpty()) + { + myUnitLower = Min (myUnitLower, theSet2->FirstUnit()); + myUnitUpper = Max (myUnitUpper, theSet2->LastUnit()); + } + myUnitCurrent = myUnitLower; + myTexture1 = (myIter1.More() && myIter1.Unit() == myUnitCurrent) + ? myIter1.ChangeValue().get() + : NULL; + myTexture2 = (myIter2.More() && myIter2.Unit() == myUnitCurrent) + ? myIter2.ChangeValue().get() + : NULL; + } + + //! Return TRUE if there are more texture units to pass through. + bool More() const { return myUnitCurrent <= myUnitUpper; } + + //! Return current texture unit. + Graphic3d_TextureUnit Unit() const { return (Graphic3d_TextureUnit )myUnitCurrent; } + + //! Access texture from first texture set. + const OpenGl_Texture* Texture1() const { return myTexture1; } + + //! Access texture from second texture set. + const OpenGl_Texture* Texture2() const { return myTexture2; } + + //! Move iterator position to the next pair. + void Next() + { + ++myUnitCurrent; + myTexture1 = myTexture2 = NULL; + for (; myIter1.More(); myIter1.Next()) + { + if (myIter1.Unit() >= myUnitCurrent) + { + myTexture1 = myIter1.Unit() == myUnitCurrent ? myIter1.ChangeValue().get() : NULL; + break; + } + } + for (; myIter2.More(); myIter2.Next()) + { + if (myIter2.Unit() >= myUnitCurrent) + { + myTexture2 = myIter2.Unit() == myUnitCurrent ? myIter2.ChangeValue().get() : NULL; + break; + } + } + } + +private: + + OpenGl_TextureSet::Iterator myIter1; + OpenGl_TextureSet::Iterator myIter2; + OpenGl_Texture* myTexture1; + OpenGl_Texture* myTexture2; + Standard_Integer myUnitLower; + Standard_Integer myUnitUpper; + Standard_Integer myUnitCurrent; + +}; + +#endif //_OpenGl_TextureSetPairIterator_Header diff --git a/tests/bugs/vis/bug31315 b/tests/bugs/vis/bug31315 new file mode 100644 index 0000000000..7bb2274a4d --- /dev/null +++ b/tests/bugs/vis/bug31315 @@ -0,0 +1,16 @@ +puts "=============" +puts "0031315: Visualization - marker texture is lost after multi-textured object" +puts "=============" + +pload MODELING VISUALIZATION +vclear +vinit View1 +box b 1 2 3 +vdisplay -dispMode 1 -highMode 1 b +vtexture b -tex0 3 -tex1 4 +vfit +vpoint p0 -1 0 0 +vaspects p0 -setMarkerSize 5 +if { [vreadpixel 15 310 -rgb -name] != "BLACK" } { puts "Error: Black color is expected" } + +vdump ${imagedir}/${casename}.png