0030748: Visualization - Marker displayed in immediate layer ruins QT Quick view...
[occt.git] / src / OpenGl / OpenGl_AspectsTextureSet.cxx
1 // Copyright (c) 2019 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
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.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <OpenGl_AspectsTextureSet.hxx>
15
16 #include <OpenGl_Context.hxx>
17 #include <OpenGl_Sampler.hxx>
18 #include <OpenGl_PointSprite.hxx>
19 #include <OpenGl_TextureSet.hxx>
20
21 #include <Graphic3d_TextureParams.hxx>
22
23 #include <Image_PixMap.hxx>
24
25 namespace
26 {
27   static const TCollection_AsciiString THE_EMPTY_KEY;
28 }
29
30 // =======================================================================
31 // function : Release
32 // purpose  :
33 // =======================================================================
34 void OpenGl_AspectsTextureSet::Release (OpenGl_Context* theCtx)
35 {
36   if (myTextures[0].IsNull())
37   {
38     return;
39   }
40
41   if (!myTextures[1].IsNull())
42   {
43     // ReleaseResource() will have no effect until nullifying all copies
44     myTextures[1]->InitZero();
45   }
46
47   for (OpenGl_TextureSet::Iterator aTextureIter (myTextures[0]); aTextureIter.More(); aTextureIter.Next())
48   {
49     Handle(OpenGl_Texture)& aTextureRes = aTextureIter.ChangeValue();
50     if (aTextureRes.IsNull())
51     {
52       continue;
53     }
54
55     if (theCtx != NULL)
56     {
57       if (aTextureRes->ResourceId().IsEmpty())
58       {
59         theCtx->DelayedRelease (aTextureRes);
60       }
61       else
62       {
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);
68       }
69     }
70     aTextureRes.Nullify();
71   }
72   myIsTextureReady = Standard_False;
73 }
74
75 // =======================================================================
76 // function : UpdateRediness
77 // purpose  :
78 // =======================================================================
79 void OpenGl_AspectsTextureSet::UpdateRediness (const Handle(Graphic3d_Aspects)& theAspect)
80 {
81   const Handle(Graphic3d_TextureSet)& aNewTextureSet = theAspect->TextureSet();
82
83   const Standard_Integer aNbTexturesOld = !myTextures[0].IsNull() ? myTextures[0]->Size() : 0;
84   Standard_Integer aNbTexturesNew = !aNewTextureSet.IsNull() && theAspect->ToMapTexture()
85                                    ? aNewTextureSet->Size()
86                                    : 0;
87   if (theAspect->IsMarkerSprite())
88   {
89     ++aNbTexturesNew;
90   }
91
92   if (aNbTexturesOld != aNbTexturesNew)
93   {
94     myIsTextureReady = Standard_False;
95     return;
96   }
97   if (aNbTexturesOld == 0
98   || !theAspect->ToMapTexture())
99   {
100     return;
101   }
102
103   Graphic3d_TextureSet::Iterator aTextureIter (aNewTextureSet);
104   OpenGl_TextureSet::Iterator aResIter (myTextures[0]);
105   for (; aTextureIter.More(); aResIter.Next(), aTextureIter.Next())
106   {
107     const Handle(OpenGl_Texture)&       aResource = aResIter.Value();
108     const Handle(Graphic3d_TextureMap)& aTexture  = aTextureIter.Value();
109     if (aTexture.IsNull() != aResource.IsNull())
110     {
111       myIsTextureReady = Standard_False;
112       return;
113     }
114     else if (aTexture.IsNull())
115     {
116       continue;
117     }
118
119     const TCollection_AsciiString& aTextureKey = aTexture->GetId();
120     if (aTextureKey.IsEmpty() || aResource->ResourceId() != aTextureKey)
121     {
122       myIsTextureReady = Standard_False;
123       return;
124     }
125     else if (aResource->Revision() != aTexture->Revision())
126     {
127       myIsTextureReady = Standard_False;
128       return;
129     }
130     else
131     {
132       // just invalidate texture parameters
133       aResource->Sampler()->SetParameters (aTexture->GetParams());
134     }
135   }
136 }
137
138 // =======================================================================
139 // function : build
140 // purpose  :
141 // =======================================================================
142 void OpenGl_AspectsTextureSet::build (const Handle(OpenGl_Context)& theCtx,
143                                       const Handle(Graphic3d_Aspects)& theAspect,
144                                       const Handle(OpenGl_PointSprite)& theSprite,
145                                       const Handle(OpenGl_PointSprite)& theSpriteA)
146 {
147   const Handle(Graphic3d_TextureSet)& aNewTextureSet = theAspect->TextureSet();
148
149   const bool hasSprite = theAspect->IsMarkerSprite();
150   const Standard_Integer aNbTexturesOld = !myTextures[0].IsNull() ? myTextures[0]->Size() : 0;
151   Standard_Integer aNbTexturesNew = !aNewTextureSet.IsNull() && theAspect->ToMapTexture()
152                                   ? aNewTextureSet->Size()
153                                   : 0;
154   if (hasSprite)
155   {
156     ++aNbTexturesNew;
157   }
158
159   // release old texture resources
160   if (aNbTexturesOld != aNbTexturesNew)
161   {
162     Release (theCtx.get());
163     if (aNbTexturesNew > 0)
164     {
165       myTextures[0] = new OpenGl_TextureSet (aNbTexturesNew);
166     }
167     else
168     {
169       myTextures[0].Nullify();
170       myTextures[1].Nullify();
171     }
172   }
173   if (myTextures[0].IsNull())
174   {
175     return;
176   }
177
178   if (theSprite == theSpriteA)
179   {
180     myTextures[1].Nullify();
181   }
182   else
183   {
184     if (myTextures[1].IsNull()
185      || myTextures[1]->Size() != myTextures[0]->Size())
186     {
187       myTextures[1] = new OpenGl_TextureSet (aNbTexturesNew);
188     }
189     else
190     {
191       myTextures[1]->InitZero();
192     }
193   }
194
195   if (theAspect->ToMapTexture())
196   {
197     Graphic3d_TextureSet::Iterator aTextureIter (aNewTextureSet);
198     OpenGl_TextureSet::Iterator aResIter0 (myTextures[0]);
199     for (; aTextureIter.More(); aResIter0.Next(), aTextureIter.Next())
200     {
201       Handle(OpenGl_Texture)& aResource = aResIter0.ChangeValue();
202       const Handle(Graphic3d_TextureMap)& aTexture = aTextureIter.Value();
203       if (!aResource.IsNull())
204       {
205         if (!aTexture.IsNull()
206          &&  aTexture->GetId()    == aResource->ResourceId()
207          &&  aTexture->Revision() != aResource->Revision())
208         {
209           if (Handle(Image_PixMap) anImage = aTexture->GetImage())
210           {
211             aResource->Sampler()->SetParameters (aTexture->GetParams());
212             aResource->Init (theCtx, *anImage.operator->(), aTexture->Type());
213             aResource->SetRevision (aTexture->Revision());
214             continue;
215           }
216         }
217
218         if (aResource->ResourceId().IsEmpty())
219         {
220           theCtx->DelayedRelease (aResource);
221           aResource.Nullify();
222         }
223         else
224         {
225           const TCollection_AsciiString aTextureKey = aResource->ResourceId();
226           aResource.Nullify(); // we need nullify all handles before ReleaseResource() call
227           theCtx->ReleaseResource (aTextureKey, Standard_True);
228         }
229       }
230
231       if (!aTexture.IsNull())
232       {
233         const TCollection_AsciiString& aTextureKeyNew = aTexture->GetId();
234         if (aTextureKeyNew.IsEmpty()
235         || !theCtx->GetResource<Handle(OpenGl_Texture)> (aTextureKeyNew, aResource))
236         {
237           aResource = new OpenGl_Texture (aTextureKeyNew, aTexture->GetParams());
238           if (Handle(Image_PixMap) anImage = aTexture->GetImage())
239           {
240             aResource->Init (theCtx, *anImage.operator->(), aTexture->Type());
241             aResource->SetRevision (aTexture->Revision());
242           }
243           if (!aTextureKeyNew.IsEmpty())
244           {
245             theCtx->ShareResource (aTextureKeyNew, aResource);
246           }
247         }
248         else
249         {
250           if (aTexture->Revision() != aResource->Revision())
251           {
252             if (Handle(Image_PixMap) anImage = aTexture->GetImage())
253             {
254               aResource->Init (theCtx, *anImage.operator->(), aTexture->Type());
255               aResource->SetRevision (aTexture->Revision());
256             }
257           }
258           aResource->Sampler()->SetParameters (aTexture->GetParams());
259         }
260       }
261     }
262   }
263
264   if (hasSprite)
265   {
266     myTextures[0]->ChangeLast() = theSprite;
267     if (!theSprite.IsNull())
268     {
269       theSprite ->Sampler()->Parameters()->SetTextureUnit (theCtx->SpriteTextureUnit());
270     }
271     if (!theSpriteA.IsNull())
272     {
273       theSpriteA->Sampler()->Parameters()->SetTextureUnit (theCtx->SpriteTextureUnit());
274     }
275   }
276   if (myTextures[1].IsNull())
277   {
278     return;
279   }
280
281   for (OpenGl_TextureSet::Iterator aResIter0 (myTextures[0]), aResIter1 (myTextures[1]); aResIter0.More(); aResIter0.Next(), aResIter1.Next())
282   {
283     aResIter1.ChangeValue() = aResIter0.Value();
284   }
285   if (hasSprite)
286   {
287     myTextures[1]->ChangeLast() = theSpriteA;
288   }
289 }