diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 93dde42fc..b0d43a9bc 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -41,52 +41,6 @@ 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::SetMaxAnisotropyImplementation AbstractTexture::setMaxAnisotropyImplementation = - &AbstractTexture::setMaxAnisotropyImplementationNoOp; -#ifndef MAGNUM_TARGET_GLES -AbstractTexture::GetLevelParameterivImplementation AbstractTexture::getLevelParameterivImplementation = - &AbstractTexture::getLevelParameterImplementationDefault; -#endif -AbstractTexture::MipmapImplementation AbstractTexture::mipmapImplementation = - &AbstractTexture::mipmapImplementationDefault; -#ifndef MAGNUM_TARGET_GLES -AbstractTexture::Storage1DImplementation AbstractTexture::storage1DImplementation = - &AbstractTexture::storageImplementationFallback; -#endif -AbstractTexture::Storage2DImplementation AbstractTexture::storage2DImplementation = - &AbstractTexture::storageImplementationFallback; -AbstractTexture::Storage3DImplementation AbstractTexture::storage3DImplementation = - &AbstractTexture::storageImplementationFallback; -#ifndef MAGNUM_TARGET_GLES -AbstractTexture::GetImageImplementation AbstractTexture::getImageImplementation = - &AbstractTexture::getImageImplementationDefault; -AbstractTexture::Image1DImplementation AbstractTexture::image1DImplementation = - &AbstractTexture::imageImplementationDefault; -#endif -AbstractTexture::Image2DImplementation AbstractTexture::image2DImplementation = - &AbstractTexture::imageImplementationDefault; -AbstractTexture::Image3DImplementation AbstractTexture::image3DImplementation = - &AbstractTexture::imageImplementationDefault; -#ifndef MAGNUM_TARGET_GLES -AbstractTexture::SubImage1DImplementation AbstractTexture::subImage1DImplementation = - &AbstractTexture::subImageImplementationDefault; -#endif -AbstractTexture::SubImage2DImplementation AbstractTexture::subImage2DImplementation = - &AbstractTexture::subImageImplementationDefault; -AbstractTexture::SubImage3DImplementation AbstractTexture::subImage3DImplementation = - &AbstractTexture::subImageImplementationDefault; - -AbstractTexture::InvalidateImageImplementation AbstractTexture::invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationNoOp; -AbstractTexture::InvalidateSubImageImplementation AbstractTexture::invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationNoOp; - Int AbstractTexture::maxLayers() { return Shader::maxCombinedTextureImageUnits(); } #ifndef MAGNUM_TARGET_GLES @@ -160,7 +114,7 @@ void AbstractTexture::bind(Int layer) { /* If already bound in given layer, nothing to do */ if(textureState->bindings[layer] == _id) return; - (this->*bindImplementation)(layer); + (this->*Context::current()->state().texture->bindImplementation)(layer); } void AbstractTexture::bindImplementationDefault(GLint layer) { @@ -185,16 +139,39 @@ AbstractTexture& AbstractTexture::setMinificationFilter(Sampler::Filter filter, CORRADE_ASSERT(_target != GL_TEXTURE_RECTANGLE || mipmap == Sampler::Mipmap::Base, "AbstractTexture: rectangle textures cannot have mipmaps", *this); #endif - (this->*parameteriImplementation)(GL_TEXTURE_MIN_FILTER, GLint(filter)|GLint(mipmap)); + (this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_MIN_FILTER, GLint(filter)|GLint(mipmap)); + return *this; +} + +AbstractTexture& AbstractTexture::setMagnificationFilter(const Sampler::Filter filter) { + (this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_MAG_FILTER, GLint(filter)); return *this; } +AbstractTexture& AbstractTexture::setBorderColor(const Color4& color) { + #ifndef MAGNUM_TARGET_GLES + (this->*Context::current()->state().texture->parameterfvImplementation)(GL_TEXTURE_BORDER_COLOR, color.data()); + #else + (this->*Context::current()->state().texture->parameterfvImplementation)(GL_TEXTURE_BORDER_COLOR_NV, color.data()); + #endif + return *this; +} + +AbstractTexture& AbstractTexture::setMaxAnisotropy(const Float anisotropy) { + (this->*Context::current()->state().texture->setMaxAnisotropyImplementation)(anisotropy); + return *this; +} + +void AbstractTexture::invalidateImage(const Int level) { + (this->*Context::current()->state().texture->invalidateImageImplementation)(level); +} + AbstractTexture& AbstractTexture::generateMipmap() { #ifndef MAGNUM_TARGET_GLES CORRADE_ASSERT(_target != GL_TEXTURE_RECTANGLE, "AbstractTexture: rectangle textures cannot have mipmaps", *this); #endif - (this->*mipmapImplementation)(); + (this->*Context::current()->state().texture->mipmapImplementation)(); return *this; } @@ -226,65 +203,6 @@ void AbstractTexture::bindInternal() { glBindTexture(_target, (textureState->bindings[internalLayer] = _id)); } -void AbstractTexture::initializeContextBasedFunctionality(Context& context) { - /* Resize bindings array to hold all possible layers */ - context.state().texture->bindings.resize(maxLayers()); - - #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) { - Debug() << "AbstractTexture: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; - - bindImplementation = &AbstractTexture::bindImplementationDSA; - parameteriImplementation = &AbstractTexture::parameterImplementationDSA; - parameterfImplementation = &AbstractTexture::parameterImplementationDSA; - parameterfvImplementation = &AbstractTexture::parameterImplementationDSA; - getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA; - mipmapImplementation = &AbstractTexture::mipmapImplementationDSA; - getImageImplementation = &AbstractTexture::getImageImplementationDSA; - image1DImplementation = &AbstractTexture::imageImplementationDSA; - image2DImplementation = &AbstractTexture::imageImplementationDSA; - image3DImplementation = &AbstractTexture::imageImplementationDSA; - subImage1DImplementation = &AbstractTexture::subImageImplementationDSA; - subImage2DImplementation = &AbstractTexture::subImageImplementationDSA; - subImage3DImplementation = &AbstractTexture::subImageImplementationDSA; - } - - if(context.isExtensionSupported()) { - Debug() << "AbstractTexture: using" << Extensions::GL::ARB::invalidate_subdata::string() << "features"; - - invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationARB; - invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationARB; - } - - if(context.isExtensionSupported() && - !context.isExtensionSupported()) { - Debug() << "AbstractTexture: using" << Extensions::GL::ARB::robustness::string() << "features"; - - getImageImplementation = &AbstractTexture::getImageImplementationRobustness; - } - - if(context.isExtensionSupported()) { - Debug() << "AbstractTexture: using" << Extensions::GL::ARB::texture_storage::string() << "features"; - - if(context.isExtensionSupported()) { - storage1DImplementation = &AbstractTexture::storageImplementationDSA; - storage2DImplementation = &AbstractTexture::storageImplementationDSA; - storage3DImplementation = &AbstractTexture::storageImplementationDSA; - } else { - storage1DImplementation = &AbstractTexture::storageImplementationDefault; - storage2DImplementation = &AbstractTexture::storageImplementationDefault; - storage3DImplementation = &AbstractTexture::storageImplementationDefault; - } - } - #endif - - if(context.isExtensionSupported()) { - Debug() << "AbstractTexture: using" << Extensions::GL::EXT::texture_filter_anisotropic::string() << "features"; - - setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationExt; - } -} - ColorFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) { switch(internalFormat) { case TextureFormat::Red: @@ -690,7 +608,7 @@ void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLfloat void AbstractTexture::setMaxAnisotropyImplementationNoOp(GLfloat) {} void AbstractTexture::setMaxAnisotropyImplementationExt(GLfloat anisotropy) { - (this->*parameterfImplementation)(GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy); + (this->*Context::current()->state().texture->parameterfImplementation)(GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy); } #ifndef MAGNUM_TARGET_GLES @@ -712,7 +630,7 @@ void AbstractTexture::storageImplementationFallback(const GLenum target, const G const ColorType type = imageTypeForInternalFormat(internalFormat); for(GLsizei level = 0; level != levels; ++level) { - (this->*image1DImplementation)(target, level, internalFormat, Math::max(Math::Vector<1, GLsizei>(1), size >> level), format, type, nullptr); + (this->*Context::current()->state().texture->image1DImplementation)(target, level, internalFormat, Math::max(Math::Vector<1, GLsizei>(1), size >> level), format, type, nullptr); } } @@ -748,7 +666,7 @@ void AbstractTexture::storageImplementationFallback(const GLenum target, const G #endif { for(GLsizei level = 0; level != levels; ++level) { - (this->*image2DImplementation)(target, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr); + (this->*Context::current()->state().texture->image2DImplementation)(target, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr); } /* Cube map additionally needs to specify all faces */ @@ -760,14 +678,14 @@ void AbstractTexture::storageImplementationFallback(const GLenum target, const G GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z}) - (this->*image2DImplementation)(face, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr); + (this->*Context::current()->state().texture->image2DImplementation)(face, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr); } #ifndef MAGNUM_TARGET_GLES /* Array texture is not scaled in "layer" dimension */ } else if(target == GL_TEXTURE_1D_ARRAY) { for(GLsizei level = 0; level != levels; ++level) { - (this->*image2DImplementation)(target, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr); + (this->*Context::current()->state().texture->image2DImplementation)(target, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr); } #endif @@ -808,7 +726,7 @@ void AbstractTexture::storageImplementationFallback(GLenum target, GLsizei level #endif { for(GLsizei level = 0; level != levels; ++level) { - (this->*image3DImplementation)(target, level, internalFormat, Math::max(Vector3i(1), size >> level), format, type, nullptr); + (this->*Context::current()->state().texture->image3DImplementation)(target, level, internalFormat, Math::max(Vector3i(1), size >> level), format, type, nullptr); } #ifndef MAGNUM_TARGET_GLES2 @@ -821,7 +739,7 @@ void AbstractTexture::storageImplementationFallback(GLenum target, GLsizei level #endif { for(GLsizei level = 0; level != levels; ++level) { - (this->*image3DImplementation)(target, level, internalFormat, Math::max(Vector3i(1), size >> level), format, type, nullptr); + (this->*Context::current()->state().texture->image3DImplementation)(target, level, internalFormat, Math::max(Vector3i(1), size >> level), format, type, nullptr); } #endif @@ -991,7 +909,7 @@ template void AbstractTexture::image(GLenum target, GLin const Math::Vector size = DataHelper::imageSize(this, target, level); const std::size_t dataSize = size.product()*image.pixelSize(); char* data = new char[dataSize]; - (this->*getImageImplementation)(target, level, image.format(), image.type(), dataSize, data); + (this->*Context::current()->state().texture->getImageImplementation)(target, level, image.format(), image.type(), dataSize, data); image.setData(image.format(), image.type(), size, data); } @@ -1006,7 +924,7 @@ template void AbstractTexture::image(GLenum target, GLin image.setData(image.format(), image.type(), size, nullptr, usage); image.buffer().bind(Buffer::Target::PixelPack); - (this->*getImageImplementation)(target, level, image.format(), image.type(), dataSize, nullptr); + (this->*Context::current()->state().texture->getImageImplementation)(target, level, image.format(), image.type(), dataSize, nullptr); } template void MAGNUM_EXPORT AbstractTexture::image<1>(GLenum, GLint, BufferImage<1>&, BufferUsage); @@ -1019,45 +937,63 @@ template void MAGNUM_EXPORT AbstractTexture::image<3>(GLenum, GLint, BufferImage #ifndef MAGNUM_TARGET_GLES Math::Vector<1, GLint> AbstractTexture::DataHelper<1>::imageSize(AbstractTexture* texture, GLenum target, GLint level) { Math::Vector<1, GLint> value; - (texture->*getLevelParameterivImplementation)(target, level, GL_TEXTURE_WIDTH, &value[0]); + (texture->*Context::current()->state().texture->getLevelParameterivImplementation)(target, level, GL_TEXTURE_WIDTH, &value[0]); return value; } Vector2i AbstractTexture::DataHelper<2>::imageSize(AbstractTexture* texture, GLenum target, GLint level) { + const Implementation::TextureState& state = *Context::current()->state().texture; + Vector2i value; - (texture->*getLevelParameterivImplementation)(target, level, GL_TEXTURE_WIDTH, &value[0]); - (texture->*getLevelParameterivImplementation)(target, level, GL_TEXTURE_HEIGHT, &value[1]); + (texture->*state.getLevelParameterivImplementation)(target, level, GL_TEXTURE_WIDTH, &value[0]); + (texture->*state.getLevelParameterivImplementation)(target, level, GL_TEXTURE_HEIGHT, &value[1]); return value; } Vector3i AbstractTexture::DataHelper<3>::imageSize(AbstractTexture* texture, GLenum target, GLint level) { + const Implementation::TextureState& state = *Context::current()->state().texture; + Vector3i value; - (texture->*getLevelParameterivImplementation)(target, level, GL_TEXTURE_WIDTH, &value[0]); - (texture->*getLevelParameterivImplementation)(target, level, GL_TEXTURE_HEIGHT, &value[1]); - (texture->*getLevelParameterivImplementation)(target, level, GL_TEXTURE_DEPTH, &value[2]); + (texture->*state.getLevelParameterivImplementation)(target, level, GL_TEXTURE_WIDTH, &value[0]); + (texture->*state.getLevelParameterivImplementation)(target, level, GL_TEXTURE_HEIGHT, &value[1]); + (texture->*state.getLevelParameterivImplementation)(target, level, GL_TEXTURE_DEPTH, &value[2]); return value; } #endif +#ifndef MAGNUM_TARGET_GLES +void AbstractTexture::DataHelper<1>::setStorage(AbstractTexture* const texture, const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Math::Vector< 1, GLsizei >& size) { + (texture->*Context::current()->state().texture->storage1DImplementation)(target, levels, internalFormat, size); +} +#endif + +void AbstractTexture::DataHelper<2>::setStorage(AbstractTexture* const texture, const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Vector2i& size) { + (texture->*Context::current()->state().texture->storage2DImplementation)(target, levels, internalFormat, size); +} + +void AbstractTexture::DataHelper<3>::setStorage(AbstractTexture* const texture, const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Vector3i& size) { + (texture->*Context::current()->state().texture->storage3DImplementation)(target, levels, internalFormat, size); +} + #ifndef MAGNUM_TARGET_GLES void AbstractTexture::DataHelper<1>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference1D& image) { Buffer::unbind(Buffer::Target::PixelUnpack); - (texture->*image1DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data()); + (texture->*Context::current()->state().texture->image1DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data()); } void AbstractTexture::DataHelper<1>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage1D& image) { image.buffer().bind(Buffer::Target::PixelUnpack); - (texture->*image1DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr); + (texture->*Context::current()->state().texture->image1DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr); } void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Math::Vector<1, GLint>& offset, const ImageReference1D& image) { Buffer::unbind(Buffer::Target::PixelUnpack); - (texture->*subImage1DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data()); + (texture->*Context::current()->state().texture->subImage1DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data()); } void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) { image.buffer().bind(Buffer::Target::PixelUnpack); - (texture->*subImage1DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr); + (texture->*Context::current()->state().texture->subImage1DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr); } #endif @@ -1065,13 +1001,13 @@ void AbstractTexture::DataHelper<2>::setImage(AbstractTexture* const texture, co #ifndef MAGNUM_TARGET_GLES2 Buffer::unbind(Buffer::Target::PixelUnpack); #endif - (texture->*image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data()); + (texture->*Context::current()->state().texture->image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data()); } #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::DataHelper<2>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage2D& image) { image.buffer().bind(Buffer::Target::PixelUnpack); - (texture->*image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr); + (texture->*Context::current()->state().texture->image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr); } #endif @@ -1079,13 +1015,13 @@ void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture* const texture, #ifndef MAGNUM_TARGET_GLES2 Buffer::unbind(Buffer::Target::PixelUnpack); #endif - (texture->*subImage2DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data()); + (texture->*Context::current()->state().texture->subImage2DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data()); } #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Vector2i& offset, BufferImage2D& image) { image.buffer().bind(Buffer::Target::PixelUnpack); - (texture->*subImage2DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr); + (texture->*Context::current()->state().texture->subImage2DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr); } #endif @@ -1093,13 +1029,13 @@ void AbstractTexture::DataHelper<3>::setImage(AbstractTexture* const texture, co #ifndef MAGNUM_TARGET_GLES2 Buffer::unbind(Buffer::Target::PixelUnpack); #endif - (texture->*image3DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data()); + (texture->*Context::current()->state().texture->image3DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data()); } #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::DataHelper<3>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage3D& image) { image.buffer().bind(Buffer::Target::PixelUnpack); - (texture->*image3DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr); + (texture->*Context::current()->state().texture->image3DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr); } #endif @@ -1107,13 +1043,33 @@ void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture* const texture, #ifndef MAGNUM_TARGET_GLES2 Buffer::unbind(Buffer::Target::PixelUnpack); #endif - (texture->*subImage3DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data()); + (texture->*Context::current()->state().texture->subImage3DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data()); } #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Vector3i& offset, BufferImage3D& image) { image.buffer().bind(Buffer::Target::PixelUnpack); - (texture->*subImage3DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr); + (texture->*Context::current()->state().texture->subImage3DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr); +} +#endif + +#ifndef MAGNUM_TARGET_GLES +void AbstractTexture::DataHelper<1>::invalidateSubImage(AbstractTexture* const texture, const GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLint>& size) { + (texture->*Context::current()->state().texture->invalidateSubImageImplementation)(level, {offset[0], 0, 0}, {size[0], 1, 1}); +} +#endif + +void AbstractTexture::DataHelper<2>::invalidateSubImage(AbstractTexture* const texture, const GLint level, const Vector2i& offset, const Vector2i& size) { + (texture->*Context::current()->state().texture->invalidateSubImageImplementation)(level, {offset, 0}, {size, 1}); +} + +void AbstractTexture::DataHelper<3>::invalidateSubImage(AbstractTexture* const texture, const GLint level, const Vector3i& offset, const Vector3i& size) { + (texture->*Context::current()->state().texture->invalidateSubImageImplementation)(level, offset, size); +} + +#ifndef MAGNUM_TARGET_GLES +void AbstractTexture::DataHelper<1>::setWrapping(AbstractTexture* const texture, const Array1D& wrapping) { + (texture->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); } #endif @@ -1122,15 +1078,19 @@ void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture* texture, const CORRADE_ASSERT(texture->_target != GL_TEXTURE_RECTANGLE || ((wrapping.x() == Sampler::Wrapping::ClampToEdge || wrapping.x() == Sampler::Wrapping::ClampToBorder) && (wrapping.y() == Sampler::Wrapping::ClampToEdge || wrapping.y() == Sampler::Wrapping::ClampToBorder)), "Texture2D::setWrapping(): rectangle texture must be clamped to border or to edge", ); #endif - (texture->*parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); - (texture->*parameteriImplementation)(GL_TEXTURE_WRAP_T, GLint(wrapping.y())); + const Implementation::TextureState& state = *Context::current()->state().texture; + + (texture->*state.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); + (texture->*state.parameteriImplementation)(GL_TEXTURE_WRAP_T, GLint(wrapping.y())); } void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture* texture, const Array3D& wrapping) { - (texture->*parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); - (texture->*parameteriImplementation)(GL_TEXTURE_WRAP_T, GLint(wrapping.y())); + const Implementation::TextureState& state = *Context::current()->state().texture; + + (texture->*state.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); + (texture->*state.parameteriImplementation)(GL_TEXTURE_WRAP_T, GLint(wrapping.y())); #ifndef MAGNUM_TARGET_GLES - (texture->*parameteriImplementation)(GL_TEXTURE_WRAP_R, GLint(wrapping.z())); + (texture->*state.parameteriImplementation)(GL_TEXTURE_WRAP_R, GLint(wrapping.z())); #endif } #endif diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 53522be75..ac3ac20ed 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -36,6 +36,8 @@ namespace Magnum { +namespace Implementation { struct TextureState; } + /** @brief Base for textures @@ -99,7 +101,7 @@ nothing. @todo Query for immutable levels (@extension{ARB,ES3_compatibility}) */ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { - friend class Context; + friend class Implementation::TextureState; public: /** @@ -243,10 +245,7 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} * with @def_gl{TEXTURE_MAG_FILTER} */ - AbstractTexture& setMagnificationFilter(Sampler::Filter filter) { - (this->*parameteriImplementation)(GL_TEXTURE_MAG_FILTER, GLint(filter)); - return *this; - } + AbstractTexture& setMagnificationFilter(Sampler::Filter filter); /** * @brief Set border color @@ -261,14 +260,7 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { * with @def_gl{TEXTURE_BORDER_COLOR} * @requires_es_extension %Extension @es_extension{NV,texture_border_clamp} */ - AbstractTexture& setBorderColor(const Color4& color) { - #ifndef MAGNUM_TARGET_GLES - (this->*parameterfvImplementation)(GL_TEXTURE_BORDER_COLOR, color.data()); - #else - (this->*parameterfvImplementation)(GL_TEXTURE_BORDER_COLOR_NV, color.data()); - #endif - return *this; - } + AbstractTexture& setBorderColor(const Color4& color); /** * @brief Set max anisotropy @@ -285,10 +277,7 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with * @def_gl{TEXTURE_MAX_ANISOTROPY_EXT} */ - AbstractTexture& setMaxAnisotropy(Float anisotropy) { - (this->*setMaxAnisotropyImplementation)(anisotropy); - return *this; - } + AbstractTexture& setMaxAnisotropy(Float anisotropy); /** * @brief Invalidate texture image @@ -299,9 +288,7 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { * @see @ref Texture::invalidateSubImage() "invalidateSubImage()", * @fn_gl{InvalidateTexImage} */ - void invalidateImage(Int level) { - (this->*invalidateImageImplementation)(level); - } + void invalidateImage(Int level); /** * @brief Generate mipmap @@ -352,142 +339,102 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { GLenum _target; private: - static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context); - - typedef void(AbstractTexture::*BindImplementation)(GLint); void MAGNUM_LOCAL bindImplementationDefault(GLint layer); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL bindImplementationDSA(GLint layer); #endif - static MAGNUM_LOCAL BindImplementation bindImplementation; - typedef void(AbstractTexture::*ParameteriImplementation)(GLenum, GLint); void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLint value); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLint value); #endif - static ParameteriImplementation parameteriImplementation; - typedef void(AbstractTexture::*ParameterfImplementation)(GLenum, GLfloat); void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLfloat value); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLfloat value); #endif - static ParameterfImplementation parameterfImplementation; - typedef void(AbstractTexture::*ParameterfvImplementation)(GLenum, const GLfloat*); void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLfloat* values); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLfloat* values); #endif - static ParameterfvImplementation parameterfvImplementation; - typedef void(AbstractTexture::*SetMaxAnisotropyImplementation)(GLfloat); void MAGNUM_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat); void MAGNUM_LOCAL setMaxAnisotropyImplementationExt(GLfloat anisotropy); - static SetMaxAnisotropyImplementation setMaxAnisotropyImplementation; #ifndef MAGNUM_TARGET_GLES - typedef void(AbstractTexture::*GetLevelParameterivImplementation)(GLenum, GLint, GLenum, GLint*); void MAGNUM_LOCAL getLevelParameterImplementationDefault(GLenum target, GLint level, GLenum parameter, GLint* values); void MAGNUM_LOCAL getLevelParameterImplementationDSA(GLenum target, GLint level, GLenum parameter, GLint* values); - static MAGNUM_LOCAL GetLevelParameterivImplementation getLevelParameterivImplementation; #endif - typedef void(AbstractTexture::*MipmapImplementation)(); void MAGNUM_LOCAL mipmapImplementationDefault(); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL mipmapImplementationDSA(); #endif - static MAGNUM_LOCAL MipmapImplementation mipmapImplementation; #ifndef MAGNUM_TARGET_GLES - typedef void(AbstractTexture::*Storage1DImplementation)(GLenum, GLsizei, TextureFormat, const Math::Vector<1, GLsizei>&); void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size); void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size); void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size); - static Storage1DImplementation storage1DImplementation; #endif - typedef void(AbstractTexture::*Storage2DImplementation)(GLenum, GLsizei, TextureFormat, const Vector2i&); void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size); #endif - static Storage2DImplementation storage2DImplementation; - typedef void(AbstractTexture::*Storage3DImplementation)(GLenum, GLsizei, TextureFormat, const Vector3i&); void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); #endif - static Storage3DImplementation storage3DImplementation; #ifndef MAGNUM_TARGET_GLES - typedef void(AbstractTexture::*GetImageImplementation)(GLenum, GLint, ColorFormat, ColorType, std::size_t, GLvoid*); void MAGNUM_LOCAL getImageImplementationDefault(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); void MAGNUM_LOCAL getImageImplementationDSA(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); void MAGNUM_LOCAL getImageImplementationRobustness(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); - static MAGNUM_LOCAL GetImageImplementation getImageImplementation; #endif #ifndef MAGNUM_TARGET_GLES - typedef void(AbstractTexture::*Image1DImplementation)(GLenum, GLint, TextureFormat, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*); void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data); void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data); - static Image1DImplementation image1DImplementation; #endif - typedef void(AbstractTexture::*Image2DImplementation)(GLenum, GLint, TextureFormat, const Vector2i&, ColorFormat, ColorType, const GLvoid*); void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data); #endif - static Image2DImplementation image2DImplementation; - typedef void(AbstractTexture::*Image3DImplementation)(GLenum, GLint, TextureFormat, const Vector3i&, ColorFormat, ColorType, const GLvoid*); void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data); #endif - static Image3DImplementation image3DImplementation; #ifndef MAGNUM_TARGET_GLES - typedef void(AbstractTexture::*SubImage1DImplementation)(GLenum, GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*); void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data); void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data); - static SubImage1DImplementation subImage1DImplementation; #endif - typedef void(AbstractTexture::*SubImage2DImplementation)(GLenum, GLint, const Vector2i&, const Vector2i&, ColorFormat, ColorType, const GLvoid*); void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data); #endif - static SubImage2DImplementation subImage2DImplementation; - typedef void(AbstractTexture::*SubImage3DImplementation)(GLenum, GLint, const Vector3i&, const Vector3i&, ColorFormat, ColorType, const GLvoid*); void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data); #endif - static SubImage3DImplementation subImage3DImplementation; - typedef void(AbstractTexture::*InvalidateImageImplementation)(GLint); void MAGNUM_LOCAL invalidateImageImplementationNoOp(GLint level); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL invalidateImageImplementationARB(GLint level); #endif - static InvalidateImageImplementation invalidateImageImplementation; - typedef void(AbstractTexture::*InvalidateSubImageImplementation)(GLint, const Vector3i&, const Vector3i&); void MAGNUM_LOCAL invalidateSubImageImplementationNoOp(GLint level, const Vector3i& offset, const Vector3i& size); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL invalidateSubImageImplementationARB(GLint level, const Vector3i& offset, const Vector3i& size); #endif - static InvalidateSubImageImplementation invalidateSubImageImplementation; ColorFormat MAGNUM_LOCAL imageFormatForInternalFormat(TextureFormat internalFormat); ColorType MAGNUM_LOCAL imageTypeForInternalFormat(TextureFormat internalFormat); @@ -506,13 +453,9 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<1> { static Math::Vector<1, GLint> imageSize(AbstractTexture* texture, GLenum target, GLint level); - static void setWrapping(AbstractTexture* texture, const Array1D& wrapping) { - (texture->*parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); - } + static void setWrapping(AbstractTexture* texture, const Array1D& wrapping); - static void setStorage(AbstractTexture* texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size) { - (texture->*storage1DImplementation)(target, levels, internalFormat, size); - } + static void setStorage(AbstractTexture* texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size); static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference1D& image); static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage1D& image); @@ -520,9 +463,7 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<1> { static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const ImageReference1D& image); static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image); - static void invalidateSubImage(AbstractTexture* texture, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLint>& size) { - (texture->*invalidateSubImageImplementation)(level, {offset[0], 0, 0}, {size[0], 1, 1}); - } + static void invalidateSubImage(AbstractTexture* texture, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLint>& size); }; #endif template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> { @@ -543,9 +484,7 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> { static void setWrapping(AbstractTexture* texture, const Array2D& wrapping); - static void setStorage(AbstractTexture* texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size) { - (texture->*storage2DImplementation)(target, levels, internalFormat, size); - } + static void setStorage(AbstractTexture* texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size); static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference2D& image); #ifndef MAGNUM_TARGET_GLES2 @@ -557,9 +496,7 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> { static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector2i& offset, BufferImage2D& image); #endif - static void invalidateSubImage(AbstractTexture* texture, GLint level, const Vector2i& offset, const Vector2i& size) { - (texture->*invalidateSubImageImplementation)(level, {offset, 0}, {size, 1}); - } + static void invalidateSubImage(AbstractTexture* texture, GLint level, const Vector2i& offset, const Vector2i& size); }; template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> { enum class Target: GLenum { @@ -582,9 +519,7 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> { static void setWrapping(AbstractTexture* texture, const Array3D& wrapping); - static void setStorage(AbstractTexture* texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size) { - (texture->*storage3DImplementation)(target, levels, internalFormat, size); - } + static void setStorage(AbstractTexture* texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference3D& image); #ifndef MAGNUM_TARGET_GLES2 @@ -596,9 +531,7 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> { static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector3i& offset, BufferImage3D& image); #endif - static void invalidateSubImage(AbstractTexture* texture, GLint level, const Vector3i& offset, const Vector3i& size) { - (texture->*invalidateSubImageImplementation)(level, offset, size); - } + static void invalidateSubImage(AbstractTexture* texture, GLint level, const Vector3i& offset, const Vector3i& size); }; #endif diff --git a/src/Magnum/BufferTexture.cpp b/src/Magnum/BufferTexture.cpp index cf9df1ff8..4fbc8af09 100644 --- a/src/Magnum/BufferTexture.cpp +++ b/src/Magnum/BufferTexture.cpp @@ -35,9 +35,6 @@ namespace Magnum { -BufferTexture::SetBufferImplementation BufferTexture::setBufferImplementation = &BufferTexture::setBufferImplementationDefault; -BufferTexture::SetBufferRangeImplementation BufferTexture::setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDefault; - Int BufferTexture::offsetAlignment() { if(!Context::current()->isExtensionSupported()) return 0; @@ -51,13 +48,12 @@ Int BufferTexture::offsetAlignment() { return value; } -void BufferTexture::initializeContextBasedFunctionality(Context& context) { - if(context.isExtensionSupported()) { - Debug() << "BufferTexture: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; +void BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer) { + (this->*Context::current()->state().texture->setBufferImplementation)(internalFormat, buffer); +} - setBufferImplementation = &BufferTexture::setBufferImplementationDSA; - setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDSA; - } +void BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer, const GLintptr offset, const GLsizeiptr size) { + (this->*Context::current()->state().texture->setBufferRangeImplementation)(internalFormat, buffer, offset, size); } void BufferTexture::setBufferImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer) { diff --git a/src/Magnum/BufferTexture.h b/src/Magnum/BufferTexture.h index 3268e00d9..20a0a1ae6 100644 --- a/src/Magnum/BufferTexture.h +++ b/src/Magnum/BufferTexture.h @@ -200,7 +200,7 @@ and respective function documentation for more information. @requires_gl Texture buffers are not available in OpenGL ES. */ class MAGNUM_EXPORT BufferTexture: private AbstractTexture { - friend class Context; + friend class Implementation::TextureState; public: /** @copydoc AbstractTexture::maxLabelLength() */ @@ -244,9 +244,7 @@ class MAGNUM_EXPORT BufferTexture: private AbstractTexture { * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexBuffer} * or @fn_gl_extension{TextureBuffer,EXT,direct_state_access} */ - void setBuffer(BufferTextureFormat internalFormat, Buffer& buffer) { - (this->*setBufferImplementation)(internalFormat, buffer); - } + void setBuffer(BufferTextureFormat internalFormat, Buffer& buffer); /** * @brief Set texture buffer @@ -262,22 +260,14 @@ class MAGNUM_EXPORT BufferTexture: private AbstractTexture { * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexBufferRange} * or @fn_gl_extension{TextureBufferRange,EXT,direct_state_access} */ - void setBuffer(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size) { - (this->*setBufferRangeImplementation)(internalFormat, buffer, offset, size); - } + void setBuffer(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size); private: - static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context); - - typedef void(BufferTexture::*SetBufferImplementation)(BufferTextureFormat, Buffer&); void MAGNUM_LOCAL setBufferImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer); void MAGNUM_LOCAL setBufferImplementationDSA(BufferTextureFormat internalFormat, Buffer& buffer); - static SetBufferImplementation setBufferImplementation; - typedef void(BufferTexture::*SetBufferRangeImplementation)(BufferTextureFormat, Buffer&, GLintptr, GLsizeiptr); void MAGNUM_LOCAL setBufferRangeImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size); void MAGNUM_LOCAL setBufferRangeImplementationDSA(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size); - static SetBufferRangeImplementation setBufferRangeImplementation; }; } diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 732c57e4c..6ca77d85e 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -449,11 +449,7 @@ Context::Context() { /* Initialize functionality based on current OpenGL version and extensions */ AbstractShaderProgram::initializeContextBasedFunctionality(*this); - AbstractTexture::initializeContextBasedFunctionality(*this); Buffer::initializeContextBasedFunctionality(*this); - #ifndef MAGNUM_TARGET_GLES - BufferTexture::initializeContextBasedFunctionality(*this); - #endif DefaultFramebuffer::initializeContextBasedFunctionality(*this); Mesh::initializeContextBasedFunctionality(*this); Renderer::initializeContextBasedFunctionality(*this); diff --git a/src/Magnum/Implementation/State.cpp b/src/Magnum/Implementation/State.cpp index 5ff69fd5d..85fc0721a 100644 --- a/src/Magnum/Implementation/State.cpp +++ b/src/Magnum/Implementation/State.cpp @@ -58,7 +58,7 @@ State::State(Context& context) { renderer = new RendererState; shader = new ShaderState; shaderProgram = new ShaderProgramState; - texture = new TextureState; + texture = new TextureState(context, extensions); /* Sort the features and remove duplicates */ std::sort(extensions.begin(), extensions.end()); diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index 7f07c4664..7bc771d66 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -25,13 +25,144 @@ #include "TextureState.h" +#include "Magnum/AbstractTexture.h" +#ifndef MAGNUM_TARGET_GLES +#include "Magnum/BufferTexture.h" +#endif +#include "Magnum/Context.h" +#include "Magnum/Extensions.h" + namespace Magnum { namespace Implementation { -TextureState::TextureState(): maxMaxAnisotropy(0.0f), currentLayer(0) +TextureState::TextureState(Context& context, std::vector& extensions): maxMaxAnisotropy(0.0f), currentLayer(0) #ifndef MAGNUM_TARGET_GLES , maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0), bufferOffsetAlignment(0) #endif - {} +{ + /* 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; + getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA; + mipmapImplementation = &AbstractTexture::mipmapImplementationDSA; + getImageImplementation = &AbstractTexture::getImageImplementationDSA; + image1DImplementation = &AbstractTexture::imageImplementationDSA; + image2DImplementation = &AbstractTexture::imageImplementationDSA; + image3DImplementation = &AbstractTexture::imageImplementationDSA; + subImage1DImplementation = &AbstractTexture::subImageImplementationDSA; + subImage2DImplementation = &AbstractTexture::subImageImplementationDSA; + subImage3DImplementation = &AbstractTexture::subImageImplementationDSA; + + setBufferImplementation = &BufferTexture::setBufferImplementationDSA; + setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDSA; + } else + #endif + { + bindImplementation = &AbstractTexture::bindImplementationDefault; + parameteriImplementation = &AbstractTexture::parameterImplementationDefault; + parameterfImplementation = &AbstractTexture::parameterImplementationDefault; + parameterfvImplementation = &AbstractTexture::parameterImplementationDefault; + #ifndef MAGNUM_TARGET_GLES + getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDefault; + #endif + mipmapImplementation = &AbstractTexture::mipmapImplementationDefault; + #ifndef MAGNUM_TARGET_GLES + getImageImplementation = &AbstractTexture::getImageImplementationDefault; + image1DImplementation = &AbstractTexture::imageImplementationDefault; + #endif + image2DImplementation = &AbstractTexture::imageImplementationDefault; + image3DImplementation = &AbstractTexture::imageImplementationDefault; + #ifndef MAGNUM_TARGET_GLES + subImage1DImplementation = &AbstractTexture::subImageImplementationDefault; + #endif + subImage2DImplementation = &AbstractTexture::subImageImplementationDefault; + subImage3DImplementation = &AbstractTexture::subImageImplementationDefault; + + #ifndef MAGNUM_TARGET_GLES + setBufferImplementation = &BufferTexture::setBufferImplementationDefault; + setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDefault; + #endif + } + + /* Data invalidation implementation */ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::ARB::invalidate_subdata::string()); + + invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationARB; + invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationARB; + } else + #endif + { + invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationNoOp; + invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationNoOp; + } + + /* Image retrieval implementation */ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported() && + !context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::ARB::robustness::string()); + + getImageImplementation = &AbstractTexture::getImageImplementationRobustness; + } else getImageImplementation = &AbstractTexture::getImageImplementationDefault; + #endif + + /* Texture storage implementation */ + #ifndef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) + #endif + { + #ifndef MAGNUM_TARGET_GLES + extensions.push_back(Extensions::GL::ARB::texture_storage::string()); + #endif + + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + storage1DImplementation = &AbstractTexture::storageImplementationDSA; + storage2DImplementation = &AbstractTexture::storageImplementationDSA; + storage3DImplementation = &AbstractTexture::storageImplementationDSA; + } else + #endif + { + #ifndef MAGNUM_TARGET_GLES + storage1DImplementation = &AbstractTexture::storageImplementationDefault; + #endif + storage2DImplementation = &AbstractTexture::storageImplementationDefault; + storage3DImplementation = &AbstractTexture::storageImplementationDefault; + } + } + #endif + #ifndef MAGNUM_TARGET_GLES3 + #ifndef MAGNUM_TARGET_GLES + else + #endif + { + #ifndef MAGNUM_TARGET_GLES + storage1DImplementation = &AbstractTexture::storageImplementationFallback; + #endif + storage2DImplementation = &AbstractTexture::storageImplementationFallback; + storage3DImplementation = &AbstractTexture::storageImplementationFallback; + } + #endif + + /* Anisotropic filter implementation */ + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::EXT::texture_filter_anisotropic::string()); + + setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationExt; + } else setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationNoOp; + + /* Resize bindings array to hold all possible layers */ + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxLayers); + bindings.resize(maxLayers); +} TextureState::~TextureState() = default; diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index 6eb4cbe23..3b766becb 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -25,16 +25,50 @@ DEALINGS IN THE SOFTWARE. */ +#include #include +#include "Magnum/Magnum.h" #include "Magnum/OpenGL.h" namespace Magnum { namespace Implementation { struct TextureState { - explicit TextureState(); + explicit TextureState(Context& context, std::vector& extensions); ~TextureState(); + void(AbstractTexture::*bindImplementation)(GLint); + void(AbstractTexture::*parameteriImplementation)(GLenum, GLint); + void(AbstractTexture::*parameterfImplementation)(GLenum, GLfloat); + void(AbstractTexture::*parameterfvImplementation)(GLenum, const GLfloat*); + void(AbstractTexture::*setMaxAnisotropyImplementation)(GLfloat); + void(AbstractTexture::*getLevelParameterivImplementation)(GLenum, GLint, GLenum, GLint*); + void(AbstractTexture::*mipmapImplementation)(); + #ifndef MAGNUM_TARGET_GLES + void(AbstractTexture::*storage1DImplementation)(GLenum, GLsizei, TextureFormat, const Math::Vector<1, GLsizei>&); + #endif + void(AbstractTexture::*storage2DImplementation)(GLenum, GLsizei, TextureFormat, const Vector2i&); + void(AbstractTexture::*storage3DImplementation)(GLenum, GLsizei, TextureFormat, const Vector3i&); + #ifndef MAGNUM_TARGET_GLES + void(AbstractTexture::*getImageImplementation)(GLenum, GLint, ColorFormat, ColorType, std::size_t, GLvoid*); + void(AbstractTexture::*image1DImplementation)(GLenum, GLint, TextureFormat, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*); + #endif + void(AbstractTexture::*image2DImplementation)(GLenum, GLint, TextureFormat, const Vector2i&, ColorFormat, ColorType, const GLvoid*); + void(AbstractTexture::*image3DImplementation)(GLenum, GLint, TextureFormat, const Vector3i&, ColorFormat, ColorType, const GLvoid*); + #ifndef MAGNUM_TARGET_GLES + void(AbstractTexture::*subImage1DImplementation)(GLenum, GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*); + #endif + void(AbstractTexture::*subImage2DImplementation)(GLenum, GLint, const Vector2i&, const Vector2i&, ColorFormat, ColorType, const GLvoid*); + void(AbstractTexture::*subImage3DImplementation)(GLenum, GLint, const Vector3i&, const Vector3i&, ColorFormat, ColorType, const GLvoid*); + void(AbstractTexture::*invalidateImageImplementation)(GLint); + void(AbstractTexture::*invalidateSubImageImplementation)(GLint, const Vector3i&, const Vector3i&); + + #ifndef MAGNUM_TARGET_GLES + void(BufferTexture::*setBufferImplementation)(BufferTextureFormat, Buffer&); + void(BufferTexture::*setBufferRangeImplementation)(BufferTextureFormat, Buffer&, GLintptr, GLsizeiptr); + #endif + + GLint maxLayers; GLfloat maxMaxAnisotropy; GLint currentLayer; #ifndef MAGNUM_TARGET_GLES