Browse Source

Using EXT_direct_state_access in textures.

Saves unnecessary calls to glActiveTexture() and glBindTexture().
vectorfields
Vladimír Vondruš 14 years ago
parent
commit
1f43839e04
  1. 160
      src/AbstractTexture.cpp
  2. 165
      src/AbstractTexture.h
  3. 23
      src/BufferedTexture.cpp
  4. 31
      src/BufferedTexture.h
  5. 4
      src/Context.cpp
  6. 8
      src/CubeMapTexture.h
  7. 12
      src/CubeMapTextureArray.h
  8. 33
      src/Texture.h

160
src/AbstractTexture.cpp

@ -16,11 +16,35 @@
#include "AbstractTexture.h" #include "AbstractTexture.h"
#include "Context.h" #include "Context.h"
#include "Extensions.h"
#include "Implementation/State.h" #include "Implementation/State.h"
#include "Implementation/TextureState.h" #include "Implementation/TextureState.h"
namespace Magnum { namespace Magnum {
AbstractTexture::BindImplementation AbstractTexture::bindImplementation =
&AbstractTexture::bindImplementationDefault;
AbstractTexture::ParameteriImplementation AbstractTexture::parameteriImplementation =
&AbstractTexture::parameterImplementationDefault;
AbstractTexture::ParameterfImplementation AbstractTexture::parameterfImplementation =
&AbstractTexture::parameterImplementationDefault;
AbstractTexture::ParameterfvImplementation AbstractTexture::parameterfvImplementation =
&AbstractTexture::parameterImplementationDefault;
AbstractTexture::MipmapImplementation AbstractTexture::mipmapImplementation =
&AbstractTexture::mipmapImplementationDefault;
AbstractTexture::Image1DImplementation AbstractTexture::image1DImplementation =
&AbstractTexture::imageImplementationDefault;
AbstractTexture::Image2DImplementation AbstractTexture::image2DImplementation =
&AbstractTexture::imageImplementationDefault;
AbstractTexture::Image3DImplementation AbstractTexture::image3DImplementation =
&AbstractTexture::imageImplementationDefault;
AbstractTexture::SubImage1DImplementation AbstractTexture::subImage1DImplementation =
&AbstractTexture::subImageImplementationDefault;
AbstractTexture::SubImage2DImplementation AbstractTexture::subImage2DImplementation =
&AbstractTexture::subImageImplementationDefault;
AbstractTexture::SubImage3DImplementation AbstractTexture::subImage3DImplementation =
&AbstractTexture::subImageImplementationDefault;
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
/* Check correctness of binary OR in setMinificationFilter(). If nobody fucks /* Check correctness of binary OR in setMinificationFilter(). If nobody fucks
@ -68,6 +92,12 @@ void AbstractTexture::bind(GLint layer) {
/* If already bound in given layer, nothing to do */ /* If already bound in given layer, nothing to do */
if(textureState->bindings[layer] == _id) return; if(textureState->bindings[layer] == _id) return;
(this->*bindImplementation)(layer);
}
void AbstractTexture::bindImplementationDefault(GLint layer) {
Implementation::TextureState* const textureState = Context::current()->state()->texture;
/* Change to given layer, if not already there */ /* Change to given layer, if not already there */
if(textureState->currentLayer != layer) if(textureState->currentLayer != layer)
glActiveTexture(GL_TEXTURE0 + (textureState->currentLayer = layer)); glActiveTexture(GL_TEXTURE0 + (textureState->currentLayer = layer));
@ -76,13 +106,16 @@ void AbstractTexture::bind(GLint layer) {
glBindTexture(_target, (textureState->bindings[layer] = _id)); glBindTexture(_target, (textureState->bindings[layer] = _id));
} }
void AbstractTexture::bindImplementationDSA(GLint layer) {
glBindMultiTextureEXT(GL_TEXTURE0 + layer, _target, (Context::current()->state()->texture->bindings[layer] = _id));
}
AbstractTexture* AbstractTexture::setMinificationFilter(Filter filter, Mipmap mipmap) { AbstractTexture* AbstractTexture::setMinificationFilter(Filter filter, Mipmap mipmap) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
CORRADE_ASSERT(_target != GL_TEXTURE_RECTANGLE || mipmap == Mipmap::BaseLevel, "AbstractTexture: rectangle textures cannot have mipmaps", this); CORRADE_ASSERT(_target != GL_TEXTURE_RECTANGLE || mipmap == Mipmap::BaseLevel, "AbstractTexture: rectangle textures cannot have mipmaps", this);
#endif #endif
bindInternal(); (this->*parameteriImplementation)(GL_TEXTURE_MIN_FILTER,
glTexParameteri(_target, GL_TEXTURE_MIN_FILTER,
static_cast<GLint>(filter)|static_cast<GLint>(mipmap)); static_cast<GLint>(filter)|static_cast<GLint>(mipmap));
return this; return this;
} }
@ -92,9 +125,17 @@ AbstractTexture* AbstractTexture::generateMipmap() {
CORRADE_ASSERT(_target != GL_TEXTURE_RECTANGLE, "AbstractTexture: rectangle textures cannot have mipmaps", this); CORRADE_ASSERT(_target != GL_TEXTURE_RECTANGLE, "AbstractTexture: rectangle textures cannot have mipmaps", this);
#endif #endif
(this->*mipmapImplementation)();
return this;
}
void AbstractTexture::mipmapImplementationDefault() {
bindInternal(); bindInternal();
glGenerateMipmap(_target); glGenerateMipmap(_target);
return this; }
void AbstractTexture::mipmapImplementationDSA() {
glGenerateTextureMipmapEXT(_id, _target);
} }
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
@ -123,6 +164,103 @@ void AbstractTexture::initializeContextBasedFunctionality(Context* context) {
/* Get the value and resize bindings array */ /* Get the value and resize bindings array */
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &value); glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &value);
textureState->bindings.resize(value); textureState->bindings.resize(value);
if(context->isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "AbstractTexture: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
bindImplementation = &AbstractTexture::bindImplementationDSA;
parameteriImplementation = &AbstractTexture::parameterImplementationDSA;
parameterfImplementation = &AbstractTexture::parameterImplementationDSA;
parameterfvImplementation = &AbstractTexture::parameterImplementationDSA;
mipmapImplementation = &AbstractTexture::mipmapImplementationDSA;
image1DImplementation = &AbstractTexture::imageImplementationDSA;
image2DImplementation = &AbstractTexture::imageImplementationDSA;
image3DImplementation = &AbstractTexture::imageImplementationDSA;
subImage1DImplementation = &AbstractTexture::subImageImplementationDSA;
subImage2DImplementation = &AbstractTexture::subImageImplementationDSA;
subImage3DImplementation = &AbstractTexture::subImageImplementationDSA;
}
}
void AbstractTexture::parameterImplementationDefault(GLenum parameter, GLint value) {
bindInternal();
glTexParameteri(_target, parameter, value);
}
void AbstractTexture::parameterImplementationDSA(GLenum parameter, GLint value) {
glTextureParameteriEXT(_id, _target, parameter, value);
}
void AbstractTexture::parameterImplementationDefault(GLenum parameter, GLfloat value) {
bindInternal();
glTexParameterf(_target, parameter, value);
}
void AbstractTexture::parameterImplementationDSA(GLenum parameter, GLfloat value) {
glTextureParameterfEXT(_id, _target, parameter, value);
}
void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLfloat* values) {
bindInternal();
glTexParameterfv(_target, parameter, values);
}
void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLfloat* values) {
glTextureParameterfvEXT(_id, _target, parameter, values);
}
void AbstractTexture::imageImplementationDefault(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector<1, GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data) {
bindInternal();
glTexImage1D(target, mipLevel, internalFormat, size[0], 0, static_cast<GLenum>(components), static_cast<GLenum>(type), data);
}
void AbstractTexture::imageImplementationDSA(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector<1, GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data) {
glTextureImage1DEXT(_id, target, mipLevel, internalFormat, size[0], 0, static_cast<GLenum>(components), static_cast<GLenum>(type), data);
}
void AbstractTexture::imageImplementationDefault(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector2<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data) {
bindInternal();
glTexImage2D(target, mipLevel, internalFormat, size.x(), size.y(), 0, static_cast<GLenum>(components), static_cast<GLenum>(type), data);
}
void AbstractTexture::imageImplementationDSA(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector2<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data) {
glTextureImage2DEXT(_id, target, mipLevel, internalFormat, size.x(), size.y(), 0, static_cast<GLenum>(components), static_cast<GLenum>(type), data);
}
void AbstractTexture::imageImplementationDefault(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector3<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data) {
bindInternal();
glTexImage3D(target, mipLevel, internalFormat, size.x(), size.y(), size.z(), 0, static_cast<GLenum>(components), static_cast<GLenum>(type), data);
}
void AbstractTexture::imageImplementationDSA(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector3<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data) {
glTextureImage3DEXT(_id, target, mipLevel, internalFormat, size.x(), size.y(), size.z(), 0, static_cast<GLenum>(components), static_cast<GLenum>(type), data);
}
void AbstractTexture::subImageImplementationDefault(GLenum target, GLint mipLevel, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data) {
bindInternal();
glTexSubImage1D(target, mipLevel, offset[0], size[0], static_cast<GLenum>(components), static_cast<GLenum>(type), data);
}
void AbstractTexture::subImageImplementationDSA(GLenum target, GLint mipLevel, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data) {
glTextureSubImage1DEXT(_id, target, mipLevel, offset[0], size[0], static_cast<GLenum>(components), static_cast<GLenum>(type), data);
}
void AbstractTexture::subImageImplementationDefault(GLenum target, GLint mipLevel, const Math::Vector2<GLint>& offset, const Math::Vector2<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data) {
bindInternal();
glTexSubImage2D(target, mipLevel, offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(components), static_cast<GLenum>(type), data);
}
void AbstractTexture::subImageImplementationDSA(GLenum target, GLint mipLevel, const Math::Vector2<GLint>& offset, const Math::Vector2<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data) {
glTextureSubImage2DEXT(_id, target, mipLevel, offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(components), static_cast<GLenum>(type), data);
}
void AbstractTexture::subImageImplementationDefault(GLenum target, GLint mipLevel, const Math::Vector3<GLint>& offset, const Math::Vector3<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data) {
bindInternal();
glTexSubImage3D(target, mipLevel, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), static_cast<GLenum>(components), static_cast<GLenum>(type), data);
}
void AbstractTexture::subImageImplementationDSA(GLenum target, GLint mipLevel, const Math::Vector3<GLint>& offset, const Math::Vector3<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data) {
glTextureSubImage3DEXT(_id, target, mipLevel, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), static_cast<GLenum>(components), static_cast<GLenum>(type), data);
} }
AbstractTexture::InternalFormat::InternalFormat(AbstractTexture::Components components, AbstractTexture::ComponentType type) { AbstractTexture::InternalFormat::InternalFormat(AbstractTexture::Components components, AbstractTexture::ComponentType type) {
@ -189,22 +327,20 @@ AbstractTexture::InternalFormat::InternalFormat(AbstractTexture::Components comp
} }
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture* texture, const Math::Vector<2, Wrapping>& wrapping) { void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture* texture, const Math::Vector2<Wrapping>& wrapping) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
CORRADE_ASSERT(texture->_target != GL_TEXTURE_RECTANGLE || ((wrapping[0] == Wrapping::ClampToEdge || wrapping[0] == Wrapping::ClampToBorder) && (wrapping[0] == Wrapping::ClampToEdge || wrapping[1] == Wrapping::ClampToEdge)), "AbstractTexture: rectangle texture wrapping must either clamp to border or to edge", ); CORRADE_ASSERT(texture->_target != GL_TEXTURE_RECTANGLE || ((wrapping[0] == Wrapping::ClampToEdge || wrapping[0] == Wrapping::ClampToBorder) && (wrapping[0] == Wrapping::ClampToEdge || wrapping[1] == Wrapping::ClampToEdge)), "AbstractTexture: rectangle texture wrapping must either clamp to border or to edge", );
#endif #endif
texture->bindInternal(); (texture->*parameteriImplementation)(GL_TEXTURE_WRAP_S, static_cast<GLint>(wrapping.x()));
glTexParameteri(texture->_target, GL_TEXTURE_WRAP_S, static_cast<GLint>(wrapping[0])); (texture->*parameteriImplementation)(GL_TEXTURE_WRAP_T, static_cast<GLint>(wrapping.y()));
glTexParameteri(texture->_target, GL_TEXTURE_WRAP_T, static_cast<GLint>(wrapping[1]));
} }
void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture* texture, const Math::Vector<3, Wrapping>& wrapping) { void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture* texture, const Math::Vector3<Wrapping>& wrapping) {
texture->bindInternal(); (texture->*parameteriImplementation)(GL_TEXTURE_WRAP_S, static_cast<GLint>(wrapping.x()));
glTexParameteri(texture->_target, GL_TEXTURE_WRAP_S, static_cast<GLint>(wrapping[0])); (texture->*parameteriImplementation)(GL_TEXTURE_WRAP_T, static_cast<GLint>(wrapping.y()));
glTexParameteri(texture->_target, GL_TEXTURE_WRAP_T, static_cast<GLint>(wrapping[1]));
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
glTexParameteri(texture->_target, GL_TEXTURE_WRAP_R, static_cast<GLint>(wrapping[2])); (texture->*parameteriImplementation)(GL_TEXTURE_WRAP_R, static_cast<GLint>(wrapping.z()));
#endif #endif
} }
#endif #endif

