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_Sampler.hxx>
18 #include <OpenGl_PointSprite.hxx>
19 #include <OpenGl_TextureSet.hxx>
21 #include <Graphic3d_TextureParams.hxx>
23 #include <Image_PixMap.hxx>
27 static const TCollection_AsciiString THE_EMPTY_KEY;
30 // =======================================================================
33 // =======================================================================
34 void OpenGl_AspectsTextureSet::Release (OpenGl_Context* theCtx)
36 if (myTextures[0].IsNull())
41 if (!myTextures[1].IsNull())
43 // ReleaseResource() will have no effect until nullifying all copies
44 myTextures[1]->InitZero();
47 for (OpenGl_TextureSet::Iterator aTextureIter (myTextures[0]); aTextureIter.More(); aTextureIter.Next())
49 Handle(OpenGl_Texture)& aTextureRes = aTextureIter.ChangeValue();
50 if (aTextureRes.IsNull())
57 if (aTextureRes->ResourceId().IsEmpty())
59 theCtx->DelayedRelease (aTextureRes);
63 // OpenGl_PointSprite will be actually released later by OpenGl_AspectsSprite,
64 // see order OpenGl_Aspects::Release()
65 const TCollection_AsciiString aName = aTextureRes->ResourceId();
66 aTextureRes.Nullify(); // we need nullify all handles before ReleaseResource() call
67 theCtx->ReleaseResource (aName, Standard_True);
70 aTextureRes.Nullify();
72 myIsTextureReady = Standard_False;
75 // =======================================================================
76 // function : UpdateRediness
78 // =======================================================================
79 void OpenGl_AspectsTextureSet::UpdateRediness (const Handle(Graphic3d_Aspects)& theAspect)
81 const Handle(Graphic3d_TextureSet)& aNewTextureSet = theAspect->TextureSet();
83 const Standard_Integer aNbTexturesOld = !myTextures[0].IsNull() ? myTextures[0]->Size() : 0;
84 Standard_Integer aNbTexturesNew = !aNewTextureSet.IsNull() && theAspect->ToMapTexture()
85 ? aNewTextureSet->Size()
87 if (theAspect->IsMarkerSprite())
92 if (aNbTexturesOld != aNbTexturesNew)
94 myIsTextureReady = Standard_False;
97 if (aNbTexturesOld == 0
98 || !theAspect->ToMapTexture())
103 Graphic3d_TextureSet::Iterator aTextureIter (aNewTextureSet);
104 OpenGl_TextureSet::Iterator aResIter (myTextures[0]);
105 for (; aTextureIter.More(); aResIter.Next(), aTextureIter.Next())
107 const Handle(OpenGl_Texture)& aResource = aResIter.Value();
108 const Handle(Graphic3d_TextureMap)& aTexture = aTextureIter.Value();
109 if (aTexture.IsNull() != aResource.IsNull())
111 myIsTextureReady = Standard_False;
114 else if (aTexture.IsNull())
119 const TCollection_AsciiString& aTextureKey = aTexture->GetId();
120 if (aTextureKey.IsEmpty() || aResource->ResourceId() != aTextureKey)
122 myIsTextureReady = Standard_False;
125 else if (aResource->Revision() != aTexture->Revision())
127 myIsTextureReady = Standard_False;
132 // just invalidate texture parameters
133 aResource->Sampler()->SetParameters (aTexture->GetParams());
134 aResIter.ChangeUnit() = aResource->Sampler()->Parameters()->TextureUnit();
139 // =======================================================================
142 // =======================================================================
143 void OpenGl_AspectsTextureSet::build (const Handle(OpenGl_Context)& theCtx,
144 const Handle(Graphic3d_Aspects)& theAspect,
145 const Handle(OpenGl_PointSprite)& theSprite,
146 const Handle(OpenGl_PointSprite)& theSpriteA)
148 const Handle(Graphic3d_TextureSet)& aNewTextureSet = theAspect->TextureSet();
150 const bool hasSprite = theAspect->IsMarkerSprite();
151 const Standard_Integer aNbTexturesOld = !myTextures[0].IsNull() ? myTextures[0]->Size() : 0;
152 Standard_Integer aNbTexturesNew = !aNewTextureSet.IsNull() && theAspect->ToMapTexture()
153 ? aNewTextureSet->Size()
160 // release old texture resources
161 if (aNbTexturesOld != aNbTexturesNew)
163 Release (theCtx.get());
164 if (aNbTexturesNew > 0)
166 myTextures[0] = new OpenGl_TextureSet (aNbTexturesNew);
170 myTextures[0].Nullify();
171 myTextures[1].Nullify();
174 if (myTextures[0].IsNull())
179 if (theSprite == theSpriteA)
181 myTextures[1].Nullify();
185 if (myTextures[1].IsNull()
186 || myTextures[1]->Size() != myTextures[0]->Size())
188 myTextures[1] = new OpenGl_TextureSet (aNbTexturesNew);
192 myTextures[1]->InitZero();
196 Standard_Integer& aTextureSetBits = myTextures[0]->ChangeTextureSetBits();
197 aTextureSetBits = Graphic3d_TextureSetBits_NONE;
198 Standard_Integer aPrevTextureUnit = -1;
199 if (theAspect->ToMapTexture())
201 Graphic3d_TextureSet::Iterator aTextureIter (aNewTextureSet);
202 OpenGl_TextureSet::Iterator aResIter0 (myTextures[0]);
203 for (; aTextureIter.More(); aResIter0.Next(), aTextureIter.Next())
205 Handle(OpenGl_Texture)& aResource = aResIter0.ChangeValue();
206 const Handle(Graphic3d_TextureMap)& aTexture = aTextureIter.Value();
207 if (!aResource.IsNull())
209 if (!aTexture.IsNull()
210 && aTexture->GetId() == aResource->ResourceId()
211 && aTexture->Revision() != aResource->Revision())
213 if (aResource->Init(theCtx, aTexture))
215 aResIter0.ChangeUnit() = aResource->Sampler()->Parameters()->TextureUnit();
216 if (aResIter0.Unit() < aPrevTextureUnit)
218 throw Standard_ProgramError("Graphic3d_TextureMap defines texture units in non-ascending order");
220 aPrevTextureUnit = aResIter0.Unit();
221 aResource->Sampler()->SetParameters(aTexture->GetParams());
222 aResource->SetRevision (aTexture->Revision());
226 if (aResource->ResourceId().IsEmpty())
228 theCtx->DelayedRelease (aResource);
233 const TCollection_AsciiString aTextureKey = aResource->ResourceId();
234 aResource.Nullify(); // we need nullify all handles before ReleaseResource() call
235 theCtx->ReleaseResource (aTextureKey, Standard_True);
239 if (!aTexture.IsNull())
241 const TCollection_AsciiString& aTextureKeyNew = aTexture->GetId();
242 if (aTextureKeyNew.IsEmpty()
243 || !theCtx->GetResource<Handle(OpenGl_Texture)> (aTextureKeyNew, aResource))
245 aResource = new OpenGl_Texture (aTextureKeyNew, aTexture->GetParams());
247 if (aResource->Init(theCtx, aTexture))
249 aResource->SetRevision (aTexture->Revision());
251 if (!aTextureKeyNew.IsEmpty())
253 theCtx->ShareResource (aTextureKeyNew, aResource);
258 if (aTexture->Revision() != aResource->Revision())
260 if (aResource->Init(theCtx, aTexture))
262 aResource->SetRevision (aTexture->Revision());
265 aResource->Sampler()->SetParameters (aTexture->GetParams());
268 // update occupation of texture units
269 const Graphic3d_TextureUnit aTexUnit = aResource->Sampler()->Parameters()->TextureUnit();
270 aResIter0.ChangeUnit() = aTexUnit;
271 if (aResIter0.Unit() < aPrevTextureUnit)
273 throw Standard_ProgramError("Graphic3d_TextureMap defines texture units in non-ascending order");
275 aPrevTextureUnit = aResIter0.Unit();
276 if (aTexUnit >= Graphic3d_TextureUnit_0 && aTexUnit <= Graphic3d_TextureUnit_5)
278 aTextureSetBits |= (1 << int(aTexUnit));
286 myTextures[0]->ChangeLast() = theSprite;
287 myTextures[0]->ChangeLastUnit() = theCtx->SpriteTextureUnit();
288 // Graphic3d_TextureUnit_PointSprite
289 if (!theSprite.IsNull())
291 theSprite ->Sampler()->Parameters()->SetTextureUnit (theCtx->SpriteTextureUnit());
293 if (!theSpriteA.IsNull())
295 theSpriteA->Sampler()->Parameters()->SetTextureUnit (theCtx->SpriteTextureUnit());
298 if (myTextures[1].IsNull())
303 myTextures[1]->ChangeTextureSetBits() = aTextureSetBits;
304 for (OpenGl_TextureSet::Iterator aResIter0 (myTextures[0]), aResIter1 (myTextures[1]); aResIter0.More(); aResIter0.Next(), aResIter1.Next())
306 aResIter1.ChangeValue() = aResIter0.Value();
307 aResIter1.ChangeUnit() = aResIter0.Unit();
311 myTextures[1]->ChangeLast() = theSpriteA;
312 myTextures[1]->ChangeLastUnit() = theCtx->SpriteTextureUnit();