From 7a1789470af135e0dd0f73d739633a7d0d213547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 18 Mar 2014 21:51:15 +0100 Subject: [PATCH] Initial ARB_multi_bind usage in *Texture::bind(). --- doc/opengl-mapping.dox | 3 +-- doc/opengl-support.dox | 2 +- src/Magnum/AbstractTexture.cpp | 8 ++++++++ src/Magnum/AbstractTexture.h | 24 ++++++++++++++-------- src/Magnum/Implementation/TextureState.cpp | 16 +++++++++++++-- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index c855e4bb8..7d77dc62f 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -62,8 +62,7 @@ OpenGL function | Matching API @fn_gl{BindRenderbuffer} | not needed, handhled internally in @ref Renderbuffer @fn_gl{BindSampler} | | @fn_gl{BindSamplers} | | -@fn_gl{BindTexture}, \n @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} | @ref AbstractTexture::bind() -@fn_gl{BindTextures} | | +@fn_gl{BindTexture}, \n @fn_gl{BindTextures}, \n @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} | @ref AbstractTexture::bind() @fn_gl{BindTransformFeedback} | | @fn_gl{BindVertexArray} | not needed, handhled internally in @ref Mesh @fn_gl{BindVertexBuffer} | | diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 7780c5b66..7a6a4e8bd 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -201,7 +201,7 @@ following: @extension{ARB,buffer_storage} | | @extension{ARB,clear_texture} | | @extension{ARB,enhanced_layouts} | done (shading language only) -@extension{ARB,multi_bind} | | +@extension{ARB,multi_bind} | only single texture binding @extension{ARB,query_buffer_object} | | @extension{ARB,texture_mirror_clamp_to_edge} | done @extension{ARB,texture_stencil8} | done diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 5594093c5..83eee7b62 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -137,6 +137,10 @@ void AbstractTexture::bindImplementationDefault(GLint layer) { } #ifndef MAGNUM_TARGET_GLES +void AbstractTexture::bindImplementationMulti(GLint layer) { + glBindTextures(layer, 1, &_id); +} + void AbstractTexture::bindImplementationDSA(GLint layer) { glBindMultiTextureEXT(GL_TEXTURE0 + layer, _target, (Context::current()->state().texture->bindings[layer] = _id)); } @@ -182,6 +186,10 @@ void AbstractTexture::mipmapImplementationDSA() { #endif void AbstractTexture::bindInternal() { + /* Using glBindTextures() here is meaningless, because the non-DSA + functions need to have the texture bound in *currently active* layer, + so we would need to call glActiveTexture() afterwards anyway. */ + Implementation::TextureState* const textureState = Context::current()->state().texture; /* If the texture is already bound in current layer, nothing to do */ diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 7062fbd64..136b46b4d 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -52,11 +52,15 @@ affect active bindings in user layers. %Texture limits and implementation-defined values (such as @ref maxColorSamples()) are cached, so repeated queries don't result in repeated @fn_gl{Get} calls. -If extension @extension{EXT,direct_state_access} is available, @ref bind() uses -DSA function to avoid unnecessary calls to @fn_gl{ActiveTexture}. Also all -texture configuration and data updating functions use DSA functions to avoid -unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. See -respective function documentation for more information. +If extension @extension{ARB,multi_bind} is available, @ref bind() uses +@fn_gl{BindTextures} to avoid unnecessary calls to @fn_gl{ActiveTexture}. +Otherwise, if extension @extension{EXT,direct_state_access} is available, +@ref bind() uses the DSA function. + +In addition, if extension @extension{EXT,direct_state_access} is available, +also all texture configuration and data updating functions use DSA functions +to avoid unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. +See respective function documentation for more information. If extension @extension{ARB,robustness} is available, image reading operations (such as @ref Texture::image()) are protected from buffer overflow. However, if @@ -208,13 +212,14 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { * @brief Bind texture for rendering * * Sets current texture as active in given layer. Note that only one - * texture can be bound to given layer. If @extension{EXT,direct_state_access} - * is not available, the layer is made active before binding the - * texture. + * texture can be bound to given layer. If @extension{ARB,multi_bind} + * (part of OpenGL 4.4) or @extension{EXT,direct_state_access} is not + * available, the layer is made active before binding the texture. * @note This function is meant to be used only internally from * @ref AbstractShaderProgram subclasses. See its documentation * for more information. - * @see @ref maxLayers(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or + * @see @ref maxLayers(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture}, + * @fn_gl{BindTextures} or * @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} */ void bind(Int layer); @@ -248,6 +253,7 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { private: void MAGNUM_LOCAL bindImplementationDefault(GLint layer); #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL bindImplementationMulti(GLint layer); void MAGNUM_LOCAL bindImplementationDSA(GLint layer); #endif diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index dc1eab00b..845ade148 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -41,12 +41,25 @@ TextureState::TextureState(Context& context, std::vector& extension , maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0), bufferOffsetAlignment(0) #endif { + /* Bind implementation */ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::ARB::multi_bind::string()); + bindImplementation = &AbstractTexture::bindImplementationMulti; + } else if(context.isExtensionSupported()) { + /* Extension name added below */ + bindImplementation = &AbstractTexture::bindImplementationDSA; + } else + #endif + { + bindImplementation = &AbstractTexture::bindImplementationDefault; + } + /* DSA/non-DSA implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); - bindImplementation = &AbstractTexture::bindImplementationDSA; parameteriImplementation = &AbstractTexture::parameterImplementationDSA; parameterfImplementation = &AbstractTexture::parameterImplementationDSA; parameterfvImplementation = &AbstractTexture::parameterImplementationDSA; @@ -65,7 +78,6 @@ TextureState::TextureState(Context& context, std::vector& extension } else #endif { - bindImplementation = &AbstractTexture::bindImplementationDefault; parameteriImplementation = &AbstractTexture::parameterImplementationDefault; parameterfImplementation = &AbstractTexture::parameterImplementationDefault; parameterfvImplementation = &AbstractTexture::parameterImplementationDefault;