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