0029517: Visualization - introduce AlphaMode property defining alpha value handling...
[occt.git] / src / OpenGl / OpenGl_Texture.cxx
CommitLineData
bf75be98 1// Created by: Kirill GAVRILOV
d5f74e42 2// Copyright (c) 2013-2014 OPEN CASCADE SAS
bf75be98 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
bf75be98 5//
d5f74e42 6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
bf75be98 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
bf75be98 14
15#include <OpenGl_Texture.hxx>
16
01ca42b2 17#include <OpenGl_ArbFBO.hxx>
bf75be98 18#include <OpenGl_Context.hxx>
3c4b62a4 19#include <OpenGl_GlCore32.hxx>
cc8cbabe 20#include <OpenGl_Sampler.hxx>
bf75be98 21#include <Graphic3d_TextureParams.hxx>
fa4dcbe0 22#include <TCollection_ExtendedString.hxx>
bf75be98 23#include <Standard_Assert.hxx>
24#include <Image_PixMap.hxx>
25
cc8cbabe 26IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_NamedResource)
92efcf78 27
74706083 28//! Simple class to reset unpack alignment settings
29struct OpenGl_UnpackAlignmentSentry
30{
31
32 //! Reset unpack alignment settings to safe values
33 void Reset()
34 {
35 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
ca3c13d1 36 #if !defined(GL_ES_VERSION_2_0)
74706083 37 glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
ca3c13d1 38 #endif
74706083 39 }
40
41 ~OpenGl_UnpackAlignmentSentry()
42 {
43 Reset();
44 }
45
46};
47
bf75be98 48// =======================================================================
49// function : OpenGl_Texture
50// purpose :
51// =======================================================================
cc8cbabe 52OpenGl_Texture::OpenGl_Texture (const TCollection_AsciiString& theResourceId,
53 const Handle(Graphic3d_TextureParams)& theParams)
54: OpenGl_NamedResource (theResourceId),
55 mySampler (new OpenGl_Sampler (theParams)),
d2edda76 56 myRevision (0),
bf75be98 57 myTextureId (NO_TEXTURE),
58 myTarget (GL_TEXTURE_2D),
59 mySizeX (0),
60 mySizeY (0),
74fb257d 61 mySizeZ (0),
8625ef7e 62 myTextFormat (GL_RGBA),
15669413 63 mySizedFormat(GL_RGBA8),
64 myNbSamples (1),
bf75be98 65 myHasMipmaps (Standard_False),
cc8cbabe 66 myIsAlpha (false)
bf75be98 67{
cc8cbabe 68 //
bf75be98 69}
70
71// =======================================================================
72// function : ~OpenGl_Texture
73// purpose :
74// =======================================================================
75OpenGl_Texture::~OpenGl_Texture()
76{
77 Release (NULL);
78}
79
bf75be98 80// =======================================================================
81// function : Create
82// purpose :
83// =======================================================================
cc8cbabe 84bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& theCtx)
bf75be98 85{
cc8cbabe 86 if (myTextureId != NO_TEXTURE)
87 {
88 return true;
89 }
90
91 theCtx->core11fwd->glGenTextures (1, &myTextureId);
bf75be98 92 if (myTextureId == NO_TEXTURE)
93 {
cc8cbabe 94 return false;
bf75be98 95 }
cc8cbabe 96
97 //mySampler->Create (theCtx); // do not create sampler object by default
98 return true;
bf75be98 99}
100
101// =======================================================================
102// function : Release
103// purpose :
104// =======================================================================
10b9c7df 105void OpenGl_Texture::Release (OpenGl_Context* theGlCtx)
bf75be98 106{
cc8cbabe 107 mySampler->Release (theGlCtx);
bf75be98 108 if (myTextureId == NO_TEXTURE)
109 {
110 return;
111 }
112
113 // application can not handle this case by exception - this is bug in code
114 Standard_ASSERT_RETURN (theGlCtx != NULL,
115 "OpenGl_Texture destroyed without GL context! Possible GPU memory leakage...",);
116
ec2eeb2d 117 if (theGlCtx->IsValid())
118 {
119 glDeleteTextures (1, &myTextureId);
120 }
bf75be98 121 myTextureId = NO_TEXTURE;
d2edda76 122 mySizeX = mySizeY = mySizeZ = 0;
bf75be98 123}
124
cc8cbabe 125// =======================================================================
126// function : applyDefaultSamplerParams
127// purpose :
128// =======================================================================
129void OpenGl_Texture::applyDefaultSamplerParams (const Handle(OpenGl_Context)& theCtx)
130{
131 OpenGl_Sampler::applySamplerParams (theCtx, mySampler->Parameters(), NULL, myTarget, myHasMipmaps);
132 if (mySampler->IsValid() && !mySampler->IsImmutable())
133 {
134 OpenGl_Sampler::applySamplerParams (theCtx, mySampler->Parameters(), mySampler.get(), myTarget, myHasMipmaps);
135 }
136}
137
bf75be98 138// =======================================================================
139// function : Bind
140// purpose :
141// =======================================================================
142void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
cc8cbabe 143 const Graphic3d_TextureUnit theTextureUnit) const
bf75be98 144{
4e1523ef 145 if (theCtx->core15fwd != NULL)
bf75be98 146 {
cc8cbabe 147 theCtx->core15fwd->glActiveTexture (GL_TEXTURE0 + theTextureUnit);
bf75be98 148 }
cc8cbabe 149 mySampler->Bind (theCtx, theTextureUnit);
bf75be98 150 glBindTexture (myTarget, myTextureId);
151}
152
153// =======================================================================
154// function : Unbind
155// purpose :
156// =======================================================================
157void OpenGl_Texture::Unbind (const Handle(OpenGl_Context)& theCtx,
cc8cbabe 158 const Graphic3d_TextureUnit theTextureUnit) const
bf75be98 159{
4e1523ef 160 if (theCtx->core15fwd != NULL)
bf75be98 161 {
cc8cbabe 162 theCtx->core15fwd->glActiveTexture (GL_TEXTURE0 + theTextureUnit);
bf75be98 163 }
cc8cbabe 164 mySampler->Unbind (theCtx, theTextureUnit);
bf75be98 165 glBindTexture (myTarget, NO_TEXTURE);
166}
167
cc8cbabe 168//=======================================================================
169//function : InitSamplerObject
170//purpose :
171//=======================================================================
172bool OpenGl_Texture::InitSamplerObject (const Handle(OpenGl_Context)& theCtx)
173{
174 return myTextureId != NO_TEXTURE
175 && mySampler->Init (theCtx, *this);
176}
177
18f4e8e2 178//=======================================================================
179//function : GetDataFormat
180//purpose :
181//=======================================================================
182bool OpenGl_Texture::GetDataFormat (const Handle(OpenGl_Context)& theCtx,
183 const Image_PixMap& theData,
184 GLint& theTextFormat,
185 GLenum& thePixelFormat,
186 GLenum& theDataType)
bf75be98 187{
18f4e8e2 188 theTextFormat = GL_RGBA8;
189 thePixelFormat = 0;
190 theDataType = 0;
191 switch (theData.Format())
bf75be98 192 {
dc858f4c 193 case Image_Format_GrayF:
bf75be98 194 {
076ca35c 195 if (theCtx->core11 == NULL)
196 {
197 theTextFormat = GL_R8; // GL_R32F
198 thePixelFormat = GL_RED;
199 }
200 else
201 {
a1073ae2 202 #if !defined(GL_ES_VERSION_2_0)
076ca35c 203 theTextFormat = GL_LUMINANCE8;
a1073ae2 204 #else
205 theTextFormat = GL_LUMINANCE;
206 #endif
076ca35c 207 thePixelFormat = GL_LUMINANCE;
208 }
209 theDataType = GL_FLOAT;
210 return true;
211 }
dc858f4c 212 case Image_Format_AlphaF:
076ca35c 213 {
214 if (theCtx->core11 == NULL)
215 {
216 theTextFormat = GL_R8; // GL_R32F
217 thePixelFormat = GL_RED;
218 }
219 else
220 {
a1073ae2 221 #if !defined(GL_ES_VERSION_2_0)
076ca35c 222 theTextFormat = GL_ALPHA8;
a1073ae2 223 #else
224 theTextFormat = GL_ALPHA;
225 #endif
076ca35c 226 thePixelFormat = GL_ALPHA;
227 }
228 theDataType = GL_FLOAT;
18f4e8e2 229 return true;
bf75be98 230 }
dc858f4c 231 case Image_Format_RGBAF:
bf75be98 232 {
076ca35c 233 theTextFormat = GL_RGBA8; // GL_RGBA32F
18f4e8e2 234 thePixelFormat = GL_RGBA;
235 theDataType = GL_FLOAT;
236 return true;
bf75be98 237 }
dc858f4c 238 case Image_Format_BGRAF:
bf75be98 239 {
240 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
241 {
242 return false;
243 }
ca3c13d1 244 theTextFormat = GL_RGBA8; // GL_RGBA32F
245 thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
18f4e8e2 246 theDataType = GL_FLOAT;
247 return true;
bf75be98 248 }
dc858f4c 249 case Image_Format_RGBF:
bf75be98 250 {
076ca35c 251 theTextFormat = GL_RGB8; // GL_RGB32F
18f4e8e2 252 thePixelFormat = GL_RGB;
253 theDataType = GL_FLOAT;
254 return true;
bf75be98 255 }
dc858f4c 256 case Image_Format_BGRF:
bf75be98 257 {
ca3c13d1 258 #if !defined(GL_ES_VERSION_2_0)
259 theTextFormat = GL_RGB8; // GL_RGB32F
18f4e8e2 260 thePixelFormat = GL_BGR; // equals to GL_BGR_EXT
261 theDataType = GL_FLOAT;
262 return true;
ca3c13d1 263 #else
264 return false;
265 #endif
bf75be98 266 }
dc858f4c 267 case Image_Format_RGBA:
bf75be98 268 {
18f4e8e2 269 theTextFormat = GL_RGBA8;
270 thePixelFormat = GL_RGBA;
271 theDataType = GL_UNSIGNED_BYTE;
272 return true;
bf75be98 273 }
dc858f4c 274 case Image_Format_BGRA:
bf75be98 275 {
177781da 276 #if !defined(GL_ES_VERSION_2_0)
bf75be98 277 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
278 {
279 return false;
280 }
ca3c13d1 281 theTextFormat = GL_RGBA8;
177781da 282 #else
283 if (!theCtx->extBgra)
284 {
285 return false;
286 }
287 theTextFormat = GL_BGRA_EXT;
288 #endif
ca3c13d1 289 thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
18f4e8e2 290 theDataType = GL_UNSIGNED_BYTE;
291 return true;
bf75be98 292 }
dc858f4c 293 case Image_Format_RGB32:
bf75be98 294 {
177781da 295 #if !defined(GL_ES_VERSION_2_0)
296 // ask driver to convert data to RGB8 to save memory
297 theTextFormat = GL_RGB8;
298 #else
299 // conversion is not supported
300 theTextFormat = GL_RGBA8;
301 #endif
18f4e8e2 302 thePixelFormat = GL_RGBA;
303 theDataType = GL_UNSIGNED_BYTE;
304 return true;
bf75be98 305 }
dc858f4c 306 case Image_Format_BGR32:
bf75be98 307 {
177781da 308 #if !defined(GL_ES_VERSION_2_0)
309 if (!theCtx->IsGlGreaterEqual(1, 2) && !theCtx->extBgra)
bf75be98 310 {
311 return false;
312 }
ca3c13d1 313 theTextFormat = GL_RGB8;
177781da 314 #else
315 if (!theCtx->extBgra)
316 {
317 return false;
318 }
319 theTextFormat = GL_BGRA_EXT;
320 #endif
ca3c13d1 321 thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
18f4e8e2 322 theDataType = GL_UNSIGNED_BYTE;
323 return true;
bf75be98 324 }
dc858f4c 325 case Image_Format_RGB:
bf75be98 326 {
18f4e8e2 327 theTextFormat = GL_RGB8;
328 thePixelFormat = GL_RGB;
329 theDataType = GL_UNSIGNED_BYTE;
330 return true;
bf75be98 331 }
dc858f4c 332 case Image_Format_BGR:
bf75be98 333 {
ca3c13d1 334 #if !defined(GL_ES_VERSION_2_0)
bf75be98 335 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
336 {
337 return false;
338 }
18f4e8e2 339 theTextFormat = GL_RGB8;
340 thePixelFormat = GL_BGR; // equals to GL_BGR_EXT
341 theDataType = GL_UNSIGNED_BYTE;
342 return true;
ca3c13d1 343 #else
344 return false;
345 #endif
bf75be98 346 }
dc858f4c 347 case Image_Format_Gray:
bf75be98 348 {
076ca35c 349 if (theCtx->core11 == NULL)
350 {
351 theTextFormat = GL_R8;
352 thePixelFormat = GL_RED;
353 }
354 else
355 {
a1073ae2 356 #if !defined(GL_ES_VERSION_2_0)
076ca35c 357 theTextFormat = GL_LUMINANCE8;
a1073ae2 358 #else
359 theTextFormat = GL_LUMINANCE;
360 #endif
076ca35c 361 thePixelFormat = GL_LUMINANCE;
362 }
363 theDataType = GL_UNSIGNED_BYTE;
364 return true;
365 }
dc858f4c 366 case Image_Format_Alpha:
076ca35c 367 {
368 if (theCtx->core11 == NULL)
369 {
370 theTextFormat = GL_R8;
371 thePixelFormat = GL_RED;
372 }
373 else
374 {
a1073ae2 375 #if !defined(GL_ES_VERSION_2_0)
076ca35c 376 theTextFormat = GL_ALPHA8;
a1073ae2 377 #else
378 theTextFormat = GL_ALPHA;
379 #endif
076ca35c 380 thePixelFormat = GL_ALPHA;
381 }
382 theDataType = GL_UNSIGNED_BYTE;
18f4e8e2 383 return true;
bf75be98 384 }
dc858f4c 385 case Image_Format_UNKNOWN:
bf75be98 386 {
387 return false;
388 }
389 }
076ca35c 390 return false;
18f4e8e2 391}
bf75be98 392
18f4e8e2 393// =======================================================================
394// function : Init
395// purpose :
396// =======================================================================
397bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
398 const Standard_Integer theTextFormat,
399 const GLenum thePixelFormat,
400 const GLenum theDataType,
401 const Standard_Integer theSizeX,
402 const Standard_Integer theSizeY,
403 const Graphic3d_TypeOfTexture theType,
404 const Image_PixMap* theImage)
405{
d2edda76 406#if !defined(GL_ES_VERSION_2_0)
407 const GLenum aTarget = theType == Graphic3d_TOT_1D
408 ? GL_TEXTURE_1D
409 : GL_TEXTURE_2D;
410#else
411 const GLenum aTarget = GL_TEXTURE_2D;
412#endif
413 const Standard_Boolean toCreateMipMaps = (theType == Graphic3d_TOT_2D_MIPMAP);
414 const bool toPatchExisting = IsValid()
415 && myTextFormat == thePixelFormat
416 && myTarget == aTarget
417 && myHasMipmaps == toCreateMipMaps
418 && mySizeX == theSizeX
419 && (mySizeY == theSizeY || theType == Graphic3d_TOT_1D);
18f4e8e2 420 if (!Create (theCtx))
421 {
422 Release (theCtx.operator->());
423 return false;
424 }
4e1523ef 425
426 if (theImage != NULL)
427 {
dc858f4c 428 myIsAlpha = theImage->Format() == Image_Format_Alpha
429 || theImage->Format() == Image_Format_AlphaF;
4e1523ef 430 }
431 else
432 {
433 myIsAlpha = thePixelFormat == GL_ALPHA;
434 }
435
d2edda76 436 myHasMipmaps = toCreateMipMaps;
8625ef7e 437 myTextFormat = thePixelFormat;
15669413 438 mySizedFormat = theTextFormat;
439 myNbSamples = 1;
8625ef7e 440#if !defined(GL_ES_VERSION_2_0)
441 const GLint anIntFormat = theTextFormat;
442#else
a1073ae2 443 // ES 2.0 does not support sized formats and format conversions - them detected from data type
444 const GLint anIntFormat = theCtx->IsGlGreaterEqual (3, 0) ? theTextFormat : thePixelFormat;
8625ef7e 445#endif
bf75be98 446
ff6665dc 447 if (theDataType == GL_FLOAT && !theCtx->arbTexFloat)
448 {
449 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
450 "Error: floating-point textures are not supported by hardware.");
451 Release (theCtx.operator->());
452 return false;
453 }
454
d2edda76 455 const GLsizei aMaxSize = theCtx->MaxTextureSize();
456 if (theSizeX > aMaxSize
457 || theSizeY > aMaxSize)
fa4dcbe0 458 {
459 TCollection_ExtendedString aWarnMessage = TCollection_ExtendedString ("Error: Texture dimension - ")
d2edda76 460 + theSizeX + "x" + theSizeY + " exceeds hardware limits (" + aMaxSize + "x" + aMaxSize + ")";
fa4dcbe0 461
462 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
463 Release (theCtx.operator->());
464 return false;
465 }
466#if !defined(GL_ES_VERSION_2_0)
467 else if (!theCtx->IsGlGreaterEqual (3, 0) && !theCtx->arbNPTW)
468 {
469 // Notice that formally general NPOT textures are required by OpenGL 2.0 specifications
470 // however some hardware (NV30 - GeForce FX, RadeOn 9xxx and Xxxx) supports GLSL but not NPOT!
471 // Trying to create NPOT textures on such hardware will not fail
472 // but driver will fall back into software rendering,
d2edda76 473 const GLsizei aWidthP2 = OpenGl_Context::GetPowerOfTwo (theSizeX, aMaxSize);
474 const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (theSizeY, aMaxSize);
fa4dcbe0 475
d2edda76 476 if (theSizeX != aWidthP2
477 || (theType != Graphic3d_TOT_1D && theSizeY != aHeightP2))
fa4dcbe0 478 {
479 TCollection_ExtendedString aWarnMessage =
d2edda76 480 TCollection_ExtendedString ("Error: NPOT Textures (") + theSizeX + "x" + theSizeY + ") are not supported by hardware.";
fa4dcbe0 481
482 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
483
484 Release (theCtx.operator->());
485 return false;
486 }
487 }
488#else
489 else if (!theCtx->IsGlGreaterEqual (3, 0) && theType == Graphic3d_TOT_2D_MIPMAP)
490 {
491 // Mipmap NPOT textures are not supported by OpenGL ES 2.0.
d2edda76 492 const GLsizei aWidthP2 = OpenGl_Context::GetPowerOfTwo (theSizeX, aMaxSize);
493 const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (theSizeY, aMaxSize);
fa4dcbe0 494
d2edda76 495 if (theSizeX != aWidthP2
496 || theSizeY != aHeightP2)
fa4dcbe0 497 {
498 TCollection_ExtendedString aWarnMessage =
d2edda76 499 TCollection_ExtendedString ("Error: Mipmap NPOT Textures (") + theSizeX + "x" + theSizeY + ") are not supported by OpenGL ES 2.0";
fa4dcbe0 500
501 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
502
503 Release (theCtx.operator->());
504 return false;
505 }
506 }
507#endif
508
ca3c13d1 509#if !defined(GL_ES_VERSION_2_0)
bf75be98 510 GLint aTestWidth = 0;
511 GLint aTestHeight = 0;
ca3c13d1 512#endif
18f4e8e2 513 GLvoid* aDataPtr = (theImage != NULL) ? (GLvoid* )theImage->Data() : NULL;
bf75be98 514
74706083 515 // setup the alignment
516 OpenGl_UnpackAlignmentSentry anUnpackSentry;
fa4dcbe0 517 (void)anUnpackSentry; // avoid compiler warning
518
18f4e8e2 519 if (aDataPtr != NULL)
520 {
521 const GLint anAligment = Min ((GLint )theImage->MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes
522 glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment);
74706083 523
ca3c13d1 524 #if !defined(GL_ES_VERSION_2_0)
18f4e8e2 525 // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension
526 const GLint anExtraBytes = GLint(theImage->RowExtraBytes());
527 const GLint aPixelsWidth = GLint(theImage->SizeRowBytes() / theImage->SizePixelBytes());
528 glPixelStorei (GL_UNPACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
ca3c13d1 529 #endif
18f4e8e2 530 }
74706083 531
d2edda76 532 myTarget = aTarget;
bf75be98 533 switch (theType)
534 {
535 case Graphic3d_TOT_1D:
536 {
ca3c13d1 537 #if !defined(GL_ES_VERSION_2_0)
bf75be98 538 Bind (theCtx);
cc8cbabe 539 applyDefaultSamplerParams (theCtx);
d2edda76 540 if (toPatchExisting)
541 {
542 glTexSubImage1D (GL_TEXTURE_1D, 0, 0,
543 theSizeX, thePixelFormat, theDataType, aDataPtr);
544 Unbind (theCtx);
545 return true;
546 }
bf75be98 547
bf75be98 548 // use proxy to check texture could be created or not
8625ef7e 549 glTexImage1D (GL_PROXY_TEXTURE_1D, 0, anIntFormat,
d2edda76 550 theSizeX, 0,
18f4e8e2 551 thePixelFormat, theDataType, NULL);
ff6665dc 552 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_1D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
15669413 553 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_1D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
bf75be98 554 if (aTestWidth == 0)
555 {
556 // no memory or broken input parameters
557 Unbind (theCtx);
18f4e8e2 558 Release (theCtx.operator->());
bf75be98 559 return false;
560 }
561
8625ef7e 562 glTexImage1D (GL_TEXTURE_1D, 0, anIntFormat,
d2edda76 563 theSizeX, 0,
18f4e8e2 564 thePixelFormat, theDataType, aDataPtr);
a174a3c5 565 if (glGetError() != GL_NO_ERROR)
566 {
567 Unbind (theCtx);
18f4e8e2 568 Release (theCtx.operator->());
a174a3c5 569 return false;
570 }
571
d2edda76 572 mySizeX = theSizeX;
a174a3c5 573 mySizeY = 1;
bf75be98 574
575 Unbind (theCtx);
576 return true;
ca3c13d1 577 #else
ff6665dc 578 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
579 "Error: 1D textures are not supported by hardware.");
fa4dcbe0 580 Release (theCtx.operator->());
ca3c13d1 581 return false;
582 #endif
bf75be98 583 }
584 case Graphic3d_TOT_2D:
585 {
bf75be98 586 Bind (theCtx);
cc8cbabe 587 applyDefaultSamplerParams (theCtx);
d2edda76 588 if (toPatchExisting)
589 {
590 glTexSubImage2D (GL_TEXTURE_2D, 0,
591 0, 0,
592 theSizeX, theSizeY,
593 thePixelFormat, theDataType, aDataPtr);
594 Unbind (theCtx);
595 return true;
596 }
bf75be98 597
ca3c13d1 598 #if !defined(GL_ES_VERSION_2_0)
bf75be98 599 // use proxy to check texture could be created or not
8625ef7e 600 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
d2edda76 601 theSizeX, theSizeY, 0,
18f4e8e2 602 thePixelFormat, theDataType, NULL);
bf75be98 603 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
604 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
15669413 605 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
bf75be98 606 if (aTestWidth == 0 || aTestHeight == 0)
607 {
608 // no memory or broken input parameters
609 Unbind (theCtx);
18f4e8e2 610 Release (theCtx.operator->());
bf75be98 611 return false;
612 }
ca3c13d1 613 #endif
bf75be98 614
8625ef7e 615 glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
d2edda76 616 theSizeX, theSizeY, 0,
18f4e8e2 617 thePixelFormat, theDataType, aDataPtr);
177781da 618 const GLenum anErr = glGetError();
619 if (anErr != GL_NO_ERROR)
a174a3c5 620 {
177781da 621 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
622 TCollection_AsciiString ("Error: 2D texture ") + theSizeX + "x" + theSizeY
623 + " IF: " + int(anIntFormat) + " PF: " + int(thePixelFormat) + " DT: " + int(theDataType)
624 + " can not be created with error " + int(anErr) + ".");
a174a3c5 625 Unbind (theCtx);
18f4e8e2 626 Release (theCtx.operator->());
a174a3c5 627 return false;
628 }
629
d2edda76 630 mySizeX = theSizeX;
631 mySizeY = theSizeY;
bf75be98 632
633 Unbind (theCtx);
634 return true;
635 }
636 case Graphic3d_TOT_2D_MIPMAP:
637 {
bf75be98 638 Bind (theCtx);
cc8cbabe 639 applyDefaultSamplerParams (theCtx);
d2edda76 640 if (toPatchExisting)
641 {
642 glTexSubImage2D (GL_TEXTURE_2D, 0,
643 0, 0,
644 theSizeX, theSizeY,
645 thePixelFormat, theDataType, aDataPtr);
646 if (theCtx->arbFBO != NULL)
647 {
648 // generate mipmaps
649 theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
650 if (glGetError() != GL_NO_ERROR)
651 {
652 Unbind (theCtx);
653 Release (theCtx.operator->());
654 return false;
655 }
656 }
657
658 Unbind (theCtx);
659 return true;
660 }
bf75be98 661
fa4dcbe0 662 #if !defined(GL_ES_VERSION_2_0)
663 // use proxy to check texture could be created or not
664 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
d2edda76 665 theSizeX, theSizeY, 0,
fa4dcbe0 666 thePixelFormat, theDataType, NULL);
667 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
668 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
15669413 669 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
fa4dcbe0 670 if (aTestWidth == 0 || aTestHeight == 0)
671 {
672 // no memory or broken input parameters
673 Unbind (theCtx);
674 Release (theCtx.operator->());
675 return false;
676 }
677 #endif
678
679 // upload main picture
680 glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
d2edda76 681 theSizeX, theSizeY, 0,
fa4dcbe0 682 thePixelFormat, theDataType, theImage->Data());
177781da 683 const GLenum aTexImgErr = glGetError();
684 if (aTexImgErr != GL_NO_ERROR)
1a7dfdb7 685 {
177781da 686 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
687 TCollection_AsciiString ("Error: 2D texture ") + theSizeX + "x" + theSizeY
688 + " IF: " + int(anIntFormat) + " PF: " + int(thePixelFormat) + " DT: " + int(theDataType)
689 + " can not be created with error " + int(aTexImgErr) + ".");
fa4dcbe0 690 Unbind (theCtx);
691 Release (theCtx.operator->());
692 return false;
693 }
694
d2edda76 695 mySizeX = theSizeX;
696 mySizeY = theSizeY;
fa4dcbe0 697
698 if (theCtx->arbFBO != NULL)
699 {
700 // generate mipmaps
701 //glHint (GL_GENERATE_MIPMAP_HINT, GL_NICEST);
702 theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
1a7dfdb7 703
a174a3c5 704 if (glGetError() != GL_NO_ERROR)
705 {
706 Unbind (theCtx);
18f4e8e2 707 Release (theCtx.operator->());
a174a3c5 708 return false;
709 }
1a7dfdb7 710 }
711 else
712 {
fa4dcbe0 713 const TCollection_ExtendedString aWarnMessage ("Warning: generating mipmaps requires GL_ARB_framebuffer_object extension which is missing.");
714
3b523c4c 715 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
a174a3c5 716
1a7dfdb7 717 Unbind (theCtx);
fa4dcbe0 718 Release (theCtx.operator->());
ca3c13d1 719 return false;
1a7dfdb7 720 }
fa4dcbe0 721
722 Unbind (theCtx);
723 return true;
bf75be98 724 }
bf75be98 725 }
d2edda76 726
727 Release (theCtx.operator->());
728 return false;
bf75be98 729}
68333c8f 730
18f4e8e2 731// =======================================================================
732// function : Init
733// purpose :
734// =======================================================================
735bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
736 const Image_PixMap& theImage,
737 const Graphic3d_TypeOfTexture theType)
738{
739 if (theImage.IsEmpty())
740 {
741 Release (theCtx.operator->());
742 return false;
743 }
744
745 GLenum aPixelFormat;
746 GLenum aDataType;
747 GLint aTextFormat;
748 if (!GetDataFormat (theCtx, theImage, aTextFormat, aPixelFormat, aDataType))
749 {
750 Release (theCtx.operator->());
751 return false;
752 }
753
754 return Init (theCtx,
755 aTextFormat, aPixelFormat, aDataType,
756 (Standard_Integer)theImage.SizeX(),
757 (Standard_Integer)theImage.SizeY(),
758 theType, &theImage);
759}
760
3c4b62a4 761// =======================================================================
762// function : Init2DMultisample
763// purpose :
764// =======================================================================
765bool OpenGl_Texture::Init2DMultisample (const Handle(OpenGl_Context)& theCtx,
766 const GLsizei theNbSamples,
767 const GLint theTextFormat,
768 const GLsizei theSizeX,
769 const GLsizei theSizeY)
770{
771 if (!Create (theCtx)
772 || theNbSamples > theCtx->MaxMsaaSamples()
773 || theNbSamples < 1)
774 {
775 return false;
776 }
777
15669413 778 myNbSamples = OpenGl_Context::GetPowerOfTwo (theNbSamples, theCtx->MaxMsaaSamples());
3c4b62a4 779 myTarget = GL_TEXTURE_2D_MULTISAMPLE;
15669413 780 myHasMipmaps = false;
3c4b62a4 781 if(theSizeX > theCtx->MaxTextureSize()
782 || theSizeY > theCtx->MaxTextureSize())
783 {
784 return false;
785 }
786
787 Bind (theCtx);
788 //myTextFormat = theTextFormat;
15669413 789 mySizedFormat = theTextFormat;
3c4b62a4 790#if !defined(GL_ES_VERSION_2_0)
791 if (theCtx->Functions()->glTexStorage2DMultisample != NULL)
792 {
15669413 793 theCtx->Functions()->glTexStorage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
3c4b62a4 794 }
795 else
796 {
15669413 797 theCtx->Functions()->glTexImage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
3c4b62a4 798 }
799#else
15669413 800 theCtx->Functions() ->glTexStorage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
3c4b62a4 801#endif
802 if (theCtx->core11fwd->glGetError() != GL_NO_ERROR)
803 {
804 Unbind (theCtx);
805 return false;
806 }
807
808 mySizeX = theSizeX;
809 mySizeY = theSizeY;
810
811 Unbind (theCtx);
812 return true;
813}
814
68333c8f 815// =======================================================================
816// function : InitRectangle
817// purpose :
818// =======================================================================
819bool OpenGl_Texture::InitRectangle (const Handle(OpenGl_Context)& theCtx,
820 const Standard_Integer theSizeX,
821 const Standard_Integer theSizeY,
822 const OpenGl_TextureFormat& theFormat)
823{
824 if (!Create (theCtx) || !theCtx->IsGlGreaterEqual (3, 0))
825 {
826 return false;
827 }
ca3c13d1 828
829#if !defined(GL_ES_VERSION_2_0)
68333c8f 830 myTarget = GL_TEXTURE_RECTANGLE;
15669413 831 myNbSamples = 1;
832 myHasMipmaps = false;
68333c8f 833
fe3a29bc 834 const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX);
835 const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY);
ca3c13d1 836
68333c8f 837 Bind (theCtx);
cc8cbabe 838 applyDefaultSamplerParams (theCtx);
68333c8f 839
15669413 840 myTextFormat = theFormat.Format();
841 mySizedFormat = theFormat.Internal();
68333c8f 842
15669413 843 glTexImage2D (GL_PROXY_TEXTURE_RECTANGLE, 0, mySizedFormat,
844 aSizeX, aSizeY, 0,
845 myTextFormat, GL_FLOAT, NULL);
68333c8f 846
847 GLint aTestSizeX = 0;
848 GLint aTestSizeY = 0;
849
15669413 850 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH, &aTestSizeX);
851 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
852 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
68333c8f 853
854 if (aTestSizeX == 0 || aTestSizeY == 0)
855 {
856 Unbind (theCtx);
857 return false;
858 }
859
15669413 860 glTexImage2D (myTarget, 0, mySizedFormat,
861 aSizeX, aSizeY, 0,
862 myTextFormat, GL_FLOAT, NULL);
68333c8f 863
864 if (glGetError() != GL_NO_ERROR)
865 {
866 Unbind (theCtx);
867 return false;
868 }
869
870 mySizeX = aSizeX;
871 mySizeY = aSizeY;
872
873 Unbind (theCtx);
874 return true;
ca3c13d1 875#else
20aeeb7b 876 (void )theSizeX;
877 (void )theSizeY;
878 (void )theFormat;
ca3c13d1 879 return false;
880#endif
68333c8f 881}
74fb257d 882
883// =======================================================================
884// function : Init3D
885// purpose :
886// =======================================================================
887bool OpenGl_Texture::Init3D (const Handle(OpenGl_Context)& theCtx,
888 const GLint theTextFormat,
889 const GLenum thePixelFormat,
890 const GLenum theDataType,
891 const Standard_Integer theSizeX,
892 const Standard_Integer theSizeY,
893 const Standard_Integer theSizeZ,
894 const void* thePixels)
895{
896 if (theCtx->Functions()->glTexImage3D == NULL)
897 {
898 TCollection_ExtendedString aMsg ("Error: three-dimensional textures are not supported by hardware.");
899
900 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
901 GL_DEBUG_TYPE_ERROR,
902 0,
903 GL_DEBUG_SEVERITY_HIGH,
904 aMsg);
905
906 return false;
907 }
908
909 if (!Create(theCtx))
910 {
911 return false;
912 }
913
914 myTarget = GL_TEXTURE_3D;
15669413 915 myNbSamples = 1;
916 myHasMipmaps = false;
74fb257d 917
918 const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX);
919 const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY);
920 const GLsizei aSizeZ = Min (theCtx->MaxTextureSize(), theSizeZ);
921
922 Bind (theCtx);
923
924 if (theDataType == GL_FLOAT && !theCtx->arbTexFloat)
925 {
926 TCollection_ExtendedString aMsg ("Error: floating-point textures are not supported by hardware.");
927
928 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
929 GL_DEBUG_TYPE_ERROR,
930 0,
931 GL_DEBUG_SEVERITY_HIGH,
932 aMsg);
933
934 Release (theCtx.operator->());
935 Unbind (theCtx);
936 return false;
937 }
938
15669413 939 mySizedFormat = theTextFormat;
74fb257d 940
941#if !defined (GL_ES_VERSION_2_0)
15669413 942 theCtx->core15fwd->glTexImage3D (GL_PROXY_TEXTURE_3D, 0, mySizedFormat,
943 aSizeX, aSizeY, aSizeZ, 0,
944 thePixelFormat, theDataType, NULL);
74fb257d 945
946 GLint aTestSizeX = 0;
947 GLint aTestSizeY = 0;
948 GLint aTestSizeZ = 0;
949
950 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &aTestSizeX);
951 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
952 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_DEPTH, &aTestSizeZ);
15669413 953 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
74fb257d 954
955 if (aTestSizeX == 0 || aTestSizeY == 0 || aTestSizeZ == 0)
956 {
957 Unbind (theCtx);
958 Release (theCtx.operator->());
959 return false;
960 }
961#endif
962
cc8cbabe 963 applyDefaultSamplerParams (theCtx);
15669413 964 theCtx->Functions()->glTexImage3D (myTarget, 0, mySizedFormat,
965 aSizeX, aSizeY, aSizeZ, 0,
966 thePixelFormat, theDataType, thePixels);
74fb257d 967
968 if (glGetError() != GL_NO_ERROR)
969 {
970 Unbind (theCtx);
971 Release (theCtx.operator->());
972 return false;
973 }
974
975 mySizeX = aSizeX;
976 mySizeY = aSizeY;
977 mySizeZ = aSizeZ;
978
979 Unbind (theCtx);
980 return true;
981}
15669413 982
983// =======================================================================
984// function : PixelSizeOfPixelFormat
985// purpose :
986// =======================================================================
987Standard_Size OpenGl_Texture::PixelSizeOfPixelFormat (Standard_Integer theInternalFormat)
988{
989 switch(theInternalFormat)
990 {
991 // RED variations (GL_RED, OpenGL 3.0+)
992 case GL_RED:
993 case GL_R8: return 1;
994 case GL_R16: return 2;
995 case GL_R16F: return 2;
996 case GL_R32F: return 4;
997 // RGB variations
998 case GL_RGB: return 3;
999 case GL_RGB8: return 3;
1000 case GL_RGB16: return 6;
1001 case GL_RGB16F: return 6;
1002 case GL_RGB32F: return 12;
1003 // RGBA variations
1004 case GL_RGBA: return 4;
1005 case GL_RGBA8: return 4;
1006 case GL_RGB10_A2: return 4;
1007 case GL_RGBA12: return 6;
1008 case GL_RGBA16: return 8;
1009 case GL_RGBA16F: return 8;
1010 case GL_RGBA32F: return 16;
1011 //
1012 case GL_BGRA_EXT: return 4;
1013 // ALPHA variations (deprecated)
1014 case GL_ALPHA:
1015 case GL_ALPHA8: return 1;
1016 case GL_ALPHA16: return 2;
1017 case GL_LUMINANCE: return 1;
1018 case GL_LUMINANCE_ALPHA: return 2;
1019 // depth-stencil
1020 case GL_DEPTH24_STENCIL8: return 4;
1021 case GL_DEPTH32F_STENCIL8: return 8;
1022 case GL_DEPTH_COMPONENT16: return 2;
1023 case GL_DEPTH_COMPONENT24: return 3;
1024 case GL_DEPTH_COMPONENT32F: return 4;
1025 }
1026 return 0;
1027}
1028
1029// =======================================================================
1030// function : EstimatedDataSize
1031// purpose :
1032// =======================================================================
1033Standard_Size OpenGl_Texture::EstimatedDataSize() const
1034{
1035 if (!IsValid())
1036 {
1037 return 0;
1038 }
1039
1040 Standard_Size aSize = PixelSizeOfPixelFormat (mySizedFormat) * mySizeX * myNbSamples;
1041 if (mySizeY != 0)
1042 {
1043 aSize *= Standard_Size(mySizeY);
1044 }
1045 if (mySizeZ != 0)
1046 {
1047 aSize *= Standard_Size(mySizeZ);
1048 }
1049 if (myHasMipmaps)
1050 {
1051 aSize = aSize + aSize / 3;
1052 }
1053 return aSize;
1054}