0026975: Visualization, TKOpenGl - handle triangle strips correctly within Ray-Tracin...
[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(),
54 myTextureId (NO_TEXTURE),
55 myTarget (GL_TEXTURE_2D),
56 mySizeX (0),
57 mySizeY (0),
8625ef7e 58 myTextFormat (GL_RGBA),
bf75be98 59 myHasMipmaps (Standard_False),
4e1523ef 60 myIsAlpha (false),
bf75be98 61 myParams (theParams)
62{
63 if (myParams.IsNull())
64 {
65 myParams = new Graphic3d_TextureParams();
66 }
67}
68
69// =======================================================================
70// function : ~OpenGl_Texture
71// purpose :
72// =======================================================================
73OpenGl_Texture::~OpenGl_Texture()
74{
75 Release (NULL);
76}
77
78// =======================================================================
79// function : HasMipmaps
80// purpose :
81// =======================================================================
487bf1ce 82Standard_Boolean OpenGl_Texture::HasMipmaps() const
bf75be98 83{
84 return myHasMipmaps;
85}
86
87// =======================================================================
88// function : GetParams
89// purpose :
90// =======================================================================
91const Handle(Graphic3d_TextureParams)& OpenGl_Texture::GetParams() const
92{
93 return myParams;
94}
95
96// =======================================================================
97// function : SetParams
98// purpose :
99// =======================================================================
100void OpenGl_Texture::SetParams (const Handle(Graphic3d_TextureParams)& theParams)
101{
102 myParams = theParams;
103}
104
105// =======================================================================
106// function : Create
107// purpose :
108// =======================================================================
109bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& )
110{
111 if (myTextureId == NO_TEXTURE)
112 {
113 glGenTextures (1, &myTextureId);
114 }
115 return myTextureId != NO_TEXTURE;
116}
117
118// =======================================================================
119// function : Release
120// purpose :
121// =======================================================================
10b9c7df 122void OpenGl_Texture::Release (OpenGl_Context* theGlCtx)
bf75be98 123{
124 if (myTextureId == NO_TEXTURE)
125 {
126 return;
127 }
128
129 // application can not handle this case by exception - this is bug in code
130 Standard_ASSERT_RETURN (theGlCtx != NULL,
131 "OpenGl_Texture destroyed without GL context! Possible GPU memory leakage...",);
132
ec2eeb2d 133 if (theGlCtx->IsValid())
134 {
135 glDeleteTextures (1, &myTextureId);
136 }
bf75be98 137 myTextureId = NO_TEXTURE;
138 mySizeX = mySizeY = 0;
139}
140
141// =======================================================================
142// function : Bind
143// purpose :
144// =======================================================================
145void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
146 const GLenum theTextureUnit) const
147{
4e1523ef 148 if (theCtx->core15fwd != NULL)
bf75be98 149 {
01ca42b2 150 theCtx->core15fwd->glActiveTexture (theTextureUnit);
bf75be98 151 }
152 glBindTexture (myTarget, myTextureId);
153}
154
155// =======================================================================
156// function : Unbind
157// purpose :
158// =======================================================================
159void OpenGl_Texture::Unbind (const Handle(OpenGl_Context)& theCtx,
160 const GLenum theTextureUnit) const
161{
4e1523ef 162 if (theCtx->core15fwd != NULL)
bf75be98 163 {
01ca42b2 164 theCtx->core15fwd->glActiveTexture (theTextureUnit);
bf75be98 165 }
166 glBindTexture (myTarget, NO_TEXTURE);
167}
168
18f4e8e2 169//=======================================================================
170//function : GetDataFormat
171//purpose :
172//=======================================================================
173bool OpenGl_Texture::GetDataFormat (const Handle(OpenGl_Context)& theCtx,
174 const Image_PixMap& theData,
175 GLint& theTextFormat,
176 GLenum& thePixelFormat,
177 GLenum& theDataType)
bf75be98 178{
18f4e8e2 179 theTextFormat = GL_RGBA8;
180 thePixelFormat = 0;
181 theDataType = 0;
182 switch (theData.Format())
bf75be98 183 {
184 case Image_PixMap::ImgGrayF:
185 {
076ca35c 186 if (theCtx->core11 == NULL)
187 {
188 theTextFormat = GL_R8; // GL_R32F
189 thePixelFormat = GL_RED;
190 }
191 else
192 {
193 theTextFormat = GL_LUMINANCE8;
194 thePixelFormat = GL_LUMINANCE;
195 }
196 theDataType = GL_FLOAT;
197 return true;
198 }
199 case Image_PixMap::ImgAlphaF:
200 {
201 if (theCtx->core11 == NULL)
202 {
203 theTextFormat = GL_R8; // GL_R32F
204 thePixelFormat = GL_RED;
205 }
206 else
207 {
208 theTextFormat = GL_ALPHA8;
209 thePixelFormat = GL_ALPHA;
210 }
211 theDataType = GL_FLOAT;
18f4e8e2 212 return true;
bf75be98 213 }
214 case Image_PixMap::ImgRGBAF:
215 {
076ca35c 216 theTextFormat = GL_RGBA8; // GL_RGBA32F
18f4e8e2 217 thePixelFormat = GL_RGBA;
218 theDataType = GL_FLOAT;
219 return true;
bf75be98 220 }
221 case Image_PixMap::ImgBGRAF:
222 {
223 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
224 {
225 return false;
226 }
ca3c13d1 227 theTextFormat = GL_RGBA8; // GL_RGBA32F
228 thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
18f4e8e2 229 theDataType = GL_FLOAT;
230 return true;
bf75be98 231 }
232 case Image_PixMap::ImgRGBF:
233 {
076ca35c 234 theTextFormat = GL_RGB8; // GL_RGB32F
18f4e8e2 235 thePixelFormat = GL_RGB;
236 theDataType = GL_FLOAT;
237 return true;
bf75be98 238 }
239 case Image_PixMap::ImgBGRF:
240 {
ca3c13d1 241 #if !defined(GL_ES_VERSION_2_0)
242 theTextFormat = GL_RGB8; // GL_RGB32F
18f4e8e2 243 thePixelFormat = GL_BGR; // equals to GL_BGR_EXT
244 theDataType = GL_FLOAT;
245 return true;
ca3c13d1 246 #else
247 return false;
248 #endif
bf75be98 249 }
250 case Image_PixMap::ImgRGBA:
251 {
18f4e8e2 252 theTextFormat = GL_RGBA8;
253 thePixelFormat = GL_RGBA;
254 theDataType = GL_UNSIGNED_BYTE;
255 return true;
bf75be98 256 }
257 case Image_PixMap::ImgBGRA:
258 {
259 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
260 {
261 return false;
262 }
ca3c13d1 263 theTextFormat = GL_RGBA8;
264 thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
18f4e8e2 265 theDataType = GL_UNSIGNED_BYTE;
266 return true;
bf75be98 267 }
268 case Image_PixMap::ImgRGB32:
269 {
18f4e8e2 270 theTextFormat = GL_RGB8;
271 thePixelFormat = GL_RGBA;
272 theDataType = GL_UNSIGNED_BYTE;
273 return true;
bf75be98 274 }
275 case Image_PixMap::ImgBGR32:
276 {
277 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
278 {
279 return false;
280 }
ca3c13d1 281 theTextFormat = GL_RGB8;
282 thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
18f4e8e2 283 theDataType = GL_UNSIGNED_BYTE;
284 return true;
bf75be98 285 }
286 case Image_PixMap::ImgRGB:
287 {
18f4e8e2 288 theTextFormat = GL_RGB8;
289 thePixelFormat = GL_RGB;
290 theDataType = GL_UNSIGNED_BYTE;
291 return true;
bf75be98 292 }
293 case Image_PixMap::ImgBGR:
294 {
ca3c13d1 295 #if !defined(GL_ES_VERSION_2_0)
bf75be98 296 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
297 {
298 return false;
299 }
18f4e8e2 300 theTextFormat = GL_RGB8;
301 thePixelFormat = GL_BGR; // equals to GL_BGR_EXT
302 theDataType = GL_UNSIGNED_BYTE;
303 return true;
ca3c13d1 304 #else
305 return false;
306 #endif
bf75be98 307 }
308 case Image_PixMap::ImgGray:
309 {
076ca35c 310 if (theCtx->core11 == NULL)
311 {
312 theTextFormat = GL_R8;
313 thePixelFormat = GL_RED;
314 }
315 else
316 {
317 theTextFormat = GL_LUMINANCE8;
318 thePixelFormat = GL_LUMINANCE;
319 }
320 theDataType = GL_UNSIGNED_BYTE;
321 return true;
322 }
323 case Image_PixMap::ImgAlpha:
324 {
325 if (theCtx->core11 == NULL)
326 {
327 theTextFormat = GL_R8;
328 thePixelFormat = GL_RED;
329 }
330 else
331 {
332 theTextFormat = GL_ALPHA8;
333 thePixelFormat = GL_ALPHA;
334 }
335 theDataType = GL_UNSIGNED_BYTE;
18f4e8e2 336 return true;
bf75be98 337 }
076ca35c 338 case Image_PixMap::ImgUNKNOWN:
bf75be98 339 {
340 return false;
341 }
342 }
076ca35c 343 return false;
18f4e8e2 344}
bf75be98 345
18f4e8e2 346// =======================================================================
347// function : Init
348// purpose :
349// =======================================================================
350bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
351 const Standard_Integer theTextFormat,
352 const GLenum thePixelFormat,
353 const GLenum theDataType,
354 const Standard_Integer theSizeX,
355 const Standard_Integer theSizeY,
356 const Graphic3d_TypeOfTexture theType,
357 const Image_PixMap* theImage)
358{
359 if (!Create (theCtx))
360 {
361 Release (theCtx.operator->());
362 return false;
363 }
4e1523ef 364
365 if (theImage != NULL)
366 {
367 myIsAlpha = theImage->Format() == Image_PixMap::ImgAlpha
368 || theImage->Format() == Image_PixMap::ImgAlphaF;
369 }
370 else
371 {
372 myIsAlpha = thePixelFormat == GL_ALPHA;
373 }
374
18f4e8e2 375 myHasMipmaps = Standard_False;
8625ef7e 376 myTextFormat = thePixelFormat;
377#if !defined(GL_ES_VERSION_2_0)
378 const GLint anIntFormat = theTextFormat;
379#else
380 // ES does not support sized formats and format conversions - them detected from data type
381 const GLint anIntFormat = thePixelFormat;
382#endif
18f4e8e2 383 const GLsizei aWidth = theSizeX;
384 const GLsizei aHeight = theSizeY;
bf75be98 385 const GLsizei aMaxSize = theCtx->MaxTextureSize();
bf75be98 386
fa4dcbe0 387 if (aWidth > aMaxSize || aHeight > aMaxSize)
388 {
389 TCollection_ExtendedString aWarnMessage = TCollection_ExtendedString ("Error: Texture dimension - ")
390 + aWidth + "x" + aHeight + " exceeds hardware limits (" + aMaxSize + "x" + aMaxSize + ")";
391
392 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
393 Release (theCtx.operator->());
394 return false;
395 }
396#if !defined(GL_ES_VERSION_2_0)
397 else if (!theCtx->IsGlGreaterEqual (3, 0) && !theCtx->arbNPTW)
398 {
399 // Notice that formally general NPOT textures are required by OpenGL 2.0 specifications
400 // however some hardware (NV30 - GeForce FX, RadeOn 9xxx and Xxxx) supports GLSL but not NPOT!
401 // Trying to create NPOT textures on such hardware will not fail
402 // but driver will fall back into software rendering,
403 const GLsizei aWidthP2 = OpenGl_Context::GetPowerOfTwo (aWidth, aMaxSize);
404 const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (aHeight, aMaxSize);
405
406 if (aWidth != aWidthP2 || (theType != Graphic3d_TOT_1D && aHeight != aHeightP2))
407 {
408 TCollection_ExtendedString aWarnMessage =
409 TCollection_ExtendedString ("Error: NPOT Textures (") + aWidth + "x" + aHeight + ") are not supported by hardware.";
410
411 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
412
413 Release (theCtx.operator->());
414 return false;
415 }
416 }
417#else
418 else if (!theCtx->IsGlGreaterEqual (3, 0) && theType == Graphic3d_TOT_2D_MIPMAP)
419 {
420 // Mipmap NPOT textures are not supported by OpenGL ES 2.0.
421 const GLsizei aWidthP2 = OpenGl_Context::GetPowerOfTwo (aWidth, aMaxSize);
422 const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (aHeight, aMaxSize);
423
424 if (aWidth != aWidthP2 || aHeight != aHeightP2)
425 {
426 TCollection_ExtendedString aWarnMessage =
427 TCollection_ExtendedString ("Error: Mipmap NPOT Textures (") + aWidth + "x" + aHeight + ") are not supported by OpenGL ES 2.0";
428
429 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
430
431 Release (theCtx.operator->());
432 return false;
433 }
434 }
435#endif
436
437 const GLenum aFilter = (myParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
438 const GLenum aWrapMode = myParams->IsRepeat() ? GL_REPEAT : theCtx->TextureWrapClamp();
bf75be98 439
ca3c13d1 440#if !defined(GL_ES_VERSION_2_0)
bf75be98 441 GLint aTestWidth = 0;
442 GLint aTestHeight = 0;
ca3c13d1 443#endif
18f4e8e2 444 GLvoid* aDataPtr = (theImage != NULL) ? (GLvoid* )theImage->Data() : NULL;
bf75be98 445
74706083 446 // setup the alignment
447 OpenGl_UnpackAlignmentSentry anUnpackSentry;
fa4dcbe0 448 (void)anUnpackSentry; // avoid compiler warning
449
18f4e8e2 450 if (aDataPtr != NULL)
451 {
452 const GLint anAligment = Min ((GLint )theImage->MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes
453 glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment);
74706083 454
ca3c13d1 455 #if !defined(GL_ES_VERSION_2_0)
18f4e8e2 456 // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension
457 const GLint anExtraBytes = GLint(theImage->RowExtraBytes());
458 const GLint aPixelsWidth = GLint(theImage->SizeRowBytes() / theImage->SizePixelBytes());
459 glPixelStorei (GL_UNPACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
ca3c13d1 460 #endif
18f4e8e2 461 }
74706083 462
bf75be98 463 switch (theType)
464 {
465 case Graphic3d_TOT_1D:
466 {
ca3c13d1 467 #if !defined(GL_ES_VERSION_2_0)
bf75be98 468 myTarget = GL_TEXTURE_1D;
469 Bind (theCtx);
fe3a29bc 470 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
471 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
472 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, aWrapMode);
bf75be98 473
bf75be98 474 // use proxy to check texture could be created or not
8625ef7e 475 glTexImage1D (GL_PROXY_TEXTURE_1D, 0, anIntFormat,
fa4dcbe0 476 aWidth, 0,
18f4e8e2 477 thePixelFormat, theDataType, NULL);
bf75be98 478 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
479 if (aTestWidth == 0)
480 {
481 // no memory or broken input parameters
482 Unbind (theCtx);
18f4e8e2 483 Release (theCtx.operator->());
bf75be98 484 return false;
485 }
486
8625ef7e 487 glTexImage1D (GL_TEXTURE_1D, 0, anIntFormat,
fa4dcbe0 488 aWidth, 0,
18f4e8e2 489 thePixelFormat, theDataType, aDataPtr);
a174a3c5 490 if (glGetError() != GL_NO_ERROR)
491 {
492 Unbind (theCtx);
18f4e8e2 493 Release (theCtx.operator->());
a174a3c5 494 return false;
495 }
496
fa4dcbe0 497 mySizeX = aWidth;
a174a3c5 498 mySizeY = 1;
bf75be98 499
500 Unbind (theCtx);
501 return true;
ca3c13d1 502 #else
fa4dcbe0 503 Release (theCtx.operator->());
ca3c13d1 504 return false;
505 #endif
bf75be98 506 }
507 case Graphic3d_TOT_2D:
508 {
509 myTarget = GL_TEXTURE_2D;
510 Bind (theCtx);
fe3a29bc 511 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilter);
512 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
513 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aWrapMode);
514 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aWrapMode);
bf75be98 515
ca3c13d1 516 #if !defined(GL_ES_VERSION_2_0)
bf75be98 517 // use proxy to check texture could be created or not
8625ef7e 518 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
fa4dcbe0 519 aWidth, aHeight, 0,
18f4e8e2 520 thePixelFormat, theDataType, NULL);
bf75be98 521 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
522 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
523 if (aTestWidth == 0 || aTestHeight == 0)
524 {
525 // no memory or broken input parameters
526 Unbind (theCtx);
18f4e8e2 527 Release (theCtx.operator->());
bf75be98 528 return false;
529 }
ca3c13d1 530 #endif
bf75be98 531
8625ef7e 532 glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
fa4dcbe0 533 aWidth, aHeight, 0,
18f4e8e2 534 thePixelFormat, theDataType, aDataPtr);
a174a3c5 535 if (glGetError() != GL_NO_ERROR)
536 {
537 Unbind (theCtx);
18f4e8e2 538 Release (theCtx.operator->());
a174a3c5 539 return false;
540 }
541
fa4dcbe0 542 mySizeX = aWidth;
543 mySizeY = aHeight;
bf75be98 544
545 Unbind (theCtx);
546 return true;
547 }
548 case Graphic3d_TOT_2D_MIPMAP:
549 {
550 myTarget = GL_TEXTURE_2D;
551 myHasMipmaps = Standard_True;
fe3a29bc 552
553 GLenum aFilterMin = aFilter;
554 aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
555 if (myParams->Filter() == Graphic3d_TOTF_BILINEAR)
556 {
557 aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
558 }
559 else if (myParams->Filter() == Graphic3d_TOTF_TRILINEAR)
560 {
561 aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
562 }
563
bf75be98 564 Bind (theCtx);
fe3a29bc 565 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
566 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
567 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aWrapMode);
568 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aWrapMode);
bf75be98 569
fa4dcbe0 570 #if !defined(GL_ES_VERSION_2_0)
571 // use proxy to check texture could be created or not
572 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
573 aWidth, aHeight, 0,
574 thePixelFormat, theDataType, NULL);
575 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
576 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
577 if (aTestWidth == 0 || aTestHeight == 0)
578 {
579 // no memory or broken input parameters
580 Unbind (theCtx);
581 Release (theCtx.operator->());
582 return false;
583 }
584 #endif
585
586 // upload main picture
587 glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
588 aWidth, aHeight, 0,
589 thePixelFormat, theDataType, theImage->Data());
590 if (glGetError() != GL_NO_ERROR)
1a7dfdb7 591 {
fa4dcbe0 592 Unbind (theCtx);
593 Release (theCtx.operator->());
594 return false;
595 }
596
597 mySizeX = aWidth;
598 mySizeY = aHeight;
599
600 if (theCtx->arbFBO != NULL)
601 {
602 // generate mipmaps
603 //glHint (GL_GENERATE_MIPMAP_HINT, GL_NICEST);
604 theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
1a7dfdb7 605
a174a3c5 606 if (glGetError() != GL_NO_ERROR)
607 {
608 Unbind (theCtx);
18f4e8e2 609 Release (theCtx.operator->());
a174a3c5 610 return false;
611 }
1a7dfdb7 612 }
613 else
614 {
fa4dcbe0 615 const TCollection_ExtendedString aWarnMessage ("Warning: generating mipmaps requires GL_ARB_framebuffer_object extension which is missing.");
616
3b523c4c 617 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
a174a3c5 618
1a7dfdb7 619 Unbind (theCtx);
fa4dcbe0 620 Release (theCtx.operator->());
ca3c13d1 621 return false;
1a7dfdb7 622 }
fa4dcbe0 623
624 Unbind (theCtx);
625 return true;
bf75be98 626 }
627 default:
628 {
18f4e8e2 629 Release (theCtx.operator->());
bf75be98 630 return false;
631 }
632 }
633}
68333c8f 634
635// =======================================================================
18f4e8e2 636// function : Init
637// purpose :
638// =======================================================================
639bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
640 const Image_PixMap& theImage,
641 const Graphic3d_TypeOfTexture theType)
642{
643 if (theImage.IsEmpty())
644 {
645 Release (theCtx.operator->());
646 return false;
647 }
648
649 GLenum aPixelFormat;
650 GLenum aDataType;
651 GLint aTextFormat;
652 if (!GetDataFormat (theCtx, theImage, aTextFormat, aPixelFormat, aDataType))
653 {
654 Release (theCtx.operator->());
655 return false;
656 }
657
658 return Init (theCtx,
659 aTextFormat, aPixelFormat, aDataType,
660 (Standard_Integer)theImage.SizeX(),
661 (Standard_Integer)theImage.SizeY(),
662 theType, &theImage);
663}
664
665// =======================================================================
3c4b62a4 666// function : Init2DMultisample
667// purpose :
668// =======================================================================
669bool OpenGl_Texture::Init2DMultisample (const Handle(OpenGl_Context)& theCtx,
670 const GLsizei theNbSamples,
671 const GLint theTextFormat,
672 const GLsizei theSizeX,
673 const GLsizei theSizeY)
674{
675 if (!Create (theCtx)
676 || theNbSamples > theCtx->MaxMsaaSamples()
677 || theNbSamples < 1)
678 {
679 return false;
680 }
681
682 const GLsizei aNbSamples = OpenGl_Context::GetPowerOfTwo (theNbSamples, theCtx->MaxMsaaSamples());
683 myTarget = GL_TEXTURE_2D_MULTISAMPLE;
684 if(theSizeX > theCtx->MaxTextureSize()
685 || theSizeY > theCtx->MaxTextureSize())
686 {
687 return false;
688 }
689
690 Bind (theCtx);
691 //myTextFormat = theTextFormat;
692#if !defined(GL_ES_VERSION_2_0)
693 if (theCtx->Functions()->glTexStorage2DMultisample != NULL)
694 {
695 theCtx->Functions()->glTexStorage2DMultisample (myTarget, aNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
696 }
697 else
698 {
699 theCtx->Functions()->glTexImage2DMultisample (myTarget, aNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
700 }
701#else
702 theCtx->Functions() ->glTexStorage2DMultisample (myTarget, aNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
703#endif
704 if (theCtx->core11fwd->glGetError() != GL_NO_ERROR)
705 {
706 Unbind (theCtx);
707 return false;
708 }
709
710 mySizeX = theSizeX;
711 mySizeY = theSizeY;
712
713 Unbind (theCtx);
714 return true;
715}
716
717// =======================================================================
68333c8f 718// function : InitRectangle
719// purpose :
720// =======================================================================
721bool OpenGl_Texture::InitRectangle (const Handle(OpenGl_Context)& theCtx,
722 const Standard_Integer theSizeX,
723 const Standard_Integer theSizeY,
724 const OpenGl_TextureFormat& theFormat)
725{
726 if (!Create (theCtx) || !theCtx->IsGlGreaterEqual (3, 0))
727 {
728 return false;
729 }
ca3c13d1 730
731#if !defined(GL_ES_VERSION_2_0)
68333c8f 732 myTarget = GL_TEXTURE_RECTANGLE;
733
fe3a29bc 734 const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX);
735 const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY);
736 const GLenum aFilter = (myParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
737 const GLenum aWrapMode = myParams->IsRepeat() ? GL_REPEAT : theCtx->TextureWrapClamp();
ca3c13d1 738
68333c8f 739 Bind (theCtx);
fe3a29bc 740 glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, aFilter);
741 glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, aFilter);
742 glTexParameteri (myTarget, GL_TEXTURE_WRAP_S, aWrapMode);
743 glTexParameteri (myTarget, GL_TEXTURE_WRAP_T, aWrapMode);
68333c8f 744
8625ef7e 745 const GLint anIntFormat = theFormat.Internal();
746 myTextFormat = theFormat.Format();
68333c8f 747
748 glTexImage2D (GL_PROXY_TEXTURE_RECTANGLE,
749 0,
8625ef7e 750 anIntFormat,
68333c8f 751 aSizeX,
752 aSizeY,
753 0,
754 theFormat.Format(),
755 GL_FLOAT,
756 NULL);
757
758 GLint aTestSizeX = 0;
759 GLint aTestSizeY = 0;
760
761 glGetTexLevelParameteriv (
762 GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH, &aTestSizeX);
763 glGetTexLevelParameteriv (
764 GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
765
766 if (aTestSizeX == 0 || aTestSizeY == 0)
767 {
768 Unbind (theCtx);
769 return false;
770 }
771
772 glTexImage2D (myTarget,
773 0,
8625ef7e 774 anIntFormat,
68333c8f 775 aSizeX,
776 aSizeY,
777 0,
778 theFormat.Format(),
779 GL_FLOAT,
780 NULL);
781
782 if (glGetError() != GL_NO_ERROR)
783 {
784 Unbind (theCtx);
785 return false;
786 }
787
788 mySizeX = aSizeX;
789 mySizeY = aSizeY;
790
791 Unbind (theCtx);
792 return true;
ca3c13d1 793#else
794 return false;
795#endif
68333c8f 796}