Browse Source

Added multi-unbind function to AbstractTexture.

More efficient (no allocation) and also more convenient than calling e.g.
unbind(7, {nullptr, nullptr, nullptr}).
pull/68/head
Vladimír Vondruš 12 years ago
parent
commit
3e84a1848f
  1. 37
      src/Magnum/AbstractTexture.cpp
  2. 26
      src/Magnum/AbstractTexture.h
  3. 2
      src/Magnum/Implementation/TextureState.h
  4. 4
      src/Magnum/Test/BufferTextureGLTest.cpp
  5. 4
      src/Magnum/Test/CubeMapTextureArrayGLTest.cpp
  6. 4
      src/Magnum/Test/CubeMapTextureGLTest.cpp
  7. 8
      src/Magnum/Test/MultisampleTextureGLTest.cpp
  8. 4
      src/Magnum/Test/RectangleTextureGLTest.cpp
  9. 8
      src/Magnum/Test/TextureArrayGLTest.cpp
  10. 12
      src/Magnum/Test/TextureGLTest.cpp

37
src/Magnum/AbstractTexture.cpp

@ -151,42 +151,45 @@ void AbstractTexture::unbindImplementationDSA(const GLint textureUnit) {
} }
#endif #endif
void AbstractTexture::unbind(const Int firstTextureUnit, const std::size_t count) {
/* State tracker is updated in the implementations */
Context::current()->state().texture->bindMultiImplementation(firstTextureUnit, {nullptr, count});
}
/** @todoc const std::initializer_list makes Doxygen grumpy */
void AbstractTexture::bind(const Int firstTextureUnit, std::initializer_list<AbstractTexture*> textures) { void AbstractTexture::bind(const Int firstTextureUnit, std::initializer_list<AbstractTexture*> textures) {
/* State tracker is updated in the implementations */ /* State tracker is updated in the implementations */
Context::current()->state().texture->bindMultiImplementation(firstTextureUnit, textures); Context::current()->state().texture->bindMultiImplementation(firstTextureUnit, {textures.begin(), textures.size()});
} }
void AbstractTexture::bindImplementationFallback(const GLint firstTextureUnit, std::initializer_list<AbstractTexture*> textures) { void AbstractTexture::bindImplementationFallback(const GLint firstTextureUnit, const Containers::ArrayReference<AbstractTexture* const> textures) {
Int unit = firstTextureUnit; for(std::size_t i = 0; i != textures.size(); ++i)
for(AbstractTexture* const texture: textures) { textures && textures[i] ? textures[i]->bind(firstTextureUnit + i) : unbind(firstTextureUnit + i);
if(texture) texture->bind(unit);
else unbind(unit);
++unit;
}
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, std::initializer_list<AbstractTexture*> textures) { void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, const Containers::ArrayReference<AbstractTexture* const> textures) {
Implementation::TextureState* const textureState = Context::current()->state().texture; Implementation::TextureState* const textureState = Context::current()->state().texture;
/* Create array of IDs and also update bindings in state tracker */ /* Create array of IDs and also update bindings in state tracker */
Containers::Array<GLuint> ids{textures.size()}; Containers::Array<GLuint> ids{textures ? textures.size() : 0};
Int i{};
bool different = false; bool different = false;
for(AbstractTexture* const texture: textures) { for(std::size_t i = 0; i != textures.size(); ++i) {
if(texture) texture->createIfNotAlready(); const GLuint id = textures && textures[i] ? textures[i]->_id : 0;
if(textures) {
if(textures[i]) textures[i]->createIfNotAlready();
ids[i] = id;
}
const GLuint id = ids[i] = texture ? texture->_id : 0;
if(textureState->bindings[firstTextureUnit + i].second != id) { if(textureState->bindings[firstTextureUnit + i].second != id) {
different = true; different = true;
textureState->bindings[firstTextureUnit + i].second = id; textureState->bindings[firstTextureUnit + i].second = id;
} }
++i;
} }
/* Avoid doing the binding if there is nothing different */ /* Avoid doing the binding if there is nothing different */
if(different) glBindTextures(firstTextureUnit, ids.size(), ids); if(different) glBindTextures(firstTextureUnit, textures.size(), ids);
} }
#endif #endif

26
src/Magnum/AbstractTexture.h

