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