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