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