1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #include <OpenGl_Texture.hxx>
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>
26 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_NamedResource)
28 //! Simple class to reset unpack alignment settings
29 struct OpenGl_UnpackAlignmentSentry
32 //! Reset unpack alignment settings to safe values
35 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
36 #if !defined(GL_ES_VERSION_2_0)
37 glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
41 OpenGl_UnpackAlignmentSentry() {}
43 ~OpenGl_UnpackAlignmentSentry()
50 // =======================================================================
51 // function : OpenGl_Texture
53 // =======================================================================
54 OpenGl_Texture::OpenGl_Texture (const TCollection_AsciiString& theResourceId,
55 const Handle(Graphic3d_TextureParams)& theParams)
56 : OpenGl_NamedResource (theResourceId),
57 mySampler (new OpenGl_Sampler (theParams)),
59 myTextureId (NO_TEXTURE),
60 myTarget (GL_TEXTURE_2D),
64 myTextFormat (GL_RGBA),
65 mySizedFormat(GL_RGBA8),
67 myHasMipmaps (Standard_False),
73 // =======================================================================
74 // function : ~OpenGl_Texture
76 // =======================================================================
77 OpenGl_Texture::~OpenGl_Texture()
82 // =======================================================================
85 // =======================================================================
86 bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& theCtx)
88 if (myTextureId != NO_TEXTURE)
93 theCtx->core11fwd->glGenTextures (1, &myTextureId);
94 if (myTextureId == NO_TEXTURE)
99 //mySampler->Create (theCtx); // do not create sampler object by default
103 // =======================================================================
104 // function : Release
106 // =======================================================================
107 void OpenGl_Texture::Release (OpenGl_Context* theGlCtx)
109 mySampler->Release (theGlCtx);
110 if (myTextureId == NO_TEXTURE)
115 // application can not handle this case by exception - this is bug in code
116 Standard_ASSERT_RETURN (theGlCtx != NULL,
117 "OpenGl_Texture destroyed without GL context! Possible GPU memory leakage...",);
119 if (theGlCtx->IsValid())
121 glDeleteTextures (1, &myTextureId);
123 myTextureId = NO_TEXTURE;
124 mySizeX = mySizeY = mySizeZ = 0;
127 // =======================================================================
128 // function : applyDefaultSamplerParams
130 // =======================================================================
131 void OpenGl_Texture::applyDefaultSamplerParams (const Handle(OpenGl_Context)& theCtx)
133 OpenGl_Sampler::applySamplerParams (theCtx, mySampler->Parameters(), NULL, myTarget, myHasMipmaps);
134 if (mySampler->IsValid() && !mySampler->IsImmutable())
136 OpenGl_Sampler::applySamplerParams (theCtx, mySampler->Parameters(), mySampler.get(), myTarget, myHasMipmaps);
140 // =======================================================================
143 // =======================================================================
144 void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
145 const Graphic3d_TextureUnit theTextureUnit) const
147 if (theCtx->core15fwd != NULL)
149 theCtx->core15fwd->glActiveTexture (GL_TEXTURE0 + theTextureUnit);
151 mySampler->Bind (theCtx, theTextureUnit);
152 glBindTexture (myTarget, myTextureId);
155 // =======================================================================
158 // =======================================================================
159 void OpenGl_Texture::Unbind (const Handle(OpenGl_Context)& theCtx,
160 const Graphic3d_TextureUnit theTextureUnit) const
162 if (theCtx->core15fwd != NULL)
164 theCtx->core15fwd->glActiveTexture (GL_TEXTURE0 + theTextureUnit);
166 mySampler->Unbind (theCtx, theTextureUnit);
167 glBindTexture (myTarget, NO_TEXTURE);
170 //=======================================================================
171 //function : InitSamplerObject
173 //=======================================================================
174 bool OpenGl_Texture::InitSamplerObject (const Handle(OpenGl_Context)& theCtx)
176 return myTextureId != NO_TEXTURE
177 && mySampler->Init (theCtx, *this);
180 //=======================================================================
181 //function : GetDataFormat
183 //=======================================================================
184 bool OpenGl_Texture::GetDataFormat (const Handle(OpenGl_Context)& theCtx,
185 const Image_Format theFormat,
186 GLint& theTextFormat,
187 GLenum& thePixelFormat,
190 theTextFormat = GL_RGBA8;
195 case Image_Format_GrayF:
197 if (theCtx->core11 == NULL)
199 theTextFormat = GL_R8; // GL_R32F
200 thePixelFormat = GL_RED;
204 #if !defined(GL_ES_VERSION_2_0)
205 theTextFormat = GL_LUMINANCE8;
207 theTextFormat = GL_LUMINANCE;
209 thePixelFormat = GL_LUMINANCE;
211 theDataType = GL_FLOAT;
214 case Image_Format_AlphaF:
216 if (theCtx->core11 == NULL)
218 theTextFormat = GL_R8; // GL_R32F
219 thePixelFormat = GL_RED;
223 #if !defined(GL_ES_VERSION_2_0)
224 theTextFormat = GL_ALPHA8;
226 theTextFormat = GL_ALPHA;
228 thePixelFormat = GL_ALPHA;
230 theDataType = GL_FLOAT;
233 case Image_Format_RGBAF:
235 theTextFormat = GL_RGBA8; // GL_RGBA32F
236 thePixelFormat = GL_RGBA;
237 theDataType = GL_FLOAT;
240 case Image_Format_BGRAF:
242 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
246 theTextFormat = GL_RGBA8; // GL_RGBA32F
247 thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
248 theDataType = GL_FLOAT;
251 case Image_Format_RGBF:
253 theTextFormat = GL_RGB8; // GL_RGB32F
254 thePixelFormat = GL_RGB;
255 theDataType = GL_FLOAT;
258 case Image_Format_BGRF:
260 #if !defined(GL_ES_VERSION_2_0)
261 theTextFormat = GL_RGB8; // GL_RGB32F
262 thePixelFormat = GL_BGR; // equals to GL_BGR_EXT
263 theDataType = GL_FLOAT;
269 case Image_Format_RGBA:
271 theTextFormat = GL_RGBA8;
272 thePixelFormat = GL_RGBA;
273 theDataType = GL_UNSIGNED_BYTE;
276 case Image_Format_BGRA:
278 #if !defined(GL_ES_VERSION_2_0)
279 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
283 theTextFormat = GL_RGBA8;
285 if (!theCtx->extBgra)
289 theTextFormat = GL_BGRA_EXT;
291 thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
292 theDataType = GL_UNSIGNED_BYTE;
295 case Image_Format_RGB32:
297 #if !defined(GL_ES_VERSION_2_0)
298 // ask driver to convert data to RGB8 to save memory
299 theTextFormat = GL_RGB8;
301 // conversion is not supported
302 theTextFormat = GL_RGBA8;
304 thePixelFormat = GL_RGBA;
305 theDataType = GL_UNSIGNED_BYTE;
308 case Image_Format_BGR32:
310 #if !defined(GL_ES_VERSION_2_0)
311 if (!theCtx->IsGlGreaterEqual(1, 2) && !theCtx->extBgra)
315 theTextFormat = GL_RGB8;
317 if (!theCtx->extBgra)
321 theTextFormat = GL_BGRA_EXT;
323 thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
324 theDataType = GL_UNSIGNED_BYTE;
327 case Image_Format_RGB:
329 theTextFormat = GL_RGB8;
330 thePixelFormat = GL_RGB;
331 theDataType = GL_UNSIGNED_BYTE;
334 case Image_Format_BGR:
336 #if !defined(GL_ES_VERSION_2_0)
337 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
341 theTextFormat = GL_RGB8;
342 thePixelFormat = GL_BGR; // equals to GL_BGR_EXT
343 theDataType = GL_UNSIGNED_BYTE;
349 case Image_Format_Gray:
351 if (theCtx->core11 == NULL)
353 theTextFormat = GL_R8;
354 thePixelFormat = GL_RED;
358 #if !defined(GL_ES_VERSION_2_0)
359 theTextFormat = GL_LUMINANCE8;
361 theTextFormat = GL_LUMINANCE;
363 thePixelFormat = GL_LUMINANCE;
365 theDataType = GL_UNSIGNED_BYTE;
368 case Image_Format_Alpha:
370 if (theCtx->core11 == NULL)
372 theTextFormat = GL_R8;
373 thePixelFormat = GL_RED;
377 #if !defined(GL_ES_VERSION_2_0)
378 theTextFormat = GL_ALPHA8;
380 theTextFormat = GL_ALPHA;
382 thePixelFormat = GL_ALPHA;
384 theDataType = GL_UNSIGNED_BYTE;
387 case Image_Format_UNKNOWN:
395 // =======================================================================
398 // =======================================================================
399 bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
400 const Standard_Integer theTextFormat,
401 const GLenum thePixelFormat,
402 const GLenum theDataType,
403 const Standard_Integer theSizeX,
404 const Standard_Integer theSizeY,
405 const Graphic3d_TypeOfTexture theType,
406 const Image_PixMap* theImage)
411 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
412 "Error: texture of 0 size cannot be created.");
413 Release (theCtx.operator->());
417 #if !defined(GL_ES_VERSION_2_0)
418 const GLenum aTarget = theType == Graphic3d_TOT_1D
422 const GLenum aTarget = GL_TEXTURE_2D;
424 const Standard_Boolean toCreateMipMaps = (theType == Graphic3d_TOT_2D_MIPMAP);
425 const bool toPatchExisting = IsValid()
426 && myTextFormat == thePixelFormat
427 && myTarget == aTarget
428 && myHasMipmaps == toCreateMipMaps
429 && mySizeX == theSizeX
430 && (mySizeY == theSizeY || theType == Graphic3d_TOT_1D);
431 if (!Create (theCtx))
433 Release (theCtx.operator->());
437 if (theImage != NULL)
439 myIsAlpha = theImage->Format() == Image_Format_Alpha
440 || theImage->Format() == Image_Format_AlphaF;
444 myIsAlpha = thePixelFormat == GL_ALPHA;
447 myHasMipmaps = toCreateMipMaps;
448 myTextFormat = thePixelFormat;
449 mySizedFormat = theTextFormat;
451 #if !defined(GL_ES_VERSION_2_0)
452 const GLint anIntFormat = theTextFormat;
454 // ES 2.0 does not support sized formats and format conversions - them detected from data type
455 const GLint anIntFormat = theCtx->IsGlGreaterEqual (3, 0) ? theTextFormat : thePixelFormat;
458 if (theDataType == GL_FLOAT && !theCtx->arbTexFloat)
460 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
461 "Error: floating-point textures are not supported by hardware.");
462 Release (theCtx.operator->());
466 const GLsizei aMaxSize = theCtx->MaxTextureSize();
467 if (theSizeX > aMaxSize
468 || theSizeY > aMaxSize)
470 TCollection_ExtendedString aWarnMessage = TCollection_ExtendedString ("Error: Texture dimension - ")
471 + theSizeX + "x" + theSizeY + " exceeds hardware limits (" + aMaxSize + "x" + aMaxSize + ")";
473 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
474 Release (theCtx.operator->());
477 #if !defined(GL_ES_VERSION_2_0)
478 else if (!theCtx->IsGlGreaterEqual (3, 0) && !theCtx->arbNPTW)
480 // Notice that formally general NPOT textures are required by OpenGL 2.0 specifications
481 // however some hardware (NV30 - GeForce FX, RadeOn 9xxx and Xxxx) supports GLSL but not NPOT!
482 // Trying to create NPOT textures on such hardware will not fail
483 // but driver will fall back into software rendering,
484 const GLsizei aWidthP2 = OpenGl_Context::GetPowerOfTwo (theSizeX, aMaxSize);
485 const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (theSizeY, aMaxSize);
487 if (theSizeX != aWidthP2
488 || (theType != Graphic3d_TOT_1D && theSizeY != aHeightP2))
490 TCollection_ExtendedString aWarnMessage =
491 TCollection_ExtendedString ("Error: NPOT Textures (") + theSizeX + "x" + theSizeY + ") are not supported by hardware.";
493 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
495 Release (theCtx.operator->());
500 else if (!theCtx->IsGlGreaterEqual (3, 0) && theType == Graphic3d_TOT_2D_MIPMAP)
502 // Mipmap NPOT textures are not supported by OpenGL ES 2.0.
503 const GLsizei aWidthP2 = OpenGl_Context::GetPowerOfTwo (theSizeX, aMaxSize);
504 const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (theSizeY, aMaxSize);
506 if (theSizeX != aWidthP2
507 || theSizeY != aHeightP2)
509 TCollection_ExtendedString aWarnMessage =
510 TCollection_ExtendedString ("Error: Mipmap NPOT Textures (") + theSizeX + "x" + theSizeY + ") are not supported by OpenGL ES 2.0";
512 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
514 Release (theCtx.operator->());
520 #if !defined(GL_ES_VERSION_2_0)
521 GLint aTestWidth = 0;
522 GLint aTestHeight = 0;
524 GLvoid* aDataPtr = (theImage != NULL) ? (GLvoid* )theImage->Data() : NULL;
526 // setup the alignment
527 OpenGl_UnpackAlignmentSentry anUnpackSentry;
528 (void)anUnpackSentry; // avoid compiler warning
530 if (aDataPtr != NULL)
532 const GLint anAligment = Min ((GLint )theImage->MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes
533 glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment);
535 #if !defined(GL_ES_VERSION_2_0)
536 // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension
537 const GLint anExtraBytes = GLint(theImage->RowExtraBytes());
538 const GLint aPixelsWidth = GLint(theImage->SizeRowBytes() / theImage->SizePixelBytes());
539 glPixelStorei (GL_UNPACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
546 case Graphic3d_TOT_1D:
548 #if !defined(GL_ES_VERSION_2_0)
550 applyDefaultSamplerParams (theCtx);
553 glTexSubImage1D (GL_TEXTURE_1D, 0, 0,
554 theSizeX, thePixelFormat, theDataType, aDataPtr);
559 // use proxy to check texture could be created or not
560 glTexImage1D (GL_PROXY_TEXTURE_1D, 0, anIntFormat,
562 thePixelFormat, theDataType, NULL);
563 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_1D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
564 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_1D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
567 // no memory or broken input parameters
569 Release (theCtx.operator->());
573 glTexImage1D (GL_TEXTURE_1D, 0, anIntFormat,
575 thePixelFormat, theDataType, aDataPtr);
576 if (glGetError() != GL_NO_ERROR)
579 Release (theCtx.operator->());
589 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
590 "Error: 1D textures are not supported by hardware.");
591 Release (theCtx.operator->());
595 case Graphic3d_TOT_2D:
598 applyDefaultSamplerParams (theCtx);
601 glTexSubImage2D (GL_TEXTURE_2D, 0,
604 thePixelFormat, theDataType, aDataPtr);
609 #if !defined(GL_ES_VERSION_2_0)
610 // use proxy to check texture could be created or not
611 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
612 theSizeX, theSizeY, 0,
613 thePixelFormat, theDataType, NULL);
614 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
615 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
616 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
617 if (aTestWidth == 0 || aTestHeight == 0)
619 // no memory or broken input parameters
621 Release (theCtx.operator->());
626 glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
627 theSizeX, theSizeY, 0,
628 thePixelFormat, theDataType, aDataPtr);
629 const GLenum anErr = glGetError();
630 if (anErr != GL_NO_ERROR)
632 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
633 TCollection_AsciiString ("Error: 2D texture ") + theSizeX + "x" + theSizeY
634 + " IF: " + int(anIntFormat) + " PF: " + int(thePixelFormat) + " DT: " + int(theDataType)
635 + " can not be created with error " + int(anErr) + ".");
637 Release (theCtx.operator->());
647 case Graphic3d_TOT_2D_MIPMAP:
650 applyDefaultSamplerParams (theCtx);
653 glTexSubImage2D (GL_TEXTURE_2D, 0,
656 thePixelFormat, theDataType, aDataPtr);
657 if (theCtx->arbFBO != NULL)
660 theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
661 if (glGetError() != GL_NO_ERROR)
664 Release (theCtx.operator->());
673 #if !defined(GL_ES_VERSION_2_0)
674 // use proxy to check texture could be created or not
675 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
676 theSizeX, theSizeY, 0,
677 thePixelFormat, theDataType, NULL);
678 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
679 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
680 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
681 if (aTestWidth == 0 || aTestHeight == 0)
683 // no memory or broken input parameters
685 Release (theCtx.operator->());
690 // upload main picture
691 glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
692 theSizeX, theSizeY, 0,
693 thePixelFormat, theDataType, theImage->Data());
694 const GLenum aTexImgErr = glGetError();
695 if (aTexImgErr != GL_NO_ERROR)
697 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
698 TCollection_AsciiString ("Error: 2D texture ") + theSizeX + "x" + theSizeY
699 + " IF: " + int(anIntFormat) + " PF: " + int(thePixelFormat) + " DT: " + int(theDataType)
700 + " can not be created with error " + int(aTexImgErr) + ".");
702 Release (theCtx.operator->());
709 if (theCtx->arbFBO != NULL)
712 //glHint (GL_GENERATE_MIPMAP_HINT, GL_NICEST);
713 theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
715 if (glGetError() != GL_NO_ERROR)
718 Release (theCtx.operator->());
724 const TCollection_ExtendedString aWarnMessage ("Warning: generating mipmaps requires GL_ARB_framebuffer_object extension which is missing.");
726 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
729 Release (theCtx.operator->());
736 case Graphic3d_TOT_CUBEMAP:
739 Release (theCtx.get());
744 Release (theCtx.operator->());
748 // =======================================================================
751 // =======================================================================
752 bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
753 const Image_PixMap& theImage,
754 const Graphic3d_TypeOfTexture theType)
756 if (theImage.IsEmpty())
758 Release (theCtx.operator->());
765 if (!GetDataFormat (theCtx, theImage, aTextFormat, aPixelFormat, aDataType))
767 Release (theCtx.operator->());
772 aTextFormat, aPixelFormat, aDataType,
773 (Standard_Integer)theImage.SizeX(),
774 (Standard_Integer)theImage.SizeY(),
778 // =======================================================================
781 // =======================================================================
782 bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
783 const Handle(Graphic3d_TextureMap)& theTextureMap)
785 if (theTextureMap.IsNull())
790 switch (theTextureMap->Type())
792 case Graphic3d_TOT_CUBEMAP:
794 return InitCubeMap (theCtx, Handle(Graphic3d_CubeMap)::DownCast(theTextureMap));
798 Handle(Image_PixMap) anImage = theTextureMap->GetImage();
799 if (anImage.IsNull())
803 return Init (theCtx, *anImage, theTextureMap->Type());
808 // =======================================================================
809 // function : Init2DMultisample
811 // =======================================================================
812 bool OpenGl_Texture::Init2DMultisample (const Handle(OpenGl_Context)& theCtx,
813 const GLsizei theNbSamples,
814 const GLint theTextFormat,
815 const GLsizei theSizeX,
816 const GLsizei theSizeY)
819 || theNbSamples > theCtx->MaxMsaaSamples()
825 myNbSamples = OpenGl_Context::GetPowerOfTwo (theNbSamples, theCtx->MaxMsaaSamples());
826 myTarget = GL_TEXTURE_2D_MULTISAMPLE;
827 myHasMipmaps = false;
828 if(theSizeX > theCtx->MaxTextureSize()
829 || theSizeY > theCtx->MaxTextureSize())
835 //myTextFormat = theTextFormat;
836 mySizedFormat = theTextFormat;
837 #if !defined(GL_ES_VERSION_2_0)
838 if (theCtx->Functions()->glTexStorage2DMultisample != NULL)
840 theCtx->Functions()->glTexStorage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
844 theCtx->Functions()->glTexImage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
847 theCtx->Functions() ->glTexStorage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
849 if (theCtx->core11fwd->glGetError() != GL_NO_ERROR)
862 // =======================================================================
863 // function : InitRectangle
865 // =======================================================================
866 bool OpenGl_Texture::InitRectangle (const Handle(OpenGl_Context)& theCtx,
867 const Standard_Integer theSizeX,
868 const Standard_Integer theSizeY,
869 const OpenGl_TextureFormat& theFormat)
871 if (!Create (theCtx) || !theCtx->IsGlGreaterEqual (3, 0))
876 #if !defined(GL_ES_VERSION_2_0)
877 myTarget = GL_TEXTURE_RECTANGLE;
879 myHasMipmaps = false;
881 const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX);
882 const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY);
885 applyDefaultSamplerParams (theCtx);
887 myTextFormat = theFormat.Format();
888 mySizedFormat = theFormat.Internal();
890 // setup the alignment
891 OpenGl_UnpackAlignmentSentry::Reset();
893 glTexImage2D (GL_PROXY_TEXTURE_RECTANGLE, 0, mySizedFormat,
895 myTextFormat, GL_FLOAT, NULL);
897 GLint aTestSizeX = 0;
898 GLint aTestSizeY = 0;
900 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH, &aTestSizeX);
901 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
902 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
904 if (aTestSizeX == 0 || aTestSizeY == 0)
910 glTexImage2D (myTarget, 0, mySizedFormat,
912 myTextFormat, GL_FLOAT, NULL);
914 if (glGetError() != GL_NO_ERROR)
933 // =======================================================================
936 // =======================================================================
937 bool OpenGl_Texture::Init3D (const Handle(OpenGl_Context)& theCtx,
938 const GLint theTextFormat,
939 const GLenum thePixelFormat,
940 const GLenum theDataType,
941 const Standard_Integer theSizeX,
942 const Standard_Integer theSizeY,
943 const Standard_Integer theSizeZ,
944 const void* thePixels)
946 if (theCtx->Functions()->glTexImage3D == NULL)
948 TCollection_ExtendedString aMsg ("Error: three-dimensional textures are not supported by hardware.");
950 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
953 GL_DEBUG_SEVERITY_HIGH,
964 myTarget = GL_TEXTURE_3D;
966 myHasMipmaps = false;
968 const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX);
969 const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY);
970 const GLsizei aSizeZ = Min (theCtx->MaxTextureSize(), theSizeZ);
974 if (theDataType == GL_FLOAT && !theCtx->arbTexFloat)
976 TCollection_ExtendedString aMsg ("Error: floating-point textures are not supported by hardware.");
978 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
981 GL_DEBUG_SEVERITY_HIGH,
984 Release (theCtx.operator->());
989 mySizedFormat = theTextFormat;
991 // setup the alignment
992 OpenGl_UnpackAlignmentSentry::Reset();
994 #if !defined (GL_ES_VERSION_2_0)
995 theCtx->core15fwd->glTexImage3D (GL_PROXY_TEXTURE_3D, 0, mySizedFormat,
996 aSizeX, aSizeY, aSizeZ, 0,
997 thePixelFormat, theDataType, NULL);
999 GLint aTestSizeX = 0;
1000 GLint aTestSizeY = 0;
1001 GLint aTestSizeZ = 0;
1003 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &aTestSizeX);
1004 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
1005 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_DEPTH, &aTestSizeZ);
1006 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
1008 if (aTestSizeX == 0 || aTestSizeY == 0 || aTestSizeZ == 0)
1011 Release (theCtx.operator->());
1016 applyDefaultSamplerParams (theCtx);
1017 theCtx->Functions()->glTexImage3D (myTarget, 0, mySizedFormat,
1018 aSizeX, aSizeY, aSizeZ, 0,
1019 thePixelFormat, theDataType, thePixels);
1021 if (glGetError() != GL_NO_ERROR)
1024 Release (theCtx.operator->());
1036 // =======================================================================
1037 // function : InitCubeMap
1039 // =======================================================================
1040 bool OpenGl_Texture::InitCubeMap (const Handle(OpenGl_Context)& theCtx,
1041 const Handle(Graphic3d_CubeMap)& theCubeMap,
1042 Standard_Size theSize,
1043 Image_Format theFormat,
1044 Standard_Boolean theToGenMipmap)
1046 if (!Create (theCtx))
1048 Release (theCtx.get());
1052 if (!theCubeMap.IsNull())
1054 Handle(Image_PixMap) anImage = theCubeMap->Reset().Value();
1055 if (!anImage.IsNull())
1057 theSize = anImage->SizeX();
1058 theFormat = anImage->Format();
1062 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
1063 "Unable to get the first side of cubemap");
1064 Release(theCtx.get());
1069 GLenum aPixelFormat = GL_RGB;
1070 GLenum aDataType = 0;
1071 GLint aTextFormat = 0;
1073 if (!GetDataFormat (theCtx, theFormat, aTextFormat, aPixelFormat, aDataType))
1076 Release(theCtx.get());
1080 myTarget = GL_TEXTURE_CUBE_MAP;
1081 myHasMipmaps = theToGenMipmap;
1084 applyDefaultSamplerParams (theCtx);
1086 for (Standard_Integer i = 0; i < 6; ++i)
1088 const void* aData = NULL;
1089 Handle(Image_PixMap) anImage;
1091 if (!theCubeMap.IsNull())
1093 anImage = theCubeMap->Value();
1094 if (!anImage.IsNull())
1096 #if !defined(GL_ES_VERSION_2_0)
1097 const GLint anAligment = Min ((GLint)anImage->MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes
1098 glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment);
1100 // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension
1101 const GLint anExtraBytes = GLint(anImage->RowExtraBytes());
1102 const GLint aPixelsWidth = GLint(anImage->SizeRowBytes() / anImage->SizePixelBytes());
1103 const GLint aRowLength = (anExtraBytes >= anAligment) ? aPixelsWidth : 0;
1104 glPixelStorei (GL_UNPACK_ROW_LENGTH, aRowLength);
1106 Handle(Image_PixMap) aCopyImage = new Image_PixMap();
1107 aCopyImage->InitTrash (theFormat, theSize, theSize);
1108 for (unsigned int y = 0; y < theSize; ++y)
1110 for (unsigned int x = 0; x < theSize; ++x)
1112 for (unsigned int aByte = 0; aByte < anImage->SizePixelBytes(); ++aByte)
1114 aCopyImage->ChangeRawValue (y, x)[aByte] = anImage->RawValue (y, x)[aByte];
1118 anImage = aCopyImage;
1119 const GLint anAligment = Min((GLint)anImage->MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes
1120 glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment);
1122 aData = anImage->Data();
1126 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, TCollection_AsciiString() +
1127 "Unable to get [" + i + "] side of cubemap");
1129 Release (theCtx.get());
1135 glTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0,
1137 GLsizei(theSize), GLsizei(theSize),
1138 0, aPixelFormat, aDataType,
1141 OpenGl_UnpackAlignmentSentry::Reset();
1143 if (glGetError() != GL_NO_ERROR)
1145 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
1146 "Unable to initialize side of cubemap");
1148 Release (theCtx.get());
1153 if (theToGenMipmap && theCtx->arbFBO != NULL)
1155 theCtx->arbFBO->glGenerateMipmap (myTarget);
1157 if (glGetError() != GL_NO_ERROR)
1159 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
1160 "Unable to generate mipmap of cubemap");
1162 Release(theCtx.get());
1167 Unbind (theCtx.get());
1171 // =======================================================================
1172 // function : PixelSizeOfPixelFormat
1174 // =======================================================================
1175 Standard_Size OpenGl_Texture::PixelSizeOfPixelFormat (Standard_Integer theInternalFormat)
1177 switch(theInternalFormat)
1179 // RED variations (GL_RED, OpenGL 3.0+)
1181 case GL_R8: return 1;
1182 case GL_R16: return 2;
1183 case GL_R16F: return 2;
1184 case GL_R32F: return 4;
1186 case GL_RGB: return 3;
1187 case GL_RGB8: return 3;
1188 case GL_RGB16: return 6;
1189 case GL_RGB16F: return 6;
1190 case GL_RGB32F: return 12;
1192 case GL_RGBA: return 4;
1193 case GL_RGBA8: return 4;
1194 case GL_RGB10_A2: return 4;
1195 case GL_RGBA12: return 6;
1196 case GL_RGBA16: return 8;
1197 case GL_RGBA16F: return 8;
1198 case GL_RGBA32F: return 16;
1200 case GL_BGRA_EXT: return 4;
1201 // ALPHA variations (deprecated)
1203 case GL_ALPHA8: return 1;
1204 case GL_ALPHA16: return 2;
1205 case GL_LUMINANCE: return 1;
1206 case GL_LUMINANCE_ALPHA: return 2;
1208 case GL_DEPTH24_STENCIL8: return 4;
1209 case GL_DEPTH32F_STENCIL8: return 8;
1210 case GL_DEPTH_COMPONENT16: return 2;
1211 case GL_DEPTH_COMPONENT24: return 3;
1212 case GL_DEPTH_COMPONENT32F: return 4;
1217 // =======================================================================
1218 // function : EstimatedDataSize
1220 // =======================================================================
1221 Standard_Size OpenGl_Texture::EstimatedDataSize() const
1228 Standard_Size aSize = PixelSizeOfPixelFormat (mySizedFormat) * mySizeX * myNbSamples;
1231 aSize *= Standard_Size(mySizeY);
1235 aSize *= Standard_Size(mySizeZ);
1239 aSize = aSize + aSize / 3;