Browse Source

Using strongly-typed enums in AbstractTexture and derived classes.

Allows safer passing of values, more descriptive and shorter enum names
and also using the same enum names/values in InternalFormat and
ColorFormat.
vectorfields
Vladimír Vondruš 15 years ago
parent
commit
e9a556cc10
  1. 21
      src/AbstractTexture.cpp
  2. 56
      src/AbstractTexture.h
  3. 16
      src/CubeMapTexture.h
  4. 8
      src/Texture.cpp
  5. 6
      src/Texture.h

21
src/AbstractTexture.cpp

@ -29,25 +29,30 @@ texture_assert(4); texture_assert(12); texture_assert(20); texture_assert(28);
texture_assert(5); texture_assert(13); texture_assert(21); texture_assert(29);
texture_assert(6); texture_assert(14); texture_assert(22); texture_assert(30);
texture_assert(7); texture_assert(15); texture_assert(23); texture_assert(31);
#undef texture_assert
/* 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),
#define filter_or(filter, mipmap) \
(static_cast<GLint>(AbstractTexture::Filter::filter)|static_cast<GLint>(AbstractTexture::Mipmap::mipmap))
static_assert((filter_or(NearestNeighbor, BaseLevel) == GL_NEAREST) &&
(filter_or(NearestNeighbor, NearestLevel) == GL_NEAREST_MIPMAP_NEAREST) &&
(filter_or(NearestNeighbor, LinearInterpolation) == GL_NEAREST_MIPMAP_LINEAR) &&
(filter_or(LinearInterpolation, BaseLevel) == GL_LINEAR) &&
(filter_or(LinearInterpolation, NearestLevel) == GL_LINEAR_MIPMAP_NEAREST) &&
(filter_or(LinearInterpolation, LinearInterpolation) == GL_LINEAR_MIPMAP_LINEAR),
"Unsupported constants for GL texture filtering");
#undef filter_or
#endif
void AbstractTexture::setMinificationFilter(Filter filter, Mipmap mipmap) {
/* Only base mip level is supported on rectangle textures */
if(target == GL_TEXTURE_RECTANGLE) mipmap = BaseMipLevel;
if(target == GL_TEXTURE_RECTANGLE) mipmap = Mipmap::BaseLevel;
bind();
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter|mipmap);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
static_cast<GLint>(filter)|static_cast<GLint>(mipmap));
unbind();
}

56
src/AbstractTexture.h

