1 // Copyright (c) 2019 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #include <OpenGl_AspectsTextureSet.hxx>
16 #include <OpenGl_Context.hxx>
17 #include <OpenGl_PointSprite.hxx>
18 #include <OpenGl_TextureSet.hxx>
20 #include <Graphic3d_TextureParams.hxx>
24 static const TCollection_AsciiString THE_EMPTY_KEY;
27 // =======================================================================
30 // =======================================================================
31 void OpenGl_AspectsTextureSet::Release (OpenGl_Context* theCtx)
33 if (myTextures[0].IsNull())
38 if (!myTextures[1].IsNull())
40 // ReleaseResource() will have no effect until nullifying all copies
41 myTextures[1]->InitZero();
44 for (OpenGl_TextureSet::Iterator aTextureIter (myTextures[0]); aTextureIter.More(); aTextureIter.Next())
46 Handle(OpenGl_Texture)& aTextureRes = aTextureIter.ChangeValue();
47 if (aTextureRes.IsNull())
54 if (aTextureRes->ResourceId().IsEmpty())
56 theCtx->DelayedRelease (aTextureRes);
60 // OpenGl_PointSprite will be actually released later by OpenGl_AspectsSprite,
61 // see order OpenGl_Aspects::Release()
62 const TCollection_AsciiString aName = aTextureRes->ResourceId();
63 aTextureRes.Nullify(); // we need nullify all handles before ReleaseResource() call
64 theCtx->ReleaseResource (aName, Standard_True);
67 aTextureRes.Nullify();
69 myIsTextureReady = Standard_False;
72 // =======================================================================
73 // function : UpdateRediness
75 // =======================================================================
76 void OpenGl_AspectsTextureSet::UpdateRediness (const Handle(Graphic3d_Aspects)& theAspect)
78 const Handle(Graphic3d_TextureSet)& aNewTextureSet = theAspect->TextureSet();
80 const Standard_Integer aNbTexturesOld = !myTextures[0].IsNull() ? myTextures[0]->Size() : 0;
81 Standard_Integer aNbTexturesNew = !aNewTextureSet.IsNull() && theAspect->ToMapTexture()
82 ? aNewTextureSet->Size()
84 if (theAspect->IsMarkerSprite())
89 if (aNbTexturesOld != aNbTexturesNew)
91 myIsTextureReady = Standard_False;
94 if (aNbTexturesOld == 0
95 || !theAspect->ToMapTexture())
100 Graphic3d_TextureSet::Iterator aTextureIter (aNewTextureSet);
101 OpenGl_TextureSet::Iterator aResIter (myTextures[0]);
102 for (; aTextureIter.More(); aResIter.Next(), aTextureIter.Next())
104 const Handle(OpenGl_Texture)& aResource = aResIter.Value();
105 const Handle(Graphic3d_TextureMap)& aTexture = aTextureIter.Value();
106 if (aTexture.IsNull() != aResource.IsNull())
108 myIsTextureReady = Standard_False;
111 else if (aTexture.IsNull())
116 const TCollection_AsciiString& aTextureKey = aTexture->GetId();
117 if (aTextureKey.IsEmpty() || aResource->ResourceId() != aTextureKey)
119 myIsTextureReady = Standard_False;
122 else if (aResource->Revision() != aTexture->Revision())
124 myIsTextureReady = Standard_False;
129 // just invalidate texture parameters
130 aResource->Sampler()->SetParameters (aTexture->GetParams());
131 aResIter.ChangeUnit() = aResource->Sampler()->Parameters()->TextureUnit();
136 // =======================================================================
139 // =======================================================================
140 void OpenGl_AspectsTextureSet::build (const Handle(OpenGl_Context)& theCtx,
141 const Handle(Graphic3d_Aspects)& theAspect,
142 const Handle(OpenGl_PointSprite)& theSprite,
143 const Handle(OpenGl_PointSprite)& theSpriteA)
145 const Handle(Graphic3d_TextureSet)& aNewTextureSet = theAspect->TextureSet();
147 const bool hasSprite = theAspect->IsMarkerSprite();
148 const Standard_Integer aNbTexturesOld = !myTextures[0].IsNull() ? myTextures[0]->Size() : 0;
149 Standard_Integer aNbTexturesNew = !aNewTextureSet.IsNull() && theAspect->ToMapTexture()
150 ? aNewTextureSet->Size()
157 // release old texture resources
158 if (aNbTexturesOld != aNbTexturesNew)
160 Release (theCtx.get());
161 if (aNbTexturesNew > 0)
163 myTextures[0] = new OpenGl_TextureSet (aNbTexturesNew);
167 myTextures[0].Nullify();
168 myTextures[1].Nullify();
171 if (myTextures[0].IsNull())
176 if (theSprite == theSpriteA)
178 myTextures[1].Nullify();
182 if (myTextures[1].IsNull()
183 || myTextures[1]->Size() != myTextures[0]->Size())
185 myTextures[1] = new OpenGl_TextureSet (aNbTexturesNew);
189 myTextures[1]->InitZero();
193 Standard_Integer& aTextureSetBits = myTextures[0]->ChangeTextureSetBits();
194 aTextureSetBits = Graphic3d_TextureSetBits_NONE;
195 Standard_Integer aPrevTextureUnit = -1;
196 if (theAspect->ToMapTexture())
198 Graphic3d_TextureSet::Iterator aTextureIter (aNewTextureSet);
199 OpenGl_TextureSet::Iterator aResIter0 (myTextures[0]);
200 for (; aTextureIter.More(); aResIter0.Next(), aTextureIter.Next())
202 Handle(OpenGl_Texture)& aResource = aResIter0.ChangeValue();
203 const Handle(Graphic3d_TextureMap)& aTexture = aTextureIter.Value();
204 if (!aResource.IsNull())
206 if (!aTexture.IsNull()
207 && aTexture->GetId() == aResource->ResourceId()
208 && aTexture->Revision() != aResource->Revision())
210 if (aResource->Init(theCtx, aTexture))
212 aResIter0.ChangeUnit() = aResource->Sampler()->Parameters()->TextureUnit();
213 if (aResIter0.Unit() < aPrevTextureUnit)
215 throw Standard_ProgramError("Graphic3d_TextureMap defines texture units in non-ascending order");
217 aPrevTextureUnit = aResIter0.Unit();
218 aResource->Sampler()->SetParameters(aTexture->GetParams());
219 aResource->SetRevision (aTexture->Revision());
223 if (aResource->ResourceId().IsEmpty())
225 theCtx->DelayedRelease (aResource);
230 const TCollection_AsciiString aTextureKey = aResource->ResourceId();
231 aResource.Nullify(); // we need nullify all handles before ReleaseResource() call
232 theCtx->ReleaseResource (aTextureKey, Standard_True);
236 if (!aTexture.IsNull())
238 const TCollection_AsciiString& aTextureKeyNew = aTexture->GetId();
239 if (aTextureKeyNew.IsEmpty()
240 || !theCtx->GetResource<Handle(OpenGl_Texture)> (aTextureKeyNew, aResource))
242 aResource = new OpenGl_Texture (aTextureKeyNew, aTexture->GetParams());
244 if (aResource->Init(theCtx, aTexture))
246 aResource->SetRevision (aTexture->Revision());
248 if (!aTextureKeyNew.IsEmpty())
250 theCtx->ShareResource (aTextureKeyNew, aResource);
255 if (aTexture->Revision() != aResource->Revision())
257 if (aResource->Init(theCtx, aTexture))
259 aResource->SetRevision (aTexture->Revision());
262 aResource->Sampler()->SetParameters (aTexture->GetParams());
265 // update occupation of texture units
266 const Graphic3d_TextureUnit aTexUnit = aResource->Sampler()->Parameters()->TextureUnit();
267 aResIter0.ChangeUnit() = aTexUnit;
268 if (aResIter0.Unit() < aPrevTextureUnit)
270 throw Standard_ProgramError("Graphic3d_TextureMap defines texture units in non-ascending order");
272 aPrevTextureUnit = aResIter0.Unit();
273 if (aTexUnit >= Graphic3d_TextureUnit_0 && aTexUnit <= Graphic3d_TextureUnit_5)
275 aTextureSetBits |= (1 << int(aTexUnit));
283 myTextures[0]->ChangeLast() = theSprite;
284 myTextures[0]->ChangeLastUnit() = theCtx->SpriteTextureUnit();
285 // Graphic3d_TextureUnit_PointSprite
286 if (!theSprite.IsNull())
288 theSprite ->Sampler()->Parameters()->SetTextureUnit (theCtx->SpriteTextureUnit());
290 if (!theSpriteA.IsNull())
292 theSpriteA->Sampler()->Parameters()->SetTextureUnit (theCtx->SpriteTextureUnit());
295 if (myTextures[1].IsNull())
300 myTextures[1]->ChangeTextureSetBits() = aTextureSetBits;
301 for (OpenGl_TextureSet::Iterator aResIter0 (myTextures[0]), aResIter1 (myTextures[1]); aResIter0.More(); aResIter0.Next(), aResIter1.Next())
303 aResIter1.ChangeValue() = aResIter0.Value();
304 aResIter1.ChangeUnit() = aResIter0.Unit();
308 myTextures[1]->ChangeLast() = theSpriteA;
309 myTextures[1]->ChangeLastUnit() = theCtx->SpriteTextureUnit();