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 "Context.h"
#include "Extensions.h"
#include "Implementation/State.h"
#include "Implementation/TextureState.h"
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
/* 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(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 */
if(textureState->currentLayer != layer)
glActiveTexture(GL_TEXTURE0 + (textureState->currentLayer = layer));
@ -76,13 +106,16 @@ void AbstractTexture::bind(GLint layer) {
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) {
#ifndef MAGNUM_TARGET_GLES
CORRADE_ASSERT(_target != GL_TEXTURE_RECTANGLE || mipmap == Mipmap::BaseLevel, "AbstractTexture: rectangle textures cannot have mipmaps", this);
#endif
bindInternal();
glTexParameteri(_target, GL_TEXTURE_MIN_FILTER,
(this->*parameteriImplementation)(GL_TEXTURE_MIN_FILTER,
static_cast<GLint>(filter)|static_cast<GLint>(mipmap));
return this;
}
@ -92,9 +125,17 @@ AbstractTexture* AbstractTexture::generateMipmap() {
CORRADE_ASSERT(_target != GL_TEXTURE_RECTANGLE, "AbstractTexture: rectangle textures cannot have mipmaps", this);
#endif
(this->*mipmapImplementation)();
return this;
}
void AbstractTexture::mipmapImplementationDefault() {
bindInternal();
glGenerateMipmap(_target);
return this;
}
void AbstractTexture::mipmapImplementationDSA() {
glGenerateTextureMipmapEXT(_id, _target);
}
#ifndef DOXYGEN_GENERATING_OUTPUT
@ -123,6 +164,103 @@ void AbstractTexture::initializeContextBasedFunctionality(Context* context) {
/* Get the value and resize bindings array */
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &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) {
@ -189,22 +327,20 @@ AbstractTexture::InternalFormat::InternalFormat(AbstractTexture::Components comp
}
#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
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
texture->bindInternal();
glTexParameteri(texture->_target, GL_TEXTURE_WRAP_S, static_cast<GLint>(wrapping[0]));
glTexParameteri(texture->_target, GL_TEXTURE_WRAP_T, static_cast<GLint>(wrapping[1]));
(texture->*parameteriImplementation)(GL_TEXTURE_WRAP_S, static_cast<GLint>(wrapping.x()));
(texture->*parameteriImplementation)(GL_TEXTURE_WRAP_T, static_cast<GLint>(wrapping.y()));
}
void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture* texture, const Math::Vector<3, Wrapping>& wrapping) {
texture->bindInternal();
glTexParameteri(texture->_target, GL_TEXTURE_WRAP_S, static_cast<GLint>(wrapping[0]));
glTexParameteri(texture->_target, GL_TEXTURE_WRAP_T, static_cast<GLint>(wrapping[1]));
void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture* texture, const Math::Vector3<Wrapping>& wrapping) {
(texture->*parameteriImplementation)(GL_TEXTURE_WRAP_S, static_cast<GLint>(wrapping.x()));
(texture->*parameteriImplementation)(GL_TEXTURE_WRAP_T, static_cast<GLint>(wrapping.y()));
#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

165
src/AbstractTexture.h

@ -23,6 +23,7 @@
#include "Magnum.h"
#include "Color.h"
#include "AbstractImage.h"
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
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 --
method chaining comes in handy -- and try to have often used textures in
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
* between 0 and maxSupportedLayerCount(). Note that only one texture
* can be bound to given layer.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture}
* can be bound to given layer. If @extension{EXT,direct_state_access}
* 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);
@ -606,12 +616,15 @@ class MAGNUM_EXPORT AbstractTexture {
* @return Pointer to self (for method chaining)
*
* 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,
* see @ref AbstractTexture::Filter "Filter" and
* @ref AbstractTexture::Mipmap "Mipmap" documentation for more
* information.
* @see bind(), @fn_gl{TexParameter} with @def_gl{TEXTURE_MIN_FILTER}
* see @ref AbstractTexture::Filter "Filter" and
* @ref AbstractTexture::Mipmap "Mipmap" documentation for more
* information.
* @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);
@ -621,12 +634,14 @@ class MAGNUM_EXPORT AbstractTexture {
* @return Pointer to self (for method chaining)
*
* Sets filter used when the object pixel size is larger than largest
* texture size.
* @see bind(), @fn_gl{TexParameter} with @def_gl{TEXTURE_MAG_FILTER}
* texture size. 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{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_MAG_FILTER}
*/
inline AbstractTexture* setMagnificationFilter(Filter filter) {
bindInternal();
glTexParameteri(_target, GL_TEXTURE_MAG_FILTER, static_cast<GLint>(filter));
(this->*parameteriImplementation)(GL_TEXTURE_MAG_FILTER, static_cast<GLint>(filter));
return this;
}
@ -636,13 +651,15 @@ class MAGNUM_EXPORT AbstractTexture {
* @return Pointer to self (for method chaining)
*
* Border color when @ref AbstractTexture::Wrapping "wrapping" is set
* to `ClampToBorder`.
* @see bind(), @fn_gl{TexParameter} with @def_gl{TEXTURE_BORDER_COLOR}
* to `ClampToBorder`. 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{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_BORDER_COLOR}
* @requires_gl
*/
inline AbstractTexture* setBorderColor(const Color4<GLfloat>& color) {
bindInternal();
glTexParameterfv(_target, GL_TEXTURE_BORDER_COLOR, color.data());
(this->*parameterfvImplementation)(GL_TEXTURE_BORDER_COLOR, color.data());
return this;
}
@ -650,15 +667,19 @@ class MAGNUM_EXPORT AbstractTexture {
* @brief Set max anisotropy
* @return Pointer to self (for method chaining)
*
* Default value is `1.0`, which means no anisotropy. Set to value
* greater than `1.0` for anisotropic filtering.
* @see maxSupportedAnisotropy(), bind(), @fn_gl{TexParameter} with @def_gl{TEXTURE_MAX_ANISOTROPY_EXT}
* Default value is `1.0f`, which means no anisotropy. Set to value
* greater than `1.0f` for anisotropic filtering. If
* @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_extension @extension{EXT,texture_filter_anisotropic}
*/
inline AbstractTexture* setMaxAnisotropy(GLfloat anisotropy) {
bindInternal();
glTexParameterf(_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
(this->*parameterfImplementation)(GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
return this;
}
#endif
@ -667,8 +688,12 @@ class MAGNUM_EXPORT AbstractTexture {
* @brief Generate mipmap
* @return Pointer to self (for method chaining)
*
* Can not be used for rectangle textures.
* @see setMinificationFilter(), @fn_gl{GenerateMipmap}
* Can not be used for rectangle textures. If
* @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}
*/
AbstractTexture* generateMipmap();
@ -678,7 +703,7 @@ class MAGNUM_EXPORT AbstractTexture {
template<std::uint8_t textureDimensions> struct DataHelper {};
/* Unlike bind() this also sets the binding layer as active */
void bindInternal();
void MAGNUM_LOCAL bindInternal();
const GLenum _target;
#endif
@ -686,6 +711,61 @@ class MAGNUM_EXPORT AbstractTexture {
private:
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;
};
@ -715,18 +795,15 @@ template<> struct AbstractTexture::DataHelper<1> {
inline constexpr static Target target() { return Target::Texture1D; }
inline static void setWrapping(AbstractTexture* texture, const Math::Vector<1, Wrapping>& wrapping) {
texture->bindInternal();
glTexParameteri(texture->_target, GL_TEXTURE_WRAP_S, static_cast<GLint>(wrapping[0]));
(texture->*parameteriImplementation)(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) {
texture->bindInternal();
glTexImage1D(target, mipLevel, internalFormat, image->size()[0], 0, static_cast<GLenum>(image->components()), static_cast<GLenum>(image->type()), image->data());
(texture->*image1DImplementation)(target, mipLevel, internalFormat, image->size(), image->components(), 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) {
texture->bindInternal();
glTexSubImage1D(target, mipLevel, offset[0], image->size()[0], static_cast<GLenum>(image->components()), static_cast<GLenum>(image->type()), image->data());
(texture->*subImage1DImplementation)(target, mipLevel, offset, image->size(), image->components(), image->type(), image->data());
}
};
#endif
@ -742,21 +819,18 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> {
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) {
texture->bindInternal();
glTexImage2D(target, mipLevel, internalFormat, image->size()[0], image->size()[1], 0, static_cast<GLenum>(image->components()), static_cast<GLenum>(image->type()), image->data());
(texture->*image2DImplementation)(target, mipLevel, internalFormat, image->size(), image->components(), 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) {
texture->bindInternal();
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 == 2, void>::type setSub(AbstractTexture* texture, GLenum target, GLint mipLevel, const Math::Vector2<GLint>& offset, Image* image) {
(texture->*subImage2DImplementation)(target, mipLevel, offset, image->size(), image->components(), 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) {
texture->bindInternal();
glTexSubImage2D(target, mipLevel, offset[0], offset[1], image->size()[0], 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::Vector2<GLint>& offset, Image* image) {
(texture->*subImage2DImplementation)(target, mipLevel, offset, Math::Vector2<GLint>(image->size(), 1), image->components(), image->type(), image->data());
}
};
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; }
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) {
texture->bindInternal();
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());
(texture->*image3DImplementation)(target, mipLevel, internalFormat, image->size(), image->components(), 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) {
texture->bindInternal();
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 == 3, void>::type setSub(AbstractTexture* texture, GLenum target, GLint mipLevel, const Math::Vector3<GLint>& offset, Image* image) {
(texture->*subImage3DImplementation)(target, mipLevel, offset, image->size(), image->components(), 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) {
texture->bindInternal();
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());
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->*subImage3DImplementation)(target, mipLevel, offset, Math::Vector3<GLint>(image->size(), 1), image->components(), image->type(), image->data());
}
};
#endif

23
src/BufferedTexture.cpp

@ -15,8 +15,31 @@
#include "BufferedTexture.h"
#include "Buffer.h"
#include "Context.h"
#include "Extensions.h"
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
BufferedTexture::InternalFormat::InternalFormat(Components components, ComponentType type) {
#define internalFormatSwitch(c) switch(type) { \

31
src/BufferedTexture.h

@ -20,10 +20,12 @@
*/
#include "AbstractTexture.h"
#include "Buffer.h"
namespace Magnum {
class Buffer;
class Context;
#ifndef MAGNUM_TARGET_GLES
/**
@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
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_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(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
* filled with data of proper format at any time using Buffer own data
* 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) {
bindInternal();
glTexBuffer(GL_TEXTURE_BUFFER, internalFormat, buffer->id());
inline void setBuffer(InternalFormat internalFormat, Buffer* buffer) {
(this->*setBufferImplementation)(internalFormat, buffer);
}
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

4
src/Context.cpp

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

8
src/CubeMapTexture.h

@ -27,9 +27,9 @@ namespace Magnum {
@brief Cube map texture
%Texture used mainly for environemnt maps. See AbstractTexture documentation
for more information about usage. It consists of 6 square textures generating
6 faces of the cube as following. Note that all images must be turned upside
down (+Y is top):
for more information. It consists of 6 square textures generating 6 faces of
the cube as following. Note that all images must be turned upside down (+Y is
top):
+----+
| -Y |
@ -105,7 +105,7 @@ class CubeMapTexture: public AbstractTexture {
* @param coordinate Coordinate
* @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);
return this;
}

12
src/CubeMapTextureArray.h

@ -26,7 +26,7 @@ namespace Magnum {
/**
@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
classic textures, coordinates for cube map textures is signed three-part
@ -59,7 +59,7 @@ class CubeMapTextureArray: public AbstractTexture {
/**
* @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);
return this;
}
@ -94,8 +94,8 @@ class CubeMapTextureArray: public AbstractTexture {
*
* @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) {
DataHelper<3>::setSub(this, GL_TEXTURE_CUBE_MAP_ARRAY, mipLevel, offset, image, Math::Vector<3, GLsizei>(Math::Vector<Image::Dimensions, GLsizei>()));
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::Vector3<GLsizei>(Math::Vector<Image::Dimensions, GLsizei>()));
return this;
}
@ -114,8 +114,8 @@ class CubeMapTextureArray: public AbstractTexture {
*
* @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) {
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>()));
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::Vector3<GLint>(offset, layer*6+static_cast<GLsizei>(coordinate)), image, Math::Vector<2, GLsizei>(Math::Vector<Image::Dimensions, GLsizei>()));
return this;
}
};

33
src/Texture.h

@ -28,7 +28,7 @@ namespace Magnum {
@brief %Texture
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`
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
* 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,
* see @ref AbstractTexture::Wrapping "Wrapping" documentation for
* more information.
* @see bind(), @fn_gl{TexParameter} with @def_gl{TEXTURE_WRAP_S},
* @def_gl{TEXTURE_WRAP_T}, @def_gl{TEXTURE_WRAP_R}
* see @ref AbstractTexture::Wrapping "Wrapping" documentation
* for more information.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* 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
* 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)
*
* Sets texture data from given image. The image is not deleted
* afterwards.
* @see bind(), @fn_gl{TexImage1D}, @fn_gl{TexImage2D}, @fn_gl{TexImage3D}
* afterwards. 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{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) {
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
* for e.g. updating 3D texture with multiple 2D images or for filling
* 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) {
DataHelper<Dimensions>::setSub(this, _target, mipLevel, offset, image);

Loading…
Cancel
Save