@ -34,39 +34,39 @@ class AbstractTexture {
public:
/** @brief Texture filtering */
enum Filter {
enum class Filter: GLint {
/**
* Nearest neighbor filtering
*/
NearestNeighborFilter = GL_NEAREST,
NearestNeighbor = GL_NEAREST,
/**
* Linear filtering
* Linear interpolation filtering
*/
LinearFilter = GL_LINEAR
LinearInterpolation = GL_LINEAR
};
/** @brief Mip level selection */
enum Mipmap {
enum class Mipmap: GLint {
/**
* Select base mip level
*/
BaseMipLevel = GL_NEAREST & ~GL_NEAREST,
BaseLevel = GL_NEAREST & ~GL_NEAREST,
/**
* Select nearest mip level. Unavailable on rectangle textures.
*/
NearestMipLevel = GL_NEAREST_MIPMAP_NEAREST & ~GL_NEAREST,
NearestLevel = GL_NEAREST_MIPMAP_NEAREST & ~GL_NEAREST,
/**
* Linear interpolation of nearest mip levels. Unavailable on
* rectangle textures.
*/
LinearMipInterpolation = GL_NEAREST_MIPMAP_LINEAR & ~GL_NEAREST
LinearInterpolation = GL_NEAREST_MIPMAP_LINEAR & ~GL_NEAREST
};
/** @brief Texture wrapping on the edge */
enum Wrapping {
enum class Wrapping: GLint {
/**
* Repeat texture. Unavailable on rectangle textures.
*/
@ -91,7 +91,13 @@ class AbstractTexture {
};
/** @brief Internal format */
enum InternalFormat {
enum class InternalFormat: GLint {
Red = GL_RED,
RedGreen = GL_RG,
RGB = GL_RGB,
RGBA = GL_RGBA,
BGR = GL_BGR,
BGRA = GL_BGRA,
CompressedRed = GL_COMPRESSED_RED,
CompressedRedGreen = GL_COMPRESSED_RG,
CompressedRGB = GL_COMPRESSED_RGB,
@ -99,7 +105,7 @@ class AbstractTexture {
};
/** @brief Color format */
enum ColorFormat {
enum class ColorFormat: GLenum {
Red = GL_RED,
RedGreen = GL_RG,
RGB = GL_RGB,
@ -164,7 +170,7 @@ class AbstractTexture {
* @attention This and setMagnificationFilter() must be called after
* creating the texture, otherwise it will be unusable.
*/
void setMinificationFilter(Filter filter, Mipmap mipmap = BaseMipLevel);
void setMinificationFilter(Filter filter, Mipmap mipmap = Mipmap::BaseLevel);
/**
* @brief Set magnification filter
@ -177,7 +183,7 @@ class AbstractTexture {
*/
inline void setMagnificationFilter(Filter filter) {
bind();
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, static_cast<GLint>(filter));
unbind();
}
@ -223,9 +229,7 @@ class AbstractTexture {
* @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 internalFormat Internal texture format
* @param dimensions %Texture dimensions
* @param colorFormat Color format of passed data. Data size
* per color channel is detected from format of passed data
@ -235,7 +239,7 @@ class AbstractTexture {
* Calls @c glTexImage1D, @c glTexImage2D, @c glTexImage3D depending
* on dimension count.
*/
template<class T> inline static void set(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector<GLsizei, textureDimensions>& dimensions, ColorFormat colorFormat, const T* data);
template<class T> inline static void set(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector<GLsizei, textureDimensions>& dimensions, ColorFormat colorFormat, const T* data);
/**
* @brief Set texture subdata
@ -264,34 +268,34 @@ class AbstractTexture {
template<> struct AbstractTexture::DataHelper<1> {
inline constexpr static GLenum target() { return GL_TEXTURE_1D; }
template<class T> inline static void set(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector<GLsizei, 1>& dimensions, ColorFormat colorFormat, const T* data) {
glTexImage1D(target, mipLevel, internalFormat, dimensions.at(0), 0, colorFormat, TypeTraits<T>::glType(), data);
template<class T> inline static void set(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector<GLsizei, 1>& dimensions, ColorFormat colorFormat, const T* data) {
glTexImage1D(target, mipLevel, static_cast<GLint>(internalFormat), dimensions.at(0), 0, static_cast<GLenum>(colorFormat), TypeTraits<T>::glType(), data);
}
template<class T> inline static void setSub(GLenum target, GLint mipLevel, const Math::Vector<GLsizei, 1>& offset, const Math::Vector<GLsizei, 1>& dimensions, ColorFormat colorFormat, const T* data) {
glTexSubImage1D(target, mipLevel, offset.at(0), dimensions.at(0), colorFormat, TypeTraits<T>::glType(), data);
glTexSubImage1D(target, mipLevel, offset.at(0), dimensions.at(0), static_cast<GLenum>(colorFormat), TypeTraits<T>::glType(), data);
}
};
template<> struct AbstractTexture::DataHelper<2> {
inline constexpr static GLenum target() { return GL_TEXTURE_2D; }
template<class T> inline static void set(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector<GLsizei, 2>& dimensions, ColorFormat colorFormat, const T* data) {
glTexImage2D(target, mipLevel, internalFormat, dimensions.at(0), dimensions.at(1), 0, colorFormat, TypeTraits<T>::glType(), data);
template<class T> inline static void set(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector<GLsizei, 2>& dimensions, ColorFormat colorFormat, const T* data) {
glTexImage2D(target, mipLevel, static_cast<GLint>(internalFormat), dimensions.at(0), dimensions.at(1), 0, static_cast<GLenum>(colorFormat), TypeTraits<T>::glType(), data);
}
template<class T> inline static void setSub(GLenum target, GLint mipLevel, const Math::Vector<GLsizei, 2>& offset, const Math::Vector<GLsizei, 2>& dimensions, ColorFormat colorFormat, const T* data) {
glTexSubImage2D(target, mipLevel, offset.at(0), offset.at(1), dimensions.at(0), dimensions.at(1), colorFormat, TypeTraits<T>::glType(), data);
glTexSubImage2D(target, mipLevel, offset.at(0), offset.at(1), dimensions.at(0), dimensions.at(1), static_cast<GLenum>(colorFormat), TypeTraits<T>::glType(), data);
}
};
template<> struct AbstractTexture::DataHelper<3> {
inline constexpr static GLenum target() { return GL_TEXTURE_3D; }
template<class T> inline static void set(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector<GLsizei, 3>& dimensions, ColorFormat colorFormat, const T* data) {
glTexImage3D(target, mipLevel, internalFormat, dimensions.at(0), dimensions.at(1), dimensions.at(2), 0, colorFormat, TypeTraits<T>::glType(), data);
template<class T> inline static void set(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector<GLsizei, 3>& dimensions, ColorFormat colorFormat, const T* data) {
glTexImage3D(target, mipLevel, static_cast<GLint>(internalFormat), dimensions.at(0), dimensions.at(1), dimensions.at(2), 0, static_cast<GLenum>(colorFormat), TypeTraits<T>::glType(), data);
}
template<class T> inline static void setSub(GLenum target, GLint mipLevel, const Math::Vector<GLsizei, 2>& offset, const Math::Vector<GLsizei, 2>& dimensions, ColorFormat colorFormat, const T* data) {
glTexSubImage3D(target, mipLevel, offset.at(0), offset.at(1), offset.at(2), dimensions.at(0), dimensions.at(1), dimensions.at(2), colorFormat, TypeTraits<T>::glType(), data);
glTexSubImage3D(target, mipLevel, offset.at(0), offset.at(1), offset.at(2), dimensions.at(0), dimensions.at(1), dimensions.at(2), static_cast<GLenum>(colorFormat), TypeTraits<T>::glType(), data);
}
};
#endif

16
src/CubeMapTexture.h

@ -56,7 +56,7 @@ class CubeMapTexture: public Texture2D {
protected:
/** @brief Deleted. Use setDataPositiveX() and others instead. */
template<class T> inline void setData(GLint mipLevel, int internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) = delete;
template<class T> inline void setData(GLint mipLevel, InternalFormat internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) = delete;
/** @brief Deleted. Use setSubDataPositiveX() and others instead. */
template<class T> inline void setSubData(GLint mipLevel, const Math::Vector<GLsizei, Dimensions>& offset, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) = delete;
@ -66,7 +66,7 @@ class CubeMapTexture: public Texture2D {
*
* @copydetails Texture::setData()
*/
template<class T> inline void setDataPositiveX(GLint mipLevel, int internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
template<class T> inline void setDataPositiveX(GLint mipLevel, InternalFormat internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
setData(GL_TEXTURE_CUBE_MAP_POSITIVE_X, mipLevel, internalFormat, _dimensions, colorFormat, data);
}
@ -84,7 +84,7 @@ class CubeMapTexture: public Texture2D {
*
* @copydetails Texture::setData()
*/
template<class T> inline void setDataNegativeX(GLint mipLevel, int internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
template<class T> inline void setDataNegativeX(GLint mipLevel, InternalFormat internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
setData(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, mipLevel, internalFormat, _dimensions, colorFormat, data);
}
@ -102,7 +102,7 @@ class CubeMapTexture: public Texture2D {
*
* @copydetails Texture::setData()
*/
template<class T> inline void setDataPositiveY(GLint mipLevel, int internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
template<class T> inline void setDataPositiveY(GLint mipLevel, InternalFormat internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
setData(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, mipLevel, internalFormat, _dimensions, colorFormat, data);
}
@ -120,7 +120,7 @@ class CubeMapTexture: public Texture2D {
*
* @copydetails Texture::setData()
*/
template<class T> inline void setDataNegativeY(GLint mipLevel, int internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
template<class T> inline void setDataNegativeY(GLint mipLevel, InternalFormat internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
setData(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mipLevel, internalFormat, _dimensions, colorFormat, data);
}
@ -138,7 +138,7 @@ class CubeMapTexture: public Texture2D {
*
* @copydetails Texture::setData()
*/
template<class T> inline void setDataPositiveZ(GLint mipLevel, int internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
template<class T> inline void setDataPositiveZ(GLint mipLevel, InternalFormat internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
setData(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, mipLevel, internalFormat, _dimensions, colorFormat, data);
}
@ -156,7 +156,7 @@ class CubeMapTexture: public Texture2D {
*
* @copydetails Texture::setData()
*/
template<class T> inline void setDataNegativeZ(GLint mipLevel, int internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
template<class T> inline void setDataNegativeZ(GLint mipLevel, InternalFormat internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
setData(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, mipLevel, internalFormat, _dimensions, colorFormat, data);
}
@ -170,7 +170,7 @@ class CubeMapTexture: public Texture2D {
}
private:
template<class T> void setData(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
template<class T> void setData(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector<GLsizei, Dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
bind();
DataHelper<Dimensions>::template set<typename TypeTraits<T>::TextureType>(target, mipLevel, internalFormat, _dimensions, colorFormat, data);
unbind();

8
src/Texture.cpp

@ -21,18 +21,18 @@ template<size_t dimensions> void Texture<dimensions>::setWrapping(const Math::Ve
bind();
for(int i = 0; i != dimensions; ++i) {
/* Repeat wrap modes are not available on rectangle textures. */
if(target == GL_TEXTURE_RECTANGLE && (wrapping.at(i) == Repeat || wrapping.at(i) == MirroredRepeat))
if(target == GL_TEXTURE_RECTANGLE && (wrapping.at(i) == Wrapping::Repeat || wrapping.at(i) == Wrapping::MirroredRepeat))
continue;
switch(i) {
case 0:
glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapping.at(i));
glTexParameteri(target, GL_TEXTURE_WRAP_S, static_cast<GLint>(wrapping.at(i)));
break;
case 1:
glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapping.at(i));
glTexParameteri(target, GL_TEXTURE_WRAP_T, static_cast<GLint>(wrapping.at(i)));
break;
case 2:
glTexParameteri(target, GL_TEXTURE_WRAP_R, wrapping.at(i));
glTexParameteri(target, GL_TEXTURE_WRAP_R, static_cast<GLint>(wrapping.at(i)));
break;
}
}

6
src/Texture.h

@ -79,15 +79,13 @@ template<size_t dimensions> class Texture: public AbstractTexture {
/**
* @brief Set texture data
* @param mipLevel Mip level
* @param internalFormat Internal texture format. One value from
* @ref Texture::InternalFormat "InternalFormat" or
* @ref Texture::ColorFormat "ColorFormat" enum.
* @param internalFormat Internal texture format
* @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
*/
template<class T> inline void setData(GLint mipLevel, int internalFormat, const Math::Vector<GLsizei, dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
template<class T> inline void setData(GLint mipLevel, InternalFormat internalFormat, const Math::Vector<GLsizei, dimensions>& _dimensions, ColorFormat colorFormat, const T* data) {
bind();
DataHelper<dimensions>::template set<typename TypeTraits<T>::TextureType>(target, mipLevel, internalFormat, _dimensions, colorFormat, data);
unbind();

Loading…
Cancel
Save