From e7fd8740bb1343c84879e0299c3adeec1eed0a3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Jun 2013 13:12:37 +0200 Subject: [PATCH] Fallback for texture storage feature. It's now possible to call *Texture::setStorage() even if OpenGL 4.2, ARB_texture_storage, OpenGL ES 3.0 or EXT_texture_storage in ES 2.0 is not available, the function will internally use sequence of setImage() calls as fallback. It seems to me that this behavior is better than forcing the user to always check for extension presence and then implementing this functionality again and again. The huge switches for setting proper image format and type are ugly though, but according to specs they must be set even if we are sending no data (which is weird). --- src/AbstractTexture.cpp | 497 +++++++++++++++++++++++++++++++++++++++- src/AbstractTexture.h | 12 + src/Texture.h | 13 +- 3 files changed, 510 insertions(+), 12 deletions(-) diff --git a/src/AbstractTexture.cpp b/src/AbstractTexture.cpp index ac34bac65..e085764ae 100644 --- a/src/AbstractTexture.cpp +++ b/src/AbstractTexture.cpp @@ -29,6 +29,8 @@ #include "Context.h" #include "Extensions.h" #include "Image.h" +#include "ImageFormat.h" +#include "TextureFormat.h" #include "Implementation/State.h" #include "Implementation/TextureState.h" @@ -50,12 +52,12 @@ AbstractTexture::MipmapImplementation AbstractTexture::mipmapImplementation = &AbstractTexture::mipmapImplementationDefault; #ifndef MAGNUM_TARGET_GLES AbstractTexture::Storage1DImplementation AbstractTexture::storage1DImplementation = - &AbstractTexture::storageImplementationDefault; + &AbstractTexture::storageImplementationFallback; #endif AbstractTexture::Storage2DImplementation AbstractTexture::storage2DImplementation = - &AbstractTexture::storageImplementationDefault; + &AbstractTexture::storageImplementationFallback; AbstractTexture::Storage3DImplementation AbstractTexture::storage3DImplementation = - &AbstractTexture::storageImplementationDefault; + &AbstractTexture::storageImplementationFallback; #ifndef MAGNUM_TARGET_GLES AbstractTexture::GetImageImplementation AbstractTexture::getImageImplementation = &AbstractTexture::getImageImplementationDefault; @@ -204,9 +206,6 @@ void AbstractTexture::initializeContextBasedFunctionality(Context* context) { parameterfvImplementation = &AbstractTexture::parameterImplementationDSA; getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA; mipmapImplementation = &AbstractTexture::mipmapImplementationDSA; - storage1DImplementation = &AbstractTexture::storageImplementationDSA; - storage2DImplementation = &AbstractTexture::storageImplementationDSA; - storage3DImplementation = &AbstractTexture::storageImplementationDSA; getImageImplementation = &AbstractTexture::getImageImplementationDSA; image1DImplementation = &AbstractTexture::imageImplementationDSA; image2DImplementation = &AbstractTexture::imageImplementationDSA; @@ -229,9 +228,396 @@ void AbstractTexture::initializeContextBasedFunctionality(Context* context) { getImageImplementation = &AbstractTexture::getImageImplementationRobustness; } + + if(context->isExtensionSupported()) { + Debug() << "AbstractTexture: using" << Extensions::GL::ARB::texture_storage::string() << "features"; + + if(context->isExtensionSupported()) { + storage1DImplementation = &AbstractTexture::storageImplementationDSA; + storage2DImplementation = &AbstractTexture::storageImplementationDSA; + storage3DImplementation = &AbstractTexture::storageImplementationDSA; + } else { + storage1DImplementation = &AbstractTexture::storageImplementationDefault; + storage2DImplementation = &AbstractTexture::storageImplementationDefault; + storage3DImplementation = &AbstractTexture::storageImplementationDefault; + } + } #endif } +ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) { + switch(internalFormat) { + case TextureFormat::Red: + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::R8: + case TextureFormat::R8Snorm: + #endif + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::R16: + case TextureFormat::R16Snorm: + #endif + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::R16F: + case TextureFormat::R32F: + #endif + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::CompressedRed: + case TextureFormat::CompressedRedRtgc1: + case TextureFormat::CompressedSignedRedRgtc1: + #endif + return ImageFormat::Red; + + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::R8UI: + case TextureFormat::R8I: + case TextureFormat::R16UI: + case TextureFormat::R16I: + case TextureFormat::R32UI: + case TextureFormat::R32I: + return ImageFormat::RedInteger; + #endif + + case TextureFormat::RG: + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::RG8: + case TextureFormat::RG8Snorm: + #endif + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::RG16: + case TextureFormat::RG16Snorm: + #endif + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::RG16F: + case TextureFormat::RG32F: + #endif + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::CompressedRG: + case TextureFormat::CompressedRGRgtc2: + case TextureFormat::CompressedSignedRGRgtc2: + #endif + return ImageFormat::RG; + + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::RG8UI: + case TextureFormat::RG8I: + case TextureFormat::RG16UI: + case TextureFormat::RG16I: + case TextureFormat::RG32UI: + case TextureFormat::RG32I: + return ImageFormat::RGInteger; + #endif + + case TextureFormat::RGB: + case TextureFormat::RGB8: + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::RGB8Snorm: + #endif + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::RGB16: + case TextureFormat::RGB16Snorm: + #endif + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::RGB16F: + case TextureFormat::RGB32F: + #endif + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::R3B3G2: + case TextureFormat::RGB4: + case TextureFormat::RGB5: + #endif + case TextureFormat::RGB565: + #ifndef MAGNUM_TARGET_GLES3 + case TextureFormat::RGB10: + #endif + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::RGB12: + #endif + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::R11FG11FB10F: + case TextureFormat::RGB9E5: + #endif + #ifndef MAGNUM_TARGET_GLES3 + case TextureFormat::SRGB: + #endif + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::SRGB8: + #endif + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::CompressedRGB: + case TextureFormat::CompressedRGBBptcUnsignedFloat: + case TextureFormat::CompressedRGBBptcSignedFloat: + #endif + return ImageFormat::RGB; + + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::RGB8UI: + case TextureFormat::RGB8I: + case TextureFormat::RGB16UI: + case TextureFormat::RGB16I: + case TextureFormat::RGB32UI: + case TextureFormat::RGB32I: + return ImageFormat::RGBInteger; + #endif + + case TextureFormat::RGBA: + case TextureFormat::RGBA8: + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::RGBA8Snorm: + #endif + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::RGBA16: + case TextureFormat::RGBA16Snorm: + #endif + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::RGBA16F: + case TextureFormat::RGBA32F: + #endif + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::RGBA2: + #endif + case TextureFormat::RGBA4: + case TextureFormat::RGB5A1: + case TextureFormat::RGB10A2: + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::RGBA12: + #endif + #ifndef MAGNUM_TARGET_GLES3 + case TextureFormat::SRGBAlpha: + #endif + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::SRGB8Alpha8: + #endif + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::CompressedRGBA: + case TextureFormat::CompressedRGBABptcUnorm: + case TextureFormat::CompressedSRGBAlphaBptcUnorm: + #endif + return ImageFormat::RGBA; + + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::RGBA8UI: + case TextureFormat::RGBA8I: + case TextureFormat::RGBA16UI: + case TextureFormat::RGBA16I: + case TextureFormat::RGBA32UI: + case TextureFormat::RGBA32I: + case TextureFormat::RGB10A2UI: + return ImageFormat::RGBAInteger; + #endif + + #ifdef MAGNUM_TARGET_GLES2 + case TextureFormat::Luminance: + return ImageFormat::Luminance; + case TextureFormat::LuminanceAlpha: + return ImageFormat::LuminanceAlpha; + #endif + + case TextureFormat::DepthComponent: + case TextureFormat::DepthComponent16: + case TextureFormat::DepthComponent24: + #ifndef MAGNUM_TARGET_GLES3 + case TextureFormat::DepthComponent32: + #endif + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::DepthComponent32F: + #endif + return ImageFormat::DepthComponent; + + case TextureFormat::DepthStencil: + case TextureFormat::Depth24Stencil8: + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::Depth32FStencil8: + #endif + return ImageFormat::DepthStencil; + } + + CORRADE_ASSERT_UNREACHABLE(); +} + +ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat internalFormat) { + switch(internalFormat) { + case TextureFormat::Red: + case TextureFormat::RG: + case TextureFormat::RGB: + case TextureFormat::RGBA: + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::R8: + case TextureFormat::RG8: + #endif + case TextureFormat::RGB8: + case TextureFormat::RGBA8: + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::R8UI: + case TextureFormat::RG8UI: + case TextureFormat::RGB8UI: + case TextureFormat::RGBA8UI: + #endif + #ifdef MAGNUM_TARGET_GLES2 + case TextureFormat::Luminance: + case TextureFormat::LuminanceAlpha: + #endif + #ifndef MAGNUM_TARGET_GLES3 + case TextureFormat::SRGB: + case TextureFormat::SRGBAlpha: + #endif + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::SRGB8: + case TextureFormat::SRGB8Alpha8: + #endif + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::RGBA2: /**< @todo really? */ + case TextureFormat::CompressedRed: + case TextureFormat::CompressedRG: + case TextureFormat::CompressedRGB: + case TextureFormat::CompressedRGBA: + case TextureFormat::CompressedRedRtgc1: + case TextureFormat::CompressedRGRgtc2: + case TextureFormat::CompressedRGBABptcUnorm: + case TextureFormat::CompressedSRGBAlphaBptcUnorm: + #endif + return ImageType::UnsignedByte; + + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::R8Snorm: + case TextureFormat::RG8Snorm: + case TextureFormat::RGB8Snorm: + case TextureFormat::RGBA8Snorm: + case TextureFormat::R8I: + case TextureFormat::RG8I: + case TextureFormat::RGB8I: + case TextureFormat::RGBA8I: + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::CompressedSignedRedRgtc1: + case TextureFormat::CompressedSignedRGRgtc2: + #endif + return ImageType::Byte; + #endif + + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::R16: + case TextureFormat::RG16: + case TextureFormat::RGB16: + case TextureFormat::RGBA16: + #endif + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::R16UI: + case TextureFormat::RG16UI: + case TextureFormat::RGB16UI: + case TextureFormat::RGBA16UI: + #endif + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::RGB12: /**< @todo really? */ + #endif + case TextureFormat::RGBA4: /**< @todo really? */ + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::RGBA12: /**< @todo really? */ + #endif + return ImageType::UnsignedShort; + + #ifndef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::R16Snorm: + case TextureFormat::RG16Snorm: + case TextureFormat::RGB16Snorm: + case TextureFormat::RGBA16Snorm: + #endif + case TextureFormat::R16I: + case TextureFormat::RG16I: + case TextureFormat::RGB16I: + case TextureFormat::RGBA16I: + return ImageType::Short; + #endif + + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::R16F: + case TextureFormat::RG16F: + case TextureFormat::RGB16F: + case TextureFormat::RGBA16F: + return ImageType::HalfFloat; + + case TextureFormat::R32UI: + case TextureFormat::RG32UI: + case TextureFormat::RGB32UI: + case TextureFormat::RGBA32UI: + return ImageType::UnsignedInt; + + case TextureFormat::R32I: + case TextureFormat::RG32I: + case TextureFormat::RGB32I: + case TextureFormat::RGBA32I: + return ImageType::Int; + + case TextureFormat::R32F: + case TextureFormat::RG32F: + case TextureFormat::RGB32F: + case TextureFormat::RGBA32F: + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::CompressedRGBBptcUnsignedFloat: + case TextureFormat::CompressedRGBBptcSignedFloat: + #endif + return ImageType::Float; + #endif + + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::R3B3G2: + return ImageType::UnsignedByte332; + case TextureFormat::RGB4: + return ImageType::UnsignedShort4444; + #endif + + #ifndef MAGNUM_TARGET_GLES + case TextureFormat::RGB5: + #endif + case TextureFormat::RGB5A1: + return ImageType::UnsignedShort5551; + + case TextureFormat::RGB565: + return ImageType::UnsignedShort565; + + #ifndef MAGNUM_TARGET_GLES3 + case TextureFormat::RGB10: + #endif + case TextureFormat::RGB10A2: + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::RGB10A2UI: + #endif + return ImageType::UnsignedInt2101010Rev; /**< @todo Rev for all? */ + + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::R11FG11FB10F: + return ImageType::UnsignedInt10F11F11FRev; + case TextureFormat::RGB9E5: + return ImageType::UnsignedInt5999Rev; + #endif + + case TextureFormat::DepthComponent16: + return ImageType::UnsignedShort; + + case TextureFormat::DepthComponent: + case TextureFormat::DepthComponent24: + #ifndef MAGNUM_TARGET_GLES3 + case TextureFormat::DepthComponent32: + #endif + return ImageType::UnsignedInt; + + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::DepthComponent32F: + return ImageType::Float; + #endif + + case TextureFormat::DepthStencil: + case TextureFormat::Depth24Stencil8: + return ImageType::UnsignedInt248; + + #ifndef MAGNUM_TARGET_GLES2 + case TextureFormat::Depth32FStencil8: + return ImageType::Float32UnsignedInt248Rev; + #endif + } + + CORRADE_ASSERT_UNREACHABLE(); +} + void AbstractTexture::parameterImplementationDefault(GLenum parameter, GLint value) { bindInternal(); glTexParameteri(_target, parameter, value); @@ -277,7 +663,20 @@ void AbstractTexture::getLevelParameterImplementationDSA(GLenum target, GLint le #endif #ifndef MAGNUM_TARGET_GLES -void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector< 1, GLsizei >& size) { +void AbstractTexture::storageImplementationFallback(const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size) { + CORRADE_INTERNAL_ASSERT(target == GL_TEXTURE_1D); + + const ImageFormat format = imageFormatForInternalFormat(internalFormat); + const ImageType type = imageTypeForInternalFormat(internalFormat); + + auto levelSize = size; + for(GLsizei level = 0; level != levels; ++level) { + (this->*image1DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr); + levelSize = Math::max(Math::Vector<1, GLsizei>(1), levelSize/2); + } +} + +void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size) { bindInternal(); /** @todo Re-enable when extension wrangler is available for ES2 */ #ifndef MAGNUM_TARGET_GLES2 @@ -291,11 +690,56 @@ void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels #endif } -void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector< 1, GLsizei >& size) { +void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size) { glTextureStorage1DEXT(_id, target, levels, GLenum(internalFormat), size[0]); } #endif +void AbstractTexture::storageImplementationFallback(const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Vector2i& size) { + const ImageFormat format = imageFormatForInternalFormat(internalFormat); + const ImageType type = imageTypeForInternalFormat(internalFormat); + + /* Common code for classic types */ + #ifndef MAGNUM_TARGET_GLES + if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE) + #else + if(target == GL_TEXTURE_2D) + #endif + { + Vector2i levelSize = size; + for(GLsizei level = 0; level != levels; ++level) { + (this->*image2DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr); + levelSize = Math::max(Vector2i(1), levelSize/2); + } + + /* Cube map additionaly needs to specify all faces */ + } else if(target == GL_TEXTURE_CUBE_MAP) { + Vector2i levelSize = size; + for(GLsizei level = 0; level != levels; ++level) { + for(GLenum face: {GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z}) + (this->*image2DImplementation)(face, level, internalFormat, levelSize, format, type, nullptr); + levelSize = Math::max(Vector2i(1), levelSize/2); + } + + #ifndef MAGNUM_TARGET_GLES + /* Array texture is not scaled in "layer" dimension */ + } else if(target == GL_TEXTURE_1D_ARRAY) { + Vector2i levelSize = size; + for(GLsizei level = 0; level != levels; ++level) { + (this->*image2DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr); + levelSize.x() = Math::max(1, levelSize.x()/2); + } + #endif + + /* No other targets are available */ + } else CORRADE_ASSERT_UNREACHABLE(); +} + void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size) { bindInternal(); /** @todo Re-enable when extension wrangler is available for ES2 */ @@ -316,6 +760,43 @@ void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, Te } #endif +void AbstractTexture::storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size) { + const ImageFormat format = imageFormatForInternalFormat(internalFormat); + const ImageType type = imageTypeForInternalFormat(internalFormat); + + /* Common code for classic type */ + #ifndef MAGNUM_TARGET_GLES2 + if(target == GL_TEXTURE_3D) + #else + if(target == GL_TEXTURE_3D_OES) + #endif + { + Vector3i levelSize = size; + for(GLsizei level = 0; level != levels; ++level) { + (this->*image3DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr); + levelSize = Math::max(Vector3i(1), levelSize/2); + } + + #ifndef MAGNUM_TARGET_GLES2 + /* Array texture is not scaled in "layer" dimension */ + } + #ifndef MAGNUM_TARGET_GLES + else if(target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_CUBE_MAP_ARRAY) + #else + else if(target == GL_TEXTURE_2D_ARRAY) + #endif + { + Vector3i levelSize = size; + for(GLsizei level = 0; level != levels; ++level) { + (this->*image3DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr); + levelSize.xy() = Math::max(Vector2i(1), levelSize.xy()/2); + } + #endif + + /* No other targets are available */ + } else CORRADE_ASSERT_UNREACHABLE(); +} + void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size) { bindInternal(); /** @todo Re-enable when extension wrangler is available for ES2 */ diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index fc2358124..b447d1f6f 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -72,6 +72,13 @@ avoid redundant consistency checks and memory reallocations when updating texture data, set texture storage at once using @ref Texture::setStorage() "setStorage()" and then set data using @ref Texture::setSubImage() "setSubImage()". +Function @ref Texture::setStorage() "setStorage()" creates immutable texture +storage, removing the need for additional consistency checks and memory +reallocations when updating the data later. If OpenGL 4.2, @extension{ARB,texture_storage}, +OpenGL ES 3.0 or @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not +available, the feature is emulated with sequence of @ref Texture::setImage() "setImage()" +calls. + You can use functions invalidateImage() and @ref Texture::invalidateSubImage() "invalidateSubImage()" if you don't need texture data anymore to avoid unnecessary memory operations performed by OpenGL in order to preserve the data. If running on OpenGL ES or @@ -314,12 +321,14 @@ class MAGNUM_EXPORT AbstractTexture { #ifndef MAGNUM_TARGET_GLES typedef void(AbstractTexture::*Storage1DImplementation)(GLenum, GLsizei, TextureFormat, const Math::Vector<1, GLsizei>&); + void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size); void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size); void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size); static Storage1DImplementation storage1DImplementation; #endif typedef void(AbstractTexture::*Storage2DImplementation)(GLenum, GLsizei, TextureFormat, const Vector2i&); + void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size); @@ -327,6 +336,7 @@ class MAGNUM_EXPORT AbstractTexture { static Storage2DImplementation storage2DImplementation; typedef void(AbstractTexture::*Storage3DImplementation)(GLenum, GLsizei, TextureFormat, const Vector3i&); + void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); @@ -399,6 +409,8 @@ class MAGNUM_EXPORT AbstractTexture { void MAGNUM_LOCAL destroy(); void MAGNUM_LOCAL move(); + ImageFormat MAGNUM_LOCAL imageFormatForInternalFormat(TextureFormat internalFormat); + ImageType MAGNUM_LOCAL imageTypeForInternalFormat(TextureFormat internalFormat); GLuint _id; }; diff --git a/src/Texture.h b/src/Texture.h index 139dc7950..9cd269e5f 100644 --- a/src/Texture.h +++ b/src/Texture.h @@ -282,14 +282,19 @@ template class Texture: public AbstractTexture { * is immutable and calling setStorage() or setImage() is not allowed. * * If @extension{EXT,direct_state_access} is not available, the - * texture is bound to some layer before the operation. + * texture is bound to some layer before the operation. If + * OpenGL 4.2, @extension{ARB,texture_storage}, OpenGL ES 3.0 or @es_extension{EXT,texture_storage} + * in OpenGL ES 2.0 is not available, the feature is emulated with + * sequence of setImage() calls. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{TexStorage1D}/@fn_gl{TexStorage2D}/@fn_gl{TexStorage3D} * or @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}/ * @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}/ - * @fn_gl_extension{TextureStorage3D,EXT,direct_state_access} - * @requires_gl42 %Extension @extension{ARB,texture_storage} - * @requires_gles30 %Extension @es_extension{EXT,texture_storage} + * @fn_gl_extension{TextureStorage3D,EXT,direct_state_access}, + * eventually @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D} or + * @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/ + * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ + * @fn_gl_extension{TextureImage3D,EXT,direct_state_access}. */ Texture* setStorage(Int levels, TextureFormat internalFormat, const typename DimensionTraits::VectorType& size) { DataHelper::setStorage(this, _target, levels, internalFormat, size);