From b924da57adb55b974722c082cef90cf35fffe604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 2 Dec 2011 00:37:04 +0100 Subject: [PATCH] Splitting non-templated things from Texture to AbstractTexture. --- src/AbstractTexture.cpp | 48 ++++++++ src/AbstractTexture.h | 249 ++++++++++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 1 + src/Texture.cpp | 28 ----- src/Texture.h | 207 +-------------------------------- 5 files changed, 301 insertions(+), 232 deletions(-) create mode 100644 src/AbstractTexture.cpp create mode 100644 src/AbstractTexture.h diff --git a/src/AbstractTexture.cpp b/src/AbstractTexture.cpp new file mode 100644 index 000000000..5c1682fa2 --- /dev/null +++ b/src/AbstractTexture.cpp @@ -0,0 +1,48 @@ +/* + Copyright © 2010, 2011 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "AbstractTexture.h" + +namespace Magnum { + +/* Check correctness of binary OR in setMinificationFilter(). If nobody fucks + anything up, this assert should produce the same results on all dimensions, + thus testing only on AbstractTexture. */ +static_assert(((AbstractTexture::NearestNeighborFilter|AbstractTexture::BaseMipLevel) == GL_NEAREST) && + ((AbstractTexture::NearestNeighborFilter|AbstractTexture::NearestMipLevel) == GL_NEAREST_MIPMAP_NEAREST) && + ((AbstractTexture::NearestNeighborFilter|AbstractTexture::LinearMipInterpolation) == GL_NEAREST_MIPMAP_LINEAR) && + ((AbstractTexture::LinearFilter|AbstractTexture::BaseMipLevel) == GL_LINEAR) && + ((AbstractTexture::LinearFilter|AbstractTexture::NearestMipLevel) == GL_LINEAR_MIPMAP_NEAREST) && + ((AbstractTexture::LinearFilter|AbstractTexture::LinearMipInterpolation) == GL_LINEAR_MIPMAP_LINEAR), + "Unsupported constants for GL texture filtering"); + +void AbstractTexture::setMinificationFilter(Filter filter, Mipmap mipmap) { + /* Only base mip level is supported on rectangle textures */ + if(target == GL_TEXTURE_RECTANGLE) mipmap = BaseMipLevel; + + bind(); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter|mipmap); + unbind(); +} + +void AbstractTexture::generateMipmap() { + if(target == GL_TEXTURE_RECTANGLE) return; + + bind(); + glGenerateMipmap(target); + unbind(); +} + +} diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h new file mode 100644 index 000000000..eb6685145 --- /dev/null +++ b/src/AbstractTexture.h @@ -0,0 +1,249 @@ +#ifndef Magnum_AbstractTexture_h +#define Magnum_AbstractTexture_h +/* + Copyright © 2010, 2011 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::AbstractTexture + */ + +#include "Magnum.h" +#include "TypeTraits.h" + +namespace Magnum { + +/** +@brief Non-templated base for Texture + +See Texture documentation for more information. +*/ +class AbstractTexture { + public: + /** @brief Texture filtering */ + enum Filter { + /** + * Nearest neighbor filtering + */ + NearestNeighborFilter = GL_NEAREST, + + /** + * Linear filtering + */ + LinearFilter = GL_LINEAR + }; + + /** @brief Mip level selection */ + enum Mipmap { + /** + * Select base mip level + */ + BaseMipLevel = GL_NEAREST & ~GL_NEAREST, + + /** + * Select nearest mip level. Unavailable on rectangle textures. + */ + NearestMipLevel = GL_NEAREST_MIPMAP_NEAREST & ~GL_NEAREST, + + /** + * Linear interpolation of nearest mip levels. Unavailable on + * rectangle textures. + */ + LinearMipInterpolation = GL_NEAREST_MIPMAP_LINEAR & ~GL_NEAREST + }; + + /** @brief Texture wrapping on the edge */ + enum Wrapping { + /** + * Repeat texture. Unavailable on rectangle textures. + */ + Repeat = GL_REPEAT, + + /** + * Repeat mirrored texture. Unavailable on rectangle textures. + */ + MirroredRepeat = GL_MIRRORED_REPEAT, + + /** + * Clamp to edge. Coordinates out of the range will be clamped to + * first / last column / row in given direction. + */ + ClampToEdge = GL_CLAMP_TO_EDGE, + + /** + * Clamp to border color. Coordinates out of range will be clamped + * to border color (set with setBorderColor()). + */ + ClampToBorder = GL_CLAMP_TO_BORDER + }; + + /** @brief Internal format */ + enum InternalFormat { + CompressedRed = GL_COMPRESSED_RED, + CompressedRedGreen = GL_COMPRESSED_RG, + CompressedRGB = GL_COMPRESSED_RGB, + CompressedRGBA = GL_COMPRESSED_RGBA + }; + + /** @brief Color format */ + enum ColorFormat { + Red = GL_RED, + RedGreen = GL_RG, + RGB = GL_RGB, + RGBA = GL_RGBA, + BGR = GL_BGR, + BGRA = GL_BGRA + }; + + /** + * @brief Constructor + * @param target Target, e.g. @c GL_TEXTURE_2D. + * + * Creates one OpenGL texture. + */ + inline AbstractTexture(GLenum target): target(target) { + glGenTextures(1, &texture); + } + + /** + * @brief Destructor + * + * Deletes assigned OpenGL texture. + */ + inline virtual ~AbstractTexture() { + glDeleteTextures(1, &texture); + } + + /** @brief Bind texture for usage / rendering */ + inline void bind() const { + glBindTexture(target, texture); + } + + /** + * @brief Unbind texture + * + * @note Unbinds any texture from given dimension, not only this + * particular one. + */ + inline void unbind() const { + glBindTexture(target, 0); + } + + /** + * @brief Set minification filter + * @param filter Filter + * @param mipmap Mipmap filtering. If set to anything else than + * BaseMipLevel, make sure textures for all mip levels are set or + * call generateMipmap(). + * + * Sets filter used when the object pixel size is smaller than the + * texture size. For rectangle textures only some modes are supported, + * see @ref AbstractTexture::Filter "Filter" and + * @ref AbstractTexture::Mipmap "Mipmap" documentation for more + * information. + * @attention This and setMagnificationFilter() must be called after + * creating the texture, otherwise it will be unusable. + */ + void setMinificationFilter(Filter filter, Mipmap mipmap = BaseMipLevel); + + /** + * @brief Set magnification filter + * @param filter Filter + * + * Sets filter used when the object pixel size is larger than largest + * texture size. + * @attention This and setMinificationFilter() must be called after + * creating the texture, otherwise it will be unusable. + */ + inline void setMagnificationFilter(Filter filter) { + bind(); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter); + unbind(); + } + + /** + * @brief Set border color + * + * Border color when @ref AbstractTexture::Wrapping "wrapping" is set + * to @c ClampToBorder. + */ + inline void setBorderColor(const Vector4& color) { + bind(); + glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, color.data()); + unbind(); + } + + /** + * @brief Generate mipmap + * + * Does nothing on rectangle textures. + * @see setMinificationFilter() + */ + void generateMipmap(); + + protected: + const GLenum target; /**< @brief Texture target */ + + /** + * @brief Helper for setting texture data + * + * Workaround for partial template specialization. + */ + template struct DataHelper { + #ifdef DOXYGEN_GENERATING_OUTPUT + /** + * @brief Set texture data + * @param target Target, such as @c GL_TEXTURE_RECTANGLE + * @param mipLevel Mip level + * @param internalFormat Internal texture format. One value from + * @ref AbstractTexture::InternalFormat "InternalFormat" or + * @ref AbstractTexture::ColorFormat "ColorFormat" enum. + * @param dimensions %Texture dimensions + * @param colorFormat Color format of passed data. Data size + * per color channel is detected from format of passed data + * array. + * @param data %Texture data + * + * Calls @c glTexImage1D, @c glTexImage2D, @c glTexImage3D depending + * on dimension count. + */ + inline void operator()(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, const T* data); + #endif + }; + + #ifndef DOXYGEN_GENERATING_OUTPUT + template struct DataHelper { + inline void operator()(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, const T* data) { + glTexImage1D(target, mipLevel, internalFormat, dimensions.at(0), 0, colorFormat, TypeTraits::glType(), data); + } + }; + template struct DataHelper { + inline void operator()(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, const T* data) { + glTexImage2D(target, mipLevel, internalFormat, dimensions.at(0), dimensions.at(1), 0, colorFormat, TypeTraits::glType(), data); + } + }; + template struct DataHelper { + inline void operator()(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, const T* data) { + glTexImage3D(target, mipLevel, internalFormat, dimensions.at(0), dimensions.at(1), dimensions.at(2), 0, colorFormat, TypeTraits::glType(), data); + } + }; + #endif + + private: + GLuint texture; +}; + +} + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 28898d050..4cb717232 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,6 +9,7 @@ add_subdirectory(Math) set(Magnum_SRCS Object.cpp + AbstractTexture.cpp AbstractShaderProgram.cpp Camera.cpp IndexedMesh.cpp diff --git a/src/Texture.cpp b/src/Texture.cpp index 2b63207a4..62b0936d2 100644 --- a/src/Texture.cpp +++ b/src/Texture.cpp @@ -17,17 +17,6 @@ namespace Magnum { -/* Check correctness of binary OR in setMinificationFilter(). If nobody fucks - anything up, this assert should produce the same results on all dimensions, - thus testing only on Texture1D. */ -static_assert(((Texture1D::NearestNeighborFilter|Texture1D::BaseMipLevel) == GL_NEAREST) && - ((Texture1D::NearestNeighborFilter|Texture1D::NearestMipLevel) == GL_NEAREST_MIPMAP_NEAREST) && - ((Texture1D::NearestNeighborFilter|Texture1D::LinearMipInterpolation) == GL_NEAREST_MIPMAP_LINEAR) && - ((Texture1D::LinearFilter|Texture1D::BaseMipLevel) == GL_LINEAR) && - ((Texture1D::LinearFilter|Texture1D::NearestMipLevel) == GL_LINEAR_MIPMAP_NEAREST) && - ((Texture1D::LinearFilter|Texture1D::LinearMipInterpolation) == GL_LINEAR_MIPMAP_LINEAR), - "Unsupported constants for GL texture filtering"); - template void Texture::setWrapping(const Math::Vector& wrapping) { bind(); for(int i = 0; i != dimensions; ++i) { @@ -50,23 +39,6 @@ template void Texture::setWrapping(const Math::Ve unbind(); } -template void Texture::setMinificationFilter(Filter filter, Mipmap mipmap) { - /* Only base mip level is supported on rectangle textures */ - if(target == GL_TEXTURE_RECTANGLE) mipmap = BaseMipLevel; - - bind(); - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter|mipmap); - unbind(); -} - -template void Texture::generateMipmap() { - if(target == GL_TEXTURE_RECTANGLE) return; - - bind(); - glGenerateMipmap(target); - unbind(); -} - /* Instantiate all textures */ template class Texture<1>; template class Texture<2>; diff --git a/src/Texture.h b/src/Texture.h index 5a2ddcea8..7ad89213a 100644 --- a/src/Texture.h +++ b/src/Texture.h @@ -19,8 +19,7 @@ * @brief Class Magnum::Texture */ -#include "Magnum.h" -#include "TypeTraits.h" +#include "AbstractTexture.h" namespace Magnum { @@ -48,85 +47,10 @@ 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 Texture { +template class Texture: public AbstractTexture { public: static const size_t Dimensions = dimensions; /**< @brief Texture dimension count */ - /** @brief Texture filtering */ - enum Filter { - /** - * Nearest neighbor filtering - */ - NearestNeighborFilter = GL_NEAREST, - - /** - * Linear filtering - */ - LinearFilter = GL_LINEAR - }; - - /** @brief Mip level selection */ - enum Mipmap { - /** - * Select base mip level - */ - BaseMipLevel = GL_NEAREST & ~GL_NEAREST, - - /** - * Select nearest mip level. Unavailable on rectangle textures. - */ - NearestMipLevel = GL_NEAREST_MIPMAP_NEAREST & ~GL_NEAREST, - - /** - * Linear interpolation of nearest mip levels. Unavailable on - * rectangle textures. - */ - LinearMipInterpolation = GL_NEAREST_MIPMAP_LINEAR & ~GL_NEAREST - }; - - /** @brief Texture wrapping on the edge */ - enum Wrapping { - /** - * Repeat texture. Unavailable on rectangle textures. - */ - Repeat = GL_REPEAT, - - /** - * Repeat mirrored texture. Unavailable on rectangle textures. - */ - MirroredRepeat = GL_MIRRORED_REPEAT, - - /** - * Clamp to edge. Coordinates out of the range will be clamped to - * first / last column / row in given direction. - */ - ClampToEdge = GL_CLAMP_TO_EDGE, - - /** - * Clamp to border color. Coordinates out of range will be clamped - * to border color (set with setBorderColor()). - */ - ClampToBorder = GL_CLAMP_TO_BORDER - }; - - /** @brief Internal format */ - enum InternalFormat { - CompressedRed = GL_COMPRESSED_RED, - CompressedRedGreen = GL_COMPRESSED_RG, - CompressedRGB = GL_COMPRESSED_RGB, - CompressedRGBA = GL_COMPRESSED_RGBA - }; - - /** @brief Color format */ - enum ColorFormat { - Red = GL_RED, - RedGreen = GL_RG, - RGB = GL_RGB, - RGBA = GL_RGBA, - BGR = GL_BGR, - BGRA = GL_BGRA - }; - /** * @brief Constructor * @param target Target, e.g. @c GL_TEXTURE_RECTANGLE. If not set, @@ -135,64 +59,7 @@ template class Texture { * * Creates one OpenGL texture. */ - inline Texture(GLenum target = GL_TEXTURE_1D + dimensions - 1): target(target) { - glGenTextures(1, &texture); - } - - /** - * @brief Destructor - * - * Deletes assigned OpenGL texture. - */ - inline virtual ~Texture() { - glDeleteTextures(1, &texture); - } - - /** @brief Bind texture for usage / rendering */ - inline void bind() const { - glBindTexture(target, texture); - } - - /** - * @brief Unbind texture - * - * @note Unbinds any texture from given dimension, not only this - * particular one. - */ - inline void unbind() const { - glBindTexture(target, 0); - } - - /** - * @brief Set minification filter - * @param filter Filter - * @param mipmap Mipmap filtering. If set to anything else than - * BaseMipLevel, make sure textures for all mip levels are set or - * call generateMipmap(). - * - * Sets filter used when the object pixel size is smaller than the - * texture size. For rectangle textures only some modes are supported, - * see @ref Texture::Filter "Filter" and @ref Texture::Mipmap "Mipmap" - * documentation for more information. - * @attention This and setMagnificationFilter() must be called after - * creating the texture, otherwise it will be unusable. - */ - void setMinificationFilter(Filter filter, Mipmap mipmap = BaseMipLevel); - - /** - * @brief Set magnification filter - * @param filter Filter - * - * Sets filter used when the object pixel size is larger than largest - * texture size. - * @attention This and setMinificationFilter() must be called after - * creating the texture, otherwise it will be unusable. - */ - inline void setMagnificationFilter(Filter filter) { - bind(); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter); - unbind(); - } + inline Texture(GLenum target = GL_TEXTURE_1D + dimensions - 1): AbstractTexture(target) {} /** * @brief Set wrapping @@ -205,26 +72,6 @@ template class Texture { */ void setWrapping(const Math::Vector& wrapping); - /** - * @brief Set border color - * - * Border color when @ref Texture::Wrapping "wrapping" is set to - * @c ClampToBorder. - */ - inline void setBorderColor(const Vector4& color) { - bind(); - glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, color.data()); - unbind(); - } - - /** - * @brief Generate mipmap - * - * Does nothing on rectangle textures. - * @see setMinificationFilter() - */ - void generateMipmap(); - protected: /** * @brief Set texture data @@ -242,54 +89,6 @@ template class Texture { DataHelper::TextureType, dimensions>()(target, mipLevel, internalFormat, _dimensions, colorFormat, data); unbind(); } - - /** - * @brief Helper for setting texture data - * - * Workaround for partial template specialization. - */ - template struct DataHelper { - #ifdef DOXYGEN_GENERATING_OUTPUT - /** - * @brief Functor - * @param target Target, such as @c GL_TEXTURE_RECTANGLE - * @param mipLevel Mip level - * @param internalFormat Internal texture format. One value from - * Texture::InternalFormat or Texture::ColorFormat enum. - * @param _dimensions %Texture dimensions - * @param colorFormat Color format of passed data. Data size - * per color channel is detected from format of passed data - * array. - * @param data %Texture data - * - * Calls @c glTexImage1D, @c glTexImage2D, @c glTexImage3D depending - * on dimension count. - */ - inline void operator()(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector& _dimensions, ColorFormat colorFormat, const T* data); - #endif - }; - - #ifndef DOXYGEN_GENERATING_OUTPUT - template struct DataHelper { - inline void operator()(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector& _dimensions, ColorFormat colorFormat, const T* data) { - glTexImage1D(target, mipLevel, internalFormat, _dimensions.at(0), 0, colorFormat, TypeTraits::glType(), data); - } - }; - template struct DataHelper { - inline void operator()(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector& _dimensions, ColorFormat colorFormat, const T* data) { - glTexImage2D(target, mipLevel, internalFormat, _dimensions.at(0), _dimensions.at(1), 0, colorFormat, TypeTraits::glType(), data); - } - }; - template struct DataHelper { - inline void operator()(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector& _dimensions, ColorFormat colorFormat, const T* data) { - glTexImage3D(target, mipLevel, internalFormat, _dimensions.at(0), _dimensions.at(1), _dimensions.at(2), 0, colorFormat, TypeTraits::glType(), data); - } - }; - #endif - - private: - GLuint texture; - const GLenum target; }; /** @brief One-dimensional texture */