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