165
src/AbstractTexture.h

@ -23,6 +23,7 @@
#include "Magnum.h" #include "Magnum.h"
#include "Color.h" #include "Color.h"
#include "AbstractImage.h"
namespace Magnum { namespace Magnum {
@ -52,6 +53,12 @@ affect active bindings in user layers. %Texture limits (such as
maxSupportedLayerCount()) are cached, so repeated queries don't result in maxSupportedLayerCount()) are cached, so repeated queries don't result in
repeated @fn_gl{Get} calls. repeated @fn_gl{Get} calls.
If extension @extension{EXT,direct_state_access} is available, bind() uses DSA
function to avoid unnecessary calls to @fn_gl{ActiveTexture}. Also all texture
configuration functions use DSA functions to avoid unnecessary calls to
@fn_gl{ActiveTexture} and @fn_gl{BindTexture}. See respective function
documentation for more information.
To achieve least state changes, fully configure each texture in one run -- To achieve least state changes, fully configure each texture in one run --
method chaining comes in handy -- and try to have often used textures in method chaining comes in handy -- and try to have often used textures in
dedicated layers, not occupied by other textures. dedicated layers, not occupied by other textures.
@ -592,8 +599,11 @@ class MAGNUM_EXPORT AbstractTexture {
* *
* Sets current texture as active in given layer. The layer must be * Sets current texture as active in given layer. The layer must be
* between 0 and maxSupportedLayerCount(). Note that only one texture * between 0 and maxSupportedLayerCount(). Note that only one texture
* can be bound to given layer. * can be bound to given layer. If @extension{EXT,direct_state_access}
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} * is not available, the layer is made active before binding the
* texture.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or
* @fn_gl_extension{BindMultiTexture,EXT,direct_state_access}
*/ */
void bind(GLint layer); void bind(GLint layer);
@ -606,12 +616,15 @@ class MAGNUM_EXPORT AbstractTexture {
* @return Pointer to self (for method chaining) * @return Pointer to self (for method chaining)
* *
* Sets filter used when the object pixel size is smaller than the * Sets filter used when the object pixel size is smaller than the
* texture size. * texture size. If @extension{EXT,direct_state_access} is not
* available, the texture is bound to some layer before the operation.
* @attention For rectangle textures only some modes are supported, * @attention For rectangle textures only some modes are supported,
* see @ref AbstractTexture::Filter "Filter" and * see @ref AbstractTexture::Filter "Filter" and
* @ref AbstractTexture::Mipmap "Mipmap" documentation for more * @ref AbstractTexture::Mipmap "Mipmap" documentation for more
* information. * information.
* @see bind(), @fn_gl{TexParameter} with @def_gl{TEXTURE_MIN_FILTER} * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_MIN_FILTER}
*/ */
AbstractTexture* setMinificationFilter(Filter filter, Mipmap mipmap = Mipmap::BaseLevel); AbstractTexture* setMinificationFilter(Filter filter, Mipmap mipmap = Mipmap::BaseLevel);
@ -621,12 +634,14 @@ class MAGNUM_EXPORT AbstractTexture {
* @return Pointer to self (for method chaining) * @return Pointer to self (for method chaining)
* *
* Sets filter used when the object pixel size is larger than largest * Sets filter used when the object pixel size is larger than largest
* texture size. * texture size. If @extension{EXT,direct_state_access} is not
* @see bind(), @fn_gl{TexParameter} with @def_gl{TEXTURE_MAG_FILTER} * available, the texture is bound to some layer before the operation.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_MAG_FILTER}
*/ */
inline AbstractTexture* setMagnificationFilter(Filter filter) { inline AbstractTexture* setMagnificationFilter(Filter filter) {
bindInternal(); (this->*parameteriImplementation)(GL_TEXTURE_MAG_FILTER, static_cast<GLint>(filter));
glTexParameteri(_target, GL_TEXTURE_MAG_FILTER, static_cast<GLint>(filter));
return this; return this;
} }
@ -636,13 +651,15 @@ class MAGNUM_EXPORT AbstractTexture {
* @return Pointer to self (for method chaining) * @return Pointer to self (for method chaining)
* *
* Border color when @ref AbstractTexture::Wrapping "wrapping" is set * Border color when @ref AbstractTexture::Wrapping "wrapping" is set
* to `ClampToBorder`. * to `ClampToBorder`. If @extension{EXT,direct_state_access} is not
* @see bind(), @fn_gl{TexParameter} with @def_gl{TEXTURE_BORDER_COLOR} * available, the texture is bound to some layer before the operation.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_BORDER_COLOR}
* @requires_gl * @requires_gl
*/ */
inline AbstractTexture* setBorderColor(const Color4<GLfloat>& color) { inline AbstractTexture* setBorderColor(const Color4<GLfloat>& color) {
bindInternal(); (this->*parameterfvImplementation)(GL_TEXTURE_BORDER_COLOR, color.data());
glTexParameterfv(_target, GL_TEXTURE_BORDER_COLOR, color.data());
return this; return this;
} }
@ -650,15 +667,19 @@ class MAGNUM_EXPORT AbstractTexture {
* @brief Set max anisotropy * @brief Set max anisotropy
* @return Pointer to self (for method chaining) * @return Pointer to self (for method chaining)
* *
* Default value is `1.0`, which means no anisotropy. Set to value * Default value is `1.0f`, which means no anisotropy. Set to value
* greater than `1.0` for anisotropic filtering. * greater than `1.0f` for anisotropic filtering. If
* @see maxSupportedAnisotropy(), bind(), @fn_gl{TexParameter} with @def_gl{TEXTURE_MAX_ANISOTROPY_EXT} * @extension{EXT,direct_state_access} is not available, the texture
* is bound to some layer before the operation.
* @see maxSupportedAnisotropy(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_MAX_ANISOTROPY_EXT}
* @requires_gl * @requires_gl
* @requires_extension @extension{EXT,texture_filter_anisotropic} * @requires_extension @extension{EXT,texture_filter_anisotropic}
*/ */
inline AbstractTexture* setMaxAnisotropy(GLfloat anisotropy) { inline AbstractTexture* setMaxAnisotropy(GLfloat anisotropy) {
bindInternal(); (this->*parameterfImplementation)(GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
glTexParameterf(_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
return this; return this;
} }
#endif #endif
@ -667,8 +688,12 @@ class MAGNUM_EXPORT AbstractTexture {
* @brief Generate mipmap * @brief Generate mipmap
* @return Pointer to self (for method chaining) * @return Pointer to self (for method chaining)
* *
* Can not be used for rectangle textures. * Can not be used for rectangle textures. If
* @see setMinificationFilter(), @fn_gl{GenerateMipmap} * @extension{EXT,direct_state_access} is not available, the texture
* is bound to some layer before the operation.
* @see setMinificationFilter(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{GenerateMipmap} or
* @fn_gl_extension{GenerateTextureMipmap,EXT,direct_state_access}
* @requires_gl30 Extension @extension{EXT,framebuffer_object} * @requires_gl30 Extension @extension{EXT,framebuffer_object}
*/ */
AbstractTexture* generateMipmap(); AbstractTexture* generateMipmap();
@ -678,7 +703,7 @@ class MAGNUM_EXPORT AbstractTexture {
template<std::uint8_t textureDimensions> struct DataHelper {}; template<std::uint8_t textureDimensions> struct DataHelper {};
/* Unlike bind() this also sets the binding layer as active */ /* Unlike bind() this also sets the binding layer as active */
void bindInternal(); void MAGNUM_LOCAL bindInternal();
const GLenum _target; const GLenum _target;
#endif #endif
@ -686,6 +711,61 @@ class MAGNUM_EXPORT AbstractTexture {
private: private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context); static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context);
typedef void(AbstractTexture::*BindImplementation)(GLint);
void MAGNUM_LOCAL bindImplementationDefault(GLint layer);
void MAGNUM_LOCAL bindImplementationDSA(GLint layer);
static MAGNUM_LOCAL BindImplementation bindImplementation;
typedef void(AbstractTexture::*ParameteriImplementation)(GLenum, GLint);
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLint value);
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLint value);
static ParameteriImplementation parameteriImplementation;
typedef void(AbstractTexture::*ParameterfImplementation)(GLenum, GLfloat);
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLfloat value);
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLfloat value);
static ParameterfImplementation parameterfImplementation;
typedef void(AbstractTexture::*ParameterfvImplementation)(GLenum, const GLfloat*);
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLfloat* values);
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLfloat* values);
static ParameterfvImplementation parameterfvImplementation;
typedef void(AbstractTexture::*MipmapImplementation)();
void MAGNUM_LOCAL mipmapImplementationDefault();
void MAGNUM_LOCAL mipmapImplementationDSA();
static MAGNUM_LOCAL MipmapImplementation mipmapImplementation;
typedef void(AbstractTexture::*Image1DImplementation)(GLenum, GLint, InternalFormat, const Math::Vector<1, GLsizei>&, AbstractImage::Components, AbstractImage::ComponentType, const GLvoid*);
void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector<1, GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data);
void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector<1, GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data);
static Image1DImplementation image1DImplementation;
typedef void(AbstractTexture::*Image2DImplementation)(GLenum, GLint, InternalFormat, const Math::Vector2<GLsizei>&, AbstractImage::Components, AbstractImage::ComponentType, const GLvoid*);
void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector2<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data);
void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector2<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data);
static Image2DImplementation image2DImplementation;
typedef void(AbstractTexture::*Image3DImplementation)(GLenum, GLint, InternalFormat, const Math::Vector3<GLsizei>&, AbstractImage::Components, AbstractImage::ComponentType, const GLvoid*);
void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector3<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data);
void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector3<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data);
static Image3DImplementation image3DImplementation;
typedef void(AbstractTexture::*SubImage1DImplementation)(GLenum, GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, AbstractImage::Components, AbstractImage::ComponentType, const GLvoid*);
void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint mipLevel, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data);
void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint mipLevel, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data);
static SubImage1DImplementation subImage1DImplementation;
typedef void(AbstractTexture::*SubImage2DImplementation)(GLenum, GLint, const Math::Vector2<GLint>&, const Math::Vector2<GLsizei>&, AbstractImage::Components, AbstractImage::ComponentType, const GLvoid*);
void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint mipLevel, const Math::Vector2<GLint>& offset, const Math::Vector2<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data);
void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint mipLevel, const Math::Vector2<GLint>& offset, const Math::Vector2<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data);
static SubImage2DImplementation subImage2DImplementation;
typedef void(AbstractTexture::*SubImage3DImplementation)(GLenum, GLint, const Math::Vector3<GLint>&, const Math::Vector3<GLsizei>&, AbstractImage::Components, AbstractImage::ComponentType, const GLvoid*);
void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint mipLevel, const Math::Vector3<GLint>& offset, const Math::Vector3<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data);
void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint mipLevel, const Math::Vector3<GLint>& offset, const Math::Vector3<GLsizei>& size, AbstractImage::Components components, AbstractImage::ComponentType type, const GLvoid* data);
static SubImage3DImplementation subImage3DImplementation;
GLuint _id; GLuint _id;
}; };
@ -715,18 +795,15 @@ template<> struct AbstractTexture::DataHelper<1> {
inline constexpr static Target target() { return Target::Texture1D; } inline constexpr static Target target() { return Target::Texture1D; }
inline static void setWrapping(AbstractTexture* texture, const Math::Vector<1, Wrapping>& wrapping) { inline static void setWrapping(AbstractTexture* texture, const Math::Vector<1, Wrapping>& wrapping) {
texture->bindInternal(); (texture->*parameteriImplementation)(GL_TEXTURE_WRAP_S, static_cast<GLint>(wrapping[0]));
glTexParameteri(texture->_target, GL_TEXTURE_WRAP_S, static_cast<GLint>(wrapping[0]));
} }
template<class Image> inline static typename std::enable_if<Image::Dimensions == 1, void>::type set(AbstractTexture* texture, GLenum target, GLint mipLevel, InternalFormat internalFormat, Image* image) { template<class Image> inline static typename std::enable_if<Image::Dimensions == 1, void>::type set(AbstractTexture* texture, GLenum target, GLint mipLevel, InternalFormat internalFormat, Image* image) {
texture->bindInternal(); (texture->*image1DImplementation)(target, mipLevel, internalFormat, image->size(), image->components(), image->type(), image->data());
glTexImage1D(target, mipLevel, internalFormat, image->size()[0], 0, static_cast<GLenum>(image->components()), static_cast<GLenum>(image->type()), image->data());
} }
template<class Image> inline static typename std::enable_if<Image::Dimensions == 1, void>::type setSub(AbstractTexture* texture, GLenum target, GLint mipLevel, const Math::Vector<1, GLint>& offset, Image* image) { template<class Image> inline static typename std::enable_if<Image::Dimensions == 1, void>::type setSub(AbstractTexture* texture, GLenum target, GLint mipLevel, const Math::Vector<1, GLint>& offset, Image* image) {
texture->bindInternal(); (texture->*subImage1DImplementation)(target, mipLevel, offset, image->size(), image->components(), image->type(), image->data());
glTexSubImage1D(target, mipLevel, offset[0], image->size()[0], static_cast<GLenum>(image->components()), static_cast<GLenum>(image->type()), image->data());
} }
}; };
#endif #endif
@ -742,21 +819,18 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> {
inline constexpr static Target target() { return Target::Texture2D; } inline constexpr static Target target() { return Target::Texture2D; }
static void setWrapping(AbstractTexture* texture, const Math::Vector<2, Wrapping>& wrapping); static void setWrapping(AbstractTexture* texture, const Math::Vector2<Wrapping>& wrapping);
template<class Image> inline static typename std::enable_if<Image::Dimensions == 2, void>::type set(AbstractTexture* texture, GLenum target, GLint mipLevel, InternalFormat internalFormat, Image* image) { template<class Image> inline static typename std::enable_if<Image::Dimensions == 2, void>::type set(AbstractTexture* texture, GLenum target, GLint mipLevel, InternalFormat internalFormat, Image* image) {
texture->bindInternal(); (texture->*image2DImplementation)(target, mipLevel, internalFormat, image->size(), image->components(), image->type(), image->data());
glTexImage2D(target, mipLevel, internalFormat, image->size()[0], image->size()[1], 0, static_cast<GLenum>(image->components()), static_cast<GLenum>(image->type()), image->data());
} }
template<class Image> inline static typename std::enable_if<Image::Dimensions == 2, void>::type setSub(AbstractTexture* texture, GLenum target, GLint mipLevel, const Math::Vector<2, GLint>& offset, Image* image) { template<class Image> inline static typename std::enable_if<Image::Dimensions == 2, void>::type setSub(AbstractTexture* texture, GLenum target, GLint mipLevel, const Math::Vector2<GLint>& offset, Image* image) {
texture->bindInternal(); (texture->*subImage2DImplementation)(target, mipLevel, offset, image->size(), image->components(), image->type(), image->data());
glTexSubImage2D(target, mipLevel, offset[0], offset[1], image->size()[0], image->size()[1], static_cast<GLenum>(image->components()), static_cast<GLenum>(image->type()), image->data());
} }
template<class Image> inline static typename std::enable_if<Image::Dimensions == 1, void>::type setSub(AbstractTexture* texture, GLenum target, GLint mipLevel, const Math::Vector<2, GLint>& offset, Image* image) { template<class Image> inline static typename std::enable_if<Image::Dimensions == 1, void>::type setSub(AbstractTexture* texture, GLenum target, GLint mipLevel, const Math::Vector2<GLint>& offset, Image* image) {
texture->bindInternal(); (texture->*subImage2DImplementation)(target, mipLevel, offset, Math::Vector2<GLint>(image->size(), 1), image->components(), image->type(), image->data());
glTexSubImage2D(target, mipLevel, offset[0], offset[1], image->size()[0], 1, static_cast<GLenum>(image->components()), static_cast<GLenum>(image->type()), image->data());
} }
}; };
template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> { template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> {
@ -767,21 +841,18 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> {
inline constexpr static Target target() { return Target::Texture3D; } inline constexpr static Target target() { return Target::Texture3D; }
static void setWrapping(AbstractTexture* texture, const Math::Vector<3, Wrapping>& wrapping); static void setWrapping(AbstractTexture* texture, const Math::Vector3<Wrapping>& wrapping);
template<class Image> inline static typename std::enable_if<Image::Dimensions == 3, void>::type set(AbstractTexture* texture, GLenum target, GLint mipLevel, InternalFormat internalFormat, Image* image) { template<class Image> inline static typename std::enable_if<Image::Dimensions == 3, void>::type set(AbstractTexture* texture, GLenum target, GLint mipLevel, InternalFormat internalFormat, Image* image) {
texture->bindInternal(); (texture->*image3DImplementation)(target, mipLevel, internalFormat, image->size(), image->components(), image->type(), image->data());
glTexImage3D(target, mipLevel, internalFormat, image->size()[0], image->size()[1], image->size()[2], 0, static_cast<GLenum>(image->components()), static_cast<GLenum>(image->type()), image->data());
} }
template<class Image> inline static typename std::enable_if<Image::Dimensions == 3, void>::type setSub(AbstractTexture* texture, GLenum target, GLint mipLevel, const Math::Vector<3, GLint>& offset, Image* image) { template<class Image> inline static typename std::enable_if<Image::Dimensions == 3, void>::type setSub(AbstractTexture* texture, GLenum target, GLint mipLevel, const Math::Vector3<GLint>& offset, Image* image) {
texture->bindInternal(); (texture->*subImage3DImplementation)(target, mipLevel, offset, image->size(), image->components(), image->type(), image->data());
glTexSubImage3D(target, mipLevel, offset[0], offset[1], offset[2], image->size()[0], image->size()[1], image->size()[2], static_cast<GLenum>(image->components()), static_cast<GLenum>(image->type()), image->data());
} }
template<class Image> inline static typename std::enable_if<Image::Dimensions == 2, void>::type setSub(AbstractTexture* texture, GLenum target, GLint mipLevel, const Math::Vector<3, GLint>& offset, Image* image) { template<class Image> inline static typename std::enable_if<Image::Dimensions == 2, void>::type setSub(AbstractTexture* texture, GLenum target, GLint mipLevel, const Math::Vector3<GLint>& offset, Image* image) {
texture->bindInternal(); (texture->*subImage3DImplementation)(target, mipLevel, offset, Math::Vector3<GLint>(image->size(), 1), image->components(), image->type(), image->data());
glTexSubImage3D(target, mipLevel, offset[0], offset[1], offset[2], image->size()[0], image->size()[1], 1, static_cast<GLenum>(image->components()), static_cast<GLenum>(image->type()), image->data());
} }
}; };
#endif #endif

23
src/BufferedTexture.cpp

@ -15,8 +15,31 @@
#include "BufferedTexture.h" #include "BufferedTexture.h"
#include "Buffer.h"
#include "Context.h"
#include "Extensions.h"
namespace Magnum { namespace Magnum {
BufferedTexture::SetBufferImplementation BufferedTexture::setBufferImplementation = &BufferedTexture::setBufferImplementationDefault;
void BufferedTexture::initializeContextBasedFunctionality(Context* context) {
if(context->isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "BufferedTexture: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
setBufferImplementation = &BufferedTexture::setBufferImplementationDSA;
}
}
void BufferedTexture::setBufferImplementationDefault(BufferedTexture::InternalFormat internalFormat, Buffer* buffer) {
bindInternal();
glTexBuffer(GL_TEXTURE_BUFFER, internalFormat, buffer->id());
}
void BufferedTexture::setBufferImplementationDSA(BufferedTexture::InternalFormat internalFormat, Buffer* buffer) {
glTextureBufferEXT(id(), GL_TEXTURE_BUFFER, internalFormat, buffer->id());
}
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
BufferedTexture::InternalFormat::InternalFormat(Components components, ComponentType type) { BufferedTexture::InternalFormat::InternalFormat(Components components, ComponentType type) {
#define internalFormatSwitch(c) switch(type) { \ #define internalFormatSwitch(c) switch(type) { \

31
src/BufferedTexture.h

@ -20,10 +20,12 @@
*/ */
#include "AbstractTexture.h" #include "AbstractTexture.h"
#include "Buffer.h"
namespace Magnum { namespace Magnum {
class Buffer;
class Context;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
@brief Buffered texture @brief Buffered texture
@ -37,10 +39,19 @@ using data setting functions in Buffer itself.
When using buffered texture in the shader, use `samplerBuffer` and fetch the When using buffered texture in the shader, use `samplerBuffer` and fetch the
data using integer coordinates in `texelFetch()`. data using integer coordinates in `texelFetch()`.
@section BufferedTexture-performance-optimization Performance optimizations
If extension @extension{EXT,direct_state_access} is available, setBuffer()
uses DSA function to avoid unnecessary calls to @fn_gl{ActiveTexture} and
@fn_gl{BindTexture}. See @ref AbstractTexture-performance-optimization
"relevant section in AbstractTexture documentation" and respective function
documentation for more information.
@requires_gl @requires_gl
@requires_gl31 Extension @extension{ARB,texture_buffer_object} @requires_gl31 Extension @extension{ARB,texture_buffer_object}
*/ */
class BufferedTexture: private AbstractTexture { class MAGNUM_EXPORT BufferedTexture: private AbstractTexture {
friend class Context;
BufferedTexture(const BufferedTexture& other) = delete; BufferedTexture(const BufferedTexture& other) = delete;
BufferedTexture(BufferedTexture&& other) = delete; BufferedTexture(BufferedTexture&& other) = delete;
BufferedTexture& operator=(const BufferedTexture& other) = delete; BufferedTexture& operator=(const BufferedTexture& other) = delete;
@ -130,12 +141,20 @@ class BufferedTexture: private AbstractTexture {
* Binds given buffer to this texture. The buffer itself can be then * Binds given buffer to this texture. The buffer itself can be then
* filled with data of proper format at any time using Buffer own data * filled with data of proper format at any time using Buffer own data
* setting functions. * setting functions.
* @see @fn_gl{BindTexture}, @fn_gl{TexBuffer} * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexBuffer}
* or @fn_gl_extension{TextureBuffer,EXT,direct_state_access}
*/ */
void setBuffer(InternalFormat internalFormat, Buffer* buffer) { inline void setBuffer(InternalFormat internalFormat, Buffer* buffer) {
bindInternal(); (this->*setBufferImplementation)(internalFormat, buffer);
glTexBuffer(GL_TEXTURE_BUFFER, internalFormat, buffer->id());
} }
private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context);
typedef void(BufferedTexture::*SetBufferImplementation)(InternalFormat, Buffer*);
void MAGNUM_LOCAL setBufferImplementationDefault(InternalFormat internalFormat, Buffer* buffer);
void MAGNUM_LOCAL setBufferImplementationDSA(InternalFormat internalFormat, Buffer* buffer);
static SetBufferImplementation setBufferImplementation;
}; };
/** @relates BufferedTexture /** @relates BufferedTexture

4
src/Context.cpp

@ -24,6 +24,7 @@
#include "Buffer.h" #include "Buffer.h"
#include "Extensions.h" #include "Extensions.h"
#include "Implementation/State.h" #include "Implementation/State.h"
#include "BufferedTexture.h"
using namespace std; using namespace std;
@ -201,8 +202,9 @@ Context::Context() {
/* Initialize functionality based on current OpenGL version and extensions */ /* Initialize functionality based on current OpenGL version and extensions */
AbstractShaderProgram::initializeContextBasedFunctionality(this); AbstractShaderProgram::initializeContextBasedFunctionality(this);
Buffer::initializeContextBasedFunctionality(this);
AbstractTexture::initializeContextBasedFunctionality(this); AbstractTexture::initializeContextBasedFunctionality(this);
Buffer::initializeContextBasedFunctionality(this);
BufferedTexture::initializeContextBasedFunctionality(this);
} }
Context::~Context() { Context::~Context() {

8
src/CubeMapTexture.h

@ -27,9 +27,9 @@ namespace Magnum {
@brief Cube map texture @brief Cube map texture
%Texture used mainly for environemnt maps. See AbstractTexture documentation %Texture used mainly for environemnt maps. See AbstractTexture documentation
for more information about usage. It consists of 6 square textures generating for more information. It consists of 6 square textures generating 6 faces of
6 faces of the cube as following. Note that all images must be turned upside the cube as following. Note that all images must be turned upside down (+Y is
down (+Y is top): top):
+----+ +----+
| -Y | | -Y |
@ -105,7 +105,7 @@ class CubeMapTexture: public AbstractTexture {
* @param coordinate Coordinate * @param coordinate Coordinate
* @return Pointer to self (for method chaining) * @return Pointer to self (for method chaining)
*/ */
template<class Image> inline CubeMapTexture* setSubData(Coordinate coordinate, GLint mipLevel, const Math::Vector<2, GLint>& offset, const Image* image) { template<class Image> inline CubeMapTexture* setSubData(Coordinate coordinate, GLint mipLevel, const Math::Vector2<GLint>& offset, const Image* image) {
DataHelper<2>::setSub(this, static_cast<GLenum>(coordinate), mipLevel, offset, image); DataHelper<2>::setSub(this, static_cast<GLenum>(coordinate), mipLevel, offset, image);
return this; return this;
} }

12
src/CubeMapTextureArray.h

@ -26,7 +26,7 @@ namespace Magnum {
/** /**
@brief Cube map texture array @brief Cube map texture array
For information about usage, see CubeMapTexture documentation. For information, see CubeMapTexture and AbstractTexture documentation.
When using cube map texture in the shader, use `samplerCubeArray`. Unlike When using cube map texture in the shader, use `samplerCubeArray`. Unlike
classic textures, coordinates for cube map textures is signed three-part classic textures, coordinates for cube map textures is signed three-part
@ -59,7 +59,7 @@ class CubeMapTextureArray: public AbstractTexture {
/** /**
* @copydoc Texture::setWrapping() * @copydoc Texture::setWrapping()
*/ */
inline CubeMapTextureArray* setWrapping(const Math::Vector<3, Wrapping>& wrapping) { inline CubeMapTextureArray* setWrapping(const Math::Vector3<Wrapping>& wrapping) {
DataHelper<3>::setWrapping(this, wrapping); DataHelper<3>::setWrapping(this, wrapping);
return this; return this;
} }
@ -94,8 +94,8 @@ class CubeMapTextureArray: public AbstractTexture {
* *
* @see setSubData(GLsizei, Coordinate, GLint, const Math::Vector<2, GLint>&, const Image*) * @see setSubData(GLsizei, Coordinate, GLint, const Math::Vector<2, GLint>&, const Image*)
*/ */
template<class Image> inline CubeMapTextureArray* setSubData(GLint mipLevel, const Math::Vector<3, GLint>& offset, const Image* image) { template<class Image> inline CubeMapTextureArray* setSubData(GLint mipLevel, const Math::Vector3<GLint>& offset, const Image* image) {
DataHelper<3>::setSub(this, GL_TEXTURE_CUBE_MAP_ARRAY, mipLevel, offset, image, Math::Vector<3, GLsizei>(Math::Vector<Image::Dimensions, GLsizei>())); DataHelper<3>::setSub(this, GL_TEXTURE_CUBE_MAP_ARRAY, mipLevel, offset, image, Math::Vector3<GLsizei>(Math::Vector<Image::Dimensions, GLsizei>()));
return this; return this;
} }
@ -114,8 +114,8 @@ class CubeMapTextureArray: public AbstractTexture {
* *
* @see setSubData(GLint, const Math::Vector<3, GLint>&, const Image*) * @see setSubData(GLint, const Math::Vector<3, GLint>&, const Image*)
*/ */
template<class Image> inline CubeMapTextureArray* setSubData(GLsizei layer, Coordinate coordinate, GLint mipLevel, const Math::Vector<2, GLint>& offset, const Image* image) { template<class Image> inline CubeMapTextureArray* setSubData(GLsizei layer, Coordinate coordinate, GLint mipLevel, const Math::Vector2<GLint>& offset, const Image* image) {
DataHelper<3>::setSub(this, GL_TEXTURE_CUBE_MAP_ARRAY, mipLevel, Math::Vector<3, GLint>(offset, layer*6+static_cast<GLsizei>(coordinate)), image, Math::Vector<2, GLsizei>(Math::Vector<Image::Dimensions, GLsizei>())); DataHelper<3>::setSub(this, GL_TEXTURE_CUBE_MAP_ARRAY, mipLevel, Math::Vector3<GLint>(offset, layer*6+static_cast<GLsizei>(coordinate)), image, Math::Vector<2, GLsizei>(Math::Vector<Image::Dimensions, GLsizei>()));
return this; return this;
} }
}; };

33
src/Texture.h

@ -28,7 +28,7 @@ namespace Magnum {
@brief %Texture @brief %Texture
Template class for one- to three-dimensional textures. See AbstractTexture Template class for one- to three-dimensional textures. See AbstractTexture
documentation for more information about usage. documentation for more information.
In shader, the texture is used via `sampler1D`, `sampler2D` or `sampler3D` In shader, the texture is used via `sampler1D`, `sampler2D` or `sampler3D`
depending on dimension count. Note that you can have more than one texture bound depending on dimension count. Note that you can have more than one texture bound
@ -120,12 +120,15 @@ template<std::uint8_t dimensions> class Texture: public AbstractTexture {
* *
* Sets wrapping type for coordinates out of range (0, 1) for normal * Sets wrapping type for coordinates out of range (0, 1) for normal
* textures and (0, textureSizeInGivenDirection-1) for rectangle * textures and (0, textureSizeInGivenDirection-1) for rectangle
* textures. * textures. If @extension{EXT,direct_state_access} is not available,
* the texture is bound to some layer before the operation.
* @attention For rectangle textures only some modes are supported, * @attention For rectangle textures only some modes are supported,
* see @ref AbstractTexture::Wrapping "Wrapping" documentation for * see @ref AbstractTexture::Wrapping "Wrapping" documentation
* more information. * for more information.
* @see bind(), @fn_gl{TexParameter} with @def_gl{TEXTURE_WRAP_S}, * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* @def_gl{TEXTURE_WRAP_T}, @def_gl{TEXTURE_WRAP_R} * or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_WRAP_S}, @def_gl{TEXTURE_WRAP_T},
* @def_gl{TEXTURE_WRAP_R}
* @todo Use something better for this than Vector (mainly something * @todo Use something better for this than Vector (mainly something
* that can easily create all values the same) * that can easily create all values the same)
*/ */
@ -143,8 +146,13 @@ template<std::uint8_t dimensions> class Texture: public AbstractTexture {
* @return Pointer to self (for method chaining) * @return Pointer to self (for method chaining)
* *
* Sets texture data from given image. The image is not deleted * Sets texture data from given image. The image is not deleted
* afterwards. * afterwards. If @extension{EXT,direct_state_access} is not available,
* @see bind(), @fn_gl{TexImage1D}, @fn_gl{TexImage2D}, @fn_gl{TexImage3D} * the texture is bound to some layer before the operation.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @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}
*/ */
template<class Image> inline Texture<Dimensions>* setData(GLint mipLevel, InternalFormat internalFormat, Image* image) { template<class Image> inline Texture<Dimensions>* setData(GLint mipLevel, InternalFormat internalFormat, Image* image) {
DataHelper<Dimensions>::set(this, _target, mipLevel, internalFormat, image); DataHelper<Dimensions>::set(this, _target, mipLevel, internalFormat, image);
@ -167,7 +175,14 @@ template<std::uint8_t dimensions> class Texture: public AbstractTexture {
* taken as if it had the last dimension equal to 1. It can be used * taken as if it had the last dimension equal to 1. It can be used
* for e.g. updating 3D texture with multiple 2D images or for filling * for e.g. updating 3D texture with multiple 2D images or for filling
* 1D texture array (which is two-dimensional) with 1D images. * 1D texture array (which is two-dimensional) with 1D images.
* @see bind(), @fn_gl{TexSubImage1D}, @fn_gl{TexSubImage2D}, @fn_gl{TexSubImage3D} *
* If @extension{EXT,direct_state_access} is not available, the
* texture is bound to some layer before the operation.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexSubImage1D}/
* @fn_gl{TexSubImage2D}/@fn_gl{TexSubImage3D} or
* @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}/
* @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}/
* @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access}
*/ */
template<class Image> inline Texture<Dimensions>* setSubData(GLint mipLevel, const typename DimensionTraits<Dimensions, GLint>::VectorType& offset, Image* image) { template<class Image> inline Texture<Dimensions>* setSubData(GLint mipLevel, const typename DimensionTraits<Dimensions, GLint>::VectorType& offset, Image* image) {
DataHelper<Dimensions>::setSub(this, _target, mipLevel, offset, image); DataHelper<Dimensions>::setSub(this, _target, mipLevel, offset, image);

Loading…
Cancel
Save