bf5f0ca2 |
1 | // Copyright (c) 2019 OPEN CASCADE SAS |
b311480e |
2 | // |
973c2be1 |
3 | // This file is part of Open CASCADE Technology software library. |
b311480e |
4 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
10 | // |
973c2be1 |
11 | // Alternatively, this file may be used under the terms of Open CASCADE |
12 | // commercial license or contractual agreement. |
b311480e |
13 | |
bf5f0ca2 |
14 | #include <OpenGl_AspectsSprite.hxx> |
15 | |
a577aaab |
16 | #include <OpenGl_Context.hxx> |
a577aaab |
17 | #include <OpenGl_PointSprite.hxx> |
bf5f0ca2 |
18 | #include <OpenGl_TextureSet.hxx> |
2166f0fa |
19 | |
a577aaab |
20 | #include <Image_PixMap.hxx> |
21 | #include <Graphic3d_MarkerImage.hxx> |
fd4a6963 |
22 | #include <TColStd_HArray1OfByte.hxx> |
a577aaab |
23 | |
30f0ad28 |
24 | namespace |
25 | { |
30f0ad28 |
26 | static const TCollection_AsciiString THE_EMPTY_KEY; |
a577aaab |
27 | } |
28 | |
fd4a6963 |
29 | // ======================================================================= |
30f0ad28 |
30 | // function : Release |
fd4a6963 |
31 | // purpose : |
32 | // ======================================================================= |
bf5f0ca2 |
33 | void OpenGl_AspectsSprite::Release (OpenGl_Context* theCtx) |
cc8cbabe |
34 | { |
35 | myIsSpriteReady = Standard_False; |
36 | if (mySprite.IsNull()) |
37 | { |
38 | return; |
39 | } |
40 | |
41 | if (theCtx != NULL) |
30f0ad28 |
42 | { |
737e9a8d |
43 | if (mySprite->ResourceId().IsEmpty()) |
cc8cbabe |
44 | { |
737e9a8d |
45 | theCtx->DelayedRelease (mySprite); |
46 | theCtx->DelayedRelease (mySpriteA); |
cc8cbabe |
47 | } |
48 | else |
30f0ad28 |
49 | { |
30f0ad28 |
50 | { |
737e9a8d |
51 | const TCollection_AsciiString aSpriteKey = mySprite->ResourceId(); |
cc8cbabe |
52 | mySprite.Nullify(); // we need nullify all handles before ReleaseResource() call |
53 | theCtx->ReleaseResource (aSpriteKey, Standard_True); |
30f0ad28 |
54 | } |
cc8cbabe |
55 | if (!mySpriteA.IsNull()) |
30f0ad28 |
56 | { |
737e9a8d |
57 | const TCollection_AsciiString aSpriteKeyA = mySpriteA->ResourceId(); |
cc8cbabe |
58 | mySpriteA.Nullify(); |
59 | theCtx->ReleaseResource (aSpriteKeyA, Standard_True); |
30f0ad28 |
60 | } |
61 | } |
30f0ad28 |
62 | } |
cc8cbabe |
63 | mySprite.Nullify(); |
64 | mySpriteA.Nullify(); |
65 | } |
66 | |
737e9a8d |
67 | // ======================================================================= |
68 | // function : HasPointSprite |
69 | // purpose : |
70 | // ======================================================================= |
71 | bool OpenGl_AspectsSprite::HasPointSprite (const Handle(OpenGl_Context)& theCtx, |
72 | const Handle(Graphic3d_Aspects)& theAspects) |
73 | { |
74 | const Handle(OpenGl_PointSprite)& aSprite = Sprite (theCtx, theAspects, false); |
75 | return !aSprite.IsNull() |
76 | && !aSprite->IsDisplayList(); |
77 | } |
78 | |
79 | // ======================================================================= |
80 | // function : IsDisplayListSprite |
81 | // purpose : |
82 | // ======================================================================= |
83 | bool OpenGl_AspectsSprite::IsDisplayListSprite (const Handle(OpenGl_Context)& theCtx, |
84 | const Handle(Graphic3d_Aspects)& theAspects) |
85 | { |
8f7159cb |
86 | if (theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES) |
87 | { |
88 | return false; |
89 | } |
90 | |
737e9a8d |
91 | const Handle(OpenGl_PointSprite)& aSprite = Sprite (theCtx, theAspects, false); |
92 | return !aSprite.IsNull() |
93 | && aSprite->IsDisplayList(); |
737e9a8d |
94 | } |
95 | |
cc8cbabe |
96 | // ======================================================================= |
bf5f0ca2 |
97 | // function : UpdateRediness |
cc8cbabe |
98 | // purpose : |
99 | // ======================================================================= |
bf5f0ca2 |
100 | void OpenGl_AspectsSprite::UpdateRediness (const Handle(Graphic3d_Aspects)& theAspect) |
cc8cbabe |
101 | { |
102 | // update sprite resource bindings |
103 | TCollection_AsciiString aSpriteKeyNew, aSpriteAKeyNew; |
bf5f0ca2 |
104 | spriteKeys (theAspect->MarkerImage(), theAspect->MarkerType(), theAspect->MarkerScale(), theAspect->ColorRGBA(), aSpriteKeyNew, aSpriteAKeyNew); |
737e9a8d |
105 | const TCollection_AsciiString& aSpriteKeyOld = !mySprite.IsNull() ? mySprite ->ResourceId() : THE_EMPTY_KEY; |
106 | const TCollection_AsciiString& aSpriteAKeyOld = !mySpriteA.IsNull() ? mySpriteA->ResourceId() : THE_EMPTY_KEY; |
cc8cbabe |
107 | if (aSpriteKeyNew.IsEmpty() || aSpriteKeyOld != aSpriteKeyNew |
108 | || aSpriteAKeyNew.IsEmpty() || aSpriteAKeyOld != aSpriteAKeyNew) |
30f0ad28 |
109 | { |
cc8cbabe |
110 | myIsSpriteReady = Standard_False; |
bf5f0ca2 |
111 | myMarkerSize = theAspect->MarkerScale(); |
cc8cbabe |
112 | } |
113 | } |
114 | |
737e9a8d |
115 | // ======================================================================= |
116 | // function : Sprite |
117 | // purpose : |
118 | // ======================================================================= |
119 | const Handle(OpenGl_PointSprite)& OpenGl_AspectsSprite::Sprite (const Handle(OpenGl_Context)& theCtx, |
120 | const Handle(Graphic3d_Aspects)& theAspects, |
121 | bool theIsAlphaSprite) |
122 | { |
123 | if (!myIsSpriteReady) |
124 | { |
125 | build (theCtx, theAspects->MarkerImage(), theAspects->MarkerType(), theAspects->MarkerScale(), theAspects->ColorRGBA(), myMarkerSize); |
126 | myIsSpriteReady = true; |
127 | } |
128 | return theIsAlphaSprite && !mySpriteA.IsNull() && mySpriteA->IsValid() |
129 | ? mySpriteA |
130 | : mySprite; |
131 | } |
132 | |
cc8cbabe |
133 | // ======================================================================= |
bf5f0ca2 |
134 | // function : build |
cc8cbabe |
135 | // purpose : |
136 | // ======================================================================= |
bf5f0ca2 |
137 | void OpenGl_AspectsSprite::build (const Handle(OpenGl_Context)& theCtx, |
138 | const Handle(Graphic3d_MarkerImage)& theMarkerImage, |
139 | Aspect_TypeOfMarker theType, |
140 | Standard_ShortReal theScale, |
141 | const Graphic3d_Vec4& theColor, |
142 | Standard_ShortReal& theMarkerSize) |
fd4a6963 |
143 | { |
30f0ad28 |
144 | // generate key for shared resource |
cc8cbabe |
145 | TCollection_AsciiString aNewKey, aNewKeyA; |
146 | spriteKeys (theMarkerImage, theType, theScale, theColor, aNewKey, aNewKeyA); |
147 | |
737e9a8d |
148 | const TCollection_AsciiString& aSpriteKeyOld = !mySprite.IsNull() ? mySprite ->ResourceId() : THE_EMPTY_KEY; |
149 | const TCollection_AsciiString& aSpriteAKeyOld = !mySpriteA.IsNull() ? mySpriteA->ResourceId() : THE_EMPTY_KEY; |
a577aaab |
150 | |
151 | // release old shared resources |
cc8cbabe |
152 | const Standard_Boolean aNewResource = aNewKey.IsEmpty() |
153 | || aSpriteKeyOld != aNewKey; |
a577aaab |
154 | if (aNewResource) |
155 | { |
cc8cbabe |
156 | if (!mySprite.IsNull()) |
a577aaab |
157 | { |
737e9a8d |
158 | if (mySprite->ResourceId().IsEmpty()) |
a577aaab |
159 | { |
737e9a8d |
160 | theCtx->DelayedRelease (mySprite); |
cc8cbabe |
161 | mySprite.Nullify(); |
a577aaab |
162 | } |
163 | else |
164 | { |
737e9a8d |
165 | const TCollection_AsciiString anOldKey = mySprite->ResourceId(); |
cc8cbabe |
166 | mySprite.Nullify(); // we need nullify all handles before ReleaseResource() call |
167 | theCtx->ReleaseResource (anOldKey, Standard_True); |
a577aaab |
168 | } |
169 | } |
a577aaab |
170 | } |
cc8cbabe |
171 | if (aNewKeyA.IsEmpty() || aSpriteAKeyOld != aNewKeyA) |
a577aaab |
172 | { |
cc8cbabe |
173 | if (!mySpriteA.IsNull()) |
a577aaab |
174 | { |
737e9a8d |
175 | if (mySpriteA->ResourceId().IsEmpty()) |
a577aaab |
176 | { |
737e9a8d |
177 | theCtx->DelayedRelease (mySpriteA); |
cc8cbabe |
178 | mySpriteA.Nullify(); |
a577aaab |
179 | } |
180 | else |
181 | { |
737e9a8d |
182 | const TCollection_AsciiString anOldKey = mySpriteA->ResourceId(); |
cc8cbabe |
183 | mySpriteA.Nullify(); // we need nullify all handles before ReleaseResource() call |
184 | theCtx->ReleaseResource (anOldKey, Standard_True); |
a577aaab |
185 | } |
186 | } |
a577aaab |
187 | } |
33cc703b |
188 | |
189 | if (!aNewResource) |
190 | { |
737e9a8d |
191 | const OpenGl_PointSprite* aSprite = dynamic_cast<OpenGl_PointSprite*> (mySprite.get()); |
cc8cbabe |
192 | if (!aSprite->IsDisplayList()) |
33cc703b |
193 | { |
cc8cbabe |
194 | theMarkerSize = Standard_ShortReal (Max (aSprite->SizeX(), aSprite->SizeY())); |
33cc703b |
195 | } |
196 | return; |
197 | } |
30f0ad28 |
198 | if (theType == Aspect_TOM_POINT |
3a4a3962 |
199 | || theType == Aspect_TOM_EMPTY |
30f0ad28 |
200 | || (theType == Aspect_TOM_USERDEFINED && theMarkerImage.IsNull())) |
a577aaab |
201 | { |
202 | // nothing to do - just simple point |
203 | return; |
204 | } |
205 | |
737e9a8d |
206 | Handle(OpenGl_PointSprite)& aSprite = mySprite; |
207 | Handle(OpenGl_PointSprite)& aSpriteA = mySpriteA; |
665dc9e5 |
208 | if (!aNewKey.IsEmpty()) |
209 | { |
210 | theCtx->GetResource<Handle(OpenGl_PointSprite)> (aNewKeyA, aSpriteA); // alpha sprite could be shared |
211 | theCtx->GetResource<Handle(OpenGl_PointSprite)> (aNewKey, aSprite); |
212 | } |
213 | |
214 | const bool hadAlreadyRGBA = !aSprite.IsNull(); |
215 | const bool hadAlreadyAlpha = !aSpriteA.IsNull(); |
216 | if (hadAlreadyRGBA |
217 | && hadAlreadyAlpha) |
a577aaab |
218 | { |
219 | // reuse shared resource |
cc8cbabe |
220 | if (!aSprite->IsDisplayList()) |
a577aaab |
221 | { |
cc8cbabe |
222 | theMarkerSize = Standard_ShortReal (Max (aSprite->SizeX(), aSprite->SizeY())); |
a577aaab |
223 | } |
224 | return; |
225 | } |
226 | |
18e85574 |
227 | if (!hadAlreadyAlpha) |
228 | { |
cc8cbabe |
229 | aSpriteA = new OpenGl_PointSprite (aNewKeyA); |
18e85574 |
230 | } |
665dc9e5 |
231 | if (!hadAlreadyRGBA) |
232 | { |
233 | aSprite = new OpenGl_PointSprite (aNewKey); |
234 | } |
a577aaab |
235 | if (!aNewKey.IsEmpty()) |
236 | { |
665dc9e5 |
237 | if (!hadAlreadyRGBA) |
238 | { |
239 | theCtx->ShareResource (aNewKey, aSprite); |
240 | } |
18e85574 |
241 | if (!hadAlreadyAlpha) |
242 | { |
cc8cbabe |
243 | theCtx->ShareResource (aNewKeyA, aSpriteA); |
18e85574 |
244 | } |
a577aaab |
245 | } |
246 | |
59500bb2 |
247 | Handle(Graphic3d_MarkerImage) aNewMarkerImage = theType == Aspect_TOM_USERDEFINED && !theMarkerImage.IsNull() |
248 | ? theMarkerImage |
249 | : Graphic3d_MarkerImage::StandardMarker (theType, theScale, theColor); |
250 | if (aNewMarkerImage.IsNull()) |
251 | { |
252 | return; |
253 | } |
254 | |
92996979 |
255 | if (theCtx->core20fwd != NULL |
43eddb47 |
256 | && (!theCtx->caps->pntSpritesDisable || theCtx->core11ffp == NULL)) |
a577aaab |
257 | { |
258 | // Creating texture resource for using it with point sprites |
59500bb2 |
259 | Handle(Image_PixMap) anImage = aNewMarkerImage->GetImage(); |
30f0ad28 |
260 | theMarkerSize = Max ((Standard_ShortReal )anImage->Width(),(Standard_ShortReal )anImage->Height()); |
a577aaab |
261 | |
665dc9e5 |
262 | if (!hadAlreadyRGBA) |
263 | { |
633084b8 |
264 | aSprite->Init (theCtx, *anImage, Graphic3d_TypeOfTexture_2D, true); |
665dc9e5 |
265 | } |
18e85574 |
266 | if (!hadAlreadyAlpha) |
a577aaab |
267 | { |
59500bb2 |
268 | if (Handle(Image_PixMap) anImageA = aSprite->GetFormat() != GL_ALPHA ? aNewMarkerImage->GetImageAlpha() : Handle(Image_PixMap)()) |
18e85574 |
269 | { |
633084b8 |
270 | aSpriteA->Init (theCtx, *anImageA, Graphic3d_TypeOfTexture_2D, true); |
18e85574 |
271 | } |
a577aaab |
272 | } |
273 | } |
43eddb47 |
274 | else if (theCtx->core11ffp != NULL) |
a577aaab |
275 | { |
276 | // Creating list with bitmap for using it in compatibility mode |
43eddb47 |
277 | GLuint aBitmapList = theCtx->core11ffp->glGenLists (1); |
cc8cbabe |
278 | aSprite->SetDisplayList (theCtx, aBitmapList); |
a577aaab |
279 | |
59500bb2 |
280 | Handle(Image_PixMap) anImage = aNewMarkerImage->IsColoredImage() |
281 | ? aNewMarkerImage->GetImage() |
282 | : Handle(Image_PixMap)(); |
283 | const OpenGl_TextureFormat aFormat = !anImage.IsNull() |
284 | ? OpenGl_TextureFormat::FindFormat (theCtx, anImage->Format(), true) |
285 | : OpenGl_TextureFormat(); |
286 | if (aFormat.IsValid()) |
a577aaab |
287 | { |
59500bb2 |
288 | if (anImage->IsTopDown()) |
a577aaab |
289 | { |
59500bb2 |
290 | Handle(Image_PixMap) anImageCopy = new Image_PixMap(); |
291 | anImageCopy->InitCopy (*anImage); |
292 | Image_PixMap::FlipY (*anImageCopy); |
293 | anImage = anImageCopy; |
a577aaab |
294 | } |
59500bb2 |
295 | const GLint anAligment = Min ((GLint)anImage->MaxRowAligmentBytes(), 8); |
43eddb47 |
296 | theCtx->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment); |
a577aaab |
297 | |
59500bb2 |
298 | const GLint anExtraBytes = GLint (anImage->RowExtraBytes()); |
299 | const GLint aPixelsWidth = GLint (anImage->SizeRowBytes() / anImage->SizePixelBytes()); |
300 | const GLint aRowLength = (anExtraBytes >= anAligment) ? aPixelsWidth : 0; |
43eddb47 |
301 | theCtx->core11fwd->glPixelStorei (GL_UNPACK_ROW_LENGTH, aRowLength); |
a577aaab |
302 | |
43eddb47 |
303 | theCtx->core11ffp->glNewList (aBitmapList, GL_COMPILE); |
59500bb2 |
304 | const Standard_Integer aWidth = (Standard_Integer )anImage->Width(), aHeight = (Standard_Integer )anImage->Height(); |
43eddb47 |
305 | theCtx->core11ffp->glBitmap (0, 0, 0, 0, GLfloat(-0.5f * aWidth), GLfloat(-0.5f * aHeight), NULL); // make offsets that will be added to the current raster position |
306 | theCtx->core11ffp->glDrawPixels (GLsizei(anImage->Width()), GLsizei(anImage->Height()), aFormat.PixelFormat(), aFormat.DataType(), anImage->Data()); |
307 | theCtx->core11ffp->glEndList(); |
308 | theCtx->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1); |
309 | theCtx->core11fwd->glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); |
59500bb2 |
310 | } |
a577aaab |
311 | |
59500bb2 |
312 | if (!aFormat.IsValid() || !hadAlreadyAlpha) |
313 | { |
314 | if (aFormat.IsValid()) |
315 | { |
8f7159cb |
316 | aBitmapList = theCtx->core11ffp->glGenLists (1); |
59500bb2 |
317 | aSpriteA->SetDisplayList (theCtx, aBitmapList); |
318 | } |
a577aaab |
319 | |
59500bb2 |
320 | Standard_Integer aWidth = 0, aHeight = 0; |
321 | aNewMarkerImage->GetTextureSize (aWidth, aHeight); |
322 | if (Handle(TColStd_HArray1OfByte) aBitMap = aNewMarkerImage->GetBitMapArray()) |
323 | { |
43eddb47 |
324 | theCtx->core11ffp->glNewList (aBitmapList, GL_COMPILE); |
325 | theCtx->core11ffp->glBitmap ((GLsizei)aWidth, (GLsizei)aHeight, (GLfloat)(0.5f * aWidth), (GLfloat)(0.5f * aHeight), |
326 | 0.f, 0.f, (const GLubyte*)&aBitMap->First()); |
327 | theCtx->core11ffp->glEndList(); |
a577aaab |
328 | } |
a577aaab |
329 | } |
330 | } |
331 | } |
fd4a6963 |
332 | // ======================================================================= |
cc8cbabe |
333 | // function : spriteKeys |
fd4a6963 |
334 | // purpose : |
335 | // ======================================================================= |
bf5f0ca2 |
336 | void OpenGl_AspectsSprite::spriteKeys (const Handle(Graphic3d_MarkerImage)& theMarkerImage, |
337 | Aspect_TypeOfMarker theType, |
338 | Standard_ShortReal theScale, |
339 | const Graphic3d_Vec4& theColor, |
340 | TCollection_AsciiString& theKey, |
341 | TCollection_AsciiString& theKeyA) |
fd4a6963 |
342 | { |
343 | // generate key for shared resource |
344 | if (theType == Aspect_TOM_USERDEFINED) |
345 | { |
346 | if (!theMarkerImage.IsNull()) |
347 | { |
348 | theKey = theMarkerImage->GetImageId(); |
349 | theKeyA = theMarkerImage->GetImageAlphaId(); |
350 | } |
351 | } |
3a4a3962 |
352 | else if (theType != Aspect_TOM_POINT |
353 | && theType != Aspect_TOM_EMPTY) |
fd4a6963 |
354 | { |
d509e5a4 |
355 | // predefined markers are defined with 0.5 step |
356 | const Standard_Integer aScale = Standard_Integer(theScale * 10.0f + 0.5f); |
fd4a6963 |
357 | theKey = TCollection_AsciiString ("OpenGl_AspectMarker") + theType + "_" + aScale; |
358 | theKeyA = theKey + "A"; |
359 | if (theType == Aspect_TOM_BALL) |
360 | { |
361 | unsigned int aColor[3] = |
362 | { |
b6472664 |
363 | (unsigned int )(255.0f * theColor.r()), |
364 | (unsigned int )(255.0f * theColor.g()), |
365 | (unsigned int )(255.0f * theColor.b()) |
fd4a6963 |
366 | }; |
367 | char aBytes[8]; |
368 | sprintf (aBytes, "%02X%02X%02X", aColor[0], aColor[1], aColor[2]); |
369 | theKey += aBytes; |
370 | } |
371 | } |
372 | } |