From 8cdf5e87c49522122a7e15cd92ce47b406c1c9f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Feb 2012 21:51:48 +0100 Subject: [PATCH] Strong typed texture targets. Only those targets which are meaningful for given dimension are available. --- src/AbstractTexture.h | 108 +++++++++++++++++++++++++++++------------- src/CubeMapTexture.h | 19 +++----- src/Texture.h | 29 +++++++----- 3 files changed, 98 insertions(+), 58 deletions(-) diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index 9c484d773..b1d365b5e 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -198,8 +198,6 @@ class MAGNUM_EXPORT AbstractTexture { void generateMipmap(); protected: - const GLenum target; /**< @brief Texture target */ - /** * @brief Helper for setting texture data * @@ -207,13 +205,34 @@ class MAGNUM_EXPORT AbstractTexture { */ template struct DataHelper { #ifdef DOXYGEN_GENERATING_OUTPUT + /** + * @brief %Texture target + * + * Each dimension has its own unique subset of these targets. + */ + enum class Target: GLenum { + Texture1D = GL_TEXTURE_1D, + Texture2D = GL_TEXTURE_2D, + Texture3D = GL_TEXTURE_3D, + Array1D = GL_TEXTURE_1D_ARRAY, + Array2D = GL_TEXTURE_2D_ARRAY, + Rectangle = GL_TEXTURE_RECTANGLE, + CubeMap = GL_TEXTURE_CUBE_MAP, + CubeMapPositiveX = GL_TEXTURE_CUBE_MAP_POSITIVE_X, + CubeMapNegativeX = GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + CubeMapPositiveY = GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + CubeMapNegativeY = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + CubeMapPositiveZ = GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + CubeMapNegativeZ = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + }; + /** * @brief Target for given dimension * - * Returns @c GL_TEXTURE_1D, @c GL_TEXTURE_2D or @c GL_TEXTURE_3D + * Returns @c Target::Texture1D, @c Target::Texture2D or @c Target::Texture3D * based on dimension count. */ - inline constexpr static GLenum target(); + inline constexpr static Target target(); /** * @brief Set texture wrapping @@ -224,7 +243,7 @@ class MAGNUM_EXPORT AbstractTexture { /** * @brief Set texture data - * @param target Target, such as @c GL_TEXTURE_RECTANGLE + * @param target %Target * @param mipLevel Mip level * @param internalFormat Internal texture format * @param dimensions %Texture dimensions @@ -235,11 +254,11 @@ class MAGNUM_EXPORT AbstractTexture { * Calls @c glTexImage1D, @c glTexImage2D, @c glTexImage3D depending * on dimension count. */ - inline static void set(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data); + inline static void set(Target target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data); /** * @brief Set texture subdata - * @param target Target, such as @c GL_TEXTURE_RECTANGLE + * @param target %Target * @param mipLevel Mip level * @param offset Offset where to put data in the texture * @param dimensions %Texture dimensions @@ -250,62 +269,85 @@ class MAGNUM_EXPORT AbstractTexture { * Calls @c glTexSubImage1D, @c glTexSubImage2D, @c glTexSubImage3D * depending on dimension count. */ - inline static void setSub(GLenum target, GLint mipLevel, const Math::Vector& offset, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data); + inline static void setSub(SubTarget target, GLint mipLevel, const Math::Vector& offset, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data); #endif }; private: + const GLenum target; const GLint _layer; GLuint texture; }; #ifndef DOXYGEN_GENERATING_OUTPUT template<> struct AbstractTexture::DataHelper<1> { - inline constexpr static GLenum target() { return GL_TEXTURE_1D; } + enum class Target: GLenum { + Texture1D = GL_TEXTURE_1D + }; + + inline constexpr static Target target() { return Target::Texture1D; } - inline static void setWrapping(GLenum target, const Math::Vector& wrapping) { - glTexParameteri(target, GL_TEXTURE_WRAP_S, static_cast(wrapping.at(0))); + inline static void setWrapping(Target target, const Math::Vector& wrapping) { + glTexParameteri(static_cast(target), GL_TEXTURE_WRAP_S, static_cast(wrapping.at(0))); } - inline static void set(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { - glTexImage1D(target, mipLevel, static_cast(internalFormat), dimensions.at(0), 0, static_cast(colorFormat), static_cast(type), data); + inline static void set(Target target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { + glTexImage1D(static_cast(target), mipLevel, static_cast(internalFormat), dimensions.at(0), 0, static_cast(colorFormat), static_cast(type), data); } - inline static void setSub(GLenum target, GLint mipLevel, const Math::Vector& offset, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { - glTexSubImage1D(target, mipLevel, offset.at(0), dimensions.at(0), static_cast(colorFormat), static_cast(type), data); + inline static void setSub(Target target, GLint mipLevel, const Math::Vector& offset, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { + glTexSubImage1D(static_cast(target), mipLevel, offset.at(0), dimensions.at(0), static_cast(colorFormat), static_cast(type), data); } }; template<> struct AbstractTexture::DataHelper<2> { - inline constexpr static GLenum target() { return GL_TEXTURE_2D; } - - inline static void setWrapping(GLenum target, const Math::Vector& wrapping) { - glTexParameteri(target, GL_TEXTURE_WRAP_S, static_cast(wrapping.at(0))); - glTexParameteri(target, GL_TEXTURE_WRAP_T, static_cast(wrapping.at(1))); + enum class Target: GLenum { + Texture2D = GL_TEXTURE_2D, + Array1D = GL_TEXTURE_1D_ARRAY, + Rectangle = GL_TEXTURE_RECTANGLE, + CubeMap = GL_TEXTURE_CUBE_MAP, + CubeMapPositiveX = GL_TEXTURE_CUBE_MAP_POSITIVE_X, + CubeMapNegativeX = GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + CubeMapPositiveY = GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + CubeMapNegativeY = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + CubeMapPositiveZ = GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + CubeMapNegativeZ = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + }; + + inline constexpr static Target target() { return Target::Texture2D; } + + inline static void setWrapping(Target target, const Math::Vector& wrapping) { + glTexParameteri(static_cast(target), GL_TEXTURE_WRAP_S, static_cast(wrapping.at(0))); + glTexParameteri(static_cast(target), GL_TEXTURE_WRAP_T, static_cast(wrapping.at(1))); } - inline static void set(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { - glTexImage2D(target, mipLevel, static_cast(internalFormat), dimensions.at(0), dimensions.at(1), 0, static_cast(colorFormat), static_cast(type), data); + inline static void set(Target target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { + glTexImage2D(static_cast(target), mipLevel, static_cast(internalFormat), dimensions.at(0), dimensions.at(1), 0, static_cast(colorFormat), static_cast(type), data); } - inline static void setSub(GLenum target, GLint mipLevel, const Math::Vector& offset, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { - glTexSubImage2D(target, mipLevel, offset.at(0), offset.at(1), dimensions.at(0), dimensions.at(1), static_cast(colorFormat), static_cast(type), data); + inline static void setSub(Target target, GLint mipLevel, const Math::Vector& offset, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { + glTexSubImage2D(static_cast(target), mipLevel, offset.at(0), offset.at(1), dimensions.at(0), dimensions.at(1), static_cast(colorFormat), static_cast(type), data); } }; template<> struct AbstractTexture::DataHelper<3> { - inline constexpr static GLenum target() { return GL_TEXTURE_3D; } + enum class Target: GLenum { + Texture3D = GL_TEXTURE_3D, + Array2D = GL_TEXTURE_2D_ARRAY + }; + + inline constexpr static Target target() { return Target::Texture3D; } - inline static void setWrapping(GLenum target, const Math::Vector& wrapping) { - glTexParameteri(target, GL_TEXTURE_WRAP_S, static_cast(wrapping.at(0))); - glTexParameteri(target, GL_TEXTURE_WRAP_T, static_cast(wrapping.at(1))); - glTexParameteri(target, GL_TEXTURE_WRAP_R, static_cast(wrapping.at(2))); + inline static void setWrapping(Target target, const Math::Vector& wrapping) { + glTexParameteri(static_cast(target), GL_TEXTURE_WRAP_S, static_cast(wrapping.at(0))); + glTexParameteri(static_cast(target), GL_TEXTURE_WRAP_T, static_cast(wrapping.at(1))); + glTexParameteri(static_cast(target), GL_TEXTURE_WRAP_R, static_cast(wrapping.at(2))); } - inline static void set(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { - glTexImage3D(target, mipLevel, static_cast(internalFormat), dimensions.at(0), dimensions.at(1), dimensions.at(2), 0, static_cast(colorFormat), static_cast(type), data); + inline static void set(Target target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { + glTexImage3D(static_cast(target), mipLevel, static_cast(internalFormat), dimensions.at(0), dimensions.at(1), dimensions.at(2), 0, static_cast(colorFormat), static_cast(type), data); } - inline static void setSub(GLenum target, GLint mipLevel, const Math::Vector& offset, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { - glTexSubImage3D(target, mipLevel, offset.at(0), offset.at(1), offset.at(2), dimensions.at(0), dimensions.at(1), dimensions.at(2), static_cast(colorFormat), static_cast(type), data); + inline static void setSub(Target target, GLint mipLevel, const Math::Vector& offset, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { + glTexSubImage3D(static_cast(target), mipLevel, offset.at(0), offset.at(1), offset.at(2), dimensions.at(0), dimensions.at(1), dimensions.at(2), static_cast(colorFormat), static_cast(type), data); } }; #endif diff --git a/src/CubeMapTexture.h b/src/CubeMapTexture.h index c10b41d73..f137114c9 100644 --- a/src/CubeMapTexture.h +++ b/src/CubeMapTexture.h @@ -60,20 +60,13 @@ class CubeMapTexture: public Texture2D { * @brief Constructor * @param layer Texture layer (number between 0 and 31) * - * Creates texture with target @c GL_TEXTURE_CUBE_MAP. + * Creates texture with target Target::CubeMap. */ - inline CubeMapTexture(GLint layer = 0): Texture2D(layer, GL_TEXTURE_CUBE_MAP) {} + inline CubeMapTexture(GLint layer = 0): Texture(layer, Target::CubeMap) {} - /** @brief Deleted. Use setData(Coordinate, GLint, InternalFormat, const Math::Vector&, ColorFormat, const T*) instead. */ template inline void setData(GLint mipLevel, InternalFormat internalFormat, const Math::Vector& _dimensions, ColorFormat colorFormat, const T* data) = delete; - - /** @brief Deleted. Use setData(Coordinate, GLint, InternalFormat, const Trade::Image*) instead. */ void setData(GLint mipLevel, InternalFormat internalFormat, const Trade::Image* image) = delete; - - /** @brief Deleted. Use @ref setSubData(Coordinate, GLint, const Math::Vector&, const Math::Vector&, ColorFormat, const T*) "setSubDataPositiveX()" and others instead. */ template inline void setSubData(GLint mipLevel, const Math::Vector& offset, const Math::Vector& _dimensions, ColorFormat colorFormat, const T* data) = delete; - - /** @brief Deleted. Use @ref setSubData(Coordinate, GLint, const Math::Vector&, const Trade::Image*) "setSubDataPositiveX()" and others instead. */ void setSubData(GLint mipLevel, const Math::Vector& offset, const Trade::Image* image) = delete; /** @@ -109,14 +102,14 @@ class CubeMapTexture: public Texture2D { } private: - void setData(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector& _dimensions, ColorFormat colorFormat, Type type, const void* data) { + void setData(Coordinate coordinate, GLint mipLevel, InternalFormat internalFormat, const Math::Vector& _dimensions, ColorFormat colorFormat, Type type, const void* data) { bind(); - DataHelper::set(target, mipLevel, internalFormat, _dimensions, colorFormat, type, data); + DataHelper::set(static_cast(coordinate), mipLevel, internalFormat, _dimensions, colorFormat, type, data); } - void setSubData(GLenum target, GLint mipLevel, const Math::Vector& offset, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { + void setSubData(Coordinate coordinate, GLint mipLevel, const Math::Vector& offset, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { bind(); - DataHelper::setSub(target, mipLevel, offset, dimensions, colorFormat, type, data); + DataHelper::setSub(static_cast(coordinate), mipLevel, offset, dimensions, colorFormat, type, data); } }; diff --git a/src/Texture.h b/src/Texture.h index 9df76a1b8..ba035a7db 100644 --- a/src/Texture.h +++ b/src/Texture.h @@ -25,6 +25,10 @@ namespace Magnum { /** @brief %Texture +@tparam dimensions %Texture dimension count +@tparam target %Target. If not set, target is based on dimension + count (@c Target::Texture1D, @c Target::Texture2D or + @c Target::Texture3D). Template class for one- to three-dimensional textures. @@ -41,27 +45,26 @@ to the shader - the only requirement is to have each texture in another layer. @section RectangleTextures Rectangle textures If you want to use rectangle textures, set target in constructor to -@c GL_TEXTURE_RECTANGLE and in shader use @c sampler2DRect. Unlike @c sampler2D, +@c Target::Rectangle and in shader use @c sampler2DRect. Unlike @c sampler2D, which accepts coordinates between 0 and 1, @c sampler2DRect accepts coordinates between 0 and @c textureSizeInGivenDirection-1. Note that rectangle textures don't support mipmapping and repeating wrapping modes, see @ref Texture::Filter "Filter", @ref Texture::Mipmap "Mipmap" and generateMipmap() documentation for more information. */ -template class MAGNUM_EXPORT Texture: public AbstractTexture { +template class Texture: public AbstractTexture { public: - static const size_t Dimensions = dimensions; /**< @brief Texture dimension count */ + static const size_t Dimensions = dimensions; /**< @brief %Texture dimension count */ + typedef typename DataHelper::Target Target; /**< @brief %Texture target */ /** * @brief Constructor - * @param layer Texture layer (number between 0 and 31) - * @param target Target, e.g. @c GL_TEXTURE_RECTANGLE. If not set, - * target is based on dimension count (@c GL_TEXTURE_1D, - * @c GL_TEXTURE_2D, @c GL_TEXTURE_3D). + * @param layer %Texture layer (number between 0 and 31) + * @param target %Texture target * * Creates one OpenGL texture. */ - inline Texture(GLint layer = 0, GLenum target = DataHelper::target()): AbstractTexture(layer, target) {} + inline Texture(GLint layer = 0, Target target = DataHelper::target()): AbstractTexture(layer, static_cast(target)), target(target) {} /** * @brief Set wrapping @@ -69,8 +72,7 @@ template class MAGNUM_EXPORT Texture: public AbstractTexture * * Sets wrapping type for coordinates out of range (0, 1) for normal * textures and (0, textureSizeInGivenDirection-1) for rectangle - * textures. Note that for rectangle textures repeating wrapping modes - * are unavailable. + * textures. */ inline void setWrapping(const Math::Vector& wrapping) { bind(); @@ -94,7 +96,7 @@ template class MAGNUM_EXPORT Texture: public AbstractTexture } /** - * @brief Set texture data + * @brief Set texture data from image * @param mipLevel Mip level * @param internalFormat Internal texture format * @param image Image @@ -125,7 +127,7 @@ template class MAGNUM_EXPORT Texture: public AbstractTexture } /** - * @brief Set texture subdata + * @brief Set texture subdata from image * @param mipLevel Mip level * @param offset Offset where to put data in the texture * @param image Image @@ -137,6 +139,9 @@ template class MAGNUM_EXPORT Texture: public AbstractTexture bind(); DataHelper::setSub(target, mipLevel, offset, image->dimensions(), image->colorFormat(), image->type(), image->data()); } + + private: + Target target; }; /** @brief One-dimensional texture */