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