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