diff --git a/src/AbstractTexture.cpp b/src/AbstractTexture.cpp index 481679606..63a8d3ccb 100644 --- a/src/AbstractTexture.cpp +++ b/src/AbstractTexture.cpp @@ -30,6 +30,7 @@ #include "Extensions.h" #include "Image.h" #include "ImageFormat.h" +#include "Shader.h" #include "TextureFormat.h" #include "Implementation/State.h" #include "Implementation/TextureState.h" @@ -80,10 +81,49 @@ AbstractTexture::SubImage3DImplementation AbstractTexture::subImage3DImplementat AbstractTexture::InvalidateImageImplementation AbstractTexture::invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationNoOp; AbstractTexture::InvalidateSubImageImplementation AbstractTexture::invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationNoOp; -Int AbstractTexture::maxSupportedLayerCount() { - return Context::current()->state().texture->maxSupportedLayerCount; +Int AbstractTexture::maxLayers() { return Shader::maxCombinedTextureImageUnits(); } + +#ifndef MAGNUM_TARGET_GLES +Int AbstractTexture::maxColorSamples() { + if(!Context::current()->isExtensionSupported()) + return 0; + + GLint& value = Context::current()->state().texture->maxColorSamples; + + /* Get the value, if not already cached */ + if(value == 0) + glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &value); + + return value; +} + +Int AbstractTexture::maxDepthSamples() { + if(!Context::current()->isExtensionSupported()) + return 0; + + GLint& value = Context::current()->state().texture->maxDepthSamples; + + /* Get the value, if not already cached */ + if(value == 0) + glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &value); + + return value; } +Int AbstractTexture::maxIntegerSamples() { + if(!Context::current()->isExtensionSupported()) + return 0; + + GLint& value = Context::current()->state().texture->maxIntegerSamples; + + /* Get the value, if not already cached */ + if(value == 0) + glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &value); + + return value; +} +#endif + void AbstractTexture::destroy() { /* Moved out */ if(!_id) return; @@ -183,7 +223,7 @@ void AbstractTexture::bindInternal() { return; /* Set internal layer as active if not already */ - const GLint internalLayer = textureState->maxSupportedLayerCount-1; + const GLint internalLayer = maxLayers()-1; if(textureState->currentLayer != internalLayer) glActiveTexture(GL_TEXTURE0 + (textureState->currentLayer = internalLayer)); @@ -193,13 +233,6 @@ void AbstractTexture::bindInternal() { } void AbstractTexture::initializeContextBasedFunctionality(Context& context) { - Implementation::TextureState* const textureState = context.state().texture; - GLint& value = textureState->maxSupportedLayerCount; - - /* Get the value and resize bindings array */ - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &value); - textureState->bindings.resize(value); - #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { Debug() << "AbstractTexture: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; @@ -246,6 +279,8 @@ void AbstractTexture::initializeContextBasedFunctionality(Context& context) { storage3DImplementation = &AbstractTexture::storageImplementationDefault; } } + #else + static_cast(context); #endif } diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index 6e505dc83..1fd395ae5 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -48,9 +48,9 @@ information and usage examples. The engine tracks currently bound textures in all available layers to avoid unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. %Texture configuration functions use dedicated highest available texture layer to not -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. +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, bind() uses DSA function to avoid unnecessary calls to @fn_gl{ActiveTexture}. Also all texture @@ -91,6 +91,10 @@ do nothing. @todo Move constructor/assignment - how to avoid creation of empty texture and then deleting it immediately? @todo ES2 - proper support for pixel unpack buffer when extension is in headers +@todo `GL_MAX_3D_TEXTURE_SIZE`, `GL_MAX_ARRAY_TEXTURE_LAYERS`, `GL_MAX_CUBE_MAP_TEXTURE_SIZE`, `GL_MAX_RECTANGLE_TEXTURE_SIZE`, `GL_MAX_TEXTURE_SIZE`, `GL_MAX_TEXTURE_BUFFER_SIZE` enable them only where it makes sense? +@todo `GL_MAX_TEXTURE_LOD_BIAS` when `TEXTURE_LOD_BIAS` is implemented +@todo `GL_NUM_COMPRESSED_TEXTURE_FORMATS` when compressed textures are implemented +@todo `GL_MAX_SAMPLE_MASK_WORDS` when @extension{ARB,texture_multisample} is done */ class MAGNUM_EXPORT AbstractTexture { friend class Context; @@ -100,12 +104,53 @@ class MAGNUM_EXPORT AbstractTexture { * @brief Max supported layer count * * The result is cached, repeated queries don't result in repeated - * OpenGL calls. - * @see @ref AbstractShaderProgram-subclassing, bind(Int), - * @fn_gl{Get} with @def_gl{MAX_COMBINED_TEXTURE_IMAGE_UNITS}, - * @fn_gl{ActiveTexture} + * OpenGL calls. This function is in fact alias to + * @ref Shader::maxCombinedTextureImageUnits(). + * @see @ref bind(Int) */ - static Int maxSupportedLayerCount(); + static Int maxLayers(); + + /** + * @copybrief maxLayers() + * @deprecated Use @ref Magnum::AbstractTexture::maxLayers() "maxLayers()" + * instead. + */ + static Int maxSupportedLayerCount() { return maxLayers(); } + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Max supported color sample count + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. If extension @extension{ARB,texture_multisample} is + * not available, returns `0`. + * @see @fn_gl{Get} with @def_gl{MAX_COLOR_TEXTURE_SAMPLES} + * @requires_gl Multisample textures are not available in OpenGL ES. + */ + static Int maxColorSamples(); + + /** + * @brief Max supported depth sample count + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. If extension @extension{ARB,texture_multisample} is + * not available, returns `0`. + * @see @fn_gl{Get} with @def_gl{MAX_DEPTH_TEXTURE_SAMPLES} + * @requires_gl Multisample textures are not available in OpenGL ES. + */ + static Int maxDepthSamples(); + + /** + * @brief Max supported integer sample count + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. If extension @extension{ARB,texture_multisample} is + * not available, returns `0`. + * @see @fn_gl{Get} with @def_gl{MAX_INTEGER_SAMPLES} + * @requires_gl Multisample textures are not available in OpenGL ES. + */ + static Int maxIntegerSamples(); + #endif /** @brief Copying is not allowed */ AbstractTexture(const AbstractTexture&) = delete; @@ -126,11 +171,10 @@ class MAGNUM_EXPORT AbstractTexture { * @brief Bind texture for rendering * * 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. 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 + * between 0 and @ref maxLayers(). 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. + * @see @ref maxLayers(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or * @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} */ void bind(Int layer); @@ -205,7 +249,7 @@ class MAGNUM_EXPORT AbstractTexture { * 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}, + * @see @ref Sampler::maxAnisotropy(), @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} diff --git a/src/Implementation/TextureState.cpp b/src/Implementation/TextureState.cpp index 7524d218b..7c08ebceb 100644 --- a/src/Implementation/TextureState.cpp +++ b/src/Implementation/TextureState.cpp @@ -26,7 +26,11 @@ namespace Magnum { namespace Implementation { -TextureState::TextureState(): maxSupportedLayerCount(0), maxSupportedAnisotropy(0.0f), currentLayer(0) {} +TextureState::TextureState(): maxAnisotropy(0.0f), currentLayer(0) + #ifndef MAGNUM_TARGET_GLES + , maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0) + #endif + {} TextureState::~TextureState() = default; diff --git a/src/Implementation/TextureState.h b/src/Implementation/TextureState.h index 2e53176c1..91875bc9e 100644 --- a/src/Implementation/TextureState.h +++ b/src/Implementation/TextureState.h @@ -34,9 +34,13 @@ struct TextureState { explicit TextureState(); ~TextureState(); - GLint maxSupportedLayerCount; - GLfloat maxSupportedAnisotropy; + GLfloat maxAnisotropy; GLint currentLayer; + #ifndef MAGNUM_TARGET_GLES + GLint maxColorSamples, + maxDepthSamples, + maxIntegerSamples; + #endif std::vector bindings; }; diff --git a/src/Platform/magnum-info.cpp b/src/Platform/magnum-info.cpp index 528f56e65..0b5ae7435 100644 --- a/src/Platform/magnum-info.cpp +++ b/src/Platform/magnum-info.cpp @@ -214,6 +214,11 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat _l(AbstractShaderProgram::maxUniformLocations()) #endif _l(AbstractShaderProgram::maxVertexAttributes()) + #ifndef MAGNUM_TARGET_GLES + _l(AbstractTexture::maxColorSamples()) + _l(AbstractTexture::maxDepthSamples()) + _l(AbstractTexture::maxIntegerSamples()) + #endif #ifndef MAGNUM_TARGET_GLES if(c->isExtensionSupported()) { @@ -329,6 +334,14 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat } #endif + #ifndef MAGNUM_TARGET_GLES3 + if(c->isExtensionSupported()) { + _h(EXT::texture_filter_anisotropic) + + _l(Sampler::maxAnisotropy()) + } + #endif + #undef _l #undef _h } diff --git a/src/Sampler.cpp b/src/Sampler.cpp index 2d65ffe11..4aa722741 100644 --- a/src/Sampler.cpp +++ b/src/Sampler.cpp @@ -46,8 +46,8 @@ static_assert((filter_or(Nearest, Base) == GL_NEAREST) && #undef filter_or #ifndef MAGNUM_TARGET_GLES3 -Float Sampler::maxSupportedAnisotropy() { - GLfloat& value = Context::current()->state().texture->maxSupportedAnisotropy; +Float Sampler::maxAnisotropy() { + GLfloat& value = Context::current()->state().texture->maxAnisotropy; /** @todo Re-enable when extension header is available */ #ifndef MAGNUM_TARGET_GLES diff --git a/src/Sampler.h b/src/Sampler.h index 54780efd4..1991ae216 100644 --- a/src/Sampler.h +++ b/src/Sampler.h @@ -39,7 +39,7 @@ namespace Magnum { @see Texture, CubeMapTexture, CubeMapTextureArray */ -class Sampler { +class MAGNUM_EXPORT Sampler { public: /** * @brief %Texture filtering @@ -144,7 +144,14 @@ class Sampler { * @requires_extension %Extension @extension{EXT,texture_filter_anisotropic} * @requires_es_extension %Extension @es_extension2{EXT,texture_filter_anisotropic,texture_filter_anisotropic} */ - static Float maxSupportedAnisotropy(); + static Float maxAnisotropy(); + + /** + * @copybrief maxAnisotropy() + * @deprecated Use @ref Magnum::Shader::maxAnisotropy() "maxAnisotropy()" + * instead. + */ + static Float maxSupportedAnisotropy() { return maxAnisotropy(); } #endif }; diff --git a/src/Texture.h b/src/Texture.h index 82251d76c..b843090b4 100644 --- a/src/Texture.h +++ b/src/Texture.h @@ -52,7 +52,7 @@ Texture2D texture; texture.setMagnificationFilter(Sampler::Filter::Linear) .setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setWrapping(Sampler::Wrapping::ClampToEdge) - .setMaxAnisotropy(Sampler::maxSupportedAnisotropy()) + .setMaxAnisotropy(Sampler::maxAnisotropy()) .setStorage(Math::log2(4096)+1, TextureFormat::RGBA8, {4096, 4096}) .setSubImage(0, {}, &image) .generateMipmap();