@ -203,6 +203,21 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
*/ */
static void unbind(Int textureUnit); static void unbind(Int textureUnit);
/**
* @brief Unbind textures in given range of texture units
*
* Unbinds all texture in the range @f$ [ firstTextureUnit ; firstTextureUnit + count ) @f$.
* If @extension{ARB,multi_bind} (part of OpenGL 4.4) is not available,
* the feature is emulated with sequence of @ref unbind(Int) calls.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref Shader::maxCombinedTextureImageUnits(), @fn_gl{BindTextures},
* eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or
* @fn_gl_extension{BindMultiTexture,EXT,direct_state_access}
*/
static void unbind(Int firstTextureUnit, std::size_t count);
/** /**
* @brief Bind textures to given range of texture units * @brief Bind textures to given range of texture units
* *
@ -210,12 +225,13 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
* `firstTextureUnit + 1` etc. If any texture is `nullptr`, given * `firstTextureUnit + 1` etc. If any texture is `nullptr`, given
* texture unit is unbound. If @extension{ARB,multi_bind} (part of * texture unit is unbound. If @extension{ARB,multi_bind} (part of
* OpenGL 4.4) is not available, the feature is emulated with sequence * OpenGL 4.4) is not available, the feature is emulated with sequence
* of @ref bind(Int) / @ref unbind() calls. * of @ref bind(Int) / @ref unbind(Int) calls.
* @note This function is meant to be used only internally from * @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation * @ref AbstractShaderProgram subclasses. See its documentation
* for more information. * for more information.
* @see @fn_gl{BindTextures}, eventually @fn_gl{ActiveTexture}, * @see @ref Shader::maxCombinedTextureImageUnits(), @fn_gl{BindTextures},
* @fn_gl{BindTexture} or @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or
* @fn_gl_extension{BindMultiTexture,EXT,direct_state_access}
*/ */
static void bind(Int firstTextureUnit, std::initializer_list<AbstractTexture*> textures); static void bind(Int firstTextureUnit, std::initializer_list<AbstractTexture*> textures);
@ -358,9 +374,9 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
static void MAGNUM_LOCAL unbindImplementationDSA(GLint textureUnit); static void MAGNUM_LOCAL unbindImplementationDSA(GLint textureUnit);
#endif #endif
static void MAGNUM_LOCAL bindImplementationFallback(GLint firstTextureUnit, std::initializer_list<AbstractTexture*> textures); static void MAGNUM_LOCAL bindImplementationFallback(GLint firstTextureUnit, Containers::ArrayReference<AbstractTexture* const> textures);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
static void MAGNUM_LOCAL bindImplementationMulti(GLint firstTextureUnit, std::initializer_list<AbstractTexture*> textures); static void MAGNUM_LOCAL bindImplementationMulti(GLint firstTextureUnit, Containers::ArrayReference<AbstractTexture* const> textures);
#endif #endif
void MAGNUM_LOCAL createIfNotAlready(); void MAGNUM_LOCAL createIfNotAlready();

2
src/Magnum/Implementation/TextureState.h

@ -40,7 +40,7 @@ struct TextureState {
void reset(); void reset();
void(*unbindImplementation)(GLint); void(*unbindImplementation)(GLint);
void(*bindMultiImplementation)(GLint, std::initializer_list<AbstractTexture*>); void(*bindMultiImplementation)(GLint, Containers::ArrayReference<AbstractTexture* const>);
void(AbstractTexture::*bindImplementation)(GLint); void(AbstractTexture::*bindImplementation)(GLint);
void(AbstractTexture::*parameteriImplementation)(GLenum, GLint); void(AbstractTexture::*parameteriImplementation)(GLenum, GLint);
void(AbstractTexture::*parameterfImplementation)(GLenum, GLfloat); void(AbstractTexture::*parameterfImplementation)(GLenum, GLfloat);

4
src/Magnum/Test/BufferTextureGLTest.cpp

@ -78,6 +78,10 @@ void BufferTextureGLTest::bind() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
void BufferTextureGLTest::setBuffer() { void BufferTextureGLTest::setBuffer() {

4
src/Magnum/Test/CubeMapTextureArrayGLTest.cpp

@ -114,6 +114,10 @@ void CubeMapTextureArrayGLTest::bind() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
void CubeMapTextureArrayGLTest::sampling() { void CubeMapTextureArrayGLTest::sampling() {

4
src/Magnum/Test/CubeMapTextureGLTest.cpp

@ -139,6 +139,10 @@ void CubeMapTextureGLTest::bind() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
void CubeMapTextureGLTest::sampling() { void CubeMapTextureGLTest::sampling() {

8
src/Magnum/Test/MultisampleTextureGLTest.cpp

@ -146,6 +146,10 @@ void MultisampleTextureGLTest::bind2D() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -165,6 +169,10 @@ void MultisampleTextureGLTest::bind2DArray() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
#endif #endif

4
src/Magnum/Test/RectangleTextureGLTest.cpp

@ -112,6 +112,10 @@ void RectangleTextureGLTest::bind() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
void RectangleTextureGLTest::sampling() { void RectangleTextureGLTest::sampling() {

8
src/Magnum/Test/TextureArrayGLTest.cpp

@ -244,6 +244,10 @@ void TextureArrayGLTest::bind1D() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
#endif #endif
@ -265,6 +269,10 @@ void TextureArrayGLTest::bind2D() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

12
src/Magnum/Test/TextureGLTest.cpp

@ -303,6 +303,10 @@ void TextureGLTest::bind1D() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
#endif #endif
@ -319,6 +323,10 @@ void TextureGLTest::bind2D() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
void TextureGLTest::bind3D() { void TextureGLTest::bind3D() {
@ -339,6 +347,10 @@ void TextureGLTest::bind3D() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

Loading…
Cancel
Save