From 28939078e2fe03d91feb9fa646fab976d7f8af9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 22 Jan 2014 23:55:18 +0100 Subject: [PATCH 01/86] Decide about used extensions on only one place. Having the same branch cascade twice for debug output and for actual feature selection is not good for maintenance. Put the extensions into some list and then make it unique instead. --- src/Magnum/Implementation/DebugState.cpp | 17 ++++++--- src/Magnum/Implementation/DebugState.h | 3 +- src/Magnum/Implementation/State.cpp | 47 ++++++++++++------------ src/Magnum/Implementation/State.h | 16 ++++---- 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/Magnum/Implementation/DebugState.cpp b/src/Magnum/Implementation/DebugState.cpp index 1e514ac54..f030a8689 100644 --- a/src/Magnum/Implementation/DebugState.cpp +++ b/src/Magnum/Implementation/DebugState.cpp @@ -31,8 +31,10 @@ namespace Magnum { namespace Implementation { -DebugState::DebugState(Context& context): maxLabelLength(0), maxLoggedMessages(0), maxMessageLength(0), messageCallback(nullptr) { +DebugState::DebugState(Context& context, std::vector& extensions): maxLabelLength(0), maxLoggedMessages(0), maxMessageLength(0), messageCallback(nullptr) { if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::KHR::debug::string()); + getLabelImplementation = &AbstractObject::getLabelImplementationKhr; labelImplementation = &AbstractObject::labelImplementationKhr; messageInsertImplementation = &DebugMessage::insertImplementationKhr; @@ -40,6 +42,8 @@ DebugState::DebugState(Context& context): maxLabelLength(0), maxLoggedMessages(0 } else { if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::EXT::debug_label::string()); + getLabelImplementation = &AbstractObject::getLabelImplementationExt; labelImplementation = &AbstractObject::labelImplementationExt; } else { @@ -47,14 +51,17 @@ DebugState::DebugState(Context& context): maxLabelLength(0), maxLoggedMessages(0 labelImplementation = &AbstractObject::labelImplementationNoOp; } - if(context.isExtensionSupported()) + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::EXT::debug_marker::string()); + messageInsertImplementation = &DebugMessage::insertImplementationExt; #ifndef MAGNUM_TARGET_GLES - else if(context.isExtensionSupported()) + } else if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::GREMEDY::string_marker::string()); + messageInsertImplementation = &DebugMessage::insertImplementationGremedy; #endif - else - messageInsertImplementation = &DebugMessage::insertImplementationNoOp; + } else messageInsertImplementation = &DebugMessage::insertImplementationNoOp; messageCallbackImplementation = &DebugMessage::callbackImplementationNoOp; } diff --git a/src/Magnum/Implementation/DebugState.h b/src/Magnum/Implementation/DebugState.h index 95955e1c2..a435e1b20 100644 --- a/src/Magnum/Implementation/DebugState.h +++ b/src/Magnum/Implementation/DebugState.h @@ -26,13 +26,14 @@ */ #include +#include #include "Magnum/DebugMessage.h" namespace Magnum { namespace Implementation { struct DebugState { - DebugState(Context& context); + explicit DebugState(Context& context, std::vector& extensions); std::string(*getLabelImplementation)(GLenum, GLuint); void(*labelImplementation)(GLenum, GLuint, const std::string&); diff --git a/src/Magnum/Implementation/State.cpp b/src/Magnum/Implementation/State.cpp index 015773280..62ee567f1 100644 --- a/src/Magnum/Implementation/State.cpp +++ b/src/Magnum/Implementation/State.cpp @@ -25,6 +25,8 @@ #include "State.h" +#include + #include "Magnum/Context.h" #include "Magnum/Extensions.h" @@ -39,32 +41,31 @@ namespace Magnum { namespace Implementation { -State::State(Context& context): - buffer(new BufferState), - debug(new DebugState(context)), - framebuffer(new FramebufferState), - mesh(new MeshState), - renderer(new RendererState), - shader(new ShaderState), - shaderProgram(new ShaderProgramState), - texture(new TextureState) -{ +State::State(Context& context) { + /* List of extensions used in current context. Guesstimate count to avoid + unnecessary reallocations. */ + std::vector extensions; + #ifndef MAGNUM_TARGET_GLES + extensions.reserve(32); + #else + extensions.reserve(8); + #endif - Debug() << "Using optional features:"; + buffer = new BufferState; + debug = new DebugState(context, extensions); + framebuffer = new FramebufferState; + mesh = new MeshState; + renderer = new RendererState; + shader = new ShaderState; + shaderProgram = new ShaderProgramState; + texture = new TextureState; - if(context.isExtensionSupported()) - Debug() << " " << Extensions::GL::KHR::debug::string(); - else { - if(context.isExtensionSupported()) - Debug() << " " << Extensions::GL::EXT::debug_label::string(); + /* Sort the features and remove duplicates */ + std::sort(extensions.begin(), extensions.end()); + extensions.erase(std::unique(extensions.begin(), extensions.end()), extensions.end()); - if(context.isExtensionSupported()) - Debug() << " " << Extensions::GL::EXT::debug_marker::string(); - #ifndef MAGNUM_TARGET_GLES - else if(context.isExtensionSupported()) - Debug() << " " << Extensions::GL::GREMEDY::string_marker::string(); - #endif - } + Debug() << "Using optional features:"; + for(const auto& ext: extensions) Debug() << " " << ext; } State::~State() { diff --git a/src/Magnum/Implementation/State.h b/src/Magnum/Implementation/State.h index 61f34a546..207594cd2 100644 --- a/src/Magnum/Implementation/State.h +++ b/src/Magnum/Implementation/State.h @@ -44,14 +44,14 @@ struct State { ~State(); - BufferState* const buffer; - DebugState* const debug; - FramebufferState* const framebuffer; - MeshState* const mesh; - RendererState* const renderer; - ShaderState* const shader; - ShaderProgramState* const shaderProgram; - TextureState* const texture; + BufferState* buffer; + DebugState* debug; + FramebufferState* framebuffer; + MeshState* mesh; + RendererState* renderer; + ShaderState* shader; + ShaderProgramState* shaderProgram; + TextureState* texture; }; }} From c1c71339e428165385efecf253d1bbf1854845f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 01:06:12 +0100 Subject: [PATCH 02/86] Moved global data from framebuffer classes to per-context state. On the way to unify and reduce the "Using optional features" messages. --- src/Magnum/AbstractFramebuffer.cpp | 83 ++--------- src/Magnum/AbstractFramebuffer.h | 25 +--- src/Magnum/CMakeLists.txt | 1 + src/Magnum/Context.cpp | 3 - src/Magnum/DefaultFramebuffer.cpp | 16 +- src/Magnum/DefaultFramebuffer.h | 14 +- src/Magnum/Framebuffer.cpp | 57 ++++--- src/Magnum/Framebuffer.h | 47 +----- .../Implementation/FramebufferState.cpp | 141 ++++++++++++++++++ src/Magnum/Implementation/FramebufferState.h | 32 +++- src/Magnum/Implementation/State.cpp | 2 +- src/Magnum/Renderbuffer.cpp | 39 +---- src/Magnum/Renderbuffer.h | 24 +-- 13 files changed, 257 insertions(+), 227 deletions(-) create mode 100644 src/Magnum/Implementation/FramebufferState.cpp diff --git a/src/Magnum/AbstractFramebuffer.cpp b/src/Magnum/AbstractFramebuffer.cpp index 8eb210fa2..9500c4b7f 100644 --- a/src/Magnum/AbstractFramebuffer.cpp +++ b/src/Magnum/AbstractFramebuffer.cpp @@ -37,19 +37,6 @@ namespace Magnum { -AbstractFramebuffer::CheckStatusImplementation AbstractFramebuffer::checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDefault; - -AbstractFramebuffer::ReadImplementation AbstractFramebuffer::readImplementation = &AbstractFramebuffer::readImplementationDefault; - -AbstractFramebuffer::DrawBuffersImplementation AbstractFramebuffer::drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDefault; -AbstractFramebuffer::DrawBufferImplementation AbstractFramebuffer::drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDefault; -AbstractFramebuffer::ReadBufferImplementation AbstractFramebuffer::readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDefault; - -#ifdef MAGNUM_TARGET_GLES2 -FramebufferTarget AbstractFramebuffer::readTarget = FramebufferTarget::ReadDraw; -FramebufferTarget AbstractFramebuffer::drawTarget = FramebufferTarget::ReadDraw; -#endif - Vector2i AbstractFramebuffer::maxViewportSize() { Vector2i& value = Context::current()->state().framebuffer->maxViewportSize; @@ -136,9 +123,9 @@ FramebufferTarget AbstractFramebuffer::bindInternal() { glBindFramebuffer(GLenum(FramebufferTarget::Read), _id); return FramebufferTarget::Read; #else - if(readTarget == FramebufferTarget::ReadDraw) state->drawBinding = _id; - glBindFramebuffer(GLenum(readTarget), _id); - return readTarget; + if(state->readTarget == FramebufferTarget::ReadDraw) state->drawBinding = _id; + glBindFramebuffer(GLenum(state->readTarget), _id); + return state->readTarget; #endif } @@ -186,20 +173,22 @@ void AbstractFramebuffer::clear(FramebufferClearMask mask) { #ifndef MAGNUM_TARGET_GLES2 bindInternal(FramebufferTarget::Draw); #else - bindInternal(drawTarget); + bindInternal(Context::current()->state().framebuffer->drawTarget); #endif glClear(GLbitfield(mask)); } void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Image2D& image) { + const Implementation::FramebufferState& state = *Context::current()->state().framebuffer; + #ifndef MAGNUM_TARGET_GLES2 bindInternal(FramebufferTarget::Read); #else - bindInternal(readTarget); + bindInternal(state.readTarget); #endif const std::size_t dataSize = image.dataSize(size); char* const data = new char[dataSize]; - readImplementation(offset, size, image.format(), image.type(), dataSize, data); + (state.readImplementation)(offset, size, image.format(), image.type(), dataSize, data); image.setData(image.format(), image.type(), size, data); } @@ -216,7 +205,7 @@ void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Buf image.setData(image.format(), image.type(), size, nullptr, usage); image.buffer().bind(Buffer::Target::PixelPack); - readImplementation(offset, size, image.format(), image.type(), image.dataSize(size), nullptr); + (Context::current()->state().framebuffer->readImplementation)(offset, size, image.format(), image.type(), image.dataSize(size), nullptr); } #endif @@ -245,60 +234,6 @@ void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attach #endif } -void AbstractFramebuffer::initializeContextBasedFunctionality(Context& context) { - #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) { - Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; - - checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA; - drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA; - drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA; - readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA; - } - #endif - - #ifdef MAGNUM_TARGET_GLES2 - /* Optimistically set separate binding targets and check if one of the - extensions providing them is available */ - readTarget = FramebufferTarget::Read; - drawTarget = FramebufferTarget::Draw; - - if(context.isExtensionSupported()) - Debug() << "AbstractFramebuffer: using" << Extensions::GL::ANGLE::framebuffer_blit::string() << "features"; - - else if(context.isExtensionSupported()) - Debug() << "AbstractFramebuffer: using" << Extensions::GL::APPLE::framebuffer_multisample::string() << "features"; - - else if(context.isExtensionSupported()) - Debug() << "AbstractFramebuffer: using" << Extensions::GL::NV::framebuffer_blit::string() << "features"; - - /* NV_framebuffer_multisample requires NV_framebuffer_blit, which has these - enums. However, on my system only NV_framebuffer_multisample is - supported, but NV_framebuffer_blit isn't. I will hold my breath and - assume these enums are available. */ - else if(context.isExtensionSupported()) - Debug() << "AbstractFramebuffer: using" << Extensions::GL::NV::framebuffer_multisample::string() << "features"; - - /* If no such extension is available, reset back to unified target */ - else readTarget = drawTarget = FramebufferTarget::ReadDraw; - #endif - - #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) - #else - if(context.isExtensionSupported()) - #endif - { - #ifndef MAGNUM_TARGET_GLES - Debug() << "AbstractFramebuffer: using" << Extensions::GL::ARB::robustness::string() << "features"; - #else - Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::robustness::string() << "features"; - #endif - - readImplementation = &AbstractFramebuffer::readImplementationRobustness; - } -} - GLenum AbstractFramebuffer::checkStatusImplementationDefault(const FramebufferTarget target) { bindInternal(target); return glCheckFramebufferStatus(GLenum(target)); diff --git a/src/Magnum/AbstractFramebuffer.h b/src/Magnum/AbstractFramebuffer.h index 8502203c6..8904ebb5f 100644 --- a/src/Magnum/AbstractFramebuffer.h +++ b/src/Magnum/AbstractFramebuffer.h @@ -127,6 +127,8 @@ enum class FramebufferTarget: GLenum { ReadDraw = GL_FRAMEBUFFER /**< For both reading and drawing. */ }; +namespace Implementation { struct FramebufferState; } + /** @brief Base for default and named framebuffers @@ -145,7 +147,7 @@ protected from buffer overflow. @todo @extension{ARB,viewport_array} (and `GL_MAX_VIEWPORTS`) */ class MAGNUM_EXPORT AbstractFramebuffer { - friend class Context; + friend class Implementation::FramebufferState; public: /** @todo `GL_IMPLEMENTATION_COLOR_READ_FORMAT`, `GL_IMPLEMENTATION_COLOR_READ_TYPE`, seems to be depending on currently bound FB (aargh) (@extension{ARB,ES2_compatibility}). */ @@ -311,23 +313,6 @@ class MAGNUM_EXPORT AbstractFramebuffer { FramebufferTarget MAGNUM_LOCAL bindInternal(); void MAGNUM_LOCAL setViewportInternal(); - #ifdef MAGNUM_TARGET_GLES2 - static MAGNUM_LOCAL FramebufferTarget readTarget; - static MAGNUM_LOCAL FramebufferTarget drawTarget; - #endif - - typedef GLenum(AbstractFramebuffer::*CheckStatusImplementation)(FramebufferTarget); - static CheckStatusImplementation checkStatusImplementation; - - typedef void(AbstractFramebuffer::*DrawBuffersImplementation)(GLsizei, const GLenum*); - static MAGNUM_LOCAL DrawBuffersImplementation drawBuffersImplementation; - - typedef void(AbstractFramebuffer::*DrawBufferImplementation)(GLenum); - static DrawBufferImplementation drawBufferImplementation; - - typedef void(AbstractFramebuffer::*ReadBufferImplementation)(GLenum); - static ReadBufferImplementation readBufferImplementation; - void MAGNUM_LOCAL invalidateImplementation(GLsizei count, GLenum* attachments); void MAGNUM_LOCAL invalidateImplementation(GLsizei count, GLenum* attachments, const Range2Di& rectangle); @@ -335,8 +320,6 @@ class MAGNUM_EXPORT AbstractFramebuffer { Range2Di _viewport; private: - static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context); - GLenum MAGNUM_LOCAL checkStatusImplementationDefault(FramebufferTarget target); #ifndef MAGNUM_TARGET_GLES GLenum MAGNUM_LOCAL checkStatusImplementationDSA(FramebufferTarget target); @@ -357,10 +340,8 @@ class MAGNUM_EXPORT AbstractFramebuffer { void MAGNUM_LOCAL readBufferImplementationDSA(GLenum buffer); #endif - typedef void(*ReadImplementation)(const Vector2i&, const Vector2i&, ColorFormat, ColorType, std::size_t, GLvoid*); static void MAGNUM_LOCAL readImplementationDefault(const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); static void MAGNUM_LOCAL readImplementationRobustness(const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); - static ReadImplementation MAGNUM_LOCAL readImplementation; }; CORRADE_ENUMSET_OPERATORS(FramebufferClearMask) diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index b688a1f46..fd98022fe 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -54,6 +54,7 @@ set(Magnum_SRCS Implementation/BufferState.cpp Implementation/DebugState.cpp + Implementation/FramebufferState.cpp Implementation/State.cpp Implementation/TextureState.cpp diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index e7abb8e15..732c57e4c 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -448,7 +448,6 @@ Context::Context() { _state = new Implementation::State(*this); /* Initialize functionality based on current OpenGL version and extensions */ - AbstractFramebuffer::initializeContextBasedFunctionality(*this); AbstractShaderProgram::initializeContextBasedFunctionality(*this); AbstractTexture::initializeContextBasedFunctionality(*this); Buffer::initializeContextBasedFunctionality(*this); @@ -456,9 +455,7 @@ Context::Context() { BufferTexture::initializeContextBasedFunctionality(*this); #endif DefaultFramebuffer::initializeContextBasedFunctionality(*this); - Framebuffer::initializeContextBasedFunctionality(*this); Mesh::initializeContextBasedFunctionality(*this); - Renderbuffer::initializeContextBasedFunctionality(*this); Renderer::initializeContextBasedFunctionality(*this); } diff --git a/src/Magnum/DefaultFramebuffer.cpp b/src/Magnum/DefaultFramebuffer.cpp index b9eb7b4ab..f2990e3f5 100644 --- a/src/Magnum/DefaultFramebuffer.cpp +++ b/src/Magnum/DefaultFramebuffer.cpp @@ -38,6 +38,10 @@ DefaultFramebuffer defaultFramebuffer; DefaultFramebuffer::DefaultFramebuffer() { _id = 0; } +DefaultFramebuffer::Status DefaultFramebuffer::checkStatus(const FramebufferTarget target) { + return Status((this->*Context::current()->state().framebuffer->checkStatusImplementation)(target)); +} + #ifndef MAGNUM_TARGET_GLES2 DefaultFramebuffer& DefaultFramebuffer::mapForDraw(std::initializer_list> attachments) { /* Max attachment location */ @@ -52,11 +56,21 @@ DefaultFramebuffer& DefaultFramebuffer::mapForDraw(std::initializer_list*drawBuffersImplementation)(max+1, _attachments); + (this->*Context::current()->state().framebuffer->drawBuffersImplementation)(max+1, _attachments); + return *this; +} + +DefaultFramebuffer& DefaultFramebuffer::mapForDraw(const DrawAttachment attachment) { + (this->*Context::current()->state().framebuffer->drawBufferImplementation)(GLenum(attachment)); return *this; } #endif +DefaultFramebuffer& DefaultFramebuffer::mapForRead(const ReadAttachment attachment) { + (this->*Context::current()->state().framebuffer->readBufferImplementation)(GLenum(attachment)); + return *this; +} + void DefaultFramebuffer::invalidate(std::initializer_list attachments) { /** @todo C++14: use VLA to avoid heap allocation */ Containers::Array _attachments(attachments.size()); diff --git a/src/Magnum/DefaultFramebuffer.h b/src/Magnum/DefaultFramebuffer.h index bbd55ca0a..61276f675 100644 --- a/src/Magnum/DefaultFramebuffer.h +++ b/src/Magnum/DefaultFramebuffer.h @@ -316,9 +316,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access} * @requires_gl30 %Extension @extension{ARB,framebuffer_object} */ - Status checkStatus(FramebufferTarget target) { - return Status((this->*checkStatusImplementation)(target)); - } + Status checkStatus(FramebufferTarget target); #ifndef MAGNUM_TARGET_GLES2 /** @@ -362,10 +360,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * @requires_gles30 Draw attachments for default framebuffer are * available only in OpenGL ES 3.0. */ - DefaultFramebuffer& mapForDraw(DrawAttachment attachment) { - (this->*drawBufferImplementation)(GLenum(attachment)); - return *this; - } + DefaultFramebuffer& mapForDraw(DrawAttachment attachment); #endif /** @@ -380,10 +375,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access} * @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} */ - DefaultFramebuffer& mapForRead(ReadAttachment attachment) { - (this->*readBufferImplementation)(GLenum(attachment)); - return *this; - } + DefaultFramebuffer& mapForRead(ReadAttachment attachment); /** * @brief Invalidate framebuffer diff --git a/src/Magnum/Framebuffer.cpp b/src/Magnum/Framebuffer.cpp index e6b73894d..141877e8a 100644 --- a/src/Magnum/Framebuffer.cpp +++ b/src/Magnum/Framebuffer.cpp @@ -42,13 +42,6 @@ namespace Magnum { -Framebuffer::RenderbufferImplementation Framebuffer::renderbufferImplementation = &Framebuffer::renderbufferImplementationDefault; -#ifndef MAGNUM_TARGET_GLES -Framebuffer::Texture1DImplementation Framebuffer::texture1DImplementation = &Framebuffer::texture1DImplementationDefault; -#endif -Framebuffer::Texture2DImplementation Framebuffer::texture2DImplementation = &Framebuffer::texture2DImplementationDefault; -Framebuffer::Texture3DImplementation Framebuffer::texture3DImplementation = &Framebuffer::texture3DImplementationDefault; - const Framebuffer::DrawAttachment Framebuffer::DrawAttachment::None = Framebuffer::DrawAttachment(GL_NONE); const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::Depth = Framebuffer::BufferAttachment(GL_DEPTH_ATTACHMENT); const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::Stencil = Framebuffer::BufferAttachment(GL_STENCIL_ATTACHMENT); @@ -104,6 +97,10 @@ Framebuffer& Framebuffer::setLabel(const std::string& label) { return *this; } +Framebuffer::Status Framebuffer::checkStatus(const FramebufferTarget target) { + return Status((this->*Context::current()->state().framebuffer->checkStatusImplementation)(target)); +} + Framebuffer& Framebuffer::mapForDraw(std::initializer_list> attachments) { /* Max attachment location */ std::size_t max = 0; @@ -117,7 +114,17 @@ Framebuffer& Framebuffer::mapForDraw(std::initializer_list*drawBuffersImplementation)(max+1, _attachments); + (this->*Context::current()->state().framebuffer->drawBuffersImplementation)(max+1, _attachments); + return *this; +} + +Framebuffer& Framebuffer::mapForDraw(const DrawAttachment attachment) { + (this->*Context::current()->state().framebuffer->drawBufferImplementation)(GLenum(attachment)); + return *this; +} + +Framebuffer& Framebuffer::mapForRead(const ColorAttachment attachment) { + (this->*Context::current()->state().framebuffer->readBufferImplementation)(GLenum(attachment)); return *this; } @@ -139,25 +146,33 @@ void Framebuffer::invalidate(std::initializer_list attac invalidateImplementation(attachments.size(), _attachments, rectangle); } +Framebuffer& Framebuffer::attachRenderbuffer(const BufferAttachment attachment, Renderbuffer& renderbuffer) { + (this->*Context::current()->state().framebuffer->renderbufferImplementation)(attachment, renderbuffer); + return *this; +} + +#ifndef MAGNUM_TARGET_GLES +Framebuffer& Framebuffer::attachTexture1D(const BufferAttachment attachment, Texture1D& texture, const Int level) { + (this->*Context::current()->state().framebuffer->texture1DImplementation)(attachment, texture, level); + return *this; +} +#endif + Framebuffer& Framebuffer::attachTexture2D(BufferAttachment attachment, Texture2D& texture, Int mipLevel) { /** @todo Check for texture target compatibility */ - (this->*texture2DImplementation)(attachment, GLenum(texture.target()), texture.id(), mipLevel); + (this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GLenum(texture.target()), texture.id(), mipLevel); return *this; } -void Framebuffer::initializeContextBasedFunctionality(Context& context) { - #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) { - Debug() << "Framebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; +Framebuffer& Framebuffer::attachCubeMapTexture(const BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, const Int level) { + (this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GLenum(coordinate), texture.id(), level); + return *this; +} - renderbufferImplementation = &Framebuffer::renderbufferImplementationDSA; - texture1DImplementation = &Framebuffer::texture1DImplementationDSA; - texture2DImplementation = &Framebuffer::texture2DImplementationDSA; - texture3DImplementation = &Framebuffer::texture3DImplementationDSA; - } - #else - static_cast(context); - #endif +Framebuffer& Framebuffer::attachTexture3D(Framebuffer::BufferAttachment attachment, Texture3D& texture, Int level, Int layer) { + /** @todo Check for texture target compatibility */ + (this->*Context::current()->state().framebuffer->texture3DImplementation)(attachment, texture, level, layer); + return *this; } void Framebuffer::renderbufferImplementationDefault(BufferAttachment attachment, Renderbuffer& renderbuffer) { diff --git a/src/Magnum/Framebuffer.h b/src/Magnum/Framebuffer.h index ff07280a5..ed984ab45 100644 --- a/src/Magnum/Framebuffer.h +++ b/src/Magnum/Framebuffer.h @@ -102,7 +102,7 @@ See their respective documentation for more information. @todo `MAX_COLOR_ATTACHMENTS` */ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObject { - friend class Context; + friend class Implementation::FramebufferState; public: /** @@ -364,9 +364,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @see @fn_gl{BindFramebuffer}, @fn_gl{CheckFramebufferStatus} or * @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access} */ - Status checkStatus(FramebufferTarget target) { - return Status((this->*checkStatusImplementation)(target)); - } + Status checkStatus(FramebufferTarget target); /** * @brief Map shader output to attachments @@ -409,10 +407,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @fn_gl{DrawBuffers} in OpenGL ES 3.0 * @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers} */ - Framebuffer& mapForDraw(DrawAttachment attachment) { - (this->*drawBufferImplementation)(GLenum(attachment)); - return *this; - } + Framebuffer& mapForDraw(DrawAttachment attachment); /** * @brief Map given color attachment for reading @@ -426,10 +421,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * or @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access} * @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} */ - Framebuffer& mapForRead(ColorAttachment attachment) { - (this->*readBufferImplementation)(GLenum(attachment)); - return *this; - } + Framebuffer& mapForRead(ColorAttachment attachment); /** * @brief Invalidate framebuffer @@ -478,10 +470,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @see @fn_gl{BindFramebuffer}, @fn_gl{FramebufferRenderbuffer} or * @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access} */ - Framebuffer& attachRenderbuffer(BufferAttachment attachment, Renderbuffer& renderbuffer) { - (this->*renderbufferImplementation)(attachment, renderbuffer); - return *this; - } + Framebuffer& attachRenderbuffer(BufferAttachment attachment, Renderbuffer& renderbuffer); #ifndef MAGNUM_TARGET_GLES /** @@ -498,10 +487,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * or @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access} * @requires_gl Only 2D and 3D textures are available in OpenGL ES. */ - Framebuffer& attachTexture1D(BufferAttachment attachment, Texture1D& texture, Int level) { - (this->*texture1DImplementation)(attachment, texture, level); - return *this; - } + Framebuffer& attachTexture1D(BufferAttachment attachment, Texture1D& texture, Int level); #endif /** @@ -535,10 +521,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @fn_gl2{FramebufferTexture2D,FramebufferTexture} or * @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access} */ - Framebuffer& attachCubeMapTexture(BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, Int level) { - (this->*texture2DImplementation)(attachment, GLenum(coordinate), texture.id(), level); - return *this; - } + Framebuffer& attachCubeMapTexture(BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, Int level); /** * @brief Attach 3D texture to given buffer @@ -555,11 +538,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * or @fn_gl_extension{NamedFramebufferTexture3D,EXT,direct_state_access} * @requires_es_extension %Extension @es_extension{OES,texture_3D} */ - Framebuffer& attachTexture3D(BufferAttachment attachment, Texture3D& texture, Int level, Int layer) { - /** @todo Check for texture target compatibility */ - (this->*texture3DImplementation)(attachment, texture, level, layer); - return *this; - } + Framebuffer& attachTexture3D(BufferAttachment attachment, Texture3D& texture, Int level, Int layer); /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT @@ -570,35 +549,25 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje #endif private: - static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context); - - typedef void(Framebuffer::*RenderbufferImplementation)(BufferAttachment, Renderbuffer&); void MAGNUM_LOCAL renderbufferImplementationDefault(BufferAttachment attachment, Renderbuffer& renderbuffer); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL renderbufferImplementationDSA(BufferAttachment attachment, Renderbuffer& renderbuffer); #endif - static RenderbufferImplementation renderbufferImplementation; #ifndef MAGNUM_TARGET_GLES - typedef void(Framebuffer::*Texture1DImplementation)(BufferAttachment, Texture1D&, GLint); void MAGNUM_LOCAL texture1DImplementationDefault(BufferAttachment attachment, Texture1D& texture, GLint level); void MAGNUM_LOCAL texture1DImplementationDSA(BufferAttachment attachment, Texture1D& texture, GLint level); - static Texture1DImplementation texture1DImplementation; #endif - typedef void(Framebuffer::*Texture2DImplementation)(BufferAttachment, GLenum, GLuint, GLint); void MAGNUM_LOCAL texture2DImplementationDefault(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL texture2DImplementationDSA(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level); #endif - static Texture2DImplementation texture2DImplementation; - typedef void(Framebuffer::*Texture3DImplementation)(BufferAttachment, Texture3D&, GLint, GLint); void MAGNUM_LOCAL texture3DImplementationDefault(BufferAttachment attachment, Texture3D& texture, GLint level, GLint layer); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL texture3DImplementationDSA(BufferAttachment attachment, Texture3D& texture, GLint level, GLint layer); #endif - static Texture3DImplementation texture3DImplementation; }; /** @debugoperator{DefaultFramebuffer} */ diff --git a/src/Magnum/Implementation/FramebufferState.cpp b/src/Magnum/Implementation/FramebufferState.cpp new file mode 100644 index 000000000..5ef927e74 --- /dev/null +++ b/src/Magnum/Implementation/FramebufferState.cpp @@ -0,0 +1,141 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "FramebufferState.h" + +#include "Magnum/Context.h" +#include "Magnum/Extensions.h" +#include "Magnum/Renderbuffer.h" + +namespace Magnum { namespace Implementation { + +FramebufferState::FramebufferState(Context& context, std::vector& extensions): readBinding(0), drawBinding(0), renderbufferBinding(0), maxDrawBuffers(0), maxColorAttachments(0), maxRenderbufferSize(0), maxSamples(0) + #ifndef MAGNUM_TARGET_GLES + , maxDualSourceDrawBuffers(0) + #endif +{ + /* DSA/non-DSA implementation */ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); + + checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA; + drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA; + drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA; + readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA; + + renderbufferImplementation = &Framebuffer::renderbufferImplementationDSA; + texture1DImplementation = &Framebuffer::texture1DImplementationDSA; + texture2DImplementation = &Framebuffer::texture2DImplementationDSA; + texture3DImplementation = &Framebuffer::texture3DImplementationDSA; + + renderbufferStorageImplementation = &Renderbuffer::storageImplementationDSA; + } else + #endif + { + checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDefault; + drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDefault; + drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDefault; + readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDefault; + + renderbufferImplementation = &Framebuffer::renderbufferImplementationDefault; + #ifndef MAGNUM_TARGET_GLES + texture1DImplementation = &Framebuffer::texture1DImplementationDefault; + #endif + texture2DImplementation = &Framebuffer::texture2DImplementationDefault; + texture3DImplementation = &Framebuffer::texture3DImplementationDefault; + + renderbufferStorageImplementation = &Renderbuffer::storageImplementationDefault; + } + + /* Framebuffer binding on ES2 */ + #ifdef MAGNUM_TARGET_GLES2 + /* Optimistically set separate binding targets and check if one of the + extensions providing them is available */ + readTarget = FramebufferTarget::Read; + drawTarget = FramebufferTarget::Draw; + + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::ANGLE::framebuffer_blit::string()); + + } else if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::APPLE::framebuffer_multisample::string()); + + } else if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::NV::framebuffer_blit::string()); + + /* NV_framebuffer_multisample requires NV_framebuffer_blit, which has these + enums. However, on my system only NV_framebuffer_multisample is + supported, but NV_framebuffer_blit isn't. I will hold my breath and + assume these enums are available. */ + } else if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::NV::framebuffer_multisample::string()); + + /* If no such extension is available, reset back to unified target */ + } else readTarget = drawTarget = FramebufferTarget::ReadDraw; + #endif + + /* Framebuffer reading implementation */ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) + #else + if(context.isExtensionSupported()) + #endif + { + #ifndef MAGNUM_TARGET_GLES + extensions.push_back(Extensions::GL::ARB::robustness::string()); + #else + extensions.push_back(Extensions::GL::EXT::robustness::string()); + #endif + + readImplementation = &AbstractFramebuffer::readImplementationRobustness; + } else readImplementation = &AbstractFramebuffer::readImplementationDefault; + + /* Multisample renderbuffer storage implementation */ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + /* Extension added above */ + + renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDSA; + } else + #endif + { + #ifdef MAGNUM_TARGET_GLES2 + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::ANGLE::framebuffer_multisample::string()); + + renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationANGLE; + } else if (context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::NV::framebuffer_multisample::string()); + + renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationNV; + } else renderbufferStorageMultisampleImplementation = nullptr; + #else + renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDefault; + #endif + } +} + +}} diff --git a/src/Magnum/Implementation/FramebufferState.h b/src/Magnum/Implementation/FramebufferState.h index b3556f8b0..9df8a9bb3 100644 --- a/src/Magnum/Implementation/FramebufferState.h +++ b/src/Magnum/Implementation/FramebufferState.h @@ -25,18 +25,34 @@ DEALINGS IN THE SOFTWARE. */ -#include "Magnum/Magnum.h" -#include "Magnum/OpenGL.h" -#include "Magnum/Math/Range.h" +#include +#include + +#include "Magnum/Framebuffer.h" namespace Magnum { namespace Implementation { struct FramebufferState { - constexpr FramebufferState(): readBinding(0), drawBinding(0), renderbufferBinding(0), maxDrawBuffers(0), maxColorAttachments(0), maxRenderbufferSize(0), maxSamples(0) - #ifndef MAGNUM_TARGET_GLES - , maxDualSourceDrawBuffers(0) - #endif - {} + explicit FramebufferState(Context& context, std::vector& extensions); + + GLenum(AbstractFramebuffer::*checkStatusImplementation)(FramebufferTarget); + void(AbstractFramebuffer::*drawBuffersImplementation)(GLsizei, const GLenum*); + void(AbstractFramebuffer::*drawBufferImplementation)(GLenum); + void(AbstractFramebuffer::*readBufferImplementation)(GLenum); + + void(Framebuffer::*renderbufferImplementation)(Framebuffer::BufferAttachment, Renderbuffer&); + #ifndef MAGNUM_TARGET_GLES + void(Framebuffer::*texture1DImplementation)(Framebuffer::BufferAttachment, Texture1D&, GLint); + #endif + void(Framebuffer::*texture2DImplementation)(Framebuffer::BufferAttachment, GLenum, GLuint, GLint); + void(Framebuffer::*texture3DImplementation)(Framebuffer::BufferAttachment, Texture3D&, GLint, GLint); + + void(Renderbuffer::*renderbufferStorageImplementation)(RenderbufferFormat, const Vector2i&); + void(Renderbuffer::*renderbufferStorageMultisampleImplementation)(GLsizei, RenderbufferFormat, const Vector2i&); + + void(*readImplementation)(const Vector2i&, const Vector2i&, ColorFormat, ColorType, std::size_t, GLvoid*); + + FramebufferTarget readTarget, drawTarget; GLuint readBinding, drawBinding, renderbufferBinding; GLint maxDrawBuffers, maxColorAttachments, maxRenderbufferSize, maxSamples; diff --git a/src/Magnum/Implementation/State.cpp b/src/Magnum/Implementation/State.cpp index 62ee567f1..5ff69fd5d 100644 --- a/src/Magnum/Implementation/State.cpp +++ b/src/Magnum/Implementation/State.cpp @@ -53,7 +53,7 @@ State::State(Context& context) { buffer = new BufferState; debug = new DebugState(context, extensions); - framebuffer = new FramebufferState; + framebuffer = new FramebufferState(context, extensions); mesh = new MeshState; renderer = new RendererState; shader = new ShaderState; diff --git a/src/Magnum/Renderbuffer.cpp b/src/Magnum/Renderbuffer.cpp index 12f27a53a..47a99b4bb 100644 --- a/src/Magnum/Renderbuffer.cpp +++ b/src/Magnum/Renderbuffer.cpp @@ -34,14 +34,6 @@ namespace Magnum { -Renderbuffer::StorageImplementation Renderbuffer::storageImplementation = &Renderbuffer::storageImplementationDefault; -Renderbuffer::StorageMultisampleImplementation Renderbuffer::storageMultisampleImplementation = - #ifndef MAGNUM_TARGET_GLES2 - &Renderbuffer::storageMultisampleImplementationDefault; - #else - nullptr; - #endif - Int Renderbuffer::maxSize() { GLint& value = Context::current()->state().framebuffer->maxRenderbufferSize; @@ -94,6 +86,14 @@ Renderbuffer& Renderbuffer::setLabel(const std::string& label) { return *this; } +void Renderbuffer::setStorage(const RenderbufferFormat internalFormat, const Vector2i& size) { + (this->*Context::current()->state().framebuffer->renderbufferStorageImplementation)(internalFormat, size); +} + +void Renderbuffer::setStorageMultisample(const Int samples, const RenderbufferFormat internalFormat, const Vector2i& size) { + (this->*Context::current()->state().framebuffer->renderbufferStorageMultisampleImplementation)(samples, internalFormat, size); +} + void Renderbuffer::bind() { GLuint& binding = Context::current()->state().framebuffer->renderbufferBinding; @@ -103,29 +103,6 @@ void Renderbuffer::bind() { glBindRenderbuffer(GL_RENDERBUFFER, _id); } -void Renderbuffer::initializeContextBasedFunctionality(Context& context) { - #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) { - Debug() << "Renderbuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; - - storageImplementation = &Renderbuffer::storageImplementationDSA; - storageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDSA; - } - #elif !defined(MAGNUM_TARGET_GLES3) - if(context.isExtensionSupported()) { - Debug() << "Renderbuffer: using" << Extensions::GL::ANGLE::framebuffer_multisample::string() << "features"; - - storageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationANGLE; - } else if (context.isExtensionSupported()) { - Debug() << "Renderbuffer: using" << Extensions::GL::NV::framebuffer_multisample::string() << "features"; - - storageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationNV; - } - #else - static_cast(context); - #endif -} - void Renderbuffer::storageImplementationDefault(RenderbufferFormat internalFormat, const Vector2i& size) { bind(); glRenderbufferStorage(GL_RENDERBUFFER, GLenum(internalFormat), size.x(), size.y()); diff --git a/src/Magnum/Renderbuffer.h b/src/Magnum/Renderbuffer.h index 36ae950b8..6bf754d1f 100644 --- a/src/Magnum/Renderbuffer.h +++ b/src/Magnum/Renderbuffer.h @@ -34,6 +34,8 @@ namespace Magnum { +namespace Implementation { struct FramebufferState; } + /** @brief %Renderbuffer @@ -54,7 +56,7 @@ See its documentation for more information. @requires_gl30 %Extension @extension{ARB,framebuffer_object} */ class MAGNUM_EXPORT Renderbuffer: public AbstractObject { - friend class Context; + friend class Implementation::FramebufferState; public: /** @@ -146,9 +148,7 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject { * @see @ref maxSize(), @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} * or @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access} */ - void setStorage(RenderbufferFormat internalFormat, const Vector2i& size) { - (this->*storageImplementation)(internalFormat, size); - } + void setStorage(RenderbufferFormat internalFormat, const Vector2i& size); /** * @brief Set multisample renderbuffer storage @@ -166,31 +166,23 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject { * @todo How about @es_extension{APPLE,framebuffer_multisample}? * @todo NaCl has @fn_gl_extension{RenderbufferStorageMultisample,EXT,multisampled_render_to_texture} */ - void setStorageMultisample(Int samples, RenderbufferFormat internalFormat, const Vector2i& size) { - (this->*storageMultisampleImplementation)(samples, internalFormat, size); - } + void setStorageMultisample(Int samples, RenderbufferFormat internalFormat, const Vector2i& size); private: - static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context); - - typedef void(Renderbuffer::*StorageImplementation)(RenderbufferFormat, const Vector2i&); void MAGNUM_LOCAL storageImplementationDefault(RenderbufferFormat internalFormat, const Vector2i& size); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL storageImplementationDSA(RenderbufferFormat internalFormat, const Vector2i& size); #endif - static StorageImplementation storageImplementation; - typedef void(Renderbuffer::*StorageMultisampleImplementation)(GLsizei, RenderbufferFormat, const Vector2i&); #ifndef MAGNUM_TARGET_GLES2 void MAGNUM_LOCAL storageMultisampleImplementationDefault(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); + #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL storageMultisampleImplementationDSA(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); + #endif #else void MAGNUM_LOCAL storageMultisampleImplementationANGLE(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageMultisampleImplementationNV(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); #endif - #ifndef MAGNUM_TARGET_GLES - void MAGNUM_LOCAL storageMultisampleImplementationDSA(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); - #endif - static StorageMultisampleImplementation storageMultisampleImplementation; void MAGNUM_LOCAL bind(); From 37b9f4d8460cf79cc824a3f6c66f329c56451b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 15:31:58 +0100 Subject: [PATCH 03/86] Moved global data from texture classes to per-context state. --- src/Magnum/AbstractTexture.cpp | 240 +++++++++------------ src/Magnum/AbstractTexture.h | 95 ++------ src/Magnum/BufferTexture.cpp | 14 +- src/Magnum/BufferTexture.h | 16 +- src/Magnum/Context.cpp | 4 - src/Magnum/Implementation/State.cpp | 2 +- src/Magnum/Implementation/TextureState.cpp | 135 +++++++++++- src/Magnum/Implementation/TextureState.h | 36 +++- 8 files changed, 291 insertions(+), 251 deletions(-) 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 From 8cdefa1e0bb7075bcea79b39b034d7e947bc83f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 16:30:35 +0100 Subject: [PATCH 04/86] Moved global data from shader classes to per-context state. --- src/Magnum/AbstractShaderProgram.cpp | 224 ++++++----- src/Magnum/AbstractShaderProgram.h | 350 ++---------------- src/Magnum/CMakeLists.txt | 1 + src/Magnum/Context.cpp | 1 - .../Implementation/ShaderProgramState.cpp | 139 +++++++ .../Implementation/ShaderProgramState.h | 57 ++- src/Magnum/Implementation/State.cpp | 2 +- 7 files changed, 360 insertions(+), 414 deletions(-) create mode 100644 src/Magnum/Implementation/ShaderProgramState.cpp diff --git a/src/Magnum/AbstractShaderProgram.cpp b/src/Magnum/AbstractShaderProgram.cpp index 93327bcbe..5ffcaa358 100644 --- a/src/Magnum/AbstractShaderProgram.cpp +++ b/src/Magnum/AbstractShaderProgram.cpp @@ -36,50 +36,6 @@ namespace Magnum { -AbstractShaderProgram::Uniform1fvImplementation AbstractShaderProgram::uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::Uniform2fvImplementation AbstractShaderProgram::uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::Uniform3fvImplementation AbstractShaderProgram::uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::Uniform4fvImplementation AbstractShaderProgram::uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::Uniform1ivImplementation AbstractShaderProgram::uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::Uniform2ivImplementation AbstractShaderProgram::uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::Uniform3ivImplementation AbstractShaderProgram::uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::Uniform4ivImplementation AbstractShaderProgram::uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationDefault; -#ifndef MAGNUM_TARGET_GLES2 -AbstractShaderProgram::Uniform1uivImplementation AbstractShaderProgram::uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::Uniform2uivImplementation AbstractShaderProgram::uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::Uniform3uivImplementation AbstractShaderProgram::uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::Uniform4uivImplementation AbstractShaderProgram::uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationDefault; -#endif -#ifndef MAGNUM_TARGET_GLES -AbstractShaderProgram::Uniform1dvImplementation AbstractShaderProgram::uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::Uniform2dvImplementation AbstractShaderProgram::uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::Uniform3dvImplementation AbstractShaderProgram::uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::Uniform4dvImplementation AbstractShaderProgram::uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -#endif - -AbstractShaderProgram::UniformMatrix2fvImplementation AbstractShaderProgram::uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix3fvImplementation AbstractShaderProgram::uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix4fvImplementation AbstractShaderProgram::uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -#ifndef MAGNUM_TARGET_GLES2 -AbstractShaderProgram::UniformMatrix2x3fvImplementation AbstractShaderProgram::uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix3x2fvImplementation AbstractShaderProgram::uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix2x4fvImplementation AbstractShaderProgram::uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix4x2fvImplementation AbstractShaderProgram::uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix3x4fvImplementation AbstractShaderProgram::uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix4x3fvImplementation AbstractShaderProgram::uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -#endif -#ifndef MAGNUM_TARGET_GLES -AbstractShaderProgram::UniformMatrix2dvImplementation AbstractShaderProgram::uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix3dvImplementation AbstractShaderProgram::uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix4dvImplementation AbstractShaderProgram::uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix2x3dvImplementation AbstractShaderProgram::uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix3x2dvImplementation AbstractShaderProgram::uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix2x4dvImplementation AbstractShaderProgram::uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix4x2dvImplementation AbstractShaderProgram::uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix3x4dvImplementation AbstractShaderProgram::uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -AbstractShaderProgram::UniformMatrix4x3dvImplementation AbstractShaderProgram::uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; -#endif - Int AbstractShaderProgram::maxVertexAttributes() { GLint& value = Context::current()->state().shaderProgram->maxVertexAttributes; @@ -356,52 +312,8 @@ Int AbstractShaderProgram::uniformLocation(const std::string& name) { return location; } -void AbstractShaderProgram::initializeContextBasedFunctionality(Context& context) { - /** @todo OpenGL ES 2 has extension @es_extension{EXT,separate_shader_objects} for this */ - #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported() || - context.isExtensionSupported()) { - Debug() << "AbstractShaderProgram: using" << (context.isExtensionSupported() ? - Extensions::GL::ARB::separate_shader_objects::string() : Extensions::GL::EXT::direct_state_access::string()) << "features"; - uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - - uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; - } - #else - static_cast(context); - #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Float* const values) { + (this->*Context::current()->state().shaderProgram->uniform1fvImplementation)(location, count, values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLfloat* const values) { @@ -415,6 +327,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<2, Float>* const values) { + (this->*Context::current()->state().shaderProgram->uniform2fvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) { use(); glUniform2fv(location, count, values[0].data()); @@ -426,6 +342,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<3, Float>* const values) { + (this->*Context::current()->state().shaderProgram->uniform3fvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) { use(); glUniform3fv(location, count, values[0].data()); @@ -437,6 +357,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<4, Float>* const values) { + (this->*Context::current()->state().shaderProgram->uniform4fvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) { use(); glUniform4fv(location, count, values[0].data()); @@ -448,6 +372,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Int* const values) { + (this->*Context::current()->state().shaderProgram->uniform1ivImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLint* const values) { use(); glUniform1iv(location, count, values); @@ -459,6 +387,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<2, Int>* const values) { + (this->*Context::current()->state().shaderProgram->uniform2ivImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) { use(); glUniform2iv(location, count, values[0].data()); @@ -470,6 +402,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<3, Int>* const values) { + (this->*Context::current()->state().shaderProgram->uniform3ivImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) { use(); glUniform3iv(location, count, values[0].data()); @@ -481,6 +417,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<4, Int>* const values) { + (this->*Context::current()->state().shaderProgram->uniform4ivImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) { use(); glUniform4iv(location, count, values[0].data()); @@ -493,6 +433,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const #endif #ifndef MAGNUM_TARGET_GLES2 +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const UnsignedInt* const values) { + (this->*Context::current()->state().shaderProgram->uniform1uivImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLuint* const values) { use(); glUniform1uiv(location, count, values); @@ -504,6 +448,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<2, UnsignedInt>* const values) { + (this->*Context::current()->state().shaderProgram->uniform2uivImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) { use(); glUniform2uiv(location, count, values[0].data()); @@ -515,6 +463,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<3, UnsignedInt>* const values) { + (this->*Context::current()->state().shaderProgram->uniform3uivImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) { use(); glUniform3uiv(location, count, values[0].data()); @@ -526,6 +478,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<4, UnsignedInt>* const values) { + (this->*Context::current()->state().shaderProgram->uniform4uivImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) { use(); glUniform4uiv(location, count, values[0].data()); @@ -539,6 +495,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const #endif #ifndef MAGNUM_TARGET_GLES +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Double* const values) { + (this->*Context::current()->state().shaderProgram->uniform1dvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLdouble* const values) { use(); glUniform1dv(location, count, values); @@ -548,6 +508,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const glProgramUniform1dv(_id, location, count, values); } +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<2, Double>* const values) { + (this->*Context::current()->state().shaderProgram->uniform2dvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLdouble>* const values) { use(); glUniform2dv(location, count, values[0].data()); @@ -557,6 +521,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const glProgramUniform2dv(_id, location, count, values[0].data()); } +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<3, Double>* const values) { + (this->*Context::current()->state().shaderProgram->uniform3dvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLdouble>* const values) { use(); glUniform3dv(location, count, values[0].data()); @@ -566,6 +534,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const glProgramUniform3dv(_id, location, count, values[0].data()); } +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<4, Double>* const values) { + (this->*Context::current()->state().shaderProgram->uniform4dvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLdouble>* const values) { use(); glUniform4dv(location, count, values[0].data()); @@ -576,6 +548,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 2, Float>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix2fvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) { use(); glUniformMatrix2fv(location, count, GL_FALSE, values[0].data()); @@ -587,6 +563,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 3, Float>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix3fvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) { use(); glUniformMatrix3fv(location, count, GL_FALSE, values[0].data()); @@ -598,6 +578,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 4, Float>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix4fvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) { use(); glUniformMatrix4fv(location, count, GL_FALSE, values[0].data()); @@ -610,6 +594,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const #endif #ifndef MAGNUM_TARGET_GLES2 +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 3, Float>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix2x3fvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) { use(); glUniformMatrix2x3fv(location, count, GL_FALSE, values[0].data()); @@ -621,6 +609,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 2, Float>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix3x2fvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) { use(); glUniformMatrix3x2fv(location, count, GL_FALSE, values[0].data()); @@ -632,6 +624,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 4, Float>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix2x4fvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) { use(); glUniformMatrix2x4fv(location, count, GL_FALSE, values[0].data()); @@ -643,6 +639,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 2, Float>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix4x2fvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) { use(); glUniformMatrix4x2fv(location, count, GL_FALSE, values[0].data()); @@ -654,6 +654,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 4, Float>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix3x4fvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) { use(); glUniformMatrix3x4fv(location, count, GL_FALSE, values[0].data()); @@ -665,6 +669,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const } #endif +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 3, Float>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix4x3fvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) { use(); glUniformMatrix4x3fv(location, count, GL_FALSE, values[0].data()); @@ -678,6 +686,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const #endif #ifndef MAGNUM_TARGET_GLES +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 2, Double>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix2dvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* const values) { use(); glUniformMatrix2dv(location, count, GL_FALSE, values[0].data()); @@ -687,6 +699,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const glProgramUniformMatrix2dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 3, Double>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix3dvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* const values) { use(); glUniformMatrix3dv(location, count, GL_FALSE, values[0].data()); @@ -696,6 +712,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const glProgramUniformMatrix3dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 4, Double>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix4dvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* const values) { use(); glUniformMatrix4dv(location, count, GL_FALSE, values[0].data()); @@ -705,6 +725,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const glProgramUniformMatrix4dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 3, Double>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix2x3dvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* const values) { use(); glUniformMatrix2x3dv(location, count, GL_FALSE, values[0].data()); @@ -714,6 +738,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const glProgramUniformMatrix2x3dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 2, Double>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix3x2dvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* const values) { use(); glUniformMatrix3x2dv(location, count, GL_FALSE, values[0].data()); @@ -723,6 +751,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const glProgramUniformMatrix3x2dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 4, Double>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix2x4dvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* const values) { use(); glUniformMatrix2x4dv(location, count, GL_FALSE, values[0].data()); @@ -732,6 +764,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const glProgramUniformMatrix2x4dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 2, Double>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix4x2dvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* const values) { use(); glUniformMatrix4x2dv(location, count, GL_FALSE, values[0].data()); @@ -741,6 +777,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const glProgramUniformMatrix4x2dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 4, Double>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix3x4dvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* const values) { use(); glUniformMatrix3x4dv(location, count, GL_FALSE, values[0].data()); @@ -750,6 +790,10 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const glProgramUniformMatrix3x4dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 3, Double>* const values) { + (this->*Context::current()->state().shaderProgram->uniformMatrix4x3dvImplementation)(location, count, values); +} + void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* const values) { use(); glUniformMatrix4x3dv(location, count, GL_FALSE, values[0].data()); diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index abed80a64..b27ae04c3 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -39,6 +39,7 @@ namespace Magnum { namespace Implementation { template struct Attribute; + class ShaderProgramState; } /** @@ -322,7 +323,7 @@ comes in handy. @todo `GL_NUM_{PROGRAM,SHADER}_BINARY_FORMATS` + `GL_{PROGRAM,SHADER}_BINARY_FORMATS` (vector), (@extension{ARB,ES2_compatibility}) */ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { - friend class Context; + friend class Implementation::ShaderProgramState; public: template class Attribute; @@ -718,44 +719,16 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { * @see @ref setUniform(Int, const T&), @fn_gl{UseProgram}, @fn_gl{Uniform} * or @fn_gl{ProgramUniform}/@fn_gl_extension{ProgramUniform,EXT,direct_state_access}. */ - void setUniform(Int location, UnsignedInt count, const Float* values) { - (this->*uniform1fvImplementation)(location, count, values); - } - - /** @copydoc setUniform(Int, UnsignedInt, const Float*) */ - void setUniform(Int location, UnsignedInt count, const Math::Vector<2, Float>* values) { - (this->*uniform2fvImplementation)(location, count, values); - } - - /** @copydoc setUniform(Int, UnsignedInt, const Float*) */ - void setUniform(Int location, UnsignedInt count, const Math::Vector<3, Float>* values) { - (this->*uniform3fvImplementation)(location, count, values); - } - - /** @copydoc setUniform(Int, UnsignedInt, const Float*) */ - void setUniform(Int location, UnsignedInt count, const Math::Vector<4, Float>* values) { - (this->*uniform4fvImplementation)(location, count, values); - } - - /** @copydoc setUniform(Int, UnsignedInt, const Float*) */ - void setUniform(Int location, UnsignedInt count, const Int* values) { - (this->*uniform1ivImplementation)(location, count, values); - } - - /** @copydoc setUniform(Int, UnsignedInt, const Float*) */ - void setUniform(Int location, UnsignedInt count, const Math::Vector<2, Int>* values) { - (this->*uniform2ivImplementation)(location, count, values); - } + void setUniform(Int location, UnsignedInt count, const Float* values); + void setUniform(Int location, UnsignedInt count, const Math::Vector<2, Float>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::Vector<3, Float>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::Vector<4, Float>* values); /**< @overload */ /** @copydoc setUniform(Int, UnsignedInt, const Float*) */ - void setUniform(Int location, UnsignedInt count, const Math::Vector<3, Int>* values) { - (this->*uniform3ivImplementation)(location, count, values); - } - - /** @copydoc setUniform(Int, UnsignedInt, const Float*) */ - void setUniform(Int location, UnsignedInt count, const Math::Vector<4, Int>* values) { - (this->*uniform4ivImplementation)(location, count, values); - } + void setUniform(Int location, UnsignedInt count, const Int* values); + void setUniform(Int location, UnsignedInt count, const Math::Vector<2, Int>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::Vector<3, Int>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::Vector<4, Int>* values); /**< @overload */ #ifndef MAGNUM_TARGET_GLES2 /** @@ -763,36 +736,10 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { * @requires_gl30 %Extension @extension{EXT,gpu_shader4} * @requires_gles30 Only signed integers are available in OpenGL ES 2.0. */ - void setUniform(Int location, UnsignedInt count, const UnsignedInt* values) { - (this->*uniform1uivImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl30 %Extension @extension{EXT,gpu_shader4} - * @requires_gles30 Only signed integers are available in OpenGL ES 2.0. - */ - void setUniform(Int location, UnsignedInt count, const Math::Vector<2, UnsignedInt>* values) { - (this->*uniform2uivImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl30 %Extension @extension{EXT,gpu_shader4} - * @requires_gles30 Only signed integers are available in OpenGL ES 2.0. - */ - void setUniform(Int location, UnsignedInt count, const Math::Vector<3, UnsignedInt>* values) { - (this->*uniform3uivImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl30 %Extension @extension{EXT,gpu_shader4} - * @requires_gles30 Only signed integers are available in OpenGL ES 2.0. - */ - void setUniform(Int location, UnsignedInt count, const Math::Vector<4, UnsignedInt>* values) { - (this->*uniform4uivImplementation)(location, count, values); - } + void setUniform(Int location, UnsignedInt count, const UnsignedInt* values); + void setUniform(Int location, UnsignedInt count, const Math::Vector<2, UnsignedInt>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::Vector<3, UnsignedInt>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::Vector<4, UnsignedInt>* values); /**< @overload */ #endif #ifndef MAGNUM_TARGET_GLES @@ -801,101 +748,28 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { * @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64} * @requires_gl Only floats are available in OpenGL ES. */ - void setUniform(Int location, UnsignedInt count, const Double* values) { - (this->*uniform1dvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64} - * @requires_gl Only floats are available in OpenGL ES. - */ - void setUniform(Int location, UnsignedInt count, const Math::Vector<2, Double>* values) { - (this->*uniform2dvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64} - * @requires_gl Only floats are available in OpenGL ES. - */ - void setUniform(Int location, UnsignedInt count, const Math::Vector<3, Double>* values) { - (this->*uniform3dvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64} - * @requires_gl Only floats are available in OpenGL ES. - */ - void setUniform(Int location, UnsignedInt count, const Math::Vector<4, Double>* values) { - (this->*uniform4dvImplementation)(location, count, values); - } + void setUniform(Int location, UnsignedInt count, const Double* values); + void setUniform(Int location, UnsignedInt count, const Math::Vector<2, Double>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::Vector<3, Double>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::Vector<4, Double>* values); /**< @overload */ #endif /** @copydoc setUniform(Int, UnsignedInt, const Float*) */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 2, Float>* values) { - (this->*uniformMatrix2fvImplementation)(location, count, values); - } - - /** @copydoc setUniform(Int, UnsignedInt, const Float*) */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 3, Float>* values) { - (this->*uniformMatrix3fvImplementation)(location, count, values); - } - - /** @copydoc setUniform(Int, UnsignedInt, const Float*) */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 4, Float>* values) { - (this->*uniformMatrix4fvImplementation)(location, count, values); - } + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 2, Float>* values); + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 3, Float>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 4, Float>* values); /**< @overload */ #ifndef MAGNUM_TARGET_GLES2 /** * @copydoc setUniform(Int, UnsignedInt, const Float*) * @requires_gles30 Only square matrices are available in OpenGL ES 2.0. */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 3, Float>* values) { - (this->*uniformMatrix2x3fvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gles30 Only square matrices are available in OpenGL ES 2.0. - */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 2, Float>* values) { - (this->*uniformMatrix3x2fvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gles30 Only square matrices are available in OpenGL ES 2.0. - */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 4, Float>* values) { - (this->*uniformMatrix2x4fvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gles30 Only square matrices are available in OpenGL ES 2.0. - */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 2, Float>* values) { - (this->*uniformMatrix4x2fvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gles30 Only square matrices are available in OpenGL ES 2.0. - */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 4, Float>* values) { - (this->*uniformMatrix3x4fvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gles30 Only square matrices are available in OpenGL ES 2.0. - */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 3, Float>* values) { - (this->*uniformMatrix4x3fvImplementation)(location, count, values); - } + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 3, Float>* values); + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 2, Float>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 4, Float>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 2, Float>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 4, Float>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 3, Float>* values); /**< @overload */ #endif #ifndef MAGNUM_TARGET_GLES @@ -904,106 +778,18 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { * @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64} * @requires_gl Only floats are available in OpenGL ES. */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 2, Double>* values) { - (this->*uniformMatrix2dvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64} - * @requires_gl Only floats are available in OpenGL ES. - */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 3, Double>* values) { - (this->*uniformMatrix3dvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64} - * @requires_gl Only floats are available in OpenGL ES. - */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 4, Double>* values) { - (this->*uniformMatrix4dvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64} - * @requires_gl Only floats are available in OpenGL ES. - */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 3, Double>* values) { - (this->*uniformMatrix2x3dvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64} - * @requires_gl Only floats are available in OpenGL ES. - */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 2, Double>* values) { - (this->*uniformMatrix3x2dvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64} - * @requires_gl Only floats are available in OpenGL ES. - */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 4, Double>* values) { - (this->*uniformMatrix2x4dvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64} - * @requires_gl Only floats are available in OpenGL ES. - */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 2, Double>* values) { - (this->*uniformMatrix4x2dvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64} - * @requires_gl Only floats are available in OpenGL ES. - */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 4, Double>* values) { - (this->*uniformMatrix3x4dvImplementation)(location, count, values); - } - - /** - * @copydoc setUniform(Int, UnsignedInt, const Float*) - * @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64} - * @requires_gl Only floats are available in OpenGL ES. - */ - void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 3, Double>* values) { - (this->*uniformMatrix4x3dvImplementation)(location, count, values); - } + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 2, Double>* values); + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 3, Double>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 4, Double>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 3, Double>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 2, Double>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 4, Double>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 2, Double>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 4, Double>* values); /**< @overload */ + void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 3, Double>* values); /**< @overload */ #endif private: - static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context); - - typedef void(AbstractShaderProgram::*Uniform1fvImplementation)(GLint, GLsizei, const GLfloat*); - typedef void(AbstractShaderProgram::*Uniform2fvImplementation)(GLint, GLsizei, const Math::Vector<2, GLfloat>*); - typedef void(AbstractShaderProgram::*Uniform3fvImplementation)(GLint, GLsizei, const Math::Vector<3, GLfloat>*); - typedef void(AbstractShaderProgram::*Uniform4fvImplementation)(GLint, GLsizei, const Math::Vector<4, GLfloat>*); - typedef void(AbstractShaderProgram::*Uniform1ivImplementation)(GLint, GLsizei, const GLint*); - typedef void(AbstractShaderProgram::*Uniform2ivImplementation)(GLint, GLsizei, const Math::Vector<2, GLint>*); - typedef void(AbstractShaderProgram::*Uniform3ivImplementation)(GLint, GLsizei, const Math::Vector<3, GLint>*); - typedef void(AbstractShaderProgram::*Uniform4ivImplementation)(GLint, GLsizei, const Math::Vector<4, GLint>*); - #ifndef MAGNUM_TARGET_GLES2 - typedef void(AbstractShaderProgram::*Uniform1uivImplementation)(GLint, GLsizei, const GLuint*); - typedef void(AbstractShaderProgram::*Uniform2uivImplementation)(GLint, GLsizei, const Math::Vector<2, GLuint>*); - typedef void(AbstractShaderProgram::*Uniform3uivImplementation)(GLint, GLsizei, const Math::Vector<3, GLuint>*); - typedef void(AbstractShaderProgram::*Uniform4uivImplementation)(GLint, GLsizei, const Math::Vector<4, GLuint>*); - #endif - #ifndef MAGNUM_TARGET_GLES - typedef void(AbstractShaderProgram::*Uniform1dvImplementation)(GLint, GLsizei, const GLdouble*); - typedef void(AbstractShaderProgram::*Uniform2dvImplementation)(GLint, GLsizei, const Math::Vector<2, GLdouble>*); - typedef void(AbstractShaderProgram::*Uniform3dvImplementation)(GLint, GLsizei, const Math::Vector<3, GLdouble>*); - typedef void(AbstractShaderProgram::*Uniform4dvImplementation)(GLint, GLsizei, const Math::Vector<4, GLdouble>*); - #endif void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLfloat* values); void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values); @@ -1040,49 +826,7 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<3, GLdouble>* values); void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values); #endif - static Uniform1fvImplementation uniform1fvImplementation; - static Uniform2fvImplementation uniform2fvImplementation; - static Uniform3fvImplementation uniform3fvImplementation; - static Uniform4fvImplementation uniform4fvImplementation; - static Uniform1ivImplementation uniform1ivImplementation; - static Uniform2ivImplementation uniform2ivImplementation; - static Uniform3ivImplementation uniform3ivImplementation; - static Uniform4ivImplementation uniform4ivImplementation; - #ifndef MAGNUM_TARGET_GLES2 - static Uniform1uivImplementation uniform1uivImplementation; - static Uniform2uivImplementation uniform2uivImplementation; - static Uniform3uivImplementation uniform3uivImplementation; - static Uniform4uivImplementation uniform4uivImplementation; - #endif - #ifndef MAGNUM_TARGET_GLES - static Uniform1dvImplementation uniform1dvImplementation; - static Uniform2dvImplementation uniform2dvImplementation; - static Uniform3dvImplementation uniform3dvImplementation; - static Uniform4dvImplementation uniform4dvImplementation; - #endif - typedef void(AbstractShaderProgram::*UniformMatrix2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 2, GLfloat>*); - typedef void(AbstractShaderProgram::*UniformMatrix3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 3, GLfloat>*); - typedef void(AbstractShaderProgram::*UniformMatrix4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 4, GLfloat>*); - #ifndef MAGNUM_TARGET_GLES2 - typedef void(AbstractShaderProgram::*UniformMatrix2x3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 3, GLfloat>*); - typedef void(AbstractShaderProgram::*UniformMatrix3x2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 2, GLfloat>*); - typedef void(AbstractShaderProgram::*UniformMatrix2x4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 4, GLfloat>*); - typedef void(AbstractShaderProgram::*UniformMatrix4x2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 2, GLfloat>*); - typedef void(AbstractShaderProgram::*UniformMatrix3x4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 4, GLfloat>*); - typedef void(AbstractShaderProgram::*UniformMatrix4x3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 3, GLfloat>*); - #endif - #ifndef MAGNUM_TARGET_GLES - typedef void(AbstractShaderProgram::*UniformMatrix2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 2, GLdouble>*); - typedef void(AbstractShaderProgram::*UniformMatrix3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 3, GLdouble>*); - typedef void(AbstractShaderProgram::*UniformMatrix4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 4, GLdouble>*); - typedef void(AbstractShaderProgram::*UniformMatrix2x3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 3, GLdouble>*); - typedef void(AbstractShaderProgram::*UniformMatrix3x2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 2, GLdouble>*); - typedef void(AbstractShaderProgram::*UniformMatrix2x4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 4, GLdouble>*); - typedef void(AbstractShaderProgram::*UniformMatrix4x2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 2, GLdouble>*); - typedef void(AbstractShaderProgram::*UniformMatrix3x4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 4, GLdouble>*); - typedef void(AbstractShaderProgram::*UniformMatrix4x3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 3, GLdouble>*); - #endif void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values); @@ -1123,28 +867,6 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* values); void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values); #endif - static UniformMatrix2fvImplementation uniformMatrix2fvImplementation; - static UniformMatrix3fvImplementation uniformMatrix3fvImplementation; - static UniformMatrix4fvImplementation uniformMatrix4fvImplementation; - #ifndef MAGNUM_TARGET_GLES2 - static UniformMatrix2x3fvImplementation uniformMatrix2x3fvImplementation; - static UniformMatrix3x2fvImplementation uniformMatrix3x2fvImplementation; - static UniformMatrix2x4fvImplementation uniformMatrix2x4fvImplementation; - static UniformMatrix4x2fvImplementation uniformMatrix4x2fvImplementation; - static UniformMatrix3x4fvImplementation uniformMatrix3x4fvImplementation; - static UniformMatrix4x3fvImplementation uniformMatrix4x3fvImplementation; - #endif - #ifndef MAGNUM_TARGET_GLES - static UniformMatrix2dvImplementation uniformMatrix2dvImplementation; - static UniformMatrix3dvImplementation uniformMatrix3dvImplementation; - static UniformMatrix4dvImplementation uniformMatrix4dvImplementation; - static UniformMatrix2x3dvImplementation uniformMatrix2x3dvImplementation; - static UniformMatrix3x2dvImplementation uniformMatrix3x2dvImplementation; - static UniformMatrix2x4dvImplementation uniformMatrix2x4dvImplementation; - static UniformMatrix4x2dvImplementation uniformMatrix4x2dvImplementation; - static UniformMatrix3x4dvImplementation uniformMatrix3x4dvImplementation; - static UniformMatrix4x3dvImplementation uniformMatrix4x3dvImplementation; - #endif GLuint _id; }; diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index fd98022fe..81f8b198b 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -55,6 +55,7 @@ set(Magnum_SRCS Implementation/BufferState.cpp Implementation/DebugState.cpp Implementation/FramebufferState.cpp + Implementation/ShaderProgramState.cpp Implementation/State.cpp Implementation/TextureState.cpp diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 6ca77d85e..35df57aad 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -448,7 +448,6 @@ Context::Context() { _state = new Implementation::State(*this); /* Initialize functionality based on current OpenGL version and extensions */ - AbstractShaderProgram::initializeContextBasedFunctionality(*this); Buffer::initializeContextBasedFunctionality(*this); DefaultFramebuffer::initializeContextBasedFunctionality(*this); Mesh::initializeContextBasedFunctionality(*this); diff --git a/src/Magnum/Implementation/ShaderProgramState.cpp b/src/Magnum/Implementation/ShaderProgramState.cpp new file mode 100644 index 000000000..9ef01e4b6 --- /dev/null +++ b/src/Magnum/Implementation/ShaderProgramState.cpp @@ -0,0 +1,139 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "ShaderProgramState.h" + +#include "Magnum/AbstractShaderProgram.h" +#include "Magnum/Context.h" +#include "Magnum/Extensions.h" + +namespace Magnum { namespace Implementation { + +ShaderProgramState::ShaderProgramState(Context& context, std::vector& extensions): current(0), maxVertexAttributes(0) + #ifndef MAGNUM_TARGET_GLES + , maxAtomicCounterBufferSize(0), maxComputeSharedMemorySize(0), maxComputeWorkGroupInvocations(0), maxImageUnits(0), maxImageSamples(0), maxCombinedShaderOutputResources(0), maxUniformLocations(0), maxShaderStorageBlockSize(0) + #endif + #ifndef MAGNUM_TARGET_GLES2 + , minTexelOffset(0), maxTexelOffset(0), maxUniformBlockSize(0) + #endif +{ + /** @todo OpenGL ES 2 has extension @es_extension{EXT,separate_shader_objects} for this */ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported() || + context.isExtensionSupported()) + { + extensions.push_back(context.isExtensionSupported() ? + Extensions::GL::ARB::separate_shader_objects::string() : Extensions::GL::EXT::direct_state_access::string()); + + uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + + uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; + } else + #endif + { + #ifdef MAGNUM_TARGET_GLES + static_cast(context); + static_cast(extensions); + #endif + + uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationDefault; + #ifndef MAGNUM_TARGET_GLES2 + uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationDefault; + #endif + #ifndef MAGNUM_TARGET_GLES + uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + #endif + + uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + #ifndef MAGNUM_TARGET_GLES2 + uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + #endif + #ifndef MAGNUM_TARGET_GLES + uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + #endif + } +} + +}} diff --git a/src/Magnum/Implementation/ShaderProgramState.h b/src/Magnum/Implementation/ShaderProgramState.h index 477b85992..d2113052e 100644 --- a/src/Magnum/Implementation/ShaderProgramState.h +++ b/src/Magnum/Implementation/ShaderProgramState.h @@ -25,19 +25,60 @@ DEALINGS IN THE SOFTWARE. */ +#include +#include + +#include "Magnum/Magnum.h" #include "Magnum/OpenGL.h" namespace Magnum { namespace Implementation { struct ShaderProgramState { - constexpr ShaderProgramState(): current(0), maxVertexAttributes(0) - #ifndef MAGNUM_TARGET_GLES - , maxAtomicCounterBufferSize(0), maxComputeSharedMemorySize(0), maxComputeWorkGroupInvocations(0), maxImageUnits(0), maxImageSamples(0), maxCombinedShaderOutputResources(0), maxUniformLocations(0), maxShaderStorageBlockSize(0) - #endif - #ifndef MAGNUM_TARGET_GLES2 - , minTexelOffset(0), maxTexelOffset(0), maxUniformBlockSize(0) - #endif - {} + explicit ShaderProgramState(Context& context, std::vector& extensions); + + void(AbstractShaderProgram::*uniform1fvImplementation)(GLint, GLsizei, const GLfloat*); + void(AbstractShaderProgram::*uniform2fvImplementation)(GLint, GLsizei, const Math::Vector<2, GLfloat>*); + void(AbstractShaderProgram::*uniform3fvImplementation)(GLint, GLsizei, const Math::Vector<3, GLfloat>*); + void(AbstractShaderProgram::*uniform4fvImplementation)(GLint, GLsizei, const Math::Vector<4, GLfloat>*); + void(AbstractShaderProgram::*uniform1ivImplementation)(GLint, GLsizei, const GLint*); + void(AbstractShaderProgram::*uniform2ivImplementation)(GLint, GLsizei, const Math::Vector<2, GLint>*); + void(AbstractShaderProgram::*uniform3ivImplementation)(GLint, GLsizei, const Math::Vector<3, GLint>*); + void(AbstractShaderProgram::*uniform4ivImplementation)(GLint, GLsizei, const Math::Vector<4, GLint>*); + #ifndef MAGNUM_TARGET_GLES2 + void(AbstractShaderProgram::*uniform1uivImplementation)(GLint, GLsizei, const GLuint*); + void(AbstractShaderProgram::*uniform2uivImplementation)(GLint, GLsizei, const Math::Vector<2, GLuint>*); + void(AbstractShaderProgram::*uniform3uivImplementation)(GLint, GLsizei, const Math::Vector<3, GLuint>*); + void(AbstractShaderProgram::*uniform4uivImplementation)(GLint, GLsizei, const Math::Vector<4, GLuint>*); + #endif + #ifndef MAGNUM_TARGET_GLES + void(AbstractShaderProgram::*uniform1dvImplementation)(GLint, GLsizei, const GLdouble*); + void(AbstractShaderProgram::*uniform2dvImplementation)(GLint, GLsizei, const Math::Vector<2, GLdouble>*); + void(AbstractShaderProgram::*uniform3dvImplementation)(GLint, GLsizei, const Math::Vector<3, GLdouble>*); + void(AbstractShaderProgram::*uniform4dvImplementation)(GLint, GLsizei, const Math::Vector<4, GLdouble>*); + #endif + + void(AbstractShaderProgram::*uniformMatrix2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 2, GLfloat>*); + void(AbstractShaderProgram::*uniformMatrix3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 3, GLfloat>*); + void(AbstractShaderProgram::*uniformMatrix4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 4, GLfloat>*); + #ifndef MAGNUM_TARGET_GLES2 + void(AbstractShaderProgram::*uniformMatrix2x3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 3, GLfloat>*); + void(AbstractShaderProgram::*uniformMatrix3x2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 2, GLfloat>*); + void(AbstractShaderProgram::*uniformMatrix2x4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 4, GLfloat>*); + void(AbstractShaderProgram::*uniformMatrix4x2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 2, GLfloat>*); + void(AbstractShaderProgram::*uniformMatrix3x4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 4, GLfloat>*); + void(AbstractShaderProgram::*uniformMatrix4x3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 3, GLfloat>*); + #endif + #ifndef MAGNUM_TARGET_GLES + void(AbstractShaderProgram::*uniformMatrix2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 2, GLdouble>*); + void(AbstractShaderProgram::*uniformMatrix3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 3, GLdouble>*); + void(AbstractShaderProgram::*uniformMatrix4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 4, GLdouble>*); + void(AbstractShaderProgram::*uniformMatrix2x3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 3, GLdouble>*); + void(AbstractShaderProgram::*uniformMatrix3x2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 2, GLdouble>*); + void(AbstractShaderProgram::*uniformMatrix2x4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 4, GLdouble>*); + void(AbstractShaderProgram::*uniformMatrix4x2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 2, GLdouble>*); + void(AbstractShaderProgram::*uniformMatrix3x4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 4, GLdouble>*); + void(AbstractShaderProgram::*uniformMatrix4x3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 3, GLdouble>*); + #endif /* Currently used program */ GLuint current; diff --git a/src/Magnum/Implementation/State.cpp b/src/Magnum/Implementation/State.cpp index 85fc0721a..f35b860a8 100644 --- a/src/Magnum/Implementation/State.cpp +++ b/src/Magnum/Implementation/State.cpp @@ -57,7 +57,7 @@ State::State(Context& context) { mesh = new MeshState; renderer = new RendererState; shader = new ShaderState; - shaderProgram = new ShaderProgramState; + shaderProgram = new ShaderProgramState(context, extensions); texture = new TextureState(context, extensions); /* Sort the features and remove duplicates */ From e921a111b59f0e4ed4d03d9dd5db091a960b625a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 18:18:35 +0100 Subject: [PATCH 05/86] Moved global data from Buffer class to per-context state. --- src/Magnum/Buffer.cpp | 96 ++++++++++++----------- src/Magnum/Buffer.h | 75 ++++-------------- src/Magnum/Context.cpp | 1 - src/Magnum/Implementation/BufferState.cpp | 61 ++++++++++++++ src/Magnum/Implementation/BufferState.h | 25 ++++-- src/Magnum/Implementation/State.cpp | 2 +- 6 files changed, 148 insertions(+), 112 deletions(-) diff --git a/src/Magnum/Buffer.cpp b/src/Magnum/Buffer.cpp index ff66c4209..9dd2a23b9 100644 --- a/src/Magnum/Buffer.cpp +++ b/src/Magnum/Buffer.cpp @@ -36,49 +36,6 @@ namespace Magnum { -#ifndef MAGNUM_TARGET_GLES2 -Buffer::CopyImplementation Buffer::copyImplementation = &Buffer::copyImplementationDefault; -#endif -Buffer::GetParameterImplementation Buffer::getParameterImplementation = &Buffer::getParameterImplementationDefault; -#ifndef MAGNUM_TARGET_GLES -Buffer::GetSubDataImplementation Buffer::getSubDataImplementation = &Buffer::getSubDataImplementationDefault; -#endif -Buffer::DataImplementation Buffer::dataImplementation = &Buffer::dataImplementationDefault; -Buffer::SubDataImplementation Buffer::subDataImplementation = &Buffer::subDataImplementationDefault; -Buffer::InvalidateImplementation Buffer::invalidateImplementation = &Buffer::invalidateImplementationNoOp; -Buffer::InvalidateSubImplementation Buffer::invalidateSubImplementation = &Buffer::invalidateSubImplementationNoOp; -Buffer::MapImplementation Buffer::mapImplementation = &Buffer::mapImplementationDefault; -Buffer::MapRangeImplementation Buffer::mapRangeImplementation = &Buffer::mapRangeImplementationDefault; -Buffer::FlushMappedRangeImplementation Buffer::flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDefault; -Buffer::UnmapImplementation Buffer::unmapImplementation = &Buffer::unmapImplementationDefault; - -void Buffer::initializeContextBasedFunctionality(Context& context) { - #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) { - Debug() << "Buffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; - - copyImplementation = &Buffer::copyImplementationDSA; - getParameterImplementation = &Buffer::getParameterImplementationDSA; - getSubDataImplementation = &Buffer::getSubDataImplementationDSA; - dataImplementation = &Buffer::dataImplementationDSA; - subDataImplementation = &Buffer::subDataImplementationDSA; - mapImplementation = &Buffer::mapImplementationDSA; - mapRangeImplementation = &Buffer::mapRangeImplementationDSA; - flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDSA; - unmapImplementation = &Buffer::unmapImplementationDSA; - } - - if(context.isExtensionSupported()) { - Debug() << "Buffer: using" << Extensions::GL::ARB::invalidate_subdata::string() << "features"; - - invalidateImplementation = &Buffer::invalidateImplementationARB; - invalidateSubImplementation = &Buffer::invalidateSubImplementationARB; - } - #else - static_cast(context); - #endif -} - #ifndef MAGNUM_TARGET_GLES Int Buffer::minMapAlignment() { if(!Context::current()->isExtensionSupported()) @@ -145,6 +102,12 @@ Int Buffer::maxUniformBindings() { } #endif +#ifndef MAGNUM_TARGET_GLES2 +void Buffer::copy(Buffer& read, Buffer& write, const GLintptr readOffset, const GLintptr writeOffset, const GLsizeiptr size) { + Context::current()->state().buffer->copyImplementation(read, write, readOffset, writeOffset, size); +} +#endif + Buffer::Buffer(Buffer::Target targetHint): _targetHint(targetHint) #ifdef CORRADE_TARGET_NACL , _mappedBuffer(nullptr) @@ -218,10 +181,36 @@ Int Buffer::size() { * couldn't find any matching extension, though) */ GLint size; - (this->*getParameterImplementation)(GL_BUFFER_SIZE, &size); + (this->*Context::current()->state().buffer->getParameterImplementation)(GL_BUFFER_SIZE, &size); return size; } +Buffer& Buffer::setData(const Containers::ArrayReference data, const BufferUsage usage) { + (this->*Context::current()->state().buffer->dataImplementation)(data.size(), data, usage); + return *this; +} + +Buffer& Buffer::setSubData(const GLintptr offset, const Containers::ArrayReference data) { + (this->*Context::current()->state().buffer->subDataImplementation)(offset, data.size(), data); + return *this; +} + +#ifndef MAGNUM_TARGET_GLES +Buffer& Buffer::invalidateData() { + (this->*Context::current()->state().buffer->invalidateImplementation)(); + return *this; +} + +Buffer& Buffer::invalidateSubData(const GLintptr offset, const GLsizeiptr length) { + (this->*Context::current()->state().buffer->invalidateSubImplementation)(offset, length); + return *this; +} +#endif + +void* Buffer::map(const MapAccess access) { + return (this->*Context::current()->state().buffer->mapImplementation)(access); +} + #ifdef MAGNUM_TARGET_GLES2 void* Buffer::mapSub(const GLintptr offset, const GLsizeiptr length, const MapAccess access) { /** @todo Enable also in Emscripten (?) when extension loader is available */ @@ -235,7 +224,20 @@ void* Buffer::mapSub(const GLintptr offset, const GLsizeiptr length, const MapAc static_cast(access); #endif } +#endif + +void* Buffer::map(const GLintptr offset, const GLsizeiptr length, const MapFlags flags) { + return (this->*Context::current()->state().buffer->mapRangeImplementation)(offset, length, flags); +} + +Buffer& Buffer::flushMappedRange(const GLintptr offset, const GLsizeiptr length) { + (this->*Context::current()->state().buffer->flushMappedRangeImplementation)(offset, length); + return *this; +} + +bool Buffer::unmap() { return (this->*Context::current()->state().buffer->unmapImplementation)(); } +#ifdef MAGNUM_TARGET_GLES2 void Buffer::unmapSub() { /** @todo Enable also in Emscripten (?) when extension loader is available */ #ifdef CORRADE_TARGET_NACL @@ -248,6 +250,12 @@ void Buffer::unmapSub() { } #endif +#ifndef MAGNUM_TARGET_GLES +void Buffer::subDataInternal(GLintptr offset, GLsizeiptr size, GLvoid* data) { + (this->*Context::current()->state().buffer->getSubDataImplementation)(offset, size, data); +} +#endif + #ifndef MAGNUM_TARGET_GLES2 void Buffer::copyImplementationDefault(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { glCopyBufferSubData(GLenum(read.bindInternal(Target::CopyRead)), GLenum(write.bindInternal(Target::CopyWrite)), readOffset, writeOffset, size); diff --git a/src/Magnum/Buffer.h b/src/Magnum/Buffer.h index cd15ca04b..c64f03ad3 100644 --- a/src/Magnum/Buffer.h +++ b/src/Magnum/Buffer.h @@ -114,6 +114,8 @@ enum class BufferUsage: GLenum { #endif }; +namespace Implementation { class BufferState; } + /** @brief %Buffer @@ -190,7 +192,7 @@ nothing. @todo BindBufferRange/BindBufferOffset/BindBufferBase for transform feedback (3.0, @extension{EXT,transform_feedback}) */ class MAGNUM_EXPORT Buffer: public AbstractObject { - friend class Context; + friend class Implementation::BufferState; public: /** @@ -512,9 +514,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @requires_gl31 %Extension @extension{ARB,copy_buffer} * @requires_gles30 %Buffer copying is not available in OpenGL ES 2.0. */ - static void copy(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { - copyImplementation(read, write, readOffset, writeOffset, size); - } + static void copy(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); #endif /** @@ -669,10 +669,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @see @ref setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{BufferData} * or @fn_gl_extension{NamedBufferData,EXT,direct_state_access} */ - Buffer& setData(Containers::ArrayReference data, BufferUsage usage) { - (this->*dataImplementation)(data.size(), data, usage); - return *this; - } + Buffer& setData(Containers::ArrayReference data, BufferUsage usage); #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -709,10 +706,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @see @ref setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{BufferSubData} * or @fn_gl_extension{NamedBufferSubData,EXT,direct_state_access} */ - Buffer& setSubData(GLintptr offset, Containers::ArrayReference data) { - (this->*subDataImplementation)(offset, data.size(), data); - return *this; - } + Buffer& setSubData(GLintptr offset, Containers::ArrayReference data); #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -746,10 +740,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * (part of OpenGL 4.3) is not available, this function does nothing. * @see @ref MapFlag::InvalidateBuffer, @fn_gl{InvalidateBufferData} */ - Buffer& invalidateData() { - (this->*invalidateImplementation)(); - return *this; - } + Buffer& invalidateData(); /** * @brief Invalidate buffer subdata @@ -761,10 +752,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * (part of OpenGL 4.3) is not available, this function does nothing. * @see @ref MapFlag::InvalidateRange, @fn_gl{InvalidateBufferData} */ - Buffer& invalidateSubData(GLintptr offset, GLsizeiptr length) { - (this->*invalidateSubImplementation)(offset, length); - return *this; - } + Buffer& invalidateSubData(GLintptr offset, GLsizeiptr length); #endif /** @@ -784,9 +772,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * OpenGL ES 2.0, use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)" * in OpenGL ES 3.0 instead. */ - void* map(MapAccess access) { - return (this->*mapImplementation)(access); - } + void* map(MapAccess access); #if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT) /** @@ -827,9 +813,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @requires_gl30 %Extension @extension{ARB,map_buffer_range} * @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} */ - void* map(GLintptr offset, GLsizeiptr length, MapFlags flags) { - return (this->*mapRangeImplementation)(offset, length, flags); - } + void* map(GLintptr offset, GLsizeiptr length, MapFlags flags); /** * @brief Flush mapped range @@ -849,10 +833,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @requires_gl30 %Extension @extension{ARB,map_buffer_range} * @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} */ - Buffer& flushMappedRange(GLintptr offset, GLsizeiptr length) { - (this->*flushMappedRangeImplementation)(offset, length); - return *this; - } + Buffer& flushMappedRange(GLintptr offset, GLsizeiptr length); /** * @brief Unmap buffer @@ -868,9 +849,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @fn_gl_extension{UnmapNamedBuffer,EXT,direct_state_access} * @requires_gles30 %Extension @es_extension{OES,mapbuffer} */ - bool unmap() { - return (this->*unmapImplementation)(); - } + bool unmap(); #if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT) /** @@ -888,89 +867,69 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { #endif private: - static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context); - static void bind(Target hint, GLuint id); Target MAGNUM_LOCAL bindInternal(Target hint); #ifndef MAGNUM_TARGET_GLES2 - typedef void(*CopyImplementation)(Buffer&, Buffer&, GLintptr, GLintptr, GLsizeiptr); static void MAGNUM_LOCAL copyImplementationDefault(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); #ifndef MAGNUM_TARGET_GLES static void MAGNUM_LOCAL copyImplementationDSA(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); #endif - static CopyImplementation copyImplementation; #endif - typedef void(Buffer::*GetParameterImplementation)(GLenum, GLint*); + #ifndef MAGNUM_TARGET_GLES + void subDataInternal(GLintptr offset, GLsizeiptr size, GLvoid* data); + #endif + void MAGNUM_LOCAL getParameterImplementationDefault(GLenum value, GLint* data); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL getParameterImplementationDSA(GLenum value, GLint* data); #endif - static MAGNUM_LOCAL GetParameterImplementation getParameterImplementation; #ifndef MAGNUM_TARGET_GLES - typedef void(Buffer::*GetSubDataImplementation)(GLintptr, GLsizeiptr, GLvoid*); void MAGNUM_LOCAL getSubDataImplementationDefault(GLintptr offset, GLsizeiptr size, GLvoid* data); void MAGNUM_LOCAL getSubDataImplementationDSA(GLintptr offset, GLsizeiptr size, GLvoid* data); - static GetSubDataImplementation getSubDataImplementation; #endif - typedef void(Buffer::*DataImplementation)(GLsizeiptr, const GLvoid*, BufferUsage); void MAGNUM_LOCAL dataImplementationDefault(GLsizeiptr size, const GLvoid* data, BufferUsage usage); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL dataImplementationDSA(GLsizeiptr size, const GLvoid* data, BufferUsage usage); #endif - static DataImplementation dataImplementation; - typedef void(Buffer::*SubDataImplementation)(GLintptr, GLsizeiptr, const GLvoid*); void MAGNUM_LOCAL subDataImplementationDefault(GLintptr offset, GLsizeiptr size, const GLvoid* data); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL subDataImplementationDSA(GLintptr offset, GLsizeiptr size, const GLvoid* data); #endif - static SubDataImplementation subDataImplementation; - typedef void(Buffer::*InvalidateImplementation)(); void MAGNUM_LOCAL invalidateImplementationNoOp(); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL invalidateImplementationARB(); #endif - static InvalidateImplementation invalidateImplementation; - typedef void(Buffer::*InvalidateSubImplementation)(GLintptr, GLsizeiptr); void MAGNUM_LOCAL invalidateSubImplementationNoOp(GLintptr offset, GLsizeiptr length); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL invalidateSubImplementationARB(GLintptr offset, GLsizeiptr length); #endif - static InvalidateSubImplementation invalidateSubImplementation; - typedef void*(Buffer::*MapImplementation)(MapAccess); void MAGNUM_LOCAL * mapImplementationDefault(MapAccess access); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL * mapImplementationDSA(MapAccess access); #endif - static MapImplementation mapImplementation; - typedef void*(Buffer::*MapRangeImplementation)(GLintptr, GLsizeiptr, MapFlags); void MAGNUM_LOCAL * mapRangeImplementationDefault(GLintptr offset, GLsizeiptr length, MapFlags access); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL * mapRangeImplementationDSA(GLintptr offset, GLsizeiptr length, MapFlags access); #endif - static MapRangeImplementation mapRangeImplementation; - typedef void(Buffer::*FlushMappedRangeImplementation)(GLintptr, GLsizeiptr); void MAGNUM_LOCAL flushMappedRangeImplementationDefault(GLintptr offset, GLsizeiptr length); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL flushMappedRangeImplementationDSA(GLintptr offset, GLsizeiptr length); #endif - static FlushMappedRangeImplementation flushMappedRangeImplementation; - typedef bool(Buffer::*UnmapImplementation)(); bool MAGNUM_LOCAL unmapImplementationDefault(); #ifndef MAGNUM_TARGET_GLES bool MAGNUM_LOCAL unmapImplementationDSA(); #endif - static UnmapImplementation unmapImplementation; GLuint _id; Target _targetHint; @@ -1003,7 +962,7 @@ template Containers::Array inline Buffer::data() { template Containers::Array inline Buffer::subData(const GLintptr offset, const GLsizeiptr size) { Containers::Array data(size); - if(size) (this->*getSubDataImplementation)(offset, size*sizeof(T), data); + if(size) subDataInternal(offset, size*sizeof(T), data); return std::move(data); } #endif diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 35df57aad..6297babc2 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -448,7 +448,6 @@ Context::Context() { _state = new Implementation::State(*this); /* Initialize functionality based on current OpenGL version and extensions */ - Buffer::initializeContextBasedFunctionality(*this); DefaultFramebuffer::initializeContextBasedFunctionality(*this); Mesh::initializeContextBasedFunctionality(*this); Renderer::initializeContextBasedFunctionality(*this); diff --git a/src/Magnum/Implementation/BufferState.cpp b/src/Magnum/Implementation/BufferState.cpp index 2c6fda44b..6be8f2945 100644 --- a/src/Magnum/Implementation/BufferState.cpp +++ b/src/Magnum/Implementation/BufferState.cpp @@ -27,6 +27,9 @@ #include +#include "Magnum/Context.h" +#include "Magnum/Extensions.h" + namespace Magnum { namespace Implementation { const Buffer::Target BufferState::targetForIndex[] = { @@ -75,4 +78,62 @@ std::size_t BufferState::indexForTarget(Buffer::Target target) { CORRADE_ASSERT_UNREACHABLE(); } +BufferState::BufferState(Context& context, std::vector& extensions): bindings() + #ifndef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES + , minMapAlignment(0), maxAtomicCounterBindings(0), maxShaderStorageBindings(0), shaderStorageOffsetAlignment(0) + #endif + , maxUniformBindings(0) + #endif +{ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); + + copyImplementation = &Buffer::copyImplementationDSA; + getParameterImplementation = &Buffer::getParameterImplementationDSA; + getSubDataImplementation = &Buffer::getSubDataImplementationDSA; + dataImplementation = &Buffer::dataImplementationDSA; + subDataImplementation = &Buffer::subDataImplementationDSA; + mapImplementation = &Buffer::mapImplementationDSA; + mapRangeImplementation = &Buffer::mapRangeImplementationDSA; + flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDSA; + unmapImplementation = &Buffer::unmapImplementationDSA; + } else + #endif + { + #ifndef MAGNUM_TARGET_GLES2 + copyImplementation = &Buffer::copyImplementationDefault; + #endif + getParameterImplementation = &Buffer::getParameterImplementationDefault; + #ifndef MAGNUM_TARGET_GLES + getSubDataImplementation = &Buffer::getSubDataImplementationDefault; + #endif + dataImplementation = &Buffer::dataImplementationDefault; + subDataImplementation = &Buffer::subDataImplementationDefault; + mapImplementation = &Buffer::mapImplementationDefault; + mapRangeImplementation = &Buffer::mapRangeImplementationDefault; + flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDefault; + unmapImplementation = &Buffer::unmapImplementationDefault; + } + + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::ARB::invalidate_subdata::string()); + + invalidateImplementation = &Buffer::invalidateImplementationARB; + invalidateSubImplementation = &Buffer::invalidateSubImplementationARB; + } else + #endif + { + invalidateImplementation = &Buffer::invalidateImplementationNoOp; + invalidateSubImplementation = &Buffer::invalidateSubImplementationNoOp; + } + + #ifdef MAGNUM_TARGET_GLES + static_cast(context); + static_cast(extensions); + #endif +} + }} diff --git a/src/Magnum/Implementation/BufferState.h b/src/Magnum/Implementation/BufferState.h index e45b5998e..4e16abb18 100644 --- a/src/Magnum/Implementation/BufferState.h +++ b/src/Magnum/Implementation/BufferState.h @@ -44,14 +44,23 @@ struct BufferState { static std::size_t indexForTarget(Buffer::Target target); static const Buffer::Target targetForIndex[TargetCount-1]; - constexpr BufferState(): bindings() - #ifndef MAGNUM_TARGET_GLES2 - #ifndef MAGNUM_TARGET_GLES - , minMapAlignment(0), maxAtomicCounterBindings(0), maxShaderStorageBindings(0), shaderStorageOffsetAlignment(0) - #endif - , maxUniformBindings(0) - #endif - {} + explicit BufferState(Context& context, std::vector& extensions); + + #ifndef MAGNUM_TARGET_GLES2 + void(*copyImplementation)(Buffer&, Buffer&, GLintptr, GLintptr, GLsizeiptr); + #endif + void(Buffer::*getParameterImplementation)(GLenum, GLint*); + #ifndef MAGNUM_TARGET_GLES2 + void(Buffer::*getSubDataImplementation)(GLintptr, GLsizeiptr, GLvoid*); + #endif + void(Buffer::*dataImplementation)(GLsizeiptr, const GLvoid*, BufferUsage); + void(Buffer::*subDataImplementation)(GLintptr, GLsizeiptr, const GLvoid*); + void(Buffer::*invalidateImplementation)(); + void(Buffer::*invalidateSubImplementation)(GLintptr, GLsizeiptr); + void*(Buffer::*mapImplementation)(Buffer::MapAccess); + void*(Buffer::*mapRangeImplementation)(GLintptr, GLsizeiptr, Buffer::MapFlags); + void(Buffer::*flushMappedRangeImplementation)(GLintptr, GLsizeiptr); + bool(Buffer::*unmapImplementation)(); /* Currently bound buffer for all targets */ GLuint bindings[TargetCount]; diff --git a/src/Magnum/Implementation/State.cpp b/src/Magnum/Implementation/State.cpp index f35b860a8..5daebb85e 100644 --- a/src/Magnum/Implementation/State.cpp +++ b/src/Magnum/Implementation/State.cpp @@ -51,7 +51,7 @@ State::State(Context& context) { extensions.reserve(8); #endif - buffer = new BufferState; + buffer = new BufferState(context, extensions); debug = new DebugState(context, extensions); framebuffer = new FramebufferState(context, extensions); mesh = new MeshState; From 1ad8be425feb29f62daaf5d446b6b962979f9c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 18:45:35 +0100 Subject: [PATCH 06/86] Moved global data from Mesh class to per-context state. --- src/Magnum/CMakeLists.txt | 1 + src/Magnum/Context.cpp | 1 - src/Magnum/Implementation/MeshState.cpp | 97 +++++++++++++++++++++++++ src/Magnum/Implementation/MeshState.h | 24 ++++-- src/Magnum/Implementation/State.cpp | 2 +- src/Magnum/Mesh.cpp | 83 ++++++--------------- src/Magnum/Mesh.h | 36 ++++----- 7 files changed, 152 insertions(+), 92 deletions(-) create mode 100644 src/Magnum/Implementation/MeshState.cpp diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 81f8b198b..b80bff4cb 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -55,6 +55,7 @@ set(Magnum_SRCS Implementation/BufferState.cpp Implementation/DebugState.cpp Implementation/FramebufferState.cpp + Implementation/MeshState.cpp Implementation/ShaderProgramState.cpp Implementation/State.cpp Implementation/TextureState.cpp diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 6297babc2..b4f8a5102 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -449,7 +449,6 @@ Context::Context() { /* Initialize functionality based on current OpenGL version and extensions */ DefaultFramebuffer::initializeContextBasedFunctionality(*this); - Mesh::initializeContextBasedFunctionality(*this); Renderer::initializeContextBasedFunctionality(*this); } diff --git a/src/Magnum/Implementation/MeshState.cpp b/src/Magnum/Implementation/MeshState.cpp new file mode 100644 index 000000000..3c9ac875a --- /dev/null +++ b/src/Magnum/Implementation/MeshState.cpp @@ -0,0 +1,97 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "MeshState.h" + +#include "Magnum/Context.h" +#include "Magnum/Extensions.h" + +namespace Magnum { namespace Implementation { + +MeshState::MeshState(Context& context, std::vector& extensions): currentVAO(0) + #ifndef MAGNUM_TARGET_GLES2 + , maxElementsIndices(0), maxElementsVertices(0) + #endif +{ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) + #elif defined(MAGNUM_TARGET_GLES2) + if(context.isExtensionSupported()) + #else + static_cast(context); + static_cast(extensions); + #endif + { + #ifndef MAGNUM_TARGET_GLES + extensions.push_back(Extensions::GL::APPLE::vertex_array_object::string()); + #elif defined(MAGNUM_TARGET_GLES2) + extensions.push_back(Extensions::GL::OES::vertex_array_object::string()); + #endif + + createImplementation = &Mesh::createImplementationVAO; + destroyImplementation = &Mesh::destroyImplementationVAO; + + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); + + attributePointerImplementation = &Mesh::attributePointerImplementationDSA; + attributeIPointerImplementation = &Mesh::attributePointerImplementationDSA; + attributeLPointerImplementation = &Mesh::attributePointerImplementationDSA; + } else + #endif + { + attributePointerImplementation = &Mesh::attributePointerImplementationVAO; + #ifndef MAGNUM_TARGET_GLES2 + attributeIPointerImplementation = &Mesh::attributePointerImplementationVAO; + #ifndef MAGNUM_TARGET_GLES + attributeLPointerImplementation = &Mesh::attributePointerImplementationVAO; + #endif + #endif + } + + bindIndexBufferImplementation = &Mesh::bindIndexBufferImplementationVAO; + bindImplementation = &Mesh::bindImplementationVAO; + unbindImplementation = &Mesh::unbindImplementationVAO; + } + #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) + else { + createImplementation = &Mesh::createImplementationDefault; + destroyImplementation = &Mesh::destroyImplementationDefault; + attributePointerImplementation = &Mesh::attributePointerImplementationDefault; + #ifndef MAGNUM_TARGET_GLES2 + attributeIPointerImplementation = &Mesh::attributePointerImplementationDefault; + #ifndef MAGNUM_TARGET_GLES + attributeLPointerImplementation = &Mesh::attributePointerImplementationDefault; + #endif + #endif + bindIndexBufferImplementation = &Mesh::bindIndexBufferImplementationDefault; + bindImplementation = &Mesh::bindImplementationDefault; + unbindImplementation = &Mesh::unbindImplementationDefault; + } + #endif +} + +}} diff --git a/src/Magnum/Implementation/MeshState.h b/src/Magnum/Implementation/MeshState.h index f13964970..ea4885b4f 100644 --- a/src/Magnum/Implementation/MeshState.h +++ b/src/Magnum/Implementation/MeshState.h @@ -25,16 +25,28 @@ DEALINGS IN THE SOFTWARE. */ -#include "Magnum/Magnum.h" +#include +#include + +#include "Magnum/Mesh.h" namespace Magnum { namespace Implementation { struct MeshState { - constexpr MeshState(): currentVAO(0) - #ifndef MAGNUM_TARGET_GLES2 - , maxElementsIndices(0), maxElementsVertices(0) - #endif - {} + explicit MeshState(Context& context, std::vector& extensions); + + void(Mesh::*createImplementation)(); + void(Mesh::*destroyImplementation)(); + void(Mesh::*attributePointerImplementation)(const Mesh::Attribute&); + #ifndef MAGNUM_TARGET_GLES2 + void(Mesh::*attributeIPointerImplementation)(const Mesh::IntegerAttribute&); + #ifndef MAGNUM_TARGET_GLES + void(Mesh::*attributeLPointerImplementation)(const Mesh::LongAttribute&); + #endif + #endif + void(Mesh::*bindIndexBufferImplementation)(Buffer&); + void(Mesh::*bindImplementation)(); + void(Mesh::*unbindImplementation)(); GLuint currentVAO; #ifndef MAGNUM_TARGET_GLES2 diff --git a/src/Magnum/Implementation/State.cpp b/src/Magnum/Implementation/State.cpp index 5daebb85e..bb5b0c1be 100644 --- a/src/Magnum/Implementation/State.cpp +++ b/src/Magnum/Implementation/State.cpp @@ -54,7 +54,7 @@ State::State(Context& context) { buffer = new BufferState(context, extensions); debug = new DebugState(context, extensions); framebuffer = new FramebufferState(context, extensions); - mesh = new MeshState; + mesh = new MeshState(context, extensions); renderer = new RendererState; shader = new ShaderState; shaderProgram = new ShaderProgramState(context, extensions); diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp index bc156867c..3db838837 100644 --- a/src/Magnum/Mesh.cpp +++ b/src/Magnum/Mesh.cpp @@ -38,19 +38,6 @@ namespace Magnum { -Mesh::CreateImplementation Mesh::createImplementation = &Mesh::createImplementationDefault; -Mesh::DestroyImplementation Mesh::destroyImplementation = &Mesh::destroyImplementationDefault; -Mesh::AttributePointerImplementation Mesh::attributePointerImplementation = &Mesh::attributePointerImplementationDefault; -#ifndef MAGNUM_TARGET_GLES2 -Mesh::AttributeIPointerImplementation Mesh::attributeIPointerImplementation = &Mesh::attributePointerImplementationDefault; -#ifndef MAGNUM_TARGET_GLES -Mesh::AttributeLPointerImplementation Mesh::attributeLPointerImplementation = &Mesh::attributePointerImplementationDefault; -#endif -#endif -Mesh::BindIndexBufferImplementation Mesh::bindIndexBufferImplementation = &Mesh::bindIndexBufferImplementationDefault; -Mesh::BindImplementation Mesh::bindImplementation = &Mesh::bindImplementationDefault; -Mesh::UnbindImplementation Mesh::unbindImplementation = &Mesh::unbindImplementationDefault; - Int Mesh::maxVertexAttributes() { return AbstractShaderProgram::maxVertexAttributes(); } #ifndef MAGNUM_TARGET_GLES2 @@ -91,7 +78,7 @@ Mesh::Mesh(MeshPrimitive primitive): _primitive(primitive), _vertexCount(0), _in #endif , _indexOffset(0), _indexType(IndexType::UnsignedInt), _indexBuffer(nullptr) { - (this->*createImplementation)(); + (this->*Context::current()->state().mesh->createImplementation)(); } Mesh::~Mesh() { @@ -102,7 +89,7 @@ Mesh::~Mesh() { GLuint& current = Context::current()->state().mesh->currentVAO; if(current == _id) current = 0; - (this->*destroyImplementation)(); + (this->*Context::current()->state().mesh->destroyImplementation)(); } Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive), _vertexCount(other._vertexCount), _indexCount(other._indexCount) @@ -175,7 +162,7 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, Unsi static_cast(start); static_cast(end); #endif - (this->*bindIndexBufferImplementation)(buffer); + (this->*Context::current()->state().mesh->bindIndexBufferImplementation)(buffer); return *this; } @@ -188,7 +175,7 @@ void Mesh::drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, /* Nothing to draw */ if(!vertexCount && !indexCount) return; - (this->*bindImplementation)(); + (this->*Context::current()->state().mesh->bindImplementation)(); /* Non-indexed mesh */ if(!indexCount) @@ -204,7 +191,7 @@ void Mesh::drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, else glDrawElements(GLenum(_primitive), indexCount, GLenum(_indexType), reinterpret_cast(indexOffset)); - (this->*unbindImplementation)(); + (this->*Context::current()->state().mesh->unbindImplementation)(); } void Mesh::bindVAO(GLuint vao) { @@ -220,6 +207,22 @@ void Mesh::bindVAO(GLuint vao) { } } +void Mesh::attributePointerInternal(const Attribute& attribute) { + (this->*Context::current()->state().mesh->attributePointerImplementation)(attribute); +} + +#ifndef MAGNUM_TARGET_GLES2 +void Mesh::attributePointerInternal(const IntegerAttribute& attribute) { + (this->*Context::current()->state().mesh->attributeIPointerImplementation)(attribute); +} + +#ifndef MAGNUM_TARGET_GLES +void Mesh::attributePointerInternal(const LongAttribute& attribute) { + (this->*Context::current()->state().mesh->attributeLPointerImplementation)(attribute); +} +#endif +#endif + void Mesh::vertexAttribPointer(const Attribute& attribute) { glEnableVertexAttribArray(attribute.location); attribute.buffer->bind(Buffer::Target::Array); @@ -242,50 +245,6 @@ void Mesh::vertexAttribPointer(const LongAttribute& attribute) { #endif #endif -void Mesh::initializeContextBasedFunctionality(Context& context) { - /** @todo Enable when some extension wrangler is available in ES 2.0 */ - #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) - #elif defined(MAGNUM_TARGET_GLES2) - if(context.isExtensionSupported()) - #else - static_cast(context); - #endif - { - #ifndef MAGNUM_TARGET_GLES - Debug() << "Mesh: using" << Extensions::GL::APPLE::vertex_array_object::string() << "features"; - #elif defined(MAGNUM_TARGET_GLES2) - Debug() << "Mesh: using" << Extensions::GL::OES::vertex_array_object::string() << "features"; - #endif - - createImplementation = &Mesh::createImplementationVAO; - destroyImplementation = &Mesh::destroyImplementationVAO; - - #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) { - Debug() << "Mesh: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; - - attributePointerImplementation = &Mesh::attributePointerImplementationDSA; - attributeIPointerImplementation = &Mesh::attributePointerImplementationDSA; - attributeLPointerImplementation = &Mesh::attributePointerImplementationDSA; - } else - #endif - { - attributePointerImplementation = &Mesh::attributePointerImplementationVAO; - #ifndef MAGNUM_TARGET_GLES2 - attributeIPointerImplementation = &Mesh::attributePointerImplementationVAO; - #ifndef MAGNUM_TARGET_GLES - attributeLPointerImplementation = &Mesh::attributePointerImplementationVAO; - #endif - #endif - } - - bindIndexBufferImplementation = &Mesh::bindIndexBufferImplementationVAO; - bindImplementation = &Mesh::bindImplementationVAO; - unbindImplementation = &Mesh::unbindImplementationVAO; - } -} - void Mesh::createImplementationDefault() { _id = 0; } void Mesh::createImplementationVAO() { diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 4330ed735..06055855f 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -115,6 +115,8 @@ enum class MeshPrimitive: GLenum { #endif }; +namespace Implementation { class MeshState; } + /** @brief %Mesh @@ -313,7 +315,7 @@ drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also @todo How to glDrawElementsBaseVertex()/vertex offset -- in draw()? */ class MAGNUM_EXPORT Mesh: public AbstractObject { - friend class Context; + friend class Implementation::MeshState; friend class MeshView; public: @@ -657,8 +659,6 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { #endif #endif - static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context); - /* Computing stride of interleaved vertex attributes */ template inline static GLsizei strideOfInterleaved(const AbstractShaderProgram::Attribute& attribute, const U&... attributes) { return attribute.vectorSize()*AbstractShaderProgram::Attribute::VectorCount + strideOfInterleaved(attributes...); @@ -683,7 +683,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { template inline void addVertexAttribute(typename std::enable_if::Type, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute::VectorCount; ++i) - (this->*attributePointerImplementation)(Attribute{ + attributePointerInternal(Attribute{ &buffer, location+i, GLint(attribute.components()), @@ -696,7 +696,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { #ifndef MAGNUM_TARGET_GLES2 template inline void addVertexAttribute(typename std::enable_if::Type>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { - (this->*attributeIPointerImplementation)(IntegerAttribute{ + attributePointerInternal(IntegerAttribute{ &buffer, location, GLint(attribute.components()), @@ -709,7 +709,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { #ifndef MAGNUM_TARGET_GLES template inline void addVertexAttribute(typename std::enable_if::Type, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute::VectorCount; ++i) - (this->*attributeLPointerImplementation)(LongAttribute{ + attributePointerInternal(LongAttribute{ &buffer, location+i, GLint(attribute.components()), @@ -723,6 +723,14 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { static void MAGNUM_LOCAL bindVAO(GLuint vao); + void attributePointerInternal(const Attribute& attribute); + #ifndef MAGNUM_TARGET_GLES2 + void attributePointerInternal(const IntegerAttribute& attribute); + #ifndef MAGNUM_TARGET_GLES + void attributePointerInternal(const LongAttribute& attribute); + #endif + #endif + void MAGNUM_LOCAL vertexAttribPointer(const Attribute& attribute); #ifndef MAGNUM_TARGET_GLES2 void MAGNUM_LOCAL vertexAttribPointer(const IntegerAttribute& attribute); @@ -737,56 +745,40 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { void drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount); #endif - typedef void(Mesh::*CreateImplementation)(); void MAGNUM_LOCAL createImplementationDefault(); void MAGNUM_LOCAL createImplementationVAO(); - static MAGNUM_LOCAL CreateImplementation createImplementation; - typedef void(Mesh::*DestroyImplementation)(); void MAGNUM_LOCAL destroyImplementationDefault(); void MAGNUM_LOCAL destroyImplementationVAO(); - static MAGNUM_LOCAL DestroyImplementation destroyImplementation; - typedef void(Mesh::*AttributePointerImplementation)(const Attribute&); void MAGNUM_LOCAL attributePointerImplementationDefault(const Attribute& attribute); void MAGNUM_LOCAL attributePointerImplementationVAO(const Attribute& attribute); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL attributePointerImplementationDSA(const Attribute& attribute); #endif - static AttributePointerImplementation attributePointerImplementation; #ifndef MAGNUM_TARGET_GLES2 - typedef void(Mesh::*AttributeIPointerImplementation)(const IntegerAttribute&); void MAGNUM_LOCAL attributePointerImplementationDefault(const IntegerAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationVAO(const IntegerAttribute& attribute); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL attributePointerImplementationDSA(const IntegerAttribute& attribute); #endif - static AttributeIPointerImplementation attributeIPointerImplementation; #ifndef MAGNUM_TARGET_GLES - typedef void(Mesh::*AttributeLPointerImplementation)(const LongAttribute&); void MAGNUM_LOCAL attributePointerImplementationDefault(const LongAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationVAO(const LongAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationDSA(const LongAttribute& attribute); - static AttributeLPointerImplementation attributeLPointerImplementation; #endif #endif - typedef void(Mesh::*BindIndexBufferImplementation)(Buffer&); void MAGNUM_LOCAL bindIndexBufferImplementationDefault(Buffer& buffer); void MAGNUM_LOCAL bindIndexBufferImplementationVAO(Buffer& buffer); - static MAGNUM_LOCAL BindIndexBufferImplementation bindIndexBufferImplementation; - typedef void(Mesh::*BindImplementation)(); void MAGNUM_LOCAL bindImplementationDefault(); void MAGNUM_LOCAL bindImplementationVAO(); - static MAGNUM_LOCAL BindImplementation bindImplementation; - typedef void(Mesh::*UnbindImplementation)(); void MAGNUM_LOCAL unbindImplementationDefault(); void MAGNUM_LOCAL unbindImplementationVAO(); - static MAGNUM_LOCAL UnbindImplementation unbindImplementation; GLuint _id; MeshPrimitive _primitive; From 5d938e7f4f5ef49edc9e63e20a24e4203ee5ce49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 19:04:04 +0100 Subject: [PATCH 07/86] Moved global data from Renderer class to per-context state. --- src/Magnum/CMakeLists.txt | 1 + src/Magnum/Context.cpp | 3 +- src/Magnum/Implementation/RendererState.cpp | 64 +++++++++++++++++++++ src/Magnum/Implementation/RendererState.h | 8 ++- src/Magnum/Implementation/State.cpp | 2 +- src/Magnum/Renderer.cpp | 39 +++---------- src/Magnum/Renderer.h | 17 ++---- 7 files changed, 89 insertions(+), 45 deletions(-) create mode 100644 src/Magnum/Implementation/RendererState.cpp diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index b80bff4cb..9b619b6f9 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -56,6 +56,7 @@ set(Magnum_SRCS Implementation/DebugState.cpp Implementation/FramebufferState.cpp Implementation/MeshState.cpp + Implementation/RendererState.cpp Implementation/ShaderProgramState.cpp Implementation/State.cpp Implementation/TextureState.cpp diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index b4f8a5102..8cd802928 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -448,8 +448,9 @@ Context::Context() { _state = new Implementation::State(*this); /* Initialize functionality based on current OpenGL version and extensions */ + /** @todo Get rid of these */ DefaultFramebuffer::initializeContextBasedFunctionality(*this); - Renderer::initializeContextBasedFunctionality(*this); + Renderer::initializeContextBasedFunctionality(); } Context::~Context() { diff --git a/src/Magnum/Implementation/RendererState.cpp b/src/Magnum/Implementation/RendererState.cpp new file mode 100644 index 000000000..9c4a932d1 --- /dev/null +++ b/src/Magnum/Implementation/RendererState.cpp @@ -0,0 +1,64 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "RendererState.h" + +#include "Magnum/Context.h" +#include "Magnum/Extensions.h" + +namespace Magnum { namespace Implementation { + +RendererState::RendererState(Context& context, std::vector& extensions): resetNotificationStrategy() { + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) + #endif + { + #ifndef MAGNUM_TARGET_GLES + extensions.push_back(Extensions::GL::ARB::ES2_compatibility::string()); + #endif + + clearDepthfImplementation = &Renderer::clearDepthfImplementationES; + } + #ifndef MAGNUM_TARGET_GLES + else clearDepthfImplementation = &Renderer::clearDepthfImplementationDefault; + #endif + + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) + #else + if(context.isExtensionSupported()) + #endif + { + #ifndef MAGNUM_TARGET_GLES + extensions.push_back(Extensions::GL::ARB::robustness::string()); + #else + extensions.push_back(Extensions::GL::EXT::robustness::string()); + #endif + + graphicsResetStatusImplementation = &Renderer::graphicsResetStatusImplementationRobustness; + } else graphicsResetStatusImplementation = &Renderer::graphicsResetStatusImplementationDefault; +} + +}} diff --git a/src/Magnum/Implementation/RendererState.h b/src/Magnum/Implementation/RendererState.h index 962fa0587..33483e632 100644 --- a/src/Magnum/Implementation/RendererState.h +++ b/src/Magnum/Implementation/RendererState.h @@ -25,12 +25,18 @@ DEALINGS IN THE SOFTWARE. */ +#include +#include + #include "Magnum/Renderer.h" namespace Magnum { namespace Implementation { struct RendererState { - constexpr RendererState(): resetNotificationStrategy() {} + explicit RendererState(Context& context, std::vector& extensions); + + void(*clearDepthfImplementation)(GLfloat); + Renderer::GraphicsResetStatus(*graphicsResetStatusImplementation)(); Renderer::ResetNotificationStrategy resetNotificationStrategy; }; diff --git a/src/Magnum/Implementation/State.cpp b/src/Magnum/Implementation/State.cpp index bb5b0c1be..82354e734 100644 --- a/src/Magnum/Implementation/State.cpp +++ b/src/Magnum/Implementation/State.cpp @@ -55,7 +55,7 @@ State::State(Context& context) { debug = new DebugState(context, extensions); framebuffer = new FramebufferState(context, extensions); mesh = new MeshState(context, extensions); - renderer = new RendererState; + renderer = new RendererState(context, extensions); shader = new ShaderState; shaderProgram = new ShaderProgramState(context, extensions); texture = new TextureState(context, extensions); diff --git a/src/Magnum/Renderer.cpp b/src/Magnum/Renderer.cpp index 78e0933b7..2020d6775 100644 --- a/src/Magnum/Renderer.cpp +++ b/src/Magnum/Renderer.cpp @@ -28,20 +28,12 @@ #include "Magnum/Math/Range.h" #include "Magnum/Color.h" #include "Magnum/Context.h" -#include "Magnum/Extensions.h" #include "Implementation/State.h" #include "Implementation/RendererState.h" namespace Magnum { -#ifndef MAGNUM_TARGET_GLES -Renderer::ClearDepthfImplementation Renderer::clearDepthfImplementation = &Renderer::clearDepthfImplementationDefault; -#else -Renderer::ClearDepthfImplementation Renderer::clearDepthfImplementation = &Renderer::clearDepthfImplementationES; -#endif -Renderer::GraphicsResetStatusImplementation Renderer::graphicsResetStatusImplementation = &Renderer::graphicsResetStatusImplementationDefault; - void Renderer::setFeature(const Feature feature, const bool enabled) { enabled ? glEnable(GLenum(feature)) : glDisable(GLenum(feature)); } @@ -60,6 +52,10 @@ void Renderer::setClearDepth(const Double depth) { } #endif +void Renderer::setClearDepth(Float depth) { + Context::current()->state().renderer->clearDepthfImplementation(depth); +} + void Renderer::setClearStencil(const Int stencil) { glClearStencil(stencil); } @@ -176,30 +172,11 @@ Renderer::ResetNotificationStrategy Renderer::resetNotificationStrategy() { return strategy; } -void Renderer::initializeContextBasedFunctionality(Context& context) { - #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) { - Debug() << "Renderer: using" << Extensions::GL::ARB::ES2_compatibility::string() << "features"; - - clearDepthfImplementation = &Renderer::clearDepthfImplementationES; - } - #endif - - #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) - #else - if(context.isExtensionSupported()) - #endif - { - #ifndef MAGNUM_TARGET_GLES - Debug() << "Renderer: using" << Extensions::GL::ARB::robustness::string() << "features"; - #else - Debug() << "Renderer: using" << Extensions::GL::EXT::robustness::string() << "features"; - #endif - - graphicsResetStatusImplementation = &Renderer::graphicsResetStatusImplementationRobustness; - } +Renderer::GraphicsResetStatus Renderer::graphicsResetStatus() { + return Context::current()->state().renderer->graphicsResetStatusImplementation(); +} +void Renderer::initializeContextBasedFunctionality() { /* Set some "corporate identity" */ setClearColor(Color3(0.125f)); } diff --git a/src/Magnum/Renderer.h b/src/Magnum/Renderer.h index f09d271f2..9040c6411 100644 --- a/src/Magnum/Renderer.h +++ b/src/Magnum/Renderer.h @@ -37,6 +37,8 @@ namespace Magnum { +namespace Implementation { struct RendererState; } + /** @nosubgrouping @brief Global renderer configuration. @@ -46,6 +48,7 @@ namespace Magnum { @todo `GL_MAX_CLIP_DISTANCES`... */ class MAGNUM_EXPORT Renderer { + friend class Implementation::RendererState; friend class Context; public: @@ -287,9 +290,7 @@ class MAGNUM_EXPORT Renderer { * If OpenGL ES, OpenGL 4.1 or extension @extension{ARB,ES2_compatibility} * is not available, this function behaves exactly as setClearDepth(Double). */ - static void setClearDepth(Float depth) { - clearDepthfImplementation(depth); - } + static void setClearDepth(Float depth); /** * @brief Set clear stencil @@ -1037,26 +1038,20 @@ class MAGNUM_EXPORT Renderer { * is not available, this function always returns @ref GraphicsResetStatus::NoError. * @see @ref resetNotificationStrategy(), @fn_gl_extension{GetGraphicsResetStatus,ARB,robustness} */ - static GraphicsResetStatus graphicsResetStatus() { - return graphicsResetStatusImplementation(); - } + static GraphicsResetStatus graphicsResetStatus(); /*@}*/ private: - static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context); + static void MAGNUM_LOCAL initializeContextBasedFunctionality(); - typedef void(*ClearDepthfImplementation)(GLfloat); #ifndef MAGNUM_TARGET_GLES static void MAGNUM_LOCAL clearDepthfImplementationDefault(GLfloat depth); #endif static void MAGNUM_LOCAL clearDepthfImplementationES(GLfloat depth); - static ClearDepthfImplementation clearDepthfImplementation; - typedef GraphicsResetStatus(*GraphicsResetStatusImplementation)(); static GraphicsResetStatus MAGNUM_LOCAL graphicsResetStatusImplementationDefault(); static GraphicsResetStatus MAGNUM_LOCAL graphicsResetStatusImplementationRobustness(); - static GraphicsResetStatusImplementation graphicsResetStatusImplementation; }; /** @debugoperator{Renderer} */ From 1ef4a364c9db3473b02a612963f568c1468b0658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 19:05:42 +0100 Subject: [PATCH 08/86] doc: actually we have a way to retrieve object labels. Not sure why I forgot it. --- doc/opengl-mapping.dox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 9af6e3774..6784f3980 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -155,7 +155,7 @@ OpenGL function | Matching API @fn_gl_extension{GetGraphicsResetStatus,ARB,robustness} | @ref Renderer::graphicsResetStatus() @fn_gl{GetInternalformat} | | @fn_gl{GetMultisample} | | -@fn_gl{GetObjectLabel}, \n @fn_gl{GetObjectPtrLabel} | not queryable, @ref AbstractShaderProgram::setLabel(), \n @ref AbstractQuery::setLabel(), \n @ref AbstractTexture::setLabel(), \n @ref Buffer::setLabel(), \n @ref Framebuffer::setLabel(), \n @ref Mesh::setLabel(), \n @ref Renderbuffer::setLabel() and \n @ref Shader::setLabel() setters only +@fn_gl{GetObjectLabel}, \n @fn_gl{GetObjectPtrLabel} | @ref AbstractShaderProgram::label(), \n @ref AbstractQuery::label(), \n @ref AbstractTexture::label(), \n @ref Buffer::label(), \n @ref Framebuffer::label(), \n @ref Mesh::label(), \n @ref Renderbuffer::label(), \n @ref Shader::label() @fn_gl{GetProgram}, \n @fn_gl{GetProgramInfoLog} | @ref AbstractShaderProgram::link(), \n @ref AbstractShaderProgram::validate() @fn_gl{GetProgramBinary} | | @fn_gl{GetProgramInterface} | | From 57ca8ee909786fa9ae8dacea00783e133123de54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 19:06:11 +0100 Subject: [PATCH 09/86] Removed Buffer::maxVertexAttributeBindings(). This queries limit for ARB_vertex_attrib_binding extension, which isn't and probably won't be implemented in near future. --- doc/opengl-mapping.dox | 2 +- src/Magnum/Buffer.h | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 6784f3980..c1ab1a932 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -343,7 +343,7 @@ OpenGL function | Matching API @def_gl{MAX_UNIFORM_BUFFER_BINDINGS} | @ref Buffer::maxUniformBindings() @def_gl{MAX_UNIFORM_LOCATIONS} | @ref AbstractShaderProgram::maxUniformLocations() @def_gl{MAX_VERTEX_ATTRIBS} | @ref AbstractShaderProgram::maxVertexAttributes() -@def_gl{MAX_VERTEX_ATTRIB_BINDINGS} | @ref Buffer::maxVertexAttributeBindings() +@def_gl{MAX_VERTEX_ATTRIB_BINDINGS} | | @def_gl{MAX_VERTEX_ATTRIB_RELATIVE_OFFSET} | | @def_gl{MAX_VIEWPORTS} | | @def_gl{MAX_VIEWPORT_DIMS} | @ref AbstractFramebuffer::maxViewportSize() diff --git a/src/Magnum/Buffer.h b/src/Magnum/Buffer.h index c64f03ad3..0da729a9c 100644 --- a/src/Magnum/Buffer.h +++ b/src/Magnum/Buffer.h @@ -479,15 +479,6 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { static Int maxUniformBindings(); #endif - /** - * @brief Max supported vertex buffer binding count - * - * The result is cached, repeated queries don't result in repeated - * OpenGL calls. - * @see @fn_gl{Get} with @def_gl{MAX_VERTEX_ATTRIB_BINDINGS} - */ - static Int maxVertexAttributeBindings(); - /** * @brief Unbind any buffer from given target * @param target %Target From 1d218cbed29bffb2102b5f195c77171206bc4047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 19:10:00 +0100 Subject: [PATCH 10/86] Enable Buffer::invalidate*Data() on ES. This smells fishy. The function _does have_ a no-op fallback implementation to remove the need to wrap everything with an #ifdef and/or extension check, so why I did exactly that everywhere? --- src/Magnum/Buffer.cpp | 2 -- src/Magnum/Buffer.h | 2 -- src/Magnum/Test/BufferGLTest.cpp | 12 +----------- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/src/Magnum/Buffer.cpp b/src/Magnum/Buffer.cpp index 9dd2a23b9..d37f253ae 100644 --- a/src/Magnum/Buffer.cpp +++ b/src/Magnum/Buffer.cpp @@ -195,7 +195,6 @@ Buffer& Buffer::setSubData(const GLintptr offset, const Containers::ArrayReferen return *this; } -#ifndef MAGNUM_TARGET_GLES Buffer& Buffer::invalidateData() { (this->*Context::current()->state().buffer->invalidateImplementation)(); return *this; @@ -205,7 +204,6 @@ Buffer& Buffer::invalidateSubData(const GLintptr offset, const GLsizeiptr length (this->*Context::current()->state().buffer->invalidateSubImplementation)(offset, length); return *this; } -#endif void* Buffer::map(const MapAccess access) { return (this->*Context::current()->state().buffer->mapImplementation)(access); diff --git a/src/Magnum/Buffer.h b/src/Magnum/Buffer.h index 0da729a9c..386f682bf 100644 --- a/src/Magnum/Buffer.h +++ b/src/Magnum/Buffer.h @@ -722,7 +722,6 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { return *this; } - #ifndef MAGNUM_TARGET_GLES /** * @brief Invalidate buffer data * @return Reference to self (for method chaining) @@ -744,7 +743,6 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @see @ref MapFlag::InvalidateRange, @fn_gl{InvalidateBufferData} */ Buffer& invalidateSubData(GLintptr offset, GLsizeiptr length); - #endif /** * @brief Map buffer to client memory diff --git a/src/Magnum/Test/BufferGLTest.cpp b/src/Magnum/Test/BufferGLTest.cpp index a5b629d81..e7e04c8de 100644 --- a/src/Magnum/Test/BufferGLTest.cpp +++ b/src/Magnum/Test/BufferGLTest.cpp @@ -53,9 +53,7 @@ class BufferGLTest: public AbstractOpenGLTester { #ifndef MAGNUM_TARGET_GLES2 void copy(); #endif - #ifndef MAGNUM_TARGET_GLES2 void invalidate(); - #endif }; BufferGLTest::BufferGLTest() { @@ -71,10 +69,7 @@ BufferGLTest::BufferGLTest() { #ifndef MAGNUM_TARGET_GLES2 &BufferGLTest::copy, #endif - #ifndef MAGNUM_TARGET_GLES - &BufferGLTest::invalidate - #endif - }); + &BufferGLTest::invalidate}); } void BufferGLTest::construct() { @@ -348,11 +343,7 @@ void BufferGLTest::copy() { } #endif -#ifndef MAGNUM_TARGET_GLES void BufferGLTest::invalidate() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::invalidate_subdata::string() + std::string(" is not supported")); - Buffer buffer; constexpr char data[] = {2, 7, 5, 13, 25}; buffer.setData(data, BufferUsage::StaticDraw); @@ -365,7 +356,6 @@ void BufferGLTest::invalidate() { buffer.invalidateData(); MAGNUM_VERIFY_NO_ERROR(); } -#endif }} From 932e6294560451526869237da00ac93324756883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 19:13:53 +0100 Subject: [PATCH 11/86] Actually implement the fallback for Renderer::resetNotificationStrategy(). It was documented and all, but wasn't ever implemented. --- src/Magnum/Renderer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Magnum/Renderer.cpp b/src/Magnum/Renderer.cpp index 2020d6775..e35a83c7f 100644 --- a/src/Magnum/Renderer.cpp +++ b/src/Magnum/Renderer.cpp @@ -28,6 +28,7 @@ #include "Magnum/Math/Range.h" #include "Magnum/Color.h" #include "Magnum/Context.h" +#include "Magnum/Extensions.h" #include "Implementation/State.h" #include "Implementation/RendererState.h" @@ -159,6 +160,13 @@ void Renderer::setLogicOperation(const LogicOperation operation) { #endif Renderer::ResetNotificationStrategy Renderer::resetNotificationStrategy() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + #else + if(!Context::current()->isExtensionSupported()) + #endif + return ResetNotificationStrategy::NoResetNotification; + ResetNotificationStrategy& strategy = Context::current()->state().renderer->resetNotificationStrategy; if(strategy == ResetNotificationStrategy()) { From 11522ac0cf28a2f830a784186616968e1c6f667a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 20:07:34 +0100 Subject: [PATCH 12/86] Get rid of pointers in internal texture implementation. --- src/Magnum/AbstractTexture.cpp | 114 +++++++++++++++---------------- src/Magnum/AbstractTexture.h | 48 ++++++------- src/Magnum/CubeMapTexture.h | 18 ++--- src/Magnum/CubeMapTextureArray.h | 16 ++--- src/Magnum/Texture.h | 16 ++--- 5 files changed, 106 insertions(+), 106 deletions(-) diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index b0d43a9bc..a60870426 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -906,7 +906,7 @@ void AbstractTexture::invalidateSubImageImplementationARB(GLint level, const Vec #ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_TARGET_GLES template void AbstractTexture::image(GLenum target, GLint level, Image& image) { - const Math::Vector size = DataHelper::imageSize(this, target, level); + const Math::Vector size = DataHelper::imageSize(*this, target, level); const std::size_t dataSize = size.product()*image.pixelSize(); char* data = new char[dataSize]; (this->*Context::current()->state().texture->getImageImplementation)(target, level, image.format(), image.type(), dataSize, data); @@ -918,7 +918,7 @@ template void MAGNUM_EXPORT AbstractTexture::image<2>(GLenum, GLint, Image<2>&); template void MAGNUM_EXPORT AbstractTexture::image<3>(GLenum, GLint, Image<3>&); template void AbstractTexture::image(GLenum target, GLint level, BufferImage& image, BufferUsage usage) { - const Math::Vector size = DataHelper::imageSize(this, target, level); + const Math::Vector size = DataHelper::imageSize(*this, target, level); const std::size_t dataSize = size.product()*image.pixelSize(); if(image.size() != size) image.setData(image.format(), image.type(), size, nullptr, usage); @@ -935,162 +935,162 @@ template void MAGNUM_EXPORT AbstractTexture::image<3>(GLenum, GLint, BufferImage #ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_TARGET_GLES -Math::Vector<1, GLint> AbstractTexture::DataHelper<1>::imageSize(AbstractTexture* texture, GLenum target, GLint level) { +Math::Vector<1, GLint> AbstractTexture::DataHelper<1>::imageSize(AbstractTexture& texture, const GLenum target, const GLint level) { Math::Vector<1, GLint> value; - (texture->*Context::current()->state().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) { +Vector2i AbstractTexture::DataHelper<2>::imageSize(AbstractTexture& texture, const GLenum target, const GLint level) { const Implementation::TextureState& state = *Context::current()->state().texture; Vector2i value; - (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_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) { +Vector3i AbstractTexture::DataHelper<3>::imageSize(AbstractTexture& texture, const GLenum target, const GLint level) { const Implementation::TextureState& state = *Context::current()->state().texture; Vector3i value; - (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]); + (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); +void AbstractTexture::DataHelper<1>::setStorage(AbstractTexture& 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<2>::setStorage(AbstractTexture& 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); +void AbstractTexture::DataHelper<3>::setStorage(AbstractTexture& 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) { +void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference1D& image) { Buffer::unbind(Buffer::Target::PixelUnpack); - (texture->*Context::current()->state().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) { +void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage1D& image) { image.buffer().bind(Buffer::Target::PixelUnpack); - (texture->*Context::current()->state().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) { +void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Math::Vector<1, GLint>& offset, const ImageReference1D& image) { Buffer::unbind(Buffer::Target::PixelUnpack); - (texture->*Context::current()->state().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) { +void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) { image.buffer().bind(Buffer::Target::PixelUnpack); - (texture->*Context::current()->state().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 -void AbstractTexture::DataHelper<2>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference2D& image) { +void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference2D& image) { #ifndef MAGNUM_TARGET_GLES2 Buffer::unbind(Buffer::Target::PixelUnpack); #endif - (texture->*Context::current()->state().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) { +void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage2D& image) { image.buffer().bind(Buffer::Target::PixelUnpack); - (texture->*Context::current()->state().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 -void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Vector2i& offset, const ImageReference2D& image) { +void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Vector2i& offset, const ImageReference2D& image) { #ifndef MAGNUM_TARGET_GLES2 Buffer::unbind(Buffer::Target::PixelUnpack); #endif - (texture->*Context::current()->state().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) { +void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Vector2i& offset, BufferImage2D& image) { image.buffer().bind(Buffer::Target::PixelUnpack); - (texture->*Context::current()->state().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 -void AbstractTexture::DataHelper<3>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference3D& image) { +void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference3D& image) { #ifndef MAGNUM_TARGET_GLES2 Buffer::unbind(Buffer::Target::PixelUnpack); #endif - (texture->*Context::current()->state().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) { +void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage3D& image) { image.buffer().bind(Buffer::Target::PixelUnpack); - (texture->*Context::current()->state().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 -void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Vector3i& offset, const ImageReference3D& image) { +void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Vector3i& offset, const ImageReference3D& image) { #ifndef MAGNUM_TARGET_GLES2 Buffer::unbind(Buffer::Target::PixelUnpack); #endif - (texture->*Context::current()->state().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) { +void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Vector3i& offset, BufferImage3D& image) { image.buffer().bind(Buffer::Target::PixelUnpack); - (texture->*Context::current()->state().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}); +void AbstractTexture::DataHelper<1>::invalidateSubImage(AbstractTexture& 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<2>::invalidateSubImage(AbstractTexture& 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); +void AbstractTexture::DataHelper<3>::invalidateSubImage(AbstractTexture& 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())); +void AbstractTexture::DataHelper<1>::setWrapping(AbstractTexture& texture, const Array1D& wrapping) { + (texture.*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); } #endif -void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture* texture, const Array2D& wrapping) { +void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture& texture, const Array2D& wrapping) { #ifndef MAGNUM_TARGET_GLES - 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", ); + 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 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())); + (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) { +void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture& texture, const Array3D& wrapping) { 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())); + (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->*state.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 ac3ac20ed..17a5e2815 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -451,19 +451,19 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<1> { constexpr static Target target() { return Target::Texture1D; } - static Math::Vector<1, GLint> imageSize(AbstractTexture* texture, GLenum target, GLint level); + static Math::Vector<1, GLint> imageSize(AbstractTexture& texture, GLenum target, GLint level); - static void setWrapping(AbstractTexture* texture, const Array1D& wrapping); + 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); + 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); + 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); - 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 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); + 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> { @@ -479,24 +479,24 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> { constexpr static Target target() { return Target::Texture2D; } #ifndef MAGNUM_TARGET_GLES - static Vector2i imageSize(AbstractTexture* texture, GLenum target, GLint level); + static Vector2i imageSize(AbstractTexture& texture, GLenum target, GLint level); #endif - static void setWrapping(AbstractTexture* texture, const Array2D& wrapping); + static void setWrapping(AbstractTexture& texture, const Array2D& wrapping); - static void setStorage(AbstractTexture* texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& 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); + static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference2D& image); #ifndef MAGNUM_TARGET_GLES2 - static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage2D& image); + static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage2D& image); #endif - static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector2i& offset, const ImageReference2D& image); + static void setSubImage(AbstractTexture& texture, GLenum target, GLint level, const Vector2i& offset, const ImageReference2D& image); #ifndef MAGNUM_TARGET_GLES2 - static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector2i& offset, BufferImage2D& image); + 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); + static void invalidateSubImage(AbstractTexture& texture, GLint level, const Vector2i& offset, const Vector2i& size); }; template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> { enum class Target: GLenum { @@ -514,24 +514,24 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> { constexpr static Target target() { return Target::Texture3D; } #ifndef MAGNUM_TARGET_GLES - static Vector3i imageSize(AbstractTexture* texture, GLenum target, GLint level); + static Vector3i imageSize(AbstractTexture& texture, GLenum target, GLint level); #endif - static void setWrapping(AbstractTexture* texture, const Array3D& wrapping); + static void setWrapping(AbstractTexture& texture, const Array3D& wrapping); - static void setStorage(AbstractTexture* texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& 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); + static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference3D& image); #ifndef MAGNUM_TARGET_GLES2 - static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage3D& image); + static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage3D& image); #endif - static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector3i& offset, const ImageReference3D& image); + static void setSubImage(AbstractTexture& texture, GLenum target, GLint level, const Vector3i& offset, const ImageReference3D& image); #ifndef MAGNUM_TARGET_GLES2 - static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector3i& offset, BufferImage3D& image); + 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); + static void invalidateSubImage(AbstractTexture& texture, GLint level, const Vector3i& offset, const Vector3i& size); }; #endif diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index b162f1ac8..1cd6401cd 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -103,7 +103,7 @@ class CubeMapTexture: public AbstractTexture { * See @ref Texture::setWrapping() for more information. */ CubeMapTexture& setWrapping(const Array3D& wrapping) { - DataHelper<3>::setWrapping(this, wrapping); + DataHelper<3>::setWrapping(*this, wrapping); return *this; } @@ -117,7 +117,7 @@ class CubeMapTexture: public AbstractTexture { * @requires_gl %Texture image queries are not available in OpenGL ES. */ Vector2i imageSize(Coordinate coordinate, Int level) { - return DataHelper<2>::imageSize(this, GLenum(coordinate), level); + return DataHelper<2>::imageSize(*this, GLenum(coordinate), level); } #endif @@ -127,7 +127,7 @@ class CubeMapTexture: public AbstractTexture { * See @ref Texture::setStorage() for more information. */ CubeMapTexture& setStorage(Int levels, TextureFormat internalFormat, const Vector2i& size) { - DataHelper<2>::setStorage(this, _target, levels, internalFormat, size); + DataHelper<2>::setStorage(*this, _target, levels, internalFormat, size); return *this; } @@ -173,14 +173,14 @@ class CubeMapTexture: public AbstractTexture { * See @ref Texture::setImage() for more information. */ CubeMapTexture& setImage(Coordinate coordinate, Int level, TextureFormat internalFormat, const ImageReference2D& image) { - DataHelper<2>::setImage(this, GLenum(coordinate), level, internalFormat, image); + DataHelper<2>::setImage(*this, GLenum(coordinate), level, internalFormat, image); return *this; } #ifndef MAGNUM_TARGET_GLES2 /** @overload */ CubeMapTexture& setImage(Coordinate coordinate, Int level, TextureFormat internalFormat, BufferImage2D& image) { - DataHelper<2>::setImage(this, GLenum(coordinate), level, internalFormat, image); + DataHelper<2>::setImage(*this, GLenum(coordinate), level, internalFormat, image); return *this; } @@ -202,20 +202,20 @@ class CubeMapTexture: public AbstractTexture { * See @ref Texture::setSubImage() for more information. */ CubeMapTexture& setSubImage(Coordinate coordinate, Int level, const Vector2i& offset, const ImageReference2D& image) { - DataHelper<2>::setSubImage(this, GLenum(coordinate), level, offset, image); + DataHelper<2>::setSubImage(*this, GLenum(coordinate), level, offset, image); return *this; } #ifndef MAGNUM_TARGET_GLES2 /** @overload */ CubeMapTexture& setSubImage(Coordinate coordinate, Int level, const Vector2i& offset, BufferImage2D& image) { - DataHelper<2>::setSubImage(this, GLenum(coordinate), level, offset, image); + DataHelper<2>::setSubImage(*this, GLenum(coordinate), level, offset, image); return *this; } /** @overload */ CubeMapTexture& setSubImage(Coordinate coordinate, Int level, const Vector2i& offset, BufferImage2D&& image) { - DataHelper<2>::setSubImage(this, GLenum(coordinate), level, offset, image); + DataHelper<2>::setSubImage(*this, GLenum(coordinate), level, offset, image); return *this; } #endif @@ -233,7 +233,7 @@ class CubeMapTexture: public AbstractTexture { * See @ref Texture::invalidateSubImage() for more information. */ void invalidateSubImage(Int level, const Vector3i& offset, const Vector3i& size) { - DataHelper<3>::invalidateSubImage(this, level, offset, size); + DataHelper<3>::invalidateSubImage(*this, level, offset, size); } /* Overloads to remove WTF-factor from method chaining order */ diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index 85b5c2f68..4767d67a7 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -94,7 +94,7 @@ class CubeMapTextureArray: public AbstractTexture { * See @ref Texture::setWrapping() for more information. */ CubeMapTextureArray& setWrapping(const Array3D& wrapping) { - DataHelper<3>::setWrapping(this, wrapping); + DataHelper<3>::setWrapping(*this, wrapping); return *this; } @@ -105,7 +105,7 @@ class CubeMapTextureArray: public AbstractTexture { * See @ref Texture::imageSize() for more information. */ Vector3i imageSize(Int level) { - return DataHelper<3>::imageSize(this, GL_TEXTURE_CUBE_MAP_ARRAY, level); + return DataHelper<3>::imageSize(*this, GL_TEXTURE_CUBE_MAP_ARRAY, level); } /** @@ -115,7 +115,7 @@ class CubeMapTextureArray: public AbstractTexture { * @ref Texture::setStorage() for more information. */ CubeMapTextureArray& setStorage(Int levels, TextureFormat internalFormat, const Vector3i& size) { - DataHelper<3>::setStorage(this, _target, levels, internalFormat, size); + DataHelper<3>::setStorage(*this, _target, levels, internalFormat, size); return *this; } @@ -163,13 +163,13 @@ class CubeMapTextureArray: public AbstractTexture { * See @ref Texture::setImage() for more information. */ CubeMapTextureArray& setImage(Int level, TextureFormat internalFormat, const ImageReference3D& image) { - DataHelper<3>::setImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, internalFormat, image); + DataHelper<3>::setImage(*this, GL_TEXTURE_CUBE_MAP_ARRAY, level, internalFormat, image); return *this; } /** @overload */ CubeMapTextureArray& setImage(Int level, TextureFormat internalFormat, BufferImage3D& image) { - DataHelper<3>::setImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, internalFormat, image); + DataHelper<3>::setImage(*this, GL_TEXTURE_CUBE_MAP_ARRAY, level, internalFormat, image); return *this; } @@ -192,13 +192,13 @@ class CubeMapTextureArray: public AbstractTexture { * See @ref Texture::setSubImage() for more information. */ CubeMapTextureArray& setSubImage(Int level, const Vector3i& offset, const ImageReference3D& image) { - DataHelper<3>::setSubImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, offset, image); + DataHelper<3>::setSubImage(*this, GL_TEXTURE_CUBE_MAP_ARRAY, level, offset, image); return *this; } /** @overload */ CubeMapTextureArray& setSubImage(Int level, const Vector3i& offset, BufferImage3D& image) { - DataHelper<3>::setSubImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, offset, image); + DataHelper<3>::setSubImage(*this, GL_TEXTURE_CUBE_MAP_ARRAY, level, offset, image); return *this; } @@ -219,7 +219,7 @@ class CubeMapTextureArray: public AbstractTexture { * See @ref Texture::invalidateSubImage() for more information. */ void invalidateSubImage(Int level, const Vector3i& offset, const Vector3i& size) { - DataHelper<3>::invalidateSubImage(this, level, offset, size); + DataHelper<3>::invalidateSubImage(*this, level, offset, size); } /* Overloads to remove WTF-factor from method chaining order */ diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index f7f2f2928..fd0832316 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -246,7 +246,7 @@ template class Texture: public AbstractTexture { * @requires_gl %Texture image queries are not available in OpenGL ES. */ typename DimensionTraits::VectorType imageSize(Int level) { - return DataHelper::imageSize(this, _target, level); + return DataHelper::imageSize(*this, _target, level); } #endif @@ -268,7 +268,7 @@ template class Texture: public AbstractTexture { * @def_gl{TEXTURE_WRAP_R} */ Texture& setWrapping(const Array& wrapping) { - DataHelper::setWrapping(this, wrapping); + DataHelper::setWrapping(*this, wrapping); return *this; } @@ -301,7 +301,7 @@ template class Texture: public AbstractTexture { * @fn_gl_extension{TextureImage3D,EXT,direct_state_access}. */ Texture& setStorage(Int levels, TextureFormat internalFormat, const typename DimensionTraits::VectorType& size) { - DataHelper::setStorage(this, _target, levels, internalFormat, size); + DataHelper::setStorage(*this, _target, levels, internalFormat, size); return *this; } @@ -368,14 +368,14 @@ template class Texture: public AbstractTexture { * @fn_gl_extension{TextureImage3D,EXT,direct_state_access} */ Texture& setImage(Int level, TextureFormat internalFormat, const ImageReference& image) { - DataHelper::setImage(this, _target, level, internalFormat, image); + DataHelper::setImage(*this, _target, level, internalFormat, image); return *this; } #ifndef MAGNUM_TARGET_GLES2 /** @overload */ Texture& setImage(Int level, TextureFormat internalFormat, BufferImage& image) { - DataHelper::setImage(this, _target, level, internalFormat, image); + DataHelper::setImage(*this, _target, level, internalFormat, image); return *this; } @@ -403,14 +403,14 @@ template class Texture: public AbstractTexture { * @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} */ Texture& setSubImage(Int level, const typename DimensionTraits::VectorType& offset, const ImageReference& image) { - DataHelper::setSubImage(this, _target, level, offset, image); + DataHelper::setSubImage(*this, _target, level, offset, image); return *this; } #ifndef MAGNUM_TARGET_GLES2 /** @overload */ Texture& setSubImage(Int level, const typename DimensionTraits::VectorType& offset, BufferImage& image) { - DataHelper::setSubImage(this, _target, level, offset, image); + DataHelper::setSubImage(*this, _target, level, offset, image); return *this; } @@ -431,7 +431,7 @@ template class Texture: public AbstractTexture { * @see @ref invalidateImage(), @fn_gl{InvalidateTexSubImage} */ void invalidateSubImage(Int level, const typename DimensionTraits::VectorType& offset, const typename DimensionTraits::VectorType& size) { - DataHelper::invalidateSubImage(this, level, offset, size); + DataHelper::invalidateSubImage(*this, level, offset, size); } /* Overloads to remove WTF-factor from method chaining order */ From fc35adaac25373521f77ded1aa8fe4fc4ee0a63b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 20:17:58 +0100 Subject: [PATCH 13/86] Use *Image::dataSize() instead of manual buggy size computation. BufferImage test currently fails. --- src/Magnum/AbstractTexture.cpp | 4 ++-- src/Magnum/BufferImage.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index a60870426..5742d3e87 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -907,7 +907,7 @@ void AbstractTexture::invalidateSubImageImplementationARB(GLint level, const Vec #ifndef MAGNUM_TARGET_GLES template void AbstractTexture::image(GLenum target, GLint level, Image& image) { const Math::Vector size = DataHelper::imageSize(*this, target, level); - const std::size_t dataSize = size.product()*image.pixelSize(); + const std::size_t dataSize = image.dataSize(size); char* data = new char[dataSize]; (this->*Context::current()->state().texture->getImageImplementation)(target, level, image.format(), image.type(), dataSize, data); image.setData(image.format(), image.type(), size, data); @@ -919,7 +919,7 @@ template void MAGNUM_EXPORT AbstractTexture::image<3>(GLenum, GLint, Image<3>&); template void AbstractTexture::image(GLenum target, GLint level, BufferImage& image, BufferUsage usage) { const Math::Vector size = DataHelper::imageSize(*this, target, level); - const std::size_t dataSize = size.product()*image.pixelSize(); + const std::size_t dataSize = image.dataSize(size); if(image.size() != size) image.setData(image.format(), image.type(), size, nullptr, usage); diff --git a/src/Magnum/BufferImage.cpp b/src/Magnum/BufferImage.cpp index a02f4533f..08c6fb1ae 100644 --- a/src/Magnum/BufferImage.cpp +++ b/src/Magnum/BufferImage.cpp @@ -29,7 +29,7 @@ namespace Magnum { #ifndef MAGNUM_TARGET_GLES2 template BufferImage::BufferImage(ColorFormat format, ColorType type, const typename DimensionTraits< Dimensions, Int >::VectorType& size, const void* data, BufferUsage usage): AbstractImage(format, type), _size(size), _buffer(Buffer::Target::PixelPack) { - _buffer.setData({data, pixelSize()*size.product()}, usage); + _buffer.setData({data, dataSize(size)}, usage); } template BufferImage::BufferImage(ColorFormat format, ColorType type): AbstractImage(format, type), _buffer(Buffer::Target::PixelPack) {} @@ -38,7 +38,7 @@ template void BufferImage::setData(ColorForm _format = format; _type = type; _size = size; - _buffer.setData({data, pixelSize()*size.product()}, usage); + _buffer.setData({data, dataSize(size)}, usage); } #ifndef DOXYGEN_GENERATING_OUTPUT From 97874a15ac059f69d0c36a080262c4d92b3fc57f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 20:18:32 +0100 Subject: [PATCH 14/86] Fix BufferImage test to pass and retrieve data with proper alignment. --- src/Magnum/Test/BufferImageGLTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Test/BufferImageGLTest.cpp b/src/Magnum/Test/BufferImageGLTest.cpp index 0290d7901..8fdc73a10 100644 --- a/src/Magnum/Test/BufferImageGLTest.cpp +++ b/src/Magnum/Test/BufferImageGLTest.cpp @@ -51,7 +51,7 @@ BufferImageTest::BufferImageTest() { } void BufferImageTest::construct() { - const unsigned char data[] = { 'a', 'b', 'c' }; + const unsigned char data[] = { 'a', 0, 0, 0, 'b', 0, 0, 0, 'c', 0, 0, 0 }; BufferImage2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data, BufferUsage::StaticDraw); #ifndef MAGNUM_TARGET_GLES @@ -67,7 +67,7 @@ void BufferImageTest::construct() { /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE_AS(std::vector(imageData.begin(), imageData.end()), - std::vector(data, data + 3), + std::vector(data, data + 12), TestSuite::Compare::Container); #endif } From a05594bdfd0395b4a544f6288445863bff0e2346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 21:42:43 +0100 Subject: [PATCH 15/86] Doc++ --- src/Magnum/Implementation/RendererState.cpp | 2 ++ src/Magnum/Texture.h | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Implementation/RendererState.cpp b/src/Magnum/Implementation/RendererState.cpp index 9c4a932d1..13fc2dc7d 100644 --- a/src/Magnum/Implementation/RendererState.cpp +++ b/src/Magnum/Implementation/RendererState.cpp @@ -31,6 +31,7 @@ namespace Magnum { namespace Implementation { RendererState::RendererState(Context& context, std::vector& extensions): resetNotificationStrategy() { + /* Float depth clear value implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) #endif @@ -45,6 +46,7 @@ RendererState::RendererState(Context& context, std::vector& extensi else clearDepthfImplementation = &Renderer::clearDepthfImplementationDefault; #endif + /* Graphics reset status implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) #else diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index fd0832316..18dbe6e98 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -285,11 +285,12 @@ template class Texture: public AbstractTexture { * is immutable and calling @ref setStorage() or @ref setImage() is not * allowed. * - * If @extension{EXT,direct_state_access} is not available, the - * texture is bound to some layer before the operation. If - * OpenGL 4.2, @extension{ARB,texture_storage}, OpenGL ES 3.0 or @es_extension{EXT,texture_storage} - * in OpenGL ES 2.0 is not available, the feature is emulated with - * sequence of @ref setImage() calls. + * If @extension{EXT,direct_state_access} is not available, the texture + * is bound to some layer before the operation. If OpenGL 4.2, + * @extension{ARB,texture_storage}, OpenGL ES 3.0 or + * @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not + * available, the feature is emulated with sequence of @ref setImage() + * calls. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{TexStorage1D}/@fn_gl{TexStorage2D}/@fn_gl{TexStorage3D} * or @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}/ From a88155a198f96f69828b55c3056dfa1f6e23f9ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 21:43:32 +0100 Subject: [PATCH 16/86] Actually make use of EXT_texture_storage on ES2. Currently it was ignored when deciding about *Texture::setStorage() implementation. --- src/Magnum/Implementation/TextureState.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index 7bc771d66..5b9988bb4 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -114,13 +114,16 @@ TextureState::TextureState(Context& context, std::vector& extension #endif /* Texture storage implementation */ - #ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) + #elif defined(MAGNUM_TARGET_GLES2) + if(context.isExtensionSupported()) #endif { #ifndef MAGNUM_TARGET_GLES extensions.push_back(Extensions::GL::ARB::texture_storage::string()); + #elif defined(MAGNUM_TARGET_GLES2) + extensions.push_back(Extensions::GL::EXT::texture_storage::string()); #endif #ifndef MAGNUM_TARGET_GLES @@ -138,12 +141,8 @@ TextureState::TextureState(Context& context, std::vector& extension storage3DImplementation = &AbstractTexture::storageImplementationDefault; } } - #endif #ifndef MAGNUM_TARGET_GLES3 - #ifndef MAGNUM_TARGET_GLES - else - #endif - { + else { #ifndef MAGNUM_TARGET_GLES storage1DImplementation = &AbstractTexture::storageImplementationFallback; #endif From 132c2f4e64af5a9336ca179aa773f39093921a20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 23:08:20 +0100 Subject: [PATCH 17/86] package: ensure that static libs are being kept in ArchLinux packages. I forgot to merge my /etc/makepkg.conf.pacnew and thus didn't notice it until now. --- package/archlinux/PKGBUILD | 2 +- package/archlinux/PKGBUILD-clang | 2 +- package/archlinux/PKGBUILD-clang-libc++ | 2 +- package/archlinux/PKGBUILD-emscripten | 2 +- package/archlinux/PKGBUILD-es2 | 2 +- package/archlinux/PKGBUILD-es2desktop | 2 +- package/archlinux/PKGBUILD-es3 | 2 +- package/archlinux/PKGBUILD-es3desktop | 2 +- package/archlinux/PKGBUILD-gcc46 | 2 +- package/archlinux/PKGBUILD-gcc47 | 2 +- package/archlinux/PKGBUILD-gcc49 | 2 +- package/archlinux/PKGBUILD-mingw32 | 2 +- package/archlinux/PKGBUILD-nacl-glibc | 2 +- package/archlinux/PKGBUILD-nacl-newlib | 2 +- package/archlinux/PKGBUILD-release | 1 + package/archlinux/magnum-git/PKGBUILD | 3 ++- 16 files changed, 17 insertions(+), 15 deletions(-) diff --git a/package/archlinux/PKGBUILD b/package/archlinux/PKGBUILD index 79a64b1a6..c21cc7040 100644 --- a/package/archlinux/PKGBUILD +++ b/package/archlinux/PKGBUILD @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('corrade' 'openal' 'freeglut' 'sdl2') makedepends=('cmake' 'ninja') -options=(!strip) +options=('!strip' 'staticlibs') provides=('magnum-git') build() { diff --git a/package/archlinux/PKGBUILD-clang b/package/archlinux/PKGBUILD-clang index f98b4b14e..45f89c36a 100644 --- a/package/archlinux/PKGBUILD-clang +++ b/package/archlinux/PKGBUILD-clang @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('corrade' 'openal' 'freeglut' 'sdl2') makedepends=('cmake' 'clang' 'ninja') -options=(!strip) +options=('!strip' 'staticlibs') provides=('magnum-git') build() { diff --git a/package/archlinux/PKGBUILD-clang-libc++ b/package/archlinux/PKGBUILD-clang-libc++ index e11965e27..88bc44219 100644 --- a/package/archlinux/PKGBUILD-clang-libc++ +++ b/package/archlinux/PKGBUILD-clang-libc++ @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('corrade' 'openal' 'freeglut' 'sdl2' 'libc++') makedepends=('cmake' 'clang' 'ninja') -options=(!strip) +options=('!strip' 'staticlibs') provides=('magnum-git') build() { diff --git a/package/archlinux/PKGBUILD-emscripten b/package/archlinux/PKGBUILD-emscripten index 30993b1f2..7de134779 100644 --- a/package/archlinux/PKGBUILD-emscripten +++ b/package/archlinux/PKGBUILD-emscripten @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('emscripten-corrade') makedepends=('cmake' 'ninja') -options=(!strip !buildflags) +options=('!strip' '!buildflags' 'staticlibs') build() { if [ ! -d "$startdir/build-emscripten" ] ; then diff --git a/package/archlinux/PKGBUILD-es2 b/package/archlinux/PKGBUILD-es2 index a841a7229..c1c9e82d3 100644 --- a/package/archlinux/PKGBUILD-es2 +++ b/package/archlinux/PKGBUILD-es2 @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('corrade' 'openal') makedepends=('cmake' 'ninja') -options=(!strip) +options=('!strip' 'staticlibs') provides=('magnum-git') build() { diff --git a/package/archlinux/PKGBUILD-es2desktop b/package/archlinux/PKGBUILD-es2desktop index bdceef969..97e88d78f 100644 --- a/package/archlinux/PKGBUILD-es2desktop +++ b/package/archlinux/PKGBUILD-es2desktop @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('corrade' 'openal') makedepends=('cmake' 'ninja') -options=(!strip) +options=('!strip' 'staticlibs') provides=('magnum-git') build() { diff --git a/package/archlinux/PKGBUILD-es3 b/package/archlinux/PKGBUILD-es3 index 4bcf048e0..dbecf3486 100644 --- a/package/archlinux/PKGBUILD-es3 +++ b/package/archlinux/PKGBUILD-es3 @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('corrade' 'openal') makedepends=('cmake' 'ninja') -options=(!strip) +options=('!strip' 'staticlibs') provides=('magnum-git') build() { diff --git a/package/archlinux/PKGBUILD-es3desktop b/package/archlinux/PKGBUILD-es3desktop index e47b3fdfc..a84fa45ea 100644 --- a/package/archlinux/PKGBUILD-es3desktop +++ b/package/archlinux/PKGBUILD-es3desktop @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('corrade' 'openal') makedepends=('cmake' 'ninja') -options=(!strip) +options=('!strip' 'staticlibs') provides=('magnum-git') build() { diff --git a/package/archlinux/PKGBUILD-gcc46 b/package/archlinux/PKGBUILD-gcc46 index ba70ed497..15a1c6100 100644 --- a/package/archlinux/PKGBUILD-gcc46 +++ b/package/archlinux/PKGBUILD-gcc46 @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('corrade' 'openal' 'freeglut' 'sdl2') makedepends=('cmake' 'ninja' 'gcc46') -options=(!strip) +options=('!strip' 'staticlibs') provides=('magnum-git') build() { diff --git a/package/archlinux/PKGBUILD-gcc47 b/package/archlinux/PKGBUILD-gcc47 index 5867486a8..600cc598f 100644 --- a/package/archlinux/PKGBUILD-gcc47 +++ b/package/archlinux/PKGBUILD-gcc47 @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('corrade' 'openal' 'freeglut' 'sdl2') makedepends=('cmake' 'ninja' 'gcc47') -options=(!strip) +options=('!strip' 'staticlibs') provides=('magnum-git') build() { diff --git a/package/archlinux/PKGBUILD-gcc49 b/package/archlinux/PKGBUILD-gcc49 index a8043f0f2..02d6db4da 100644 --- a/package/archlinux/PKGBUILD-gcc49 +++ b/package/archlinux/PKGBUILD-gcc49 @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('corrade' 'openal' 'freeglut' 'sdl2') makedepends=('cmake' 'ninja' 'gcc-git') -options=(!strip) +options=('!strip' 'staticlibs') provides=('magnum-git') build() { diff --git a/package/archlinux/PKGBUILD-mingw32 b/package/archlinux/PKGBUILD-mingw32 index 782719c79..594932067 100644 --- a/package/archlinux/PKGBUILD-mingw32 +++ b/package/archlinux/PKGBUILD-mingw32 @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('mingw32-runtime' 'mingw32-corrade' 'mingw32-freeglut' 'mingw32-openal') makedepends=('mingw32-gcc' 'cmake' 'ninja' 'corrade') -options=(!buildflags !strip) +options=('!buildflags' '!strip' 'staticlibs') build() { mkdir -p "$startdir/build-win" diff --git a/package/archlinux/PKGBUILD-nacl-glibc b/package/archlinux/PKGBUILD-nacl-glibc index ba1684803..3a3477d09 100644 --- a/package/archlinux/PKGBUILD-nacl-glibc +++ b/package/archlinux/PKGBUILD-nacl-glibc @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('nacl-corrade') makedepends=('nacl-sdk' 'cmake' 'corrade' 'ninja') -options=(!buildflags !strip) +options=('!buildflags' '!strip' 'staticlibs') build() { # Build 32bit diff --git a/package/archlinux/PKGBUILD-nacl-newlib b/package/archlinux/PKGBUILD-nacl-newlib index 5d9409892..d2a23fb6f 100644 --- a/package/archlinux/PKGBUILD-nacl-newlib +++ b/package/archlinux/PKGBUILD-nacl-newlib @@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('nacl-corrade') makedepends=('nacl-sdk' 'cmake' 'corrade' 'ninja') -options=(!buildflags !strip) +options=('!buildflags' '!strip' 'staticlibs') build() { # Build 32bit diff --git a/package/archlinux/PKGBUILD-release b/package/archlinux/PKGBUILD-release index 031abcd9d..61ff12d04 100644 --- a/package/archlinux/PKGBUILD-release +++ b/package/archlinux/PKGBUILD-release @@ -9,6 +9,7 @@ license=('MIT') depends=('corrade' 'openal' 'sdl2' 'freeglut') makedepends=('cmake' 'ninja') provides=('magnum-git') +options=('staticlibs') build() { mkdir -p "$startdir/build" diff --git a/package/archlinux/magnum-git/PKGBUILD b/package/archlinux/magnum-git/PKGBUILD index 45260cd8a..f48968bd3 100644 --- a/package/archlinux/magnum-git/PKGBUILD +++ b/package/archlinux/magnum-git/PKGBUILD @@ -1,6 +1,6 @@ # Author: mosra pkgname=magnum-git -pkgver=20130819 +pkgver=20140123 pkgrel=1 pkgdesc="C++11 and OpenGL 2D/3D graphics engine (Git version)" arch=('i686' 'x86_64') @@ -10,6 +10,7 @@ depends=('corrade-git' 'openal' 'freeglut') makedepends=('cmake' 'git') provides=('magnum') conflicts=('magnum') +options=('staticlibs') _gitroot="git://github.com/mosra/magnum.git" _gitname="magnum" From 10669f9e78fc7b3fcdc630142a9be4897cf62292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 23:12:28 +0100 Subject: [PATCH 18/86] Fix class/struct mismatch. Thanks, Clang. --- src/Magnum/AbstractFramebuffer.h | 2 +- src/Magnum/AbstractShaderProgram.h | 4 ++-- src/Magnum/AbstractTexture.h | 2 +- src/Magnum/Buffer.h | 4 ++-- src/Magnum/BufferTexture.h | 2 +- src/Magnum/Framebuffer.h | 2 +- src/Magnum/Mesh.h | 4 ++-- src/Magnum/Renderbuffer.h | 2 +- src/Magnum/Renderer.h | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Magnum/AbstractFramebuffer.h b/src/Magnum/AbstractFramebuffer.h index 8904ebb5f..c6f45c396 100644 --- a/src/Magnum/AbstractFramebuffer.h +++ b/src/Magnum/AbstractFramebuffer.h @@ -147,7 +147,7 @@ protected from buffer overflow. @todo @extension{ARB,viewport_array} (and `GL_MAX_VIEWPORTS`) */ class MAGNUM_EXPORT AbstractFramebuffer { - friend class Implementation::FramebufferState; + friend struct Implementation::FramebufferState; public: /** @todo `GL_IMPLEMENTATION_COLOR_READ_FORMAT`, `GL_IMPLEMENTATION_COLOR_READ_TYPE`, seems to be depending on currently bound FB (aargh) (@extension{ARB,ES2_compatibility}). */ diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index b27ae04c3..5cdb6a3ba 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -39,7 +39,7 @@ namespace Magnum { namespace Implementation { template struct Attribute; - class ShaderProgramState; + struct ShaderProgramState; } /** @@ -323,7 +323,7 @@ comes in handy. @todo `GL_NUM_{PROGRAM,SHADER}_BINARY_FORMATS` + `GL_{PROGRAM,SHADER}_BINARY_FORMATS` (vector), (@extension{ARB,ES2_compatibility}) */ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { - friend class Implementation::ShaderProgramState; + friend struct Implementation::ShaderProgramState; public: template class Attribute; diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 17a5e2815..a234e6887 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -101,7 +101,7 @@ nothing. @todo Query for immutable levels (@extension{ARB,ES3_compatibility}) */ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { - friend class Implementation::TextureState; + friend struct Implementation::TextureState; public: /** diff --git a/src/Magnum/Buffer.h b/src/Magnum/Buffer.h index 386f682bf..29a85d0f0 100644 --- a/src/Magnum/Buffer.h +++ b/src/Magnum/Buffer.h @@ -114,7 +114,7 @@ enum class BufferUsage: GLenum { #endif }; -namespace Implementation { class BufferState; } +namespace Implementation { struct BufferState; } /** @brief %Buffer @@ -192,7 +192,7 @@ nothing. @todo BindBufferRange/BindBufferOffset/BindBufferBase for transform feedback (3.0, @extension{EXT,transform_feedback}) */ class MAGNUM_EXPORT Buffer: public AbstractObject { - friend class Implementation::BufferState; + friend struct Implementation::BufferState; public: /** diff --git a/src/Magnum/BufferTexture.h b/src/Magnum/BufferTexture.h index 20a0a1ae6..d30e4f4c0 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 Implementation::TextureState; + friend struct Implementation::TextureState; public: /** @copydoc AbstractTexture::maxLabelLength() */ diff --git a/src/Magnum/Framebuffer.h b/src/Magnum/Framebuffer.h index ed984ab45..20fbc65ae 100644 --- a/src/Magnum/Framebuffer.h +++ b/src/Magnum/Framebuffer.h @@ -102,7 +102,7 @@ See their respective documentation for more information. @todo `MAX_COLOR_ATTACHMENTS` */ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObject { - friend class Implementation::FramebufferState; + friend struct Implementation::FramebufferState; public: /** diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 06055855f..bb6158b2a 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -115,7 +115,7 @@ enum class MeshPrimitive: GLenum { #endif }; -namespace Implementation { class MeshState; } +namespace Implementation { struct MeshState; } /** @brief %Mesh @@ -315,8 +315,8 @@ drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also @todo How to glDrawElementsBaseVertex()/vertex offset -- in draw()? */ class MAGNUM_EXPORT Mesh: public AbstractObject { - friend class Implementation::MeshState; friend class MeshView; + friend struct Implementation::MeshState; public: #ifdef MAGNUM_BUILD_DEPRECATED diff --git a/src/Magnum/Renderbuffer.h b/src/Magnum/Renderbuffer.h index 6bf754d1f..c7be10d5c 100644 --- a/src/Magnum/Renderbuffer.h +++ b/src/Magnum/Renderbuffer.h @@ -56,7 +56,7 @@ See its documentation for more information. @requires_gl30 %Extension @extension{ARB,framebuffer_object} */ class MAGNUM_EXPORT Renderbuffer: public AbstractObject { - friend class Implementation::FramebufferState; + friend struct Implementation::FramebufferState; public: /** diff --git a/src/Magnum/Renderer.h b/src/Magnum/Renderer.h index 9040c6411..439fdd626 100644 --- a/src/Magnum/Renderer.h +++ b/src/Magnum/Renderer.h @@ -48,8 +48,8 @@ namespace Implementation { struct RendererState; } @todo `GL_MAX_CLIP_DISTANCES`... */ class MAGNUM_EXPORT Renderer { - friend class Implementation::RendererState; friend class Context; + friend struct Implementation::RendererState; public: Renderer() = delete; From 370f1bf7e321cb32584685ce5d0ed7ff124163b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 23:12:53 +0100 Subject: [PATCH 19/86] Hide yet-unused private function on ES. --- src/Magnum/DebugMessage.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Magnum/DebugMessage.cpp b/src/Magnum/DebugMessage.cpp index f63166b0d..7be007f5c 100644 --- a/src/Magnum/DebugMessage.cpp +++ b/src/Magnum/DebugMessage.cpp @@ -36,12 +36,15 @@ namespace Magnum { namespace { +/** @todo Re-enable when extension wrangler is available for ES */ +#ifndef MAGNUM_TARGET_GLES #ifdef CORRADE_TARGET_WINDOWS APIENTRY #endif void callbackWrapper(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) { Context::current()->state().debug->messageCallback(DebugMessage::Source(source), DebugMessage::Type(type), id, DebugMessage::Severity(severity), std::string(message, length), userParam); } +#endif void defaultCallback(const DebugMessage::Source source, const DebugMessage::Type type, const UnsignedInt id, const DebugMessage::Severity severity, const std::string& string, const void*) { switch(severity) { From deb69d11974684a3ac474eeeaa8044494e881d76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 23:19:21 +0100 Subject: [PATCH 20/86] Print more information when cannot retrieve OpenGL version. At least the OpenGL error should be enough to pinpoint what went wrong. --- src/Magnum/Context.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 8cd802928..cca441d77 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -305,8 +305,11 @@ Context::Context() { #endif _version = static_cast(_majorVersion*100+_minorVersion*10); - CORRADE_ASSERT(Renderer::error() == Renderer::Error::NoError, - "Context: cannot retrieve OpenGL version", ); + #ifndef CORRADE_NO_ASSERT + const auto error = Renderer::error(); + CORRADE_ASSERT(error == Renderer::Error::NoError, + "Context: cannot retrieve OpenGL version:" << error, ); + #endif #ifndef MAGNUM_TARGET_GLES CORRADE_ASSERT(isVersionSupported(Version::GL210), "Context: unsupported OpenGL version" << Int(_version), ); From fa4558f5b57e80f5bcc4a521bb13a7224e7c8870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 24 Jan 2014 00:25:52 +0100 Subject: [PATCH 21/86] Use version() utility function also internally. --- src/Magnum/Context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index cca441d77..c9b198999 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -303,7 +303,7 @@ Context::Context() { _majorVersion = 2; _minorVersion = 0; #endif - _version = static_cast(_majorVersion*100+_minorVersion*10); + _version = Magnum::version(_majorVersion, _minorVersion); #ifndef CORRADE_NO_ASSERT const auto error = Renderer::error(); From 17ae24cee23e007dbc63d2d2e22bd1121af37181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 24 Jan 2014 00:26:43 +0100 Subject: [PATCH 22/86] It probably isn't good idea to have version checks as assertions. In particular when building with CORRADE_NO_ASSERT the version doesn't get checked at all, silently failing on null pointer somewhere else. --- src/Magnum/Context.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index c9b198999..6fedbee74 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -312,12 +312,20 @@ Context::Context() { #endif #ifndef MAGNUM_TARGET_GLES - CORRADE_ASSERT(isVersionSupported(Version::GL210), "Context: unsupported OpenGL version" << Int(_version), ); + if(!isVersionSupported(Version::GL210)) #elif defined(MAGNUM_TARGET_GLES2) - CORRADE_ASSERT(isVersionSupported(Version::GLES200), "Context: unsupported OpenGL ES version" << Int(_version), ); + if(!isVersionSupported(Version::GLES200)) #else - CORRADE_ASSERT(isVersionSupported(Version::GLES300), "Context: unsupported OpenGL ES version" << Int(_version), ); + if(!isVersionSupported(Version::GLES300)) #endif + { + #ifndef MAGNUM_TARGET_GLES + Error() << "Context: unsupported OpenGL version" << Int(_version); + #else + Error() << "Context: unsupported OpenGL ES version" << Int(_version); + #endif + std::exit(1); + } /* Context flags are supported since GL 3.0 */ #ifndef MAGNUM_TARGET_GLES From 41235c20eb2ab65bc034eefd77cadee33210b730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 24 Jan 2014 00:28:48 +0100 Subject: [PATCH 23/86] Fix version checks on OpenGL 2.1 and OpenGL ES 2.0. Both don't have GL_{MAJOR,MINOR}_VERSION enums so we must decide whether the version is older than OpenGL 3.0 / ES 3.0 either using MAGNUM_TARGET_GLES2 preprocessor definition or checking for invalid enum error and then we have to parse version string to ensure that the version is not too old. On ES2 the version check wasn't present at all (only optimistic hope), this makes it more hardened. --- src/Magnum/Context.cpp | 48 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 6fedbee74..6dea2f604 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -295,22 +295,60 @@ Context::Context() { } #endif - /* Version */ - #ifndef MAGNUM_TARGET_GLES2 + /* Get version */ + #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2) glGetIntegerv(GL_MAJOR_VERSION, &_majorVersion); glGetIntegerv(GL_MINOR_VERSION, &_minorVersion); #else - _majorVersion = 2; - _minorVersion = 0; + + /* On GL 2.1 and ES 2.0 there is no GL_{MAJOR,MINOR}_VERSION, we have to + parse version string. On desktop GL we have no way to check version + without version (duh) so we work around that by checking for invalid + enum error. */ + #ifndef MAGNUM_TARGET_GLES2 + glGetIntegerv(GL_MAJOR_VERSION, &_majorVersion); + auto error = Renderer::error(); + if(error == Renderer::Error::NoError) + glGetIntegerv(GL_MINOR_VERSION, &_minorVersion); + else #endif + { + #ifndef MAGNUM_TARGET_GLES2 + CORRADE_ASSERT(error == Renderer::Error::InvalidEnum, + "Context: cannot retrieve OpenGL version:" << error, ); + #endif + + const std::string version = versionString(); + #ifndef MAGNUM_TARGET_GLES + if(version.find("OpenGL 2.1") != std::string::npos) + #else + if(version.find("OpenGL ES 2.0") != std::string::npos) + #endif + { + _majorVersion = 2; + #ifndef MAGNUM_TARGET_GLES + _minorVersion = 1; + #else + _minorVersion = 0; + #endif + } else { + Error() << "Context: unsupported version string:" << version; + std::exit(1); + } + } + #endif + + /* Compose the version enum */ _version = Magnum::version(_majorVersion, _minorVersion); + /* Check that version retrieval went right */ #ifndef CORRADE_NO_ASSERT - const auto error = Renderer::error(); + error = Renderer::error(); CORRADE_ASSERT(error == Renderer::Error::NoError, "Context: cannot retrieve OpenGL version:" << error, ); #endif + /* Check that the version is supported (now it probably is, but be sure) */ #ifndef MAGNUM_TARGET_GLES if(!isVersionSupported(Version::GL210)) #elif defined(MAGNUM_TARGET_GLES2) From a4fa56b36d869b5d463f813a69095f6e4a614f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 24 Jan 2014 00:51:33 +0100 Subject: [PATCH 24/86] Fix ES3 build. Gah. And I tested it seven times. --- src/Magnum/Context.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 6dea2f604..eb8d2e3b8 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -307,15 +307,15 @@ Context::Context() { enum error. */ #ifndef MAGNUM_TARGET_GLES2 glGetIntegerv(GL_MAJOR_VERSION, &_majorVersion); - auto error = Renderer::error(); - if(error == Renderer::Error::NoError) + const auto versionNumberError = Renderer::error(); + if(versionNumberError == Renderer::Error::NoError) glGetIntegerv(GL_MINOR_VERSION, &_minorVersion); else #endif { #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(error == Renderer::Error::InvalidEnum, - "Context: cannot retrieve OpenGL version:" << error, ); + CORRADE_ASSERT(versionNumberError == Renderer::Error::InvalidEnum, + "Context: cannot retrieve OpenGL version:" << versionNumberError, ); #endif const std::string version = versionString(); @@ -343,7 +343,7 @@ Context::Context() { /* Check that version retrieval went right */ #ifndef CORRADE_NO_ASSERT - error = Renderer::error(); + const auto error = Renderer::error(); CORRADE_ASSERT(error == Renderer::Error::NoError, "Context: cannot retrieve OpenGL version:" << error, ); #endif From 8a865e10a636f9d722f493a83e631651427dcc06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 24 Jan 2014 01:14:03 +0100 Subject: [PATCH 25/86] Fix version string comparison on desktop GL. I should really read the specs more carefully, this seems to be a very dark corner of desktop/ES compatibility. --- src/Magnum/Context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index eb8d2e3b8..8771da18a 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -320,7 +320,7 @@ Context::Context() { const std::string version = versionString(); #ifndef MAGNUM_TARGET_GLES - if(version.find("OpenGL 2.1") != std::string::npos) + if(version.compare(0, 4, "2.1 ") == 0) #else if(version.find("OpenGL ES 2.0") != std::string::npos) #endif From dd2cac1e8a4874f253297bad8ac5b58e7b4b0e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 24 Jan 2014 02:10:05 +0100 Subject: [PATCH 26/86] Assert on each OES_vertex_array_object function occurence. Until we have extension wrangler set up for ES2. --- src/Magnum/Mesh.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp index 3db838837..250a7f0bd 100644 --- a/src/Magnum/Mesh.cpp +++ b/src/Magnum/Mesh.cpp @@ -251,6 +251,9 @@ void Mesh::createImplementationVAO() { /** @todo Get some extension wrangler instead to avoid linker errors to glGenVertexArrays() on ES2 */ #ifndef MAGNUM_TARGET_GLES2 glGenVertexArrays(1, &_id); + #else + //glGenVertexArraysOES(1, &_id); + CORRADE_INTERNAL_ASSERT(false); #endif } @@ -260,6 +263,9 @@ void Mesh::destroyImplementationVAO() { /** @todo Get some extension wrangler instead to avoid linker errors to glDeleteVertexArrays() on ES2 */ #ifndef MAGNUM_TARGET_GLES2 glDeleteVertexArrays(1, &_id); + #else + //glDeleteVertexArraysOES(1, &_id); + CORRADE_INTERNAL_ASSERT(false); #endif } From 99c0ec719575579eacc0c582267e71a6c43ad88c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 24 Jan 2014 02:15:19 +0100 Subject: [PATCH 27/86] doc: Missing include in Getting Started Guide. And unfortunately this one spits out insanely large compiler error. Sorry! --- doc/getting-started.dox | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/getting-started.dox b/doc/getting-started.dox index 71fab0589..722235f03 100644 --- a/doc/getting-started.dox +++ b/doc/getting-started.dox @@ -164,6 +164,7 @@ First include the needed headers: #include #include #include +#include @endcode And in the constructor (which is currently empty) change the clear color and From 57eb4ea649c6b0836975cea8f17b720f168c3044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 27 Jan 2014 15:48:19 +0100 Subject: [PATCH 28/86] Code cleanup. --- src/Magnum/Magnum.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index f45796a7b..5166cd1dd 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -559,7 +559,6 @@ enum class ColorType: GLenum; typedef ColorFormat ImageFormat; typedef ColorType ColorType; -enum class Version: Int; class Context; class CubeMapTexture; @@ -618,6 +617,8 @@ enum class TextureFormat: GLenum; class Timeline; +enum class Version: Int; + } #endif From ce403cd6a5c54fc0ac2c4fb98bb239e8f8e9c42b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 27 Jan 2014 15:28:44 +0100 Subject: [PATCH 29/86] 3D textures _are_ available in OpenGL ES 3.0. --- doc/opengl-support.dox | 2 +- src/Magnum/Context.cpp | 6 +++--- src/Magnum/Extensions.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index e93162150..96c926d28 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -250,6 +250,7 @@ supported. @es_extension{OES,depth24} | done @es_extension{OES,element_index_uint} | done @es_extension{OES,rgb8_rgba8} | done (desktop-compatible subset) +@es_extension{OES,texture_3D} | missing limit query @es_extension2{OES,texture_half_float_linear,OES_texture_float_linear} | done @es_extension{OES,texture_float_linear} | done @es_extension2{OES,texture_half_float,OES_texture_float} | done @@ -286,7 +287,6 @@ Only extensions not already listed in above tables are included here. @es_extension{OES,mapbuffer} | done @es_extension{OES,stencil1} | done @es_extension{OES,stencil4} | done -@es_extension{OES,texture_3D} | missing limit query @section opengl-unsupported Unsupported OpenGL features diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 8771da18a..a428575fc 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -214,8 +214,7 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,OES,depth32), _extension(GL,OES,mapbuffer), _extension(GL,OES,stencil1), - _extension(GL,OES,stencil4), - _extension(GL,OES,texture_3D)}; + _extension(GL,OES,stencil4)}; #ifdef MAGNUM_TARGET_GLES2 static const std::vector extensionsES300{ _extension(GL,ANGLE,framebuffer_blit), @@ -238,6 +237,7 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,OES,depth24), _extension(GL,OES,element_index_uint), _extension(GL,OES,rgb8_rgba8), + _extension(GL,OES,texture_3D), _extension(GL,OES,texture_half_float_linear), _extension(GL,OES,texture_float_linear), _extension(GL,OES,texture_half_float), @@ -468,7 +468,6 @@ Context::Context() { _disable(GL,KHR,debug) _disable(GL,NV,read_buffer_front) _disable(GL,OES,mapbuffer) - _disable(GL,OES,texture_3D) #ifdef MAGNUM_TARGET_GLES2 _disable(GL,ANGLE,framebuffer_blit) _disable(GL,ANGLE,framebuffer_multisample) @@ -484,6 +483,7 @@ Context::Context() { _disable(GL,NV,fbo_color_attachments) // ?? _disable(GL,NV,read_buffer) _disable(GL,NV,framebuffer_multisample) + _disable(GL,OES,texture_3D) _disable(GL,OES,vertex_array_object) #endif #undef _disable diff --git a/src/Magnum/Extensions.h b/src/Magnum/Extensions.h index 6a7aafb6e..67ef86c65 100644 --- a/src/Magnum/Extensions.h +++ b/src/Magnum/Extensions.h @@ -276,8 +276,8 @@ namespace GL { #endif _extension(GL,OES,stencil1, GLES200, None) // #31 _extension(GL,OES,stencil4, GLES200, None) // #32 - _extension(GL,OES,texture_3D, GLES200, None) // #34 #ifdef MAGNUM_TARGET_GLES2 + _extension(GL,OES,texture_3D, GLES200, GLES300) // #34 _extension(GL,OES,texture_half_float_linear, GLES200, GLES300) // #35 _extension(GL,OES,texture_float_linear, GLES200, GLES300) // #35 _extension(GL,OES,texture_half_float, GLES200, GLES300) // #36 From 72fe6c3e10427650c3e0e980e85152a2c3926f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 27 Jan 2014 15:49:54 +0100 Subject: [PATCH 30/86] Update OpenGL support. Don't be too optimistic :-) --- doc/opengl-support.dox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 96c926d28..938b75587 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -90,7 +90,7 @@ following: %Extension | Status -------------------------------------------- | ------ -@extension{ARB,geometry_shader4} | done (GL 3.2 subset) +@extension{ARB,geometry_shader4} | missing layered attachments @extension{ARB,depth_clamp} | done @extension{ARB,draw_elements_base_vertex} | | @extension{ARB,fragment_coord_conventions} | done (shading language only) From 9e0db81093da8f22fbe43cd6c3b60298bedb526a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 27 Jan 2014 15:29:25 +0100 Subject: [PATCH 31/86] Doc++ --- src/Magnum/Buffer.h | 8 ++++---- src/Magnum/Sampler.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Buffer.h b/src/Magnum/Buffer.h index 29a85d0f0..73674d6ac 100644 --- a/src/Magnum/Buffer.h +++ b/src/Magnum/Buffer.h @@ -174,8 +174,8 @@ The engine tracks currently bound buffers to avoid unnecessary calls to and @ref unmap() use that target instead of binding the buffer to some specific target. You can also use @ref setTargetHint() to possibly reduce unnecessary rebinding. %Buffer limits and implementation-defined values (such as -@ref maxVertexAttributeBindings()) are cached, so repeated queries don't result -in repeated @fn_gl{Get} calls. +@ref maxUniformBindings()) are cached, so repeated queries don't result in +repeated @fn_gl{Get} calls. If extension @extension{EXT,direct_state_access} is available, functions @ref copy(), @ref setData(), @ref setSubData(), @ref map(), @ref flushMappedRange() @@ -664,7 +664,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { #ifdef MAGNUM_BUILD_DEPRECATED /** - * @brief Set buffer data + * @copybrief setData(Containers::ArrayReference, BufferUsage) * @deprecated Use @ref Magnum::Buffer::setData(Containers::ArrayReference, BufferUsage) "setData(Containers::ArrayReference, BufferUsage)" * instead. */ @@ -701,7 +701,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { #ifdef MAGNUM_BUILD_DEPRECATED /** - * @brief Set buffer subdata + * @copybrief setSubData(GLintptr, Containers::ArrayReference) * @deprecated Use @ref Magnum::Buffer::setSubData(GLintptr, Containers::ArrayReference) "setSubData(GLintptr, Containers::ArrayReference)" * instead. */ diff --git a/src/Magnum/Sampler.h b/src/Magnum/Sampler.h index a3bbb68de..cb0b1ed9c 100644 --- a/src/Magnum/Sampler.h +++ b/src/Magnum/Sampler.h @@ -122,7 +122,7 @@ class MAGNUM_EXPORT Sampler { #ifndef MAGNUM_TARGET_GLES /** * Mirror the texture once in negative coordinates and clamp to - * edge after that. + * edge after that. **Unavailable on rectangle textures.** * @requires_gl44 %Extension @extension{ARB,texture_mirror_clamp_to_edge}, * @extension{ATI,texture_mirror_once} or @extension{EXT,texture_mirror_clamp} * @requires_gl Only separate @ref Magnum::Sampler::Wrapping "Wrapping::MirroredRepeat" From 959d40a02d0ff3adeef3fc62b663db10bd2977b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 27 Jan 2014 15:38:56 +0100 Subject: [PATCH 32/86] Split Texture into TextureArray, MultisampleTexture and RectangleTexture. Each texture has slightly different usage requirements and having everything under one generic class is not worth the additional runtime checks and whatnot. The current way with Texture::Target enum (hopefully not too widely used) is now deprecated and will be removed in some future release. However general Texture1D/2D/3D usage is not changed in any way. --- doc/opengl-mapping.dox | 8 +- src/Magnum/AbstractTexture.cpp | 25 +- src/Magnum/AbstractTexture.h | 143 +-- src/Magnum/BufferTexture.h | 9 +- src/Magnum/CMakeLists.txt | 7 +- src/Magnum/CubeMapTexture.h | 63 +- src/Magnum/CubeMapTextureArray.h | 65 +- src/Magnum/Magnum.h | 18 +- src/Magnum/MultisampleTexture.h | 116 ++ src/Magnum/RectangleTexture.h | 323 +++++ src/Magnum/Test/CMakeLists.txt | 3 + src/Magnum/Test/CubeMapTextureArrayGLTest.cpp | 3 +- src/Magnum/Test/CubeMapTextureGLTest.cpp | 3 +- src/Magnum/Test/MeshGLTest.cpp | 1 + src/Magnum/Test/MultisampleTextureGLTest.cpp | 212 ++++ src/Magnum/Test/RectangleTextureGLTest.cpp | 250 ++++ src/Magnum/Test/TextureArrayGLTest.cpp | 683 +++++++++++ src/Magnum/Test/TextureGLTest.cpp | 1061 +---------------- src/Magnum/Text/AbstractFont.cpp | 1 + src/Magnum/Text/Renderer.cpp | 1 + src/Magnum/Text/Test/AbstractFontTest.cpp | 1 + src/Magnum/Texture.h | 369 +++--- src/Magnum/TextureArray.h | 302 +++++ 23 files changed, 2230 insertions(+), 1437 deletions(-) create mode 100644 src/Magnum/MultisampleTexture.h create mode 100644 src/Magnum/RectangleTexture.h create mode 100644 src/Magnum/Test/MultisampleTextureGLTest.cpp create mode 100644 src/Magnum/Test/RectangleTextureGLTest.cpp create mode 100644 src/Magnum/Test/TextureArrayGLTest.cpp create mode 100644 src/Magnum/TextureArray.h diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index c1ab1a932..98d1c6a4a 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -137,7 +137,7 @@ OpenGL function | Matching API @fn_gl{GenTextures}, @fn_gl{DeleteTextures} | @ref AbstractTexture constructor and destructor @fn_gl{GenTransformFeedbacks}, @fn_gl{DeleteTransformFeedbacks} | | @fn_gl{GenVertexArrays}, @fn_gl{DeleteVertexArrays} | @ref Mesh constructor and destructor -@fn_gl{GenerateMipmap}, \n @fn_gl_extension{GenerateTextureMipmap,EXT,direct_state_access} | @ref AbstractTexture::generateMipmap() +@fn_gl{GenerateMipmap}, \n @fn_gl_extension{GenerateTextureMipmap,EXT,direct_state_access} | @ref Texture::generateMipmap(), \n @ref TextureArray::generateMipmap(), \n @ref CubeMapTexture::generateMipmap(), \n @ref CubeMapTextureArray::generateMipmap() @fn_gl{Get} | see @ref opengl-mapping-state "table below" @fn_gl2{GetActiveAtomicCounterBuffer,GetActiveAtomicCounterBufferiv} | not queryable @fn_gl{GetActiveAttrib}, \n @fn_gl{GetActiveSubroutineName}, \n @fn_gl{GetActiveSubroutineUniform}, \n @fn_gl{GetActiveSubroutineUniformName}, \n @fn_gl{GetActiveUniform}, \n @fn_gl{GetActiveUniformBlock}, \n @fn_gl{GetActiveUniformBlockName}, \n @fn_gl{GetActiveUniformName}, \n @fn_gl{GetActiveUniforms} | not queryable @@ -193,8 +193,8 @@ OpenGL function | Matching API @fn_gl{InvalidateBufferSubData} | @ref Buffer::invalidateSubData() @fn_gl{InvalidateFramebuffer}, \n @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate() @fn_gl{InvalidateSubFramebuffer}, \n @fn_gles_extension{DiscardSubFramebuffer,EXT,discard_framebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate() -@fn_gl{InvalidateTexImage} | @ref AbstractTexture::invalidateImage() -@fn_gl{InvalidateTexSubImage} | @ref Texture::invalidateSubImage(),\n @ref CubeMapTexture::invalidateSubImage(), \n @ref CubeMapTextureArray::invalidateSubImage() +@fn_gl{InvalidateTexImage} | @ref Texture::invalidateImage(), \n @ref TextureArray::invalidateImage(), \n @ref CubeMapTexture::invalidateImage(), \n @ref CubeMapTextureArray::invalidateImage(), \n @ref MultisampleTexture::invalidateImage(), \n @ref RectangleTexture::invalidateImage() +@fn_gl{InvalidateTexSubImage} | @ref Texture::invalidateSubImage(), \n @ref TextureArray::invalidateSubImage(), \n @ref CubeMapTexture::invalidateSubImage(), \n @ref CubeMapTextureArray::invalidateSubImage(), \n @ref MultisampleTexture::invalidateSubImage(), \n @ref RectangleTexture::invalidateSubImage() @fn_gl{IsBuffer}, \n @fn_gl{IsFramebuffer}, \n @fn_gl{IsProgram}, \n @fn_gl{IsProgramPipeline}, \n @fn_gl{IsQuery}, \n @fn_gl{IsRenderbuffer}, \n @fn_gl{IsSampler}, \n @fn_gl{IsShader}, \n @fn_gl{IsSync}, \n @fn_gl{IsTexture}, \n @fn_gl{IsTransformFeedback}, \n @fn_gl{IsVertexArray} | not needed, objects are strongly typed @fn_gl{IsEnabled} | not queryable, @ref Renderer::setFeature() setter only @fn_gl{LineWidth} | @ref Renderer::setLineWidth() @@ -239,7 +239,7 @@ OpenGL function | Matching API @fn_gl{TexBuffer}, \n @fn_gl_extension{TextureBuffer,EXT,direct_state_access}, \n @fn_gl{TexBufferRange}, \n @fn_gl_extension{TextureBufferRange,EXT,direct_state_access} | @ref BufferTexture::setBuffer() @fn_gl{TexImage1D}, \n @fn_gl_extension{TextureImage1D,EXT,direct_state_access} \n @fn_gl{TexImage2D}, \n @fn_gl_extension{TextureImage2D,EXT,direct_state_access}, \n @fn_gl{TexImage3D}, \n @fn_gl_extension{TextureImage3D,EXT,direct_state_access} | @ref Texture::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage() @fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | | -@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref AbstractTexture::setMinificationFilter(), \n @ref AbstractTexture::setMagnificationFilter(), \n @ref AbstractTexture::setBorderColor(), \n @ref AbstractTexture::setMaxAnisotropy(), \n @ref Texture::setWrapping(), \n @ref CubeMapTexture::setWrapping(), \n @ref CubeMapTextureArray::setWrapping() +@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setMinificationFilter(), \n @ref TextureArray::setMinificationFilter(), \n @ref CubeMapTexture::setMinificationFilter(), \n @ref CubeMapTextureArray::setMinificationFilter(), \n @ref RectangleTexture::setMinificationFilter(), \n @ref Texture::setMagnificationFilter(), \n @ref TextureArray::setMagnificationFilter(), \n @ref CubeMapTexture::setMagnificationFilter(), \n @ref CubeMapTextureArray::setMagnificationFilter(), \n @ref RectangleTexture::setMagnificationFilter(), \n @ref Texture::setBorderColor(), \n @ref TextureArray::setBorderColor(), \n @ref CubeMapTexture::setBorderColor(), \n @ref CubeMapTextureArray::setBorderColor(), \n @ref RectangleTexture::setBorderColor(), \n @ref Texture::setMaxAnisotropy(), \n @ref TextureArray::setMaxAnisotropy(), \n @ref CubeMapTexture::setMaxAnisotropy(), \n @ref CubeMapTextureArray::setMaxAnisotropy(), \n @ref RectangleTexture::setMaxAnisotropy(), \n @ref Texture::setWrapping(), \n @ref TextureArray::setWrapping(), \n @ref CubeMapTexture::setWrapping(), \n @ref CubeMapTextureArray::setWrapping(), \n @ref RectangleTexture::setWrapping() @fn_gl{TexStorage1D}, \n @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}, \n @fn_gl{TexStorage2D}, \n @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, \n @fn_gl{TexStorage3D}, \n @fn_gl_extension{TextureStorage3D,EXT,direct_state_access} | @ref Texture::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage() @fn_gl{TexStorage2DMultisample}, \n @fn_gl{TexStorage3DMultisample} | | @fn_gl{TexSubImage1D}, \n @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{TexSubImage2D}, \n @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{TexSubImage3D}, \n @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} | @ref Texture::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage() diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 5742d3e87..4d2dd9d40 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -28,6 +28,8 @@ #ifndef MAGNUM_TARGET_GLES2 #include "Magnum/BufferImage.h" #endif +#include "Magnum/Array.h" +#include "Magnum/Color.h" #include "Magnum/ColorFormat.h" #include "Magnum/Context.h" #include "Magnum/Extensions.h" @@ -134,45 +136,32 @@ void AbstractTexture::bindImplementationDSA(GLint layer) { } #endif -AbstractTexture& AbstractTexture::setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap) { - #ifndef MAGNUM_TARGET_GLES - CORRADE_ASSERT(_target != GL_TEXTURE_RECTANGLE || mipmap == Sampler::Mipmap::Base, "AbstractTexture: rectangle textures cannot have mipmaps", *this); - #endif - +void AbstractTexture::setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap) { (this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_MIN_FILTER, GLint(filter)|GLint(mipmap)); - return *this; } -AbstractTexture& AbstractTexture::setMagnificationFilter(const Sampler::Filter filter) { +void 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) { +void 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) { +void 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 - +void AbstractTexture::generateMipmap() { (this->*Context::current()->state().texture->mipmapImplementation)(); - return *this; } void AbstractTexture::mipmapImplementationDefault() { diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index a234e6887..8a10eede1 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -29,8 +29,6 @@ * @brief Class @ref Magnum::AbstractTexture */ -#include "Magnum/Array.h" -#include "Magnum/Color.h" #include "Magnum/Sampler.h" #include "Magnum/AbstractObject.h" @@ -81,7 +79,7 @@ OpenGL ES 3.0 or @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not available, the feature is emulated with sequence of @ref Texture::setImage() "setImage()" calls. -You can use functions @ref invalidateImage() and +You can use functions @ref Texture::invalidateImage() and @ref Texture::invalidateSubImage() "invalidateSubImage()" if you don't need texture data anymore to avoid unnecessary memory operations performed by OpenGL in order to preserve the data. If running on OpenGL ES or extension @@ -158,6 +156,14 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { static Int maxIntegerSamples(); #endif + /** + * @brief Destructor + * + * Deletes associated OpenGL texture. + * @see @fn_gl{DeleteTextures} + */ + ~AbstractTexture(); + /** @brief Copying is not allowed */ AbstractTexture(const AbstractTexture&) = delete; @@ -211,116 +217,6 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { */ void bind(Int layer); - /** - * @brief Set minification filter - * @param filter Filter - * @param mipmap Mipmap filtering. If set to anything else than - * @ref Sampler::Mipmap::Base, make sure textures for all mip - * levels are set or call @ref generateMipmap(). - * @return Reference to self (for method chaining) - * - * Sets filter used when the object pixel size is smaller than the - * texture size. If @extension{EXT,direct_state_access} is not - * available, the texture is bound to some layer before the operation. - * Initial value is (@ref Sampler::Filter::Nearest, @ref Sampler::Mipmap::Linear). - * @attention For rectangle textures only some modes are supported, - * see @ref Sampler::Filter and @ref Sampler::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(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base); - - /** - * @brief Set magnification filter - * @param filter Filter - * @return Reference to self (for method chaining) - * - * Sets filter used when the object pixel size is larger than largest - * texture size. If @extension{EXT,direct_state_access} is not - * available, the texture is bound to some layer before the operation. - * Initial value is @ref Sampler::Filter::Linear. - * @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} - */ - AbstractTexture& setMagnificationFilter(Sampler::Filter filter); - - /** - * @brief Set border color - * @return Reference to self (for method chaining) - * - * Border color when wrapping is set to @ref Sampler::Wrapping::ClampToBorder. - * If @extension{EXT,direct_state_access} is not available, the texture - * is bound to some layer before the operation. Initial value is - * `{0.0f, 0.0f, 0.0f, 0.0f}`. - * @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_es_extension %Extension @es_extension{NV,texture_border_clamp} - */ - AbstractTexture& setBorderColor(const Color4& color); - - /** - * @brief Set max anisotropy - * @return Reference to self (for method chaining) - * - * Default value is `1.0f`, which means no anisotropy. Set to value - * greater than `1.0f` for anisotropic filtering. If extension - * @extension{EXT,texture_filter_anisotropic} (desktop or ES) is not - * available, this function does nothing. If - * @extension{EXT,direct_state_access} is not available, the texture is - * bound to some layer before the operation. - * @see @ref Sampler::maxMaxAnisotropy(), @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} - */ - AbstractTexture& setMaxAnisotropy(Float anisotropy); - - /** - * @brief Invalidate texture image - * @param level Mip level - * - * If running on OpenGL ES or extension @extension{ARB,invalidate_subdata} - * (part of OpenGL 4.3) is not available, this function does nothing. - * @see @ref Texture::invalidateSubImage() "invalidateSubImage()", - * @fn_gl{InvalidateTexImage} - */ - void invalidateImage(Int level); - - /** - * @brief Generate mipmap - * @return Reference to self (for method chaining) - * - * 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{ARB,framebuffer_object} - */ - AbstractTexture& generateMipmap(); - - protected: - /** - * @brief Constructor - * - * Creates new OpenGL texture. - * @see @fn_gl{GenTextures} - */ - explicit AbstractTexture(GLenum target); - - /** - * @brief Destructor - * - * Deletes assigned OpenGL texture. - * @see @fn_gl{DeleteTextures} - */ - ~AbstractTexture(); - #ifdef DOXYGEN_GENERATING_OUTPUT private: #else @@ -328,9 +224,18 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { #endif template struct DataHelper {}; + explicit AbstractTexture(GLenum target); + /* Unlike bind() this also sets the binding layer as active */ void MAGNUM_LOCAL bindInternal(); + void setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap); + void setMagnificationFilter(Sampler::Filter filter); + void setBorderColor(const Color4& color); + void setMaxAnisotropy(Float anisotropy); + void invalidateImage(Int level); + void generateMipmap(); + #ifndef MAGNUM_TARGET_GLES template void image(GLenum target, GLint level, Image& image); template void image(GLenum target, GLint level, BufferImage& image, BufferUsage usage); @@ -445,11 +350,11 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { #ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_TARGET_GLES template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<1> { + #ifdef MAGNUM_BUILD_DEPRECATED enum class Target: GLenum { Texture1D = GL_TEXTURE_1D }; - - constexpr static Target target() { return Target::Texture1D; } + #endif static Math::Vector<1, GLint> imageSize(AbstractTexture& texture, GLenum target, GLint level); @@ -467,6 +372,7 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<1> { }; #endif template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> { + #ifdef MAGNUM_BUILD_DEPRECATED enum class Target: GLenum { Texture2D = GL_TEXTURE_2D, #ifndef MAGNUM_TARGET_GLES @@ -475,8 +381,7 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> { Rectangle = GL_TEXTURE_RECTANGLE #endif }; - - constexpr static Target target() { return Target::Texture2D; } + #endif #ifndef MAGNUM_TARGET_GLES static Vector2i imageSize(AbstractTexture& texture, GLenum target, GLint level); @@ -499,6 +404,7 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> { static void invalidateSubImage(AbstractTexture& texture, GLint level, const Vector2i& offset, const Vector2i& size); }; template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> { + #ifdef MAGNUM_BUILD_DEPRECATED enum class Target: GLenum { #ifndef MAGNUM_TARGET_GLES2 Texture3D = GL_TEXTURE_3D, @@ -510,8 +416,7 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> { Texture3D = GL_TEXTURE_3D_OES #endif }; - - constexpr static Target target() { return Target::Texture3D; } + #endif #ifndef MAGNUM_TARGET_GLES static Vector3i imageSize(AbstractTexture& texture, GLenum target, GLint level); diff --git a/src/Magnum/BufferTexture.h b/src/Magnum/BufferTexture.h index d30e4f4c0..67d9931ee 100644 --- a/src/Magnum/BufferTexture.h +++ b/src/Magnum/BufferTexture.h @@ -195,7 +195,8 @@ functions use DSA to avoid unnecessary calls to @fn_gl{ActiveTexture} and @ref AbstractTexture-performance-optimization "relevant section in AbstractTexture documentation" and respective function documentation for more information. -@see @ref Texture, @ref CubeMapTexture, @ref CubeMapTextureArray +@see @ref Texture, @ref TextureArray, @ref CubeMapTexture, + @ref CubeMapTextureArray, @ref MultisampleTexture, @ref RectangleTexture @requires_gl31 %Extension @extension{ARB,texture_buffer_object} @requires_gl Texture buffers are not available in OpenGL ES. */ @@ -216,6 +217,12 @@ class MAGNUM_EXPORT BufferTexture: private AbstractTexture { */ static Int offsetAlignment(); + /** + * @brief Constructor + * + * Creates new OpenGL texture object. + * @see @fn_gl{GenTextures} with @def_gl{TEXTURE_BUFFER} + */ explicit BufferTexture(): AbstractTexture(GL_TEXTURE_BUFFER) {} /** @copydoc AbstractTexture::id() */ diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 9b619b6f9..359fa3301 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -138,14 +138,17 @@ endif() if(NOT TARGET_GLES) set(Magnum_HEADERS ${Magnum_HEADERS} BufferTexture.h - CubeMapTextureArray.h) + CubeMapTextureArray.h + MultisampleTexture.h + RectangleTexture.h) set(Magnum_SRCS ${Magnum_SRCS} $) endif() # Not-ES2 headers if(NOT TARGET_GLES2) set(Magnum_HEADERS ${Magnum_HEADERS} - BufferImage.h) + BufferImage.h + TextureArray.h) endif() # Files shared between main library and math unit test library diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index 1cd6401cd..8db6acaf7 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -30,6 +30,8 @@ */ #include "Magnum/AbstractTexture.h" +#include "Magnum/Array.h" +#include "Magnum/Math/Vector2.h" namespace Magnum { @@ -92,21 +94,41 @@ class CubeMapTexture: public AbstractTexture { /** * @brief Constructor * - * Creates one cube map OpenGL texture. + * Creates new OpenGL texture object. * @see @fn_gl{GenTextures} with @def_gl{TEXTURE_CUBE_MAP} */ explicit CubeMapTexture(): AbstractTexture(GL_TEXTURE_CUBE_MAP) {} - /** - * @brief Set wrapping - * - * See @ref Texture::setWrapping() for more information. - */ + /** @copydoc Texture::setMinificationFilter() */ + CubeMapTexture& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { + AbstractTexture::setMinificationFilter(filter, mipmap); + return *this; + } + + /** @copydoc Texture::setMagnificationFilter() */ + CubeMapTexture& setMagnificationFilter(Sampler::Filter filter) { + AbstractTexture::setMagnificationFilter(filter); + return *this; + } + + /** @copydoc Texture::setWrapping() */ CubeMapTexture& setWrapping(const Array3D& wrapping) { DataHelper<3>::setWrapping(*this, wrapping); return *this; } + /** @copydoc Texture::setBorderColor() */ + CubeMapTexture& setBorderColor(const Color4& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + + /** @copydoc Texture::setMaxAnisotropy() */ + CubeMapTexture& setMaxAnisotropy(Float anisotropy) { + AbstractTexture::setMaxAnisotropy(anisotropy); + return *this; + } + #ifndef MAGNUM_TARGET_GLES /** * @brief %Image size in given mip level @@ -220,6 +242,15 @@ class CubeMapTexture: public AbstractTexture { } #endif + /** @copydoc Texture::generateMipmap() */ + CubeMapTexture& generateMipmap() { + AbstractTexture::generateMipmap(); + return *this; + } + + /** @copydoc Texture::invalidateImage() */ + void invalidateImage(Int level) { AbstractTexture::invalidateImage(level); } + /** * @brief Invalidate texture subimage * @param level Mip level @@ -242,26 +273,6 @@ class CubeMapTexture: public AbstractTexture { AbstractTexture::setLabel(label); return *this; } - CubeMapTexture& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { - AbstractTexture::setMinificationFilter(filter, mipmap); - return *this; - } - CubeMapTexture& setMagnificationFilter(Sampler::Filter filter) { - AbstractTexture::setMagnificationFilter(filter); - return *this; - } - CubeMapTexture& setBorderColor(const Color4& color) { - AbstractTexture::setBorderColor(color); - return *this; - } - CubeMapTexture& setMaxAnisotropy(Float anisotropy) { - AbstractTexture::setMaxAnisotropy(anisotropy); - return *this; - } - CubeMapTexture& generateMipmap() { - AbstractTexture::generateMipmap(); - return *this; - } #endif }; diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index 4767d67a7..a22b89ece 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -32,6 +32,8 @@ #endif #include "Magnum/AbstractTexture.h" +#include "Magnum/Array.h" +#include "Magnum/Math/Vector2.h" #ifndef MAGNUM_TARGET_GLES namespace Magnum { @@ -83,21 +85,41 @@ class CubeMapTextureArray: public AbstractTexture { /** * @brief Constructor * - * Creates one cube map OpenGL texture. - * @see @fn_gl{GenTextures} with @def_gl{TEXTURE_CUBE_MAP} + * Creates new OpenGL texture object. + * @see @fn_gl{GenTextures} with @def_gl{TEXTURE_CUBE_MAP_ARRAY} */ explicit CubeMapTextureArray(): AbstractTexture(GL_TEXTURE_CUBE_MAP_ARRAY) {} - /** - * @brief Set wrapping - * - * See @ref Texture::setWrapping() for more information. - */ + /** @copydoc Texture::setMinificationFilter() */ + CubeMapTextureArray& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { + AbstractTexture::setMinificationFilter(filter, mipmap); + return *this; + } + + /** @copydoc Texture::setMagnificationFilter() */ + CubeMapTextureArray& setMagnificationFilter(Sampler::Filter filter) { + AbstractTexture::setMagnificationFilter(filter); + return *this; + } + + /** @copydoc Texture::setWrapping() */ CubeMapTextureArray& setWrapping(const Array3D& wrapping) { DataHelper<3>::setWrapping(*this, wrapping); return *this; } + /** @copydoc Texture::setBorderColor() */ + CubeMapTextureArray& setBorderColor(const Color4& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + + /** @copydoc Texture::setMaxAnisotropy() */ + CubeMapTextureArray& setMaxAnisotropy(Float anisotropy) { + AbstractTexture::setMaxAnisotropy(anisotropy); + return *this; + } + /** * @brief %Image size in given mip level * @param level Mip level @@ -207,6 +229,15 @@ class CubeMapTextureArray: public AbstractTexture { return setSubImage(level, offset, image); } + /** @copydoc Texture::generateMipmap() */ + CubeMapTextureArray& generateMipmap() { + AbstractTexture::generateMipmap(); + return *this; + } + + /** @copydoc Texture::invalidateImage() */ + void invalidateImage(Int level) { AbstractTexture::invalidateImage(level); } + /** * @brief Invalidate texture subimage * @param level Mip level @@ -228,26 +259,6 @@ class CubeMapTextureArray: public AbstractTexture { AbstractTexture::setLabel(label); return *this; } - CubeMapTextureArray& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { - AbstractTexture::setMinificationFilter(filter, mipmap); - return *this; - } - CubeMapTextureArray& setMagnificationFilter(Sampler::Filter filter) { - AbstractTexture::setMagnificationFilter(filter); - return *this; - } - CubeMapTextureArray& setBorderColor(const Color4& color) { - AbstractTexture::setBorderColor(color); - return *this; - } - CubeMapTextureArray& setMaxAnisotropy(Float anisotropy) { - AbstractTexture::setMaxAnisotropy(anisotropy); - return *this; - } - CubeMapTextureArray& generateMipmap() { - AbstractTexture::generateMipmap(); - return *this; - } #endif }; diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index 5166cd1dd..969b9b4f4 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -560,8 +560,8 @@ typedef ColorFormat ImageFormat; typedef ColorType ColorType; class Context; -class CubeMapTexture; +class CubeMapTexture; #ifndef MAGNUM_TARGET_GLES class CubeMapTextureArray; #endif @@ -588,11 +588,19 @@ enum class MeshPrimitive: GLenum; class Mesh; class MeshView; +#ifndef MAGNUM_TARGET_GLES +template class MultisampleTexture; +typedef MultisampleTexture<2> MultisampleTexture2D; +typedef MultisampleTexture<3> MultisampleTexture2DArray; +#endif + /* AbstractQuery is not used directly */ class PrimitiveQuery; class SampleQuery; class TimeQuery; +class RectangleTexture; + class Renderbuffer; enum class RenderbufferFormat: GLenum; @@ -613,6 +621,14 @@ typedef Texture<1> Texture1D; typedef Texture<2> Texture2D; typedef Texture<3> Texture3D; +#ifndef MAGNUM_TARGET_GLES2 +template class TextureArray; +#ifndef MAGNUM_TARGET_GLES +typedef TextureArray<1> Texture1DArray; +#endif +typedef TextureArray<2> Texture2DArray; +#endif + enum class TextureFormat: GLenum; class Timeline; diff --git a/src/Magnum/MultisampleTexture.h b/src/Magnum/MultisampleTexture.h new file mode 100644 index 000000000..cff1c1d2b --- /dev/null +++ b/src/Magnum/MultisampleTexture.h @@ -0,0 +1,116 @@ +#ifndef Magnum_MultisampleTexture_h +#define Magnum_MultisampleTexture_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MAGNUM_TARGET_GLES +/** @file + * @brief Class @ref Magnum::MultisampleTexture, typedef @ref Magnum::MultisampleTexture2D, @ref Magnum::MultisampleTexture2DArray + */ +#endif + +#include "Magnum/AbstractTexture.h" +#include "Magnum/DimensionTraits.h" +#include "Magnum/Math/Vector3.h" + +#ifndef MAGNUM_TARGET_GLES +namespace Magnum { + +namespace Implementation { + template constexpr GLenum multisampleTextureTarget(); + template<> inline constexpr GLenum multisampleTextureTarget<2>() { return GL_TEXTURE_2D_MULTISAMPLE; } + template<> inline constexpr GLenum multisampleTextureTarget<3>() { return GL_TEXTURE_2D_MULTISAMPLE_ARRAY; } +} + +/** +@brief Mulitsample texture + +Template class for 2D mulitsample texture and 2D multisample texture array. See +also @ref AbstractTexture documentation for more information. + +@todoc Finish when fully implemented + +The texture is bound to layer specified by shader via @ref bind(). In shader, +the texture is used via `sampler2DMS`/`sampler2DMSArray`, +`isampler2DMS`/`isampler2DMSArray` or `usampler2DMS`/`usampler2DMSArray`. See +@ref AbstractShaderProgram documentation for more information about usage in +shaders. + +@requires_gl32 %Extension @extension{ARB,texture_multisample} +@requires_gl Multisample textures are not available in OpenGL ES. + +@see @ref MultisampleTexture2D, @ref MultisampleTexture2DArray, @ref Texture, + @ref TextureArray, @ref BufferTexture, @ref CubeMapTexture, + @ref CubeMapTextureArray, @ref RectangleTexture + */ +template class MultisampleTexture: public AbstractTexture { + public: + static const UnsignedInt Dimensions = dimensions; /**< @brief %Texture dimension count */ + + /** + * @brief Constructor + * + * Creates new OpenGL texture object. + * @see @fn_gl{GenTextures} with @def_gl{TEXTURE_2D_MULTISAMPLE} or + * @def_gl{TEXTURE_2D_MULTISAMPLE_ARRAY} + */ + explicit MultisampleTexture(): AbstractTexture(Implementation::multisampleTextureTarget()) {} + + #ifndef MAGNUM_TARGET_GLES + /** @copydoc Texture::imageSize() */ + typename DimensionTraits::VectorType imageSize(Int level) { + return DataHelper::imageSize(*this, _target, level); + } + #endif + + /** @copydoc Texture::invalidateImage() */ + void invalidateImage(Int level) { AbstractTexture::invalidateImage(level); } + + /** @copydoc Texture::invalidateSubImage() */ + void invalidateSubImage(Int level, const typename DimensionTraits::VectorType& offset, const typename DimensionTraits::VectorType& size) { + DataHelper::invalidateSubImage(*this, level, offset, size); + } + + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + MultisampleTexture& setLabel(const std::string& label) { + AbstractTexture::setLabel(label); + return *this; + } + #endif +}; + +/** @brief Two-dimensional multisample texture */ +typedef MultisampleTexture<2> MultisampleTexture2D; + +/** @brief Two-dimensional multisample texture array */ +typedef MultisampleTexture<3> MultisampleTexture2DArray; + +} +#else +#error this header is available only on desktop OpenGL build +#endif + +#endif diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h new file mode 100644 index 000000000..d226bc9c8 --- /dev/null +++ b/src/Magnum/RectangleTexture.h @@ -0,0 +1,323 @@ +#ifndef Magnum_RectangleTexture_h +#define Magnum_RectangleTexture_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MAGNUM_TARGET_GLES +/** @file + * @brief Class @ref Magnum::RectangleTexture + */ +#endif + +#include "Magnum/AbstractTexture.h" +#include "Magnum/Array.h" +#include "Magnum/Math/Vector2.h" + +#ifndef MAGNUM_TARGET_GLES +namespace Magnum { + +/** +@brief Rectangle texture + +See also @ref AbstractTexture documentation for more information. + +@section RectangleTexture-usage Usage + +Common usage is to fully configure all texture parameters and then set the +data from e.g. @ref Image2D. Example configuration: +@code +Image2D image(ColorFormat::RGBA, ColorType::UnsignedByte, {526, 137}, data); + +RectangleTexture texture; +texture.setMagnificationFilter(Sampler::Filter::Linear) + .setMinificationFilter(Sampler::Filter::Linear) + .setWrapping(Sampler::Wrapping::ClampToEdge) + .setMaxAnisotropy(Sampler::maxMaxAnisotropy()) + .setStorage(TextureFormat::RGBA8, {526, 137}) + .setSubImage({}, image); +@endcode + +The texture is bound to layer specified by shader via @ref bind(). In shader, +the texture is used via sampler2DRect`, `sampler2DRectShadow`, `isampler2DRect` +or `usampler2DRect`. See @ref AbstractShaderProgram documentation for more +information about usage in shaders. + +@requires_gl31 %Extension @extension{ARB,texture_rectangle} +@requires_gl Rectangle textures are not available in OpenGL ES. + +@see @ref Texture, @ref TextureArray, @ref BufferTexture, @ref CubeMapTexture, + @ref CubeMapTextureArray, @ref MultisampleTexture + */ +class RectangleTexture: public AbstractTexture { + public: + /** + * @brief Constructor + * + * Creates new OpenGL texture object. + * @see @fn_gl{GenTextures} with @def_gl{TEXTURE_RECTANGLE} + */ + explicit RectangleTexture(): AbstractTexture(GL_TEXTURE_RECTANGLE) {} + + /** + * @brief Set minification filter + * @param filter Filter + * @return Reference to self (for method chaining) + * + * Sets filter used when the object pixel size is smaller than the + * texture size. If @extension{EXT,direct_state_access} is not + * available, the texture is bound to some layer before the operation. + * Initial value is @ref Sampler::Filter::Linear. + * @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} + */ + RectangleTexture& setMinificationFilter(Sampler::Filter filter) { + AbstractTexture::setMinificationFilter(filter, Sampler::Mipmap::Base); + return *this; + } + + /** @copydoc Texture::setMagnificationFilter() */ + RectangleTexture& setMagnificationFilter(Sampler::Filter filter) { + AbstractTexture::setMagnificationFilter(filter); + return *this; + } + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief %Image size + * + * The result is not cached in any way. 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{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} + * with @def_gl{TEXTURE_WIDTH} and @def_gl{TEXTURE_HEIGHT} + * @requires_gl %Texture image queries are not available in OpenGL ES. + */ + Vector2i imageSize() { return DataHelper<2>::imageSize(*this, _target, 0); } + #endif + + /** + * @brief Set wrapping + * @param wrapping Wrapping type for all texture dimensions + * @return Reference to self (for method chaining) + * + * Sets wrapping type for coordinates out of (0, textureSizeInGivenDirection-1) + * range for rectangle textures. If @extension{EXT,direct_state_access} + * is not available, the texture is bound to some layer before the + * operation. Initial value is @ref Sampler::Wrapping::ClampToEdge. + * @attention Only @ref Sampler::Wrapping::ClampToEdge and + * @ref Sampler::Wrapping::ClampToBorder is supported on this + * texture type. + * @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} + */ + RectangleTexture& setWrapping(const Array2D& wrapping) { + DataHelper<2>::setWrapping(*this, wrapping); + return *this; + } + + /** @copydoc Texture::setBorderColor() */ + RectangleTexture& setBorderColor(const Color4& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + + /** @copydoc Texture::setMaxAnisotropy() */ + RectangleTexture& setMaxAnisotropy(Float anisotropy) { + AbstractTexture::setMaxAnisotropy(anisotropy); + return *this; + } + + /** + * @brief Set storage + * @param internalFormat Internal format + * @param size Size + * @return Reference to self (for method chaining) + * + * Specifies entire structure of a texture at once, removing the need + * for additional consistency checks and memory reallocations when + * updating the data later. After calling this function the texture + * is immutable and calling @ref setStorage() or @ref setImage() is not + * allowed. + * + * If @extension{EXT,direct_state_access} is not available, the texture + * is bound to some layer before the operation. If OpenGL 4.2, + * @extension{ARB,texture_storage}, OpenGL ES 3.0 or + * @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not + * available, the feature is emulated with @ref setImage() call. + * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexStorage2D} + * or @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, + * eventually @fn_gl{TexImage2D} or + * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}. + */ + RectangleTexture& setStorage(TextureFormat internalFormat, const Vector2i& size) { + DataHelper<2>::setStorage(*this, _target, 1, internalFormat, size); + return *this; + } + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Read texture to image + * @param image %Image where to put the data + * + * %Image parameters like format and type of pixel data are taken from + * given image, image size is taken from the texture using + * @ref imageSize(). + * + * If @extension{EXT,direct_state_access} is not available, the + * texture is bound to some layer before the operation. If + * @extension{ARB,robustness} is available, the operation is protected + * from buffer overflow. However, if both @extension{EXT,direct_state_access} + * and @extension{ARB,robustness} are available, the DSA version is + * used, because it is better for performance and there isn't any + * function combining both features. + * @requires_gl %Texture image queries are not available in OpenGL ES. + * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} + * with @def_gl{TEXTURE_WIDTH} and @def_gl{TEXTURE_HEIGHT}, then + * @fn_gl{GetTexImage}, @fn_gl_extension{GetTextureImage,EXT,direct_state_access} + * or @fn_gl_extension{GetnTexImage,ARB,robustness} + */ + void image(Image2D& image) { + AbstractTexture::image<2>(_target, 0, image); + } + + /** + * @brief Read given mip level of texture to buffer image + * @param image %Buffer image where to put the data + * @param usage %Buffer usage + * + * See @ref image(Image2D&) for more information. + * @requires_gl %Texture image queries are not available in OpenGL ES. + */ + void image(BufferImage2D& image, BufferUsage usage) { + AbstractTexture::image<2>(_target, 0, image, usage); + } + #endif + + /** + * @brief Set image data + * @param internalFormat Internal format + * @param image @ref Image2D, @ref ImageReference2D or + * @ref Trade::ImageData2D + * @return Reference to self (for method chaining) + * + * For better performance when calling @ref setImage() more than once + * use @ref setStorage() and @ref setSubImage() instead. + * + * 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{TexImage2D} + * or @fn_gl_extension{TextureImage2D,EXT,direct_state_access} + */ + RectangleTexture& setImage(TextureFormat internalFormat, const ImageReference2D& image) { + DataHelper<2>::setImage(*this, _target, 0, internalFormat, image); + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @overload */ + RectangleTexture& setImage(TextureFormat internalFormat, BufferImage2D& image) { + DataHelper<2>::setImage(*this, _target, 0, internalFormat, image); + return *this; + } + + /** @overload */ + RectangleTexture& setImage(TextureFormat internalFormat, BufferImage2D&& image) { + return setImage(internalFormat, image); + } + #endif + + /** + * @brief Set image subdata + * @param offset Offset where to put data in the texture + * @param image @ref Image2D, @ref ImageReference2D or + * @ref Trade::ImageData2D + * @return Reference to self (for method chaining) + * + * If @extension{EXT,direct_state_access} is not available, the + * texture is bound to some layer before the operation. + * @see @ref setStorage(), @ref setImage(), @fn_gl{ActiveTexture}, + * @fn_gl{BindTexture} and @fn_gl{TexSubImage2D} or + * @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access} + */ + RectangleTexture& setSubImage(const Vector2i& offset, const ImageReference2D& image) { + DataHelper<2>::setSubImage(*this, _target, 0, offset, image); + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @overload */ + RectangleTexture& setSubImage(const Vector2i& offset, BufferImage2D& image) { + DataHelper<2>::setSubImage(*this, _target, 0, offset, image); + return *this; + } + + /** @overload */ + RectangleTexture& setSubImage(const Vector2i& offset, BufferImage2D&& image) { + return setSubImage(offset, image); + } + #endif + + /** + * @brief Invalidate texture image + * + * If running on OpenGL ES or extension @extension{ARB,invalidate_subdata} + * (part of OpenGL 4.3) is not available, this function does nothing. + * @see @ref invalidateSubImage(), @fn_gl{InvalidateTexImage} + */ + void invalidateImage() { AbstractTexture::invalidateImage(0); } + + /** + * @brief Invalidate texture subimage + * @param offset Offset into the texture + * @param size Size of invalidated data + * + * If running on OpenGL ES or extension @extension{ARB,invalidate_subdata} + * (part of OpenGL 4.3) is not available, this function does nothing. + * @see @ref invalidateImage(), @fn_gl{InvalidateTexSubImage} + */ + void invalidateSubImage(const Vector2i& offset, const Vector2i& size) { + DataHelper<2>::invalidateSubImage(*this, 0, offset, size); + } + + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + RectangleTexture& setLabel(const std::string& label) { + AbstractTexture::setLabel(label); + return *this; + } + #endif +}; + +} +#else +#error this header is available only on desktop OpenGL build +#endif + +#endif diff --git a/src/Magnum/Test/CMakeLists.txt b/src/Magnum/Test/CMakeLists.txt index 04ccc8a94..76f3eafa3 100644 --- a/src/Magnum/Test/CMakeLists.txt +++ b/src/Magnum/Test/CMakeLists.txt @@ -77,12 +77,15 @@ if(BUILD_GL_TESTS) corrade_add_test(ShaderGLTest ShaderGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) if(NOT MAGNUM_TARGET_GLES2) + corrade_add_test(TextureArrayGLTest TextureArrayGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) corrade_add_test(BufferImageGLTest BufferImageGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) endif() if(NOT MAGNUM_TARGET_GLES) corrade_add_test(BufferTextureGLTest BufferTextureGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) corrade_add_test(CubeMapTextureArrayGLTest CubeMapTextureArrayGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) + corrade_add_test(MultisampleTextureGLTest MultisampleTextureGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) + corrade_add_test(RectangleTextureGLTest RectangleTextureGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) endif() endif() diff --git a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp index c04774c45..e3da6a916 100644 --- a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp @@ -26,9 +26,10 @@ #include #include "Magnum/BufferImage.h" +#include "Magnum/Color.h" #include "Magnum/ColorFormat.h" -#include "Magnum/Image.h" #include "Magnum/CubeMapTextureArray.h" +#include "Magnum/Image.h" #include "Magnum/TextureFormat.h" #include "Magnum/Test/AbstractOpenGLTester.h" diff --git a/src/Magnum/Test/CubeMapTextureGLTest.cpp b/src/Magnum/Test/CubeMapTextureGLTest.cpp index a7ba9d9e8..6e4d75a77 100644 --- a/src/Magnum/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureGLTest.cpp @@ -29,9 +29,10 @@ #ifndef MAGNUM_TARGET_GLES2 #include "Magnum/BufferImage.h" #endif +#include "Magnum/Color.h" #include "Magnum/ColorFormat.h" -#include "Magnum/Image.h" #include "Magnum/CubeMapTexture.h" +#include "Magnum/Image.h" #include "Magnum/TextureFormat.h" #include "Magnum/Test/AbstractOpenGLTester.h" diff --git a/src/Magnum/Test/MeshGLTest.cpp b/src/Magnum/Test/MeshGLTest.cpp index dcc412b86..8ec197adf 100644 --- a/src/Magnum/Test/MeshGLTest.cpp +++ b/src/Magnum/Test/MeshGLTest.cpp @@ -24,6 +24,7 @@ */ #include "Magnum/Buffer.h" +#include "Magnum/Color.h" #include "Magnum/ColorFormat.h" #include "Magnum/Framebuffer.h" #include "Magnum/Image.h" diff --git a/src/Magnum/Test/MultisampleTextureGLTest.cpp b/src/Magnum/Test/MultisampleTextureGLTest.cpp new file mode 100644 index 000000000..6c5e959cc --- /dev/null +++ b/src/Magnum/Test/MultisampleTextureGLTest.cpp @@ -0,0 +1,212 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum/MultisampleTexture.h" +#include "Magnum/Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class MultisampleTextureGLTest: public AbstractOpenGLTester { + public: + explicit MultisampleTextureGLTest(); + + void construct2D(); + void construct2DArray(); + + void storage2D(); + void storage2DArray(); + + void image2D(); + void image2DBuffer(); + void image2DArray(); + void image2DArrayBuffer(); + + void subImage2D(); + void subImage2DBuffer(); + void subImage2DArray(); + void subImage2DArrayBuffer(); + + void invalidateImage2D(); + void invalidateImage2DArray(); + + void invalidateSubImage2D(); + void invalidateSubImage2DArray(); +}; + +MultisampleTextureGLTest::MultisampleTextureGLTest() { + addTests({&MultisampleTextureGLTest::construct2D, + &MultisampleTextureGLTest::construct2DArray, + + &MultisampleTextureGLTest::storage2D, + &MultisampleTextureGLTest::storage2DArray, + + &MultisampleTextureGLTest::image2D, + &MultisampleTextureGLTest::image2DBuffer, + &MultisampleTextureGLTest::image2DArray, + &MultisampleTextureGLTest::image2DArrayBuffer, + + &MultisampleTextureGLTest::subImage2D, + &MultisampleTextureGLTest::subImage2DBuffer, + &MultisampleTextureGLTest::subImage2DArray, + &MultisampleTextureGLTest::subImage2DArrayBuffer, + + &MultisampleTextureGLTest::invalidateImage2D, + &MultisampleTextureGLTest::invalidateImage2DArray, + + &MultisampleTextureGLTest::invalidateSubImage2D, + &MultisampleTextureGLTest::invalidateSubImage2DArray}); +} + +void MultisampleTextureGLTest::construct2D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + { + MultisampleTexture2D texture; + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(texture.id() > 0); + } + + MAGNUM_VERIFY_NO_ERROR(); +} + +void MultisampleTextureGLTest::construct2DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + { + MultisampleTexture2DArray texture; + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(texture.id() > 0); + } + + MAGNUM_VERIFY_NO_ERROR(); +} + +void MultisampleTextureGLTest::storage2D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Not implemented yet."); +} + +void MultisampleTextureGLTest::storage2DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Not implemented yet."); +} + +void MultisampleTextureGLTest::image2D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Not implemented yet."); +} + +void MultisampleTextureGLTest::image2DBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Not implemented yet."); +} + +void MultisampleTextureGLTest::image2DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Not implemented yet."); +} + +void MultisampleTextureGLTest::image2DArrayBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Not implemented yet."); +} + +void MultisampleTextureGLTest::subImage2D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Not implemented yet."); +} + +void MultisampleTextureGLTest::subImage2DBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Not implemented yet."); +} + +void MultisampleTextureGLTest::subImage2DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Not implemented yet."); +} + +void MultisampleTextureGLTest::subImage2DArrayBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Not implemented yet."); +} + +void MultisampleTextureGLTest::invalidateImage2D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Multisample storage is not implemented yet."); +} + +void MultisampleTextureGLTest::invalidateImage2DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Multisample storage is not implemented yet."); +} + +void MultisampleTextureGLTest::invalidateSubImage2D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Multisample storage is not implemented yet."); +} + +void MultisampleTextureGLTest::invalidateSubImage2DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + CORRADE_SKIP("Multisample storage is not implemented yet."); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::MultisampleTextureGLTest) diff --git a/src/Magnum/Test/RectangleTextureGLTest.cpp b/src/Magnum/Test/RectangleTextureGLTest.cpp new file mode 100644 index 000000000..e4ff02c4e --- /dev/null +++ b/src/Magnum/Test/RectangleTextureGLTest.cpp @@ -0,0 +1,250 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum/configure.h" +#include "Magnum/BufferImage.h" +#include "Magnum/Color.h" +#include "Magnum/ColorFormat.h" +#include "Magnum/Image.h" +#include "Magnum/RectangleTexture.h" +#include "Magnum/TextureFormat.h" +#include "Magnum/Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class TextureGLTest: public AbstractOpenGLTester { + public: + explicit TextureGLTest(); + + void construct(); + void sampling(); + void storage(); + + void image(); + void imageBuffer(); + + void subImage(); + void subImageBuffer(); + + void invalidateImage(); + void invalidateSubImage(); +}; + +TextureGLTest::TextureGLTest() { + addTests({&TextureGLTest::construct, + &TextureGLTest::sampling, + &TextureGLTest::storage, + + &TextureGLTest::image, + &TextureGLTest::imageBuffer, + + &TextureGLTest::subImage, + &TextureGLTest::subImageBuffer, + + &TextureGLTest::invalidateImage, + &TextureGLTest::invalidateSubImage}); +} + +void TextureGLTest::construct() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + + { + RectangleTexture texture; + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(texture.id() > 0); + } + + MAGNUM_VERIFY_NO_ERROR(); +} + +void TextureGLTest::sampling() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + + RectangleTexture texture; + texture.setMinificationFilter(Sampler::Filter::Linear) + .setMagnificationFilter(Sampler::Filter::Linear) + .setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Color3(0.5f)) + .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); + + MAGNUM_VERIFY_NO_ERROR(); +} + +void TextureGLTest::storage() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + + RectangleTexture texture; + texture.setStorage(TextureFormat::RGBA8, Vector2i(32)); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(texture.imageSize(), Vector2i(32)); + + MAGNUM_VERIFY_NO_ERROR(); +} + +void TextureGLTest::image() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + + constexpr UnsignedByte data[] = { 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }; + RectangleTexture texture; + texture.setImage(TextureFormat::RGBA8, + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), data)); + + MAGNUM_VERIFY_NO_ERROR(); + + Image2D image(ColorFormat::RGBA, ColorType::UnsignedByte); + texture.image(image); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i(2)); + CORRADE_COMPARE_AS(std::vector(image.data(), image.data()+image.pixelSize()*image.size().product()), + std::vector(data, data + 16), TestSuite::Compare::Container); +} + +void TextureGLTest::imageBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + + constexpr UnsignedByte data[] = { 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }; + RectangleTexture texture; + texture.setImage(TextureFormat::RGBA8, + BufferImage2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), data, BufferUsage::StaticDraw)); + + MAGNUM_VERIFY_NO_ERROR(); + + BufferImage2D image(ColorFormat::RGBA, ColorType::UnsignedByte); + texture.image(image, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i(2)); + CORRADE_COMPARE_AS(std::vector(imageData.begin(), imageData.end()), + std::vector(data, data+16), TestSuite::Compare::Container); +} + +void TextureGLTest::subImage() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + + constexpr UnsignedByte zero[4*4*4] = {}; + constexpr UnsignedByte subData[] = { 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }; + RectangleTexture texture; + texture.setImage(TextureFormat::RGBA8, + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(4), zero)); + texture.setSubImage(Vector2i(1), + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), subData)); + + MAGNUM_VERIFY_NO_ERROR(); + + Image2D image(ColorFormat::RGBA, ColorType::UnsignedByte); + texture.image(image); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i(4)); + CORRADE_COMPARE_AS(std::vector(image.data(), image.data()+image.pixelSize()*image.size().product()), (std::vector{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, + 0, 0, 0, 0, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }), TestSuite::Compare::Container); +} + +void TextureGLTest::subImageBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + + constexpr UnsignedByte zero[4*4*4] = {}; + constexpr UnsignedByte subData[] = { 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }; + RectangleTexture texture; + texture.setImage(TextureFormat::RGBA8, + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(4), zero)); + texture.setSubImage(Vector2i(1), + BufferImage2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), subData, BufferUsage::StaticDraw)); + + MAGNUM_VERIFY_NO_ERROR(); + + BufferImage2D image(ColorFormat::RGBA, ColorType::UnsignedByte); + texture.image(image, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i(4)); + CORRADE_COMPARE_AS(std::vector(imageData.begin(), imageData.end()), (std::vector{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, + 0, 0, 0, 0, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }), TestSuite::Compare::Container); +} + +void TextureGLTest::invalidateImage() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + + RectangleTexture texture; + texture.setStorage(TextureFormat::RGBA8, Vector2i(32)); + texture.invalidateImage(); + + MAGNUM_VERIFY_NO_ERROR(); +} + +void TextureGLTest::invalidateSubImage() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + + RectangleTexture texture; + texture.setStorage(TextureFormat::RGBA8, Vector2i(32)); + texture.invalidateSubImage(Vector2i(4), Vector2i(16)); + + MAGNUM_VERIFY_NO_ERROR(); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::TextureGLTest) diff --git a/src/Magnum/Test/TextureArrayGLTest.cpp b/src/Magnum/Test/TextureArrayGLTest.cpp new file mode 100644 index 000000000..2c2eccfde --- /dev/null +++ b/src/Magnum/Test/TextureArrayGLTest.cpp @@ -0,0 +1,683 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum/configure.h" +#include "Magnum/BufferImage.h" +#include "Magnum/Color.h" +#include "Magnum/ColorFormat.h" +#include "Magnum/Image.h" +#include "Magnum/TextureArray.h" +#include "Magnum/TextureFormat.h" +#include "Magnum/Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class TextureGLTest: public AbstractOpenGLTester { + public: + explicit TextureGLTest(); + + #ifndef MAGNUM_TARGET_GLES + void construct1DArray(); + #endif + void construct2DArray(); + + #ifndef MAGNUM_TARGET_GLES + void sampling1DArray(); + #endif + void sampling2DArray(); + + #ifdef MAGNUM_TARGET_GLES + void samplingBorder2DArray(); + #endif + + #ifndef MAGNUM_TARGET_GLES + void storage1DArray(); + #endif + void storage2DArray(); + + #ifndef MAGNUM_TARGET_GLES + void image1DArray(); + void image1DArrayBuffer(); + #endif + #ifndef MAGNUM_TARGET_GLES2 + void image2DArray(); + void image2DArrayBuffer(); + #endif + + #ifndef MAGNUM_TARGET_GLES + void subImage1DArray(); + void subImage1DArrayBuffer(); + #endif + void subImage2DArray(); + void subImage2DArrayBuffer(); + + #ifndef MAGNUM_TARGET_GLES + void generateMipmap1DArray(); + #endif + void generateMipmap2DArray(); + + #ifndef MAGNUM_TARGET_GLES + void invalidateImage1DArray(); + #endif + void invalidateImage2DArray(); + + #ifndef MAGNUM_TARGET_GLES + void invalidateSubImage1DArray(); + #endif + void invalidateSubImage2DArray(); +}; + +TextureGLTest::TextureGLTest() { + addTests({ + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::construct1DArray, + #endif + &TextureGLTest::construct2DArray, + + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::sampling1DArray, + #endif + &TextureGLTest::sampling2DArray, + + #ifdef MAGNUM_TARGET_GLES + &TextureGLTest::samplingBorder2DArray, + #endif + + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::storage1DArray, + #endif + &TextureGLTest::storage2DArray, + + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::image1DArray, + &TextureGLTest::image1DArrayBuffer, + #endif + &TextureGLTest::image2DArray, + &TextureGLTest::image2DArrayBuffer, + + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::subImage1DArray, + &TextureGLTest::subImage1DArrayBuffer, + #endif + &TextureGLTest::subImage2DArray, + &TextureGLTest::subImage2DArrayBuffer, + + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::generateMipmap1DArray, + #endif + &TextureGLTest::generateMipmap2DArray, + + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::invalidateImage1DArray, + #endif + &TextureGLTest::invalidateImage2DArray, + + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::invalidateSubImage1DArray, + #endif + &TextureGLTest::invalidateSubImage2DArray + }); +} + +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::construct1DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + + { + Texture1DArray texture; + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(texture.id() > 0); + } + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + +void TextureGLTest::construct2DArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + #endif + + { + Texture2DArray texture; + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(texture.id() > 0); + } + + MAGNUM_VERIFY_NO_ERROR(); +} + +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::sampling1DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + + Texture1DArray texture; + texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) + .setMagnificationFilter(Sampler::Filter::Linear) + .setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Color3(0.5f)) + .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + +void TextureGLTest::sampling2DArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + #endif + + Texture2DArray texture; + texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) + .setMagnificationFilter(Sampler::Filter::Linear) + #ifndef MAGNUM_TARGET_GLES + .setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Color3(0.5f)) + #else + .setWrapping(Sampler::Wrapping::ClampToEdge) + #endif + .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); + + MAGNUM_VERIFY_NO_ERROR(); +} + +#ifdef MAGNUM_TARGET_GLES +void TextureGLTest::samplingBorder2DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::NV::texture_border_clamp::string() + std::string(" is not supported.")); + + Texture2DArray texture; + texture.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Color3(0.5f)); + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::storage1DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + + Texture1DArray texture; + texture.setStorage(5, TextureFormat::RGBA8, Vector2i(32)); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(texture.imageSize(0), Vector2i(32, 32)); + CORRADE_COMPARE(texture.imageSize(1), Vector2i(16, 32)); + CORRADE_COMPARE(texture.imageSize(2), Vector2i( 8, 32)); + CORRADE_COMPARE(texture.imageSize(3), Vector2i( 4, 32)); + CORRADE_COMPARE(texture.imageSize(4), Vector2i( 2, 32)); + CORRADE_COMPARE(texture.imageSize(5), Vector2i( 0, 0)); /* not available */ + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + +void TextureGLTest::storage2DArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + #endif + + Texture2DArray texture; + texture.setStorage(5, TextureFormat::RGBA8, Vector3i(32)); + + MAGNUM_VERIFY_NO_ERROR(); + + /** @todo How to test this on ES? */ + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE(texture.imageSize(0), Vector3i(32, 32, 32)); + CORRADE_COMPARE(texture.imageSize(1), Vector3i(16, 16, 32)); + CORRADE_COMPARE(texture.imageSize(2), Vector3i( 8, 8, 32)); + CORRADE_COMPARE(texture.imageSize(3), Vector3i( 4, 4, 32)); + CORRADE_COMPARE(texture.imageSize(4), Vector3i( 2, 2, 32)); + CORRADE_COMPARE(texture.imageSize(5), Vector3i( 0, 0, 0)); /* not available */ + + MAGNUM_VERIFY_NO_ERROR(); + #endif +} + +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::image1DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + + constexpr UnsignedByte data[] = { 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }; + Texture1DArray texture; + texture.setImage(0, TextureFormat::RGBA8, + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), data)); + + MAGNUM_VERIFY_NO_ERROR(); + + Image2D image(ColorFormat::RGBA, ColorType::UnsignedByte); + texture.image(0, image); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i(2)); + CORRADE_COMPARE_AS(std::vector(image.data(), image.data()+image.pixelSize()*image.size().product()), + std::vector(data, data + 16), TestSuite::Compare::Container); +} + +void TextureGLTest::image1DArrayBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + + constexpr UnsignedByte data[] = { 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }; + Texture1DArray texture; + texture.setImage(0, TextureFormat::RGBA8, + BufferImage2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), data, BufferUsage::StaticDraw)); + + MAGNUM_VERIFY_NO_ERROR(); + + BufferImage2D image(ColorFormat::RGBA, ColorType::UnsignedByte); + texture.image(0, image, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i(2)); + CORRADE_COMPARE_AS(std::vector(imageData.begin(), imageData.end()), + std::vector(data, data + 16), TestSuite::Compare::Container); +} +#endif + +void TextureGLTest::image2DArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + #endif + + constexpr UnsignedByte data[] = { 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f }; + Texture2DArray texture; + texture.setImage(0, TextureFormat::RGBA8, + ImageReference3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(2), data)); + + MAGNUM_VERIFY_NO_ERROR(); + + /** @todo How to test this on ES? */ + #ifndef MAGNUM_TARGET_GLES + Image3D image(ColorFormat::RGBA, ColorType::UnsignedByte); + texture.image(0, image); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector3i(2)); + CORRADE_COMPARE_AS(std::vector(image.data(), image.data()+image.pixelSize()*image.size().product()), + std::vector(data, data + 32), TestSuite::Compare::Container); + #endif +} + +void TextureGLTest::image2DArrayBuffer() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + #endif + + constexpr UnsignedByte data[] = { 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f }; + Texture2DArray texture; + texture.setImage(0, TextureFormat::RGBA8, + BufferImage3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(2), data, BufferUsage::StaticDraw)); + + MAGNUM_VERIFY_NO_ERROR(); + + /** @todo How to test this on ES? */ + #ifndef MAGNUM_TARGET_GLES + BufferImage3D image(ColorFormat::RGBA, ColorType::UnsignedByte); + texture.image(0, image, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector3i(2)); + CORRADE_COMPARE_AS(std::vector(imageData.begin(), imageData.end()), + std::vector(data, data + 32), TestSuite::Compare::Container); + #endif +} + +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::subImage1DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + + constexpr UnsignedByte zero[4*4*4] = {}; + constexpr UnsignedByte subData[] = { 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }; + Texture1DArray texture; + texture.setImage(0, TextureFormat::RGBA8, + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(4), zero)); + texture.setSubImage(0, Vector2i(1), + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), subData)); + + MAGNUM_VERIFY_NO_ERROR(); + + Image2D image(ColorFormat::RGBA, ColorType::UnsignedByte); + texture.image(0, image); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i(4)); + CORRADE_COMPARE_AS(std::vector(image.data(), image.data()+image.pixelSize()*image.size().product()), (std::vector{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, + 0, 0, 0, 0, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }), TestSuite::Compare::Container); +} + +void TextureGLTest::subImage1DArrayBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + + constexpr UnsignedByte zero[4*4*4] = {}; + constexpr UnsignedByte subData[] = { 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }; + Texture1DArray texture; + texture.setImage(0, TextureFormat::RGBA8, + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(4), zero)); + texture.setSubImage(0, Vector2i(1), + BufferImage2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), subData, BufferUsage::StaticDraw)); + + MAGNUM_VERIFY_NO_ERROR(); + + BufferImage2D image(ColorFormat::RGBA, ColorType::UnsignedByte); + texture.image(0, image, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i(4)); + CORRADE_COMPARE_AS(std::vector(imageData.begin(), imageData.end()), (std::vector{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, + 0, 0, 0, 0, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }), TestSuite::Compare::Container); +} +#endif + +void TextureGLTest::subImage2DArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + #endif + + constexpr UnsignedByte zero[4*4*4*4] = {}; + constexpr UnsignedByte subData[] = { 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f }; + Texture2DArray texture; + texture.setImage(0, TextureFormat::RGBA8, + ImageReference3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(4), zero)); + texture.setSubImage(0, Vector3i(1), + ImageReference3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(2), subData)); + + MAGNUM_VERIFY_NO_ERROR(); + + /** @todo How to test this on ES? */ + #ifndef MAGNUM_TARGET_GLES + Image3D image(ColorFormat::RGBA, ColorType::UnsignedByte); + texture.image(0, image); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector3i(4)); + CORRADE_COMPARE_AS(std::vector(image.data(), image.data()+image.pixelSize()*image.size().product()), (std::vector{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, + 0, 0, 0, 0, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0, 0, 0, 0, + 0, 0, 0, 0, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }), TestSuite::Compare::Container); + #endif +} + +void TextureGLTest::subImage2DArrayBuffer() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + #endif + + constexpr UnsignedByte zero[4*4*4*4] = {}; + constexpr UnsignedByte subData[] = { 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f }; + Texture2DArray texture; + texture.setImage(0, TextureFormat::RGBA8, + ImageReference3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(4), zero)); + texture.setSubImage(0, Vector3i(1), + BufferImage3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(2), subData, BufferUsage::StaticDraw)); + + MAGNUM_VERIFY_NO_ERROR(); + + /** @todo How to test this on ES? */ + #ifndef MAGNUM_TARGET_GLES + BufferImage3D image(ColorFormat::RGBA, ColorType::UnsignedByte); + texture.image(0, image, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector3i(4)); + CORRADE_COMPARE_AS(std::vector(imageData.begin(), imageData.end()), (std::vector{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, + 0, 0, 0, 0, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0, 0, 0, 0, + 0, 0, 0, 0, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }), TestSuite::Compare::Container); + #endif +} + +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::generateMipmap1DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + + Texture1DArray texture; + texture.setImage(0, TextureFormat::RGBA8, + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32))); + + CORRADE_COMPARE(texture.imageSize(0), Vector2i(32)); + CORRADE_COMPARE(texture.imageSize(1), Vector2i( 0)); + + texture.generateMipmap(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(texture.imageSize(0), Vector2i(32, 32)); + CORRADE_COMPARE(texture.imageSize(1), Vector2i(16, 32)); + CORRADE_COMPARE(texture.imageSize(2), Vector2i( 8, 32)); + CORRADE_COMPARE(texture.imageSize(3), Vector2i( 4, 32)); + CORRADE_COMPARE(texture.imageSize(4), Vector2i( 2, 32)); + CORRADE_COMPARE(texture.imageSize(5), Vector2i( 1, 32)); + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + +void TextureGLTest::generateMipmap2DArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + #endif + + Texture2DArray texture; + texture.setImage(0, TextureFormat::RGBA8, + ImageReference3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(32))); + + /** @todo How to test this on ES? */ + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE(texture.imageSize(0), Vector3i(32)); + CORRADE_COMPARE(texture.imageSize(1), Vector3i( 0)); + #endif + + texture.generateMipmap(); + + MAGNUM_VERIFY_NO_ERROR(); + + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE(texture.imageSize(0), Vector3i(32, 32, 32)); + CORRADE_COMPARE(texture.imageSize(1), Vector3i(16, 16, 32)); + CORRADE_COMPARE(texture.imageSize(2), Vector3i( 8, 8, 32)); + CORRADE_COMPARE(texture.imageSize(3), Vector3i( 4, 4, 32)); + CORRADE_COMPARE(texture.imageSize(4), Vector3i( 2, 2, 32)); + CORRADE_COMPARE(texture.imageSize(5), Vector3i( 1, 1, 32)); + + MAGNUM_VERIFY_NO_ERROR(); + #endif +} + +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::invalidateImage1DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + + Texture1DArray texture; + texture.setStorage(2, TextureFormat::RGBA8, Vector2i(32)); + texture.invalidateImage(1); + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + +void TextureGLTest::invalidateImage2DArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + #endif + + Texture2DArray texture; + texture.setStorage(2, TextureFormat::RGBA8, Vector3i(32)); + texture.invalidateImage(1); + + MAGNUM_VERIFY_NO_ERROR(); +} + +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::invalidateSubImage1DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + + Texture1DArray texture; + texture.setStorage(2, TextureFormat::RGBA8, Vector2i(32)); + texture.invalidateSubImage(1, Vector2i(2), Vector2i(8)); + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + +void TextureGLTest::invalidateSubImage2DArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + #endif + + Texture2DArray texture; + texture.setStorage(2, TextureFormat::RGBA8, Vector3i(32)); + texture.invalidateSubImage(1, Vector3i(2), Vector3i(8)); + + MAGNUM_VERIFY_NO_ERROR(); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::TextureGLTest) diff --git a/src/Magnum/Test/TextureGLTest.cpp b/src/Magnum/Test/TextureGLTest.cpp index 1da5b1264..79a9368ae 100644 --- a/src/Magnum/Test/TextureGLTest.cpp +++ b/src/Magnum/Test/TextureGLTest.cpp @@ -29,6 +29,7 @@ #ifndef MAGNUM_TARGET_GLES2 #include "Magnum/BufferImage.h" #endif +#include "Magnum/Color.h" #include "Magnum/ColorFormat.h" #include "Magnum/Image.h" #include "Magnum/Texture.h" @@ -46,39 +47,16 @@ class TextureGLTest: public AbstractOpenGLTester { #endif void construct2D(); void construct3D(); - #ifndef MAGNUM_TARGET_GLES - void construct1DArray(); - #endif - #ifndef MAGNUM_TARGET_GLES2 - void construct2DArray(); - #endif - #ifndef MAGNUM_TARGET_GLES - void construct2DMultisample(); - void construct2DMultisampleArray(); - void constructRectangle(); - #endif #ifndef MAGNUM_TARGET_GLES void sampling1D(); #endif void sampling2D(); void sampling3D(); - #ifndef MAGNUM_TARGET_GLES - void sampling1DArray(); - #endif - #ifndef MAGNUM_TARGET_GLES2 - void sampling2DArray(); - #endif - #ifndef MAGNUM_TARGET_GLES - void samplingRectangle(); - #endif #ifdef MAGNUM_TARGET_GLES void samplingBorder2D(); void samplingBorder3D(); - #ifndef MAGNUM_TARGET_GLES2 - void samplingBorder2DArray(); - #endif #endif #ifndef MAGNUM_TARGET_GLES @@ -86,17 +64,6 @@ class TextureGLTest: public AbstractOpenGLTester { #endif void storage2D(); void storage3D(); - #ifndef MAGNUM_TARGET_GLES - void storage1DArray(); - #endif - #ifndef MAGNUM_TARGET_GLES2 - void storage2DArray(); - #endif - #ifndef MAGNUM_TARGET_GLES - void storage2DMultisample(); - void storage2DMultisampleArray(); - void storageRectangle(); - #endif #ifndef MAGNUM_TARGET_GLES void image1D(); @@ -112,22 +79,6 @@ class TextureGLTest: public AbstractOpenGLTester { #ifndef MAGNUM_TARGET_GLES2 void image3DBuffer(); #endif - #ifndef MAGNUM_TARGET_GLES - void image1DArray(); - void image1DArrayBuffer(); - #endif - #ifndef MAGNUM_TARGET_GLES2 - void image2DArray(); - void image2DArrayBuffer(); - #endif - #ifndef MAGNUM_TARGET_GLES - void image2DMultisample(); - void image2DMultisampleBuffer(); - void image2DMultisampleArray(); - void image2DMultisampleArrayBuffer(); - void imageRectangle(); - void imageRectangleBuffer(); - #endif #ifndef MAGNUM_TARGET_GLES void subImage1D(); @@ -141,68 +92,24 @@ class TextureGLTest: public AbstractOpenGLTester { #ifndef MAGNUM_TARGET_GLES2 void subImage3DBuffer(); #endif - #ifndef MAGNUM_TARGET_GLES - void subImage1DArray(); - void subImage1DArrayBuffer(); - #endif - #ifndef MAGNUM_TARGET_GLES2 - void subImage2DArray(); - void subImage2DArrayBuffer(); - #endif - #ifndef MAGNUM_TARGET_GLES - void subImage2DMultisample(); - void subImage2DMultisampleBuffer(); - void subImage2DMultisampleArray(); - void subImage2DMultisampleArrayBuffer(); - void subImageRectangle(); - void subImageRectangleBuffer(); - #endif #ifndef MAGNUM_TARGET_GLES void generateMipmap1D(); #endif void generateMipmap2D(); void generateMipmap3D(); - #ifndef MAGNUM_TARGET_GLES - void generateMipmap1DArray(); - #endif - #ifndef MAGNUM_TARGET_GLES2 - void generateMipmap2DArray(); - #endif #ifndef MAGNUM_TARGET_GLES void invalidateImage1D(); #endif void invalidateImage2D(); void invalidateImage3D(); - #ifndef MAGNUM_TARGET_GLES - void invalidateImage1DArray(); - #endif - #ifndef MAGNUM_TARGET_GLES2 - void invalidateImage2DArray(); - #endif - #ifndef MAGNUM_TARGET_GLES - void invalidateImage2DMultisample(); - void invalidateImage2DMultisampleArray(); - void invalidateImageRectangle(); - #endif #ifndef MAGNUM_TARGET_GLES void invalidateSubImage1D(); #endif void invalidateSubImage2D(); void invalidateSubImage3D(); - #ifndef MAGNUM_TARGET_GLES - void invalidateSubImage1DArray(); - #endif - #ifndef MAGNUM_TARGET_GLES2 - void invalidateSubImage2DArray(); - #endif - #ifndef MAGNUM_TARGET_GLES - void invalidateSubImage2DMultisample(); - void invalidateSubImage2DMultisampleArray(); - void invalidateSubImageRectangle(); - #endif }; TextureGLTest::TextureGLTest() { @@ -212,39 +119,16 @@ TextureGLTest::TextureGLTest() { #endif &TextureGLTest::construct2D, &TextureGLTest::construct3D, - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::construct1DArray, - #endif - #ifndef MAGNUM_TARGET_GLES2 - &TextureGLTest::construct2DArray, - #endif - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::construct2DMultisample, - &TextureGLTest::construct2DMultisampleArray, - &TextureGLTest::constructRectangle, - #endif #ifndef MAGNUM_TARGET_GLES &TextureGLTest::sampling1D, #endif &TextureGLTest::sampling2D, &TextureGLTest::sampling3D, - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::sampling1DArray, - #endif - #ifndef MAGNUM_TARGET_GLES2 - &TextureGLTest::sampling2DArray, - #endif - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::samplingRectangle, - #endif #ifdef MAGNUM_TARGET_GLES &TextureGLTest::samplingBorder2D, &TextureGLTest::samplingBorder3D, - #ifndef MAGNUM_TARGET_GLES2 - &TextureGLTest::samplingBorder2DArray, - #endif #endif #ifndef MAGNUM_TARGET_GLES @@ -252,17 +136,6 @@ TextureGLTest::TextureGLTest() { #endif &TextureGLTest::storage2D, &TextureGLTest::storage3D, - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::storage1DArray, - #endif - #ifndef MAGNUM_TARGET_GLES2 - &TextureGLTest::storage2DArray, - #endif - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::storage2DMultisample, - &TextureGLTest::storage2DMultisampleArray, - &TextureGLTest::storageRectangle, - #endif #ifndef MAGNUM_TARGET_GLES &TextureGLTest::image1D, @@ -276,22 +149,6 @@ TextureGLTest::TextureGLTest() { #ifndef MAGNUM_TARGET_GLES2 &TextureGLTest::image3DBuffer, #endif - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::image1DArray, - &TextureGLTest::image1DArrayBuffer, - #endif - #ifndef MAGNUM_TARGET_GLES2 - &TextureGLTest::image2DArray, - &TextureGLTest::image2DArrayBuffer, - #endif - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::image2DMultisample, - &TextureGLTest::image2DMultisampleBuffer, - &TextureGLTest::image2DMultisampleArray, - &TextureGLTest::image2DMultisampleArrayBuffer, - &TextureGLTest::imageRectangle, - &TextureGLTest::imageRectangleBuffer, - #endif #ifndef MAGNUM_TARGET_GLES &TextureGLTest::subImage1D, @@ -305,68 +162,24 @@ TextureGLTest::TextureGLTest() { #ifndef MAGNUM_TARGET_GLES2 &TextureGLTest::subImage3DBuffer, #endif - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::subImage1DArray, - &TextureGLTest::subImage1DArrayBuffer, - #endif - #ifndef MAGNUM_TARGET_GLES2 - &TextureGLTest::subImage2DArray, - &TextureGLTest::subImage2DArrayBuffer, - #endif - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::subImage2DMultisample, - &TextureGLTest::subImage2DMultisampleBuffer, - &TextureGLTest::subImage2DMultisampleArray, - &TextureGLTest::subImage2DMultisampleArrayBuffer, - &TextureGLTest::subImageRectangle, - &TextureGLTest::subImageRectangleBuffer, - #endif #ifndef MAGNUM_TARGET_GLES &TextureGLTest::generateMipmap1D, #endif &TextureGLTest::generateMipmap2D, &TextureGLTest::generateMipmap3D, - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::generateMipmap1DArray, - #endif - #ifndef MAGNUM_TARGET_GLES2 - &TextureGLTest::generateMipmap2DArray, - #endif #ifndef MAGNUM_TARGET_GLES &TextureGLTest::invalidateImage1D, #endif &TextureGLTest::invalidateImage2D, &TextureGLTest::invalidateImage3D, - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::invalidateImage1DArray, - #endif - #ifndef MAGNUM_TARGET_GLES2 - &TextureGLTest::invalidateImage2DArray, - #endif - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::invalidateImage2DMultisample, - &TextureGLTest::invalidateImage2DMultisampleArray, - &TextureGLTest::invalidateImageRectangle, - #endif #ifndef MAGNUM_TARGET_GLES &TextureGLTest::invalidateSubImage1D, #endif &TextureGLTest::invalidateSubImage2D, &TextureGLTest::invalidateSubImage3D, - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::invalidateSubImage1DArray, - #endif - #ifndef MAGNUM_TARGET_GLES2 - &TextureGLTest::invalidateSubImage2DArray, - #endif - #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::invalidateSubImage2DMultisample, - &TextureGLTest::invalidateSubImage2DMultisampleArray, - &TextureGLTest::invalidateSubImageRectangle - #endif }); } @@ -410,84 +223,6 @@ void TextureGLTest::construct3D() { MAGNUM_VERIFY_NO_ERROR(); } -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::construct1DArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - - { - Texture2D texture(Texture2D::Target::Texture1DArray); - - MAGNUM_VERIFY_NO_ERROR(); - CORRADE_VERIFY(texture.id() > 0); - } - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif - -#ifndef MAGNUM_TARGET_GLES2 -void TextureGLTest::construct2DArray() { - #ifndef MAGNUM_TARGET_GLES - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - #endif - - { - Texture3D texture(Texture3D::Target::Texture2DArray); - - MAGNUM_VERIFY_NO_ERROR(); - CORRADE_VERIFY(texture.id() > 0); - } - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif - -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::construct2DMultisample() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - { - Texture2D texture(Texture2D::Target::Texture2DMultisample); - - MAGNUM_VERIFY_NO_ERROR(); - CORRADE_VERIFY(texture.id() > 0); - } - - MAGNUM_VERIFY_NO_ERROR(); -} - -void TextureGLTest::construct2DMultisampleArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - { - Texture3D texture(Texture3D::Target::Texture2DMultisampleArray); - - MAGNUM_VERIFY_NO_ERROR(); - CORRADE_VERIFY(texture.id() > 0); - } - - MAGNUM_VERIFY_NO_ERROR(); -} - -void TextureGLTest::constructRectangle() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); - - { - Texture2D texture(Texture2D::Target::Rectangle); - - MAGNUM_VERIFY_NO_ERROR(); - CORRADE_VERIFY(texture.id() > 0); - } - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif - #ifndef MAGNUM_TARGET_GLES void TextureGLTest::sampling1D() { Texture1D texture; @@ -567,73 +302,6 @@ void TextureGLTest::samplingBorder3D() { } #endif -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::sampling1DArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - - Texture2D texture(Texture2D::Target::Texture1DArray); - texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) - .setMagnificationFilter(Sampler::Filter::Linear) - .setWrapping(Sampler::Wrapping::ClampToBorder) - .setBorderColor(Color3(0.5f)) - .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif - -#ifndef MAGNUM_TARGET_GLES2 -void TextureGLTest::sampling2DArray() { - #ifndef MAGNUM_TARGET_GLES - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - #endif - - Texture3D texture(Texture3D::Target::Texture2DArray); - texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) - .setMagnificationFilter(Sampler::Filter::Linear) - #ifndef MAGNUM_TARGET_GLES - .setWrapping(Sampler::Wrapping::ClampToBorder) - .setBorderColor(Color3(0.5f)) - #else - .setWrapping(Sampler::Wrapping::ClampToEdge) - #endif - .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); - - MAGNUM_VERIFY_NO_ERROR(); -} - -#ifdef MAGNUM_TARGET_GLES -void TextureGLTest::samplingBorder2DArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::NV::texture_border_clamp::string() + std::string(" is not supported.")); - - Texture3D texture(Texture3D::Target::Texture2DArray); - texture.setWrapping(Sampler::Wrapping::ClampToBorder) - .setBorderColor(Color3(0.5f)); - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif -#endif - -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::samplingRectangle() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); - - Texture2D texture(Texture2D::Target::Rectangle); - texture.setMinificationFilter(Sampler::Filter::Linear) - .setMagnificationFilter(Sampler::Filter::Linear) - .setWrapping(Sampler::Wrapping::ClampToBorder) - .setBorderColor(Color3(0.5f)) - .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif - #ifndef MAGNUM_TARGET_GLES void TextureGLTest::storage1D() { Texture1D texture; @@ -695,87 +363,6 @@ void TextureGLTest::storage3D() { #endif } -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::storage1DArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - - Texture2D texture(Texture2D::Target::Texture1DArray); - texture.setStorage(5, TextureFormat::RGBA8, Vector2i(32)); - - MAGNUM_VERIFY_NO_ERROR(); - - /** @todo How to test this on ES? */ - #ifndef MAGNUM_TARGET_GLES - CORRADE_COMPARE(texture.imageSize(0), Vector2i(32, 32)); - CORRADE_COMPARE(texture.imageSize(1), Vector2i(16, 32)); - CORRADE_COMPARE(texture.imageSize(2), Vector2i( 8, 32)); - CORRADE_COMPARE(texture.imageSize(3), Vector2i( 4, 32)); - CORRADE_COMPARE(texture.imageSize(4), Vector2i( 2, 32)); - CORRADE_COMPARE(texture.imageSize(5), Vector2i( 0, 0)); /* not available */ - - MAGNUM_VERIFY_NO_ERROR(); - #endif -} -#endif - -#ifndef MAGNUM_TARGET_GLES2 -void TextureGLTest::storage2DArray() { - #ifndef MAGNUM_TARGET_GLES - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - #endif - - Texture3D texture(Texture3D::Target::Texture2DArray); - texture.setStorage(5, TextureFormat::RGBA8, Vector3i(32)); - - MAGNUM_VERIFY_NO_ERROR(); - - /** @todo How to test this on ES? */ - #ifndef MAGNUM_TARGET_GLES - CORRADE_COMPARE(texture.imageSize(0), Vector3i(32, 32, 32)); - CORRADE_COMPARE(texture.imageSize(1), Vector3i(16, 16, 32)); - CORRADE_COMPARE(texture.imageSize(2), Vector3i( 8, 8, 32)); - CORRADE_COMPARE(texture.imageSize(3), Vector3i( 4, 4, 32)); - CORRADE_COMPARE(texture.imageSize(4), Vector3i( 2, 2, 32)); - CORRADE_COMPARE(texture.imageSize(5), Vector3i( 0, 0, 0)); /* not available */ - - MAGNUM_VERIFY_NO_ERROR(); - #endif -} -#endif - -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::storage2DMultisample() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void TextureGLTest::storage2DMultisampleArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void TextureGLTest::storageRectangle() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); - - Texture2D texture(Texture2D::Target::Rectangle); - texture.setStorage(1, TextureFormat::RGBA8, Vector2i(32)); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(texture.imageSize(0), Vector2i(32)); - CORRADE_COMPARE(texture.imageSize(1), Vector2i( 0)); /* not available */ - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif - #ifndef MAGNUM_TARGET_GLES void TextureGLTest::image1D() { constexpr UnsignedByte data[] = { 0x00, 0x01, 0x02, 0x03, @@ -932,205 +519,6 @@ void TextureGLTest::image3DBuffer() { } #endif -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::image1DArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - - constexpr UnsignedByte data[] = { 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }; - Texture2D texture(Texture2D::Target::Texture1DArray); - texture.setImage(0, TextureFormat::RGBA8, - ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), data)); - - MAGNUM_VERIFY_NO_ERROR(); - - Image2D image(ColorFormat::RGBA, ColorType::UnsignedByte); - texture.image(0, image); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(image.size(), Vector2i(2)); - CORRADE_COMPARE_AS(std::vector(image.data(), image.data()+image.pixelSize()*image.size().product()), - std::vector(data, data + 16), TestSuite::Compare::Container); -} - -void TextureGLTest::image1DArrayBuffer() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - - constexpr UnsignedByte data[] = { 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }; - Texture2D texture(Texture2D::Target::Texture1DArray); - texture.setImage(0, TextureFormat::RGBA8, - BufferImage2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), data, BufferUsage::StaticDraw)); - - MAGNUM_VERIFY_NO_ERROR(); - - BufferImage2D image(ColorFormat::RGBA, ColorType::UnsignedByte); - texture.image(0, image, BufferUsage::StaticRead); - const auto imageData = image.buffer().data(); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(image.size(), Vector2i(2)); - CORRADE_COMPARE_AS(std::vector(imageData.begin(), imageData.end()), - std::vector(data, data + 16), TestSuite::Compare::Container); -} -#endif - -#ifndef MAGNUM_TARGET_GLES2 -void TextureGLTest::image2DArray() { - #ifndef MAGNUM_TARGET_GLES - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - #endif - - constexpr UnsignedByte data[] = { 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1e, 0x1f }; - Texture3D texture(Texture3D::Target::Texture2DArray); - texture.setImage(0, TextureFormat::RGBA8, - ImageReference3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(2), data)); - - MAGNUM_VERIFY_NO_ERROR(); - - /** @todo How to test this on ES? */ - #ifndef MAGNUM_TARGET_GLES - Image3D image(ColorFormat::RGBA, ColorType::UnsignedByte); - texture.image(0, image); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(image.size(), Vector3i(2)); - CORRADE_COMPARE_AS(std::vector(image.data(), image.data()+image.pixelSize()*image.size().product()), - std::vector(data, data + 32), TestSuite::Compare::Container); - #endif -} - -void TextureGLTest::image2DArrayBuffer() { - #ifndef MAGNUM_TARGET_GLES - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - #endif - - constexpr UnsignedByte data[] = { 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1e, 0x1f }; - Texture3D texture(Texture3D::Target::Texture2DArray); - texture.setImage(0, TextureFormat::RGBA8, - BufferImage3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(2), data, BufferUsage::StaticDraw)); - - MAGNUM_VERIFY_NO_ERROR(); - - /** @todo How to test this on ES? */ - #ifndef MAGNUM_TARGET_GLES - BufferImage3D image(ColorFormat::RGBA, ColorType::UnsignedByte); - texture.image(0, image, BufferUsage::StaticRead); - const auto imageData = image.buffer().data(); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(image.size(), Vector3i(2)); - CORRADE_COMPARE_AS(std::vector(imageData.begin(), imageData.end()), - std::vector(data, data + 32), TestSuite::Compare::Container); - #endif -} -#endif - -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::image2DMultisample() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void TextureGLTest::image2DMultisampleBuffer() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void TextureGLTest::image2DMultisampleArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void TextureGLTest::image2DMultisampleArrayBuffer() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void TextureGLTest::imageRectangle() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); - - constexpr UnsignedByte data[] = { 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }; - Texture2D texture(Texture2D::Target::Rectangle); - texture.setImage(0, TextureFormat::RGBA8, - ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), data)); - - MAGNUM_VERIFY_NO_ERROR(); - - Image2D image(ColorFormat::RGBA, ColorType::UnsignedByte); - texture.image(0, image); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(image.size(), Vector2i(2)); - CORRADE_COMPARE_AS(std::vector(image.data(), image.data()+image.pixelSize()*image.size().product()), - std::vector(data, data + 16), TestSuite::Compare::Container); -} - -void TextureGLTest::imageRectangleBuffer() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); - - constexpr UnsignedByte data[] = { 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }; - Texture2D texture; - texture.setImage(0, TextureFormat::RGBA8, - BufferImage2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), data, BufferUsage::StaticDraw)); - - MAGNUM_VERIFY_NO_ERROR(); - - BufferImage2D image(ColorFormat::RGBA, ColorType::UnsignedByte); - texture.image(0, image, BufferUsage::StaticRead); - const auto imageData = image.buffer().data(); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(image.size(), Vector2i(2)); - CORRADE_COMPARE_AS(std::vector(imageData.begin(), imageData.end()), - std::vector(data, data+16), TestSuite::Compare::Container); -} -#endif - #ifndef MAGNUM_TARGET_GLES void TextureGLTest::subImage1D() { constexpr UnsignedByte zero[4*4] = {}; @@ -1353,277 +741,6 @@ void TextureGLTest::subImage3DBuffer() { } #endif -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::subImage1DArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - - constexpr UnsignedByte zero[4*4*4] = {}; - constexpr UnsignedByte subData[] = { 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }; - Texture2D texture(Texture2D::Target::Texture1DArray); - texture.setImage(0, TextureFormat::RGBA8, - ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(4), zero)); - texture.setSubImage(0, Vector2i(1), - ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), subData)); - - MAGNUM_VERIFY_NO_ERROR(); - - Image2D image(ColorFormat::RGBA, ColorType::UnsignedByte); - texture.image(0, image); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(image.size(), Vector2i(4)); - CORRADE_COMPARE_AS(std::vector(image.data(), image.data()+image.pixelSize()*image.size().product()), (std::vector{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, - 0, 0, 0, 0, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }), TestSuite::Compare::Container); -} - -void TextureGLTest::subImage1DArrayBuffer() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - - constexpr UnsignedByte zero[4*4*4] = {}; - constexpr UnsignedByte subData[] = { 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }; - Texture2D texture(Texture2D::Target::Texture1DArray); - texture.setImage(0, TextureFormat::RGBA8, - ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(4), zero)); - texture.setSubImage(0, Vector2i(1), - BufferImage2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), subData, BufferUsage::StaticDraw)); - - MAGNUM_VERIFY_NO_ERROR(); - - BufferImage2D image(ColorFormat::RGBA, ColorType::UnsignedByte); - texture.image(0, image, BufferUsage::StaticRead); - const auto imageData = image.buffer().data(); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(image.size(), Vector2i(4)); - CORRADE_COMPARE_AS(std::vector(imageData.begin(), imageData.end()), (std::vector{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, - 0, 0, 0, 0, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }), TestSuite::Compare::Container); -} -#endif - -#ifndef MAGNUM_TARGET_GLES2 -void TextureGLTest::subImage2DArray() { - #ifndef MAGNUM_TARGET_GLES - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - #endif - - constexpr UnsignedByte zero[4*4*4*4] = {}; - constexpr UnsignedByte subData[] = { 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1e, 0x1f }; - Texture3D texture(Texture3D::Target::Texture2DArray); - texture.setImage(0, TextureFormat::RGBA8, - ImageReference3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(4), zero)); - texture.setSubImage(0, Vector3i(1), - ImageReference3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(2), subData)); - - MAGNUM_VERIFY_NO_ERROR(); - - /** @todo How to test this on ES? */ - #ifndef MAGNUM_TARGET_GLES - Image3D image(ColorFormat::RGBA, ColorType::UnsignedByte); - texture.image(0, image); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(image.size(), Vector3i(4)); - CORRADE_COMPARE_AS(std::vector(image.data(), image.data()+image.pixelSize()*image.size().product()), (std::vector{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, - 0, 0, 0, 0, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0, 0, 0, 0, - 0, 0, 0, 0, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }), TestSuite::Compare::Container); - #endif -} - -void TextureGLTest::subImage2DArrayBuffer() { - #ifndef MAGNUM_TARGET_GLES - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - #endif - - constexpr UnsignedByte zero[4*4*4*4] = {}; - constexpr UnsignedByte subData[] = { 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1e, 0x1f }; - Texture3D texture(Texture3D::Target::Texture2DArray); - texture.setImage(0, TextureFormat::RGBA8, - ImageReference3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(4), zero)); - texture.setSubImage(0, Vector3i(1), - BufferImage3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(2), subData, BufferUsage::StaticDraw)); - - MAGNUM_VERIFY_NO_ERROR(); - - /** @todo How to test this on ES? */ - #ifndef MAGNUM_TARGET_GLES - BufferImage3D image(ColorFormat::RGBA, ColorType::UnsignedByte); - texture.image(0, image, BufferUsage::StaticRead); - const auto imageData = image.buffer().data(); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(image.size(), Vector3i(4)); - CORRADE_COMPARE_AS(std::vector(imageData.begin(), imageData.end()), (std::vector{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, - 0, 0, 0, 0, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0, 0, 0, 0, - 0, 0, 0, 0, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }), TestSuite::Compare::Container); - #endif -} -#endif - -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::subImage2DMultisample() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void TextureGLTest::subImage2DMultisampleBuffer() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void TextureGLTest::subImage2DMultisampleArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void TextureGLTest::subImage2DMultisampleArrayBuffer() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void TextureGLTest::subImageRectangle() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); - - constexpr UnsignedByte zero[4*4*4] = {}; - constexpr UnsignedByte subData[] = { 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }; - Texture2D texture(Texture2D::Target::Rectangle); - texture.setImage(0, TextureFormat::RGBA8, - ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(4), zero)); - texture.setSubImage(0, Vector2i(1), - ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), subData)); - - MAGNUM_VERIFY_NO_ERROR(); - - Image2D image(ColorFormat::RGBA, ColorType::UnsignedByte); - texture.image(0, image); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(image.size(), Vector2i(4)); - CORRADE_COMPARE_AS(std::vector(image.data(), image.data()+image.pixelSize()*image.size().product()), (std::vector{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, - 0, 0, 0, 0, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }), TestSuite::Compare::Container); -} - -void TextureGLTest::subImageRectangleBuffer() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); - - constexpr UnsignedByte zero[4*4*4] = {}; - constexpr UnsignedByte subData[] = { 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }; - Texture2D texture(Texture2D::Target::Rectangle); - texture.setImage(0, TextureFormat::RGBA8, - ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(4), zero)); - texture.setSubImage(0, Vector2i(1), - BufferImage2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(2), subData, BufferUsage::StaticDraw)); - - MAGNUM_VERIFY_NO_ERROR(); - - BufferImage2D image(ColorFormat::RGBA, ColorType::UnsignedByte); - texture.image(0, image, BufferUsage::StaticRead); - const auto imageData = image.buffer().data(); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(image.size(), Vector2i(4)); - CORRADE_COMPARE_AS(std::vector(imageData.begin(), imageData.end()), (std::vector{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, - 0, 0, 0, 0, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }), TestSuite::Compare::Container); -} -#endif - #ifndef MAGNUM_TARGET_GLES void TextureGLTest::generateMipmap1D() { if(!Context::current()->isExtensionSupported()) @@ -1720,72 +837,6 @@ void TextureGLTest::generateMipmap3D() { #endif } -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::generateMipmap1DArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not supported.")); - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - - Texture2D texture(Texture2D::Target::Texture1DArray); - texture.setImage(0, TextureFormat::RGBA8, - ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32))); - - CORRADE_COMPARE(texture.imageSize(0), Vector2i(32)); - CORRADE_COMPARE(texture.imageSize(1), Vector2i( 0)); - - texture.generateMipmap(); - - MAGNUM_VERIFY_NO_ERROR(); - - CORRADE_COMPARE(texture.imageSize(0), Vector2i(32, 32)); - CORRADE_COMPARE(texture.imageSize(1), Vector2i(16, 32)); - CORRADE_COMPARE(texture.imageSize(2), Vector2i( 8, 32)); - CORRADE_COMPARE(texture.imageSize(3), Vector2i( 4, 32)); - CORRADE_COMPARE(texture.imageSize(4), Vector2i( 2, 32)); - CORRADE_COMPARE(texture.imageSize(5), Vector2i( 1, 32)); - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif - -#ifndef MAGNUM_TARGET_GLES2 -void TextureGLTest::generateMipmap2DArray() { - #ifndef MAGNUM_TARGET_GLES - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not supported.")); - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - #endif - - Texture3D texture(Texture3D::Target::Texture2DArray); - texture.setImage(0, TextureFormat::RGBA8, - ImageReference3D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i(32))); - - /** @todo How to test this on ES? */ - #ifndef MAGNUM_TARGET_GLES - CORRADE_COMPARE(texture.imageSize(0), Vector3i(32)); - CORRADE_COMPARE(texture.imageSize(1), Vector3i( 0)); - #endif - - texture.generateMipmap(); - - MAGNUM_VERIFY_NO_ERROR(); - - /** @todo How to test this on ES? */ - #ifndef MAGNUM_TARGET_GLES - CORRADE_COMPARE(texture.imageSize(0), Vector3i(32, 32, 32)); - CORRADE_COMPARE(texture.imageSize(1), Vector3i(16, 16, 32)); - CORRADE_COMPARE(texture.imageSize(2), Vector3i( 8, 8, 32)); - CORRADE_COMPARE(texture.imageSize(3), Vector3i( 4, 4, 32)); - CORRADE_COMPARE(texture.imageSize(4), Vector3i( 2, 2, 32)); - CORRADE_COMPARE(texture.imageSize(5), Vector3i( 1, 1, 32)); - - MAGNUM_VERIFY_NO_ERROR(); - #endif -} -#endif - #ifndef MAGNUM_TARGET_GLES void TextureGLTest::invalidateImage1D() { Texture1D texture; @@ -1817,61 +868,6 @@ void TextureGLTest::invalidateImage3D() { MAGNUM_VERIFY_NO_ERROR(); } -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::invalidateImage1DArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - - Texture2D texture(Texture2D::Target::Texture1DArray); - texture.setStorage(2, TextureFormat::RGBA8, Vector2i(32)); - texture.invalidateImage(1); - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif - -#ifndef MAGNUM_TARGET_GLES2 -void TextureGLTest::invalidateImage2DArray() { - #ifndef MAGNUM_TARGET_GLES - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - #endif - - Texture3D texture(Texture3D::Target::Texture2DArray); - texture.setStorage(2, TextureFormat::RGBA8, Vector3i(32)); - texture.invalidateImage(1); - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif - -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::invalidateImage2DMultisample() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Multisample storage is not implemented yet."); -} - -void TextureGLTest::invalidateImage2DMultisampleArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Multisample storage is not implemented yet."); -} - -void TextureGLTest::invalidateImageRectangle() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); - - Texture2D texture(Texture2D::Target::Rectangle); - texture.setStorage(1, TextureFormat::RGBA8, Vector2i(32)); - texture.invalidateImage(0); - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif - #ifndef MAGNUM_TARGET_GLES void TextureGLTest::invalidateSubImage1D() { Texture1D texture; @@ -1903,61 +899,6 @@ void TextureGLTest::invalidateSubImage3D() { MAGNUM_VERIFY_NO_ERROR(); } -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::invalidateSubImage1DArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - - Texture2D texture(Texture2D::Target::Texture1DArray); - texture.setStorage(2, TextureFormat::RGBA8, Vector2i(32)); - texture.invalidateSubImage(1, Vector2i(2), Vector2i(8)); - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif - -#ifndef MAGNUM_TARGET_GLES2 -void TextureGLTest::invalidateSubImage2DArray() { - #ifndef MAGNUM_TARGET_GLES - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); - #endif - - Texture3D texture(Texture3D::Target::Texture2DArray); - texture.setStorage(2, TextureFormat::RGBA8, Vector3i(32)); - texture.invalidateSubImage(1, Vector3i(2), Vector3i(8)); - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif - -#ifndef MAGNUM_TARGET_GLES -void TextureGLTest::invalidateSubImage2DMultisample() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Multisample storage is not implemented yet."); -} - -void TextureGLTest::invalidateSubImage2DMultisampleArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Multisample storage is not implemented yet."); -} - -void TextureGLTest::invalidateSubImageRectangle() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); - - Texture2D texture(Texture2D::Target::Rectangle); - texture.setStorage(1, TextureFormat::RGBA8, Vector2i(32)); - texture.invalidateSubImage(0, Vector2i(4), Vector2i(16)); - - MAGNUM_VERIFY_NO_ERROR(); -} -#endif - }} CORRADE_TEST_MAIN(Magnum::Test::TextureGLTest) diff --git a/src/Magnum/Text/AbstractFont.cpp b/src/Magnum/Text/AbstractFont.cpp index fc9410116..f0db13818 100644 --- a/src/Magnum/Text/AbstractFont.cpp +++ b/src/Magnum/Text/AbstractFont.cpp @@ -29,6 +29,7 @@ #include #include +#include "Magnum/Math/Functions.h" #include "Magnum/Text/GlyphCache.h" namespace Magnum { namespace Text { diff --git a/src/Magnum/Text/Renderer.cpp b/src/Magnum/Text/Renderer.cpp index c8b83e93f..2256ecd9c 100644 --- a/src/Magnum/Text/Renderer.cpp +++ b/src/Magnum/Text/Renderer.cpp @@ -28,6 +28,7 @@ #include "Magnum/Context.h" #include "Magnum/Extensions.h" #include "Magnum/Mesh.h" +#include "Magnum/Math/Functions.h" #include "Magnum/Shaders/AbstractVector.h" #include "Magnum/Text/AbstractFont.h" diff --git a/src/Magnum/Text/Test/AbstractFontTest.cpp b/src/Magnum/Text/Test/AbstractFontTest.cpp index 484762172..0bc52a7a6 100644 --- a/src/Magnum/Text/Test/AbstractFontTest.cpp +++ b/src/Magnum/Text/Test/AbstractFontTest.cpp @@ -27,6 +27,7 @@ #include #include +#include "Magnum/Math/Vector2.h" #include "Magnum/Text/AbstractFont.h" #include "configure.h" diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 18dbe6e98..3beb01e88 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -29,11 +29,30 @@ * @brief Class @ref Magnum::Texture, typedef @ref Magnum::Texture1D, @ref Magnum::Texture2D, @ref Magnum::Texture3D */ +#include + #include "Magnum/AbstractTexture.h" +#include "Magnum/Array.h" #include "Magnum/DimensionTraits.h" +#include "Magnum/Math/Vector3.h" namespace Magnum { +namespace Implementation { + template constexpr GLenum textureTarget(); + #ifndef MAGNUM_TARGET_GLES + template<> inline constexpr GLenum textureTarget<1>() { return GL_TEXTURE_1D; } + #endif + template<> inline constexpr GLenum textureTarget<2>() { return GL_TEXTURE_2D; } + template<> inline constexpr GLenum textureTarget<3>() { + #ifndef MAGNUM_TARGET_GLES2 + return GL_TEXTURE_3D; + #else + return GL_TEXTURE_3D_OES; + #endif + } +} + /** @brief %Texture @@ -58,180 +77,95 @@ texture.setMagnificationFilter(Sampler::Filter::Linear) .generateMipmap(); @endcode -@attention Don't forget to fully configure the texture before use. Note that - default configuration (if @ref setMinificationFilter() is not called with - another value) is to use mipmaps, so be sure to either call @ref setMinificationFilter(), - explicitly specify all mip levels with @ref setStorage() and @ref setImage() - or call @ref generateMipmap(). If using rectangle texture, you must also - call @ref setWrapping(), because the initial value is not supported on - rectangle textures. See also @ref setMagnificationFilter() and - @ref setBorderColor(). +@attention Note that default configuration (if @ref setMinificationFilter() is + not called with another value) is to use mipmaps, so be sure to either call + @ref setMinificationFilter(), explicitly specify all mip levels with + @ref setStorage() and @ref setImage() or call @ref generateMipmap(). The texture is bound to layer specified by shader via @ref bind(). In shader, -the texture is used via `sampler2D` and friends, see @ref Target enum -documentation for more information. See also AbstractShaderProgram -documentation for more information about usage in shaders. - -@section Texture-array Texture arrays - -You can create texture arrays by passing -@ref Target::Texture1DArray "Texture2D::Target::Texture1DArray" or -@ref Target::Texture2DArray "Texture3D::Target::Texture2DArray" to constructor. - -It is possible to specify each layer separately using @ref setSubImage(), but -you have to allocate the memory for all layers first by calling @ref setStorage(). -Example: 2D texture array with 16 layers of 64x64 images: -@code -Texture3D texture(Texture3D::Target::Texture2DArray); -texture.setMagnificationFilter(Sampler::Filter::Linear) - // ... - .setStorage(levels, TextureFormat::RGBA8, {64, 64,16}); - -for(std::size_t i = 0; i != 16; ++i) { - // ... - Image2D image(ColorFormat::RGBA, ColorType::UnsignedByte, {64, 64}, data[i]); - texture.setSubImage(0, Vector3i::zAxis(i), image); -} - -// ... -@endcode - -Similar approach can be used for any other texture types (e.g. setting -@ref Texture3D data using 2D layers, @ref Texture2D data using one-dimensional -chunks etc.). - -@requires_gl30 %Extension @extension{EXT,texture_array} for texture arrays. -@requires_gles30 %Array textures are not available in OpenGL ES 2.0. - -@section Texture-multisample Multisample textures - -You can create multisample textures by passing -@ref Target::Texture2DMultisample "Texture2D::Target::Texture2DMultisample" or -@ref Target::Texture2DMultisampleArray "Texture3D::Target::Texture2DMultisampleArray" -to constructor. - -@todoc finish this when fully implemented - -@requires_gl32 %Extension @extension{ARB,texture_multisample} for multisample - textures. -@requires_gl Multisample textures are not available in OpenGL ES. - -@section Texture-rectangle Rectangle textures - -Rectangle texture is created by passing @ref Target::Rectangle "Texture2D::Target::Rectangle" -to constructor. In shader, the texture is used via `sampler2DRect` and friends. -Unlike `sampler2D`, which accepts coordinates between 0 and 1, `sampler2DRect` -accepts coordinates between 0 and `textureSizeInGivenDirection-1`. Note that -rectangle textures don't support mipmapping and repeating wrapping modes, see -@ref Sampler::Filter, @ref Sampler::Mipmap and @ref generateMipmap() -documentation for more information. - -@requires_gl31 %Extension @extension{ARB,texture_rectangle} for rectangle - textures. -@requires_gl Rectangle textures are not available in OpenGL ES. - -@see @ref Texture1D, @ref Texture2D, @ref Texture3D, @ref CubeMapTexture, - @ref CubeMapTextureArray, @ref BufferTexture -@todo @extension{AMD,sparse_texture} -@todo Separate multisample, array and rectangle texture classes to avoid confusion, then remove Target enum +the texture is used via `sampler1D`/`sampler2D`/`sampler3D`, +`sampler1DShadow`/`sampler2DShadow`/`sampler3DShadow`, +`isampler1D`/`isampler2D`/`isampler3D` or `usampler1D`/`usampler2D`/`usampler3D`. +See @ref AbstractShaderProgram documentation for more information about usage +in shaders. + +@requires_gles30 %Extension @es_extension{OES,texture_3D} for 3D textures. +@requires_gl 1D textures are not available in OpenGL ES, only 2D and 3D ones. + +@see @ref Texture1D, @ref Texture2D, @ref Texture3D, @ref TextureArray, + @ref BufferTexture, @ref CubeMapTexture, @ref CubeMapTextureArray, + @ref MultisampleTexture, @ref RectangleTexture */ template class Texture: public AbstractTexture { public: static const UnsignedInt Dimensions = dimensions; /**< @brief %Texture dimension count */ - #ifdef DOXYGEN_GENERATING_OUTPUT + #ifdef MAGNUM_BUILD_DEPRECATED /** * @brief %Texture target * - * Each dimension has its own unique subset of these targets. + * @deprecated Use dedicated classes instead, see documentation of + * particular enum value for more information. */ + #ifdef DOXYGEN_GENERATING_OUTPUT enum class Target: GLenum { - /** - * One-dimensional texture. Use `sampler1D`, `sampler1DShadow`, - * `isampler1D` or `usampler1D` in shader. - * @requires_gl Only 2D and 3D textures are available in OpenGL - * ES. - */ + /** @deprecated Used implicitly in @ref Magnum::Texture1D "Texture1D" class. */ Texture1D = GL_TEXTURE_1D, - /** - * Two-dimensional texture. Use `sampler2D`, `sampler2DShadow`, - * `isampler2D` or `usampler2D` in shader. - */ + /** @deprecated Used implicitly in @ref Magnum::Texture2D "Texture2D" class. */ Texture2D = GL_TEXTURE_2D, - /** - * Three-dimensional texture. Use `sampler3D`, `isampler3D` or - * `usampler3D` in shader. - * @requires_gles30 %Extension @es_extension{OES,texture_3D} - */ + /** @deprecated Used implicitly in @ref Magnum::Texture3D "Texture3D" class. */ Texture3D = GL_TEXTURE_3D, - /** - * One-dimensional texture array (i.e. two dimensions in total). - * Use `sampler1DArray`, `sampler1DArrayShadow`, `isampler1DArray` - * or `usampler1DArray` in shader. - * @requires_gl30 %Extension @extension{EXT,texture_array} - * @requires_gl Only 2D and 3D textures are available in OpenGL - * ES. - */ + /** @deprecated Use @ref Magnum::Texture1DArray "Texture1DArray" class instead. */ Texture1DArray = GL_TEXTURE_1D_ARRAY, - /** - * Two-dimensional texture array (i.e. three dimensions in total). - * Use `sampler2DArray`, `sampler2DArrayShadow`, `isampler2DArray` - * or `usampler2DArray` in shader. - * @requires_gl30 %Extension @extension{EXT,texture_array} - * @requires_gles30 %Array textures are not available in OpenGL ES - * 2.0. - */ + /** @deprecated Use @ref Magnum::Texture2DArray "Texture2DArray" class instead. */ Texture2DArray = GL_TEXTURE_2D_ARRAY, - /** - * Multisampled two-dimensional texture. Use `sampler2DMS`, - * `isampler2DMS` or `usampler2DMS` in shader. - * @requires_gl32 %Extension @extension{ARB,texture_multisample} - * @requires_gl Multisample textures are not available in OpenGL - * ES. - */ + /** @deprecated Use @ref Magnum::MultisampleTexture2D "MultisampleTexture2D" class instead. */ Texture2DMultisample = GL_TEXTURE_2D_MULTISAMPLE, - /** - * Multisampled two-dimensional texture array (i.e. three - * dimensions in total). Use `sampler2DMSArray`, - * `isampler2DMSArray` or `usampler2DMSArray` in shader. - * @requires_gl32 %Extension @extension{ARB,texture_multisample} - * @requires_gl Multisample textures are not available in OpenGL - * ES. - */ + /** @deprecated Use @ref Magnum::MultisampleTexture2DArray "MultisampleTexture2DArray" class instead. */ Texture2DMultisampleArray = GL_TEXTURE_2D_MULTISAMPLE_ARRAY, - /** - * Rectangle texture (i.e. two dimensions). Use `sampler2DRect`, - * `sampler2DRectShadow`, `isampler2DRect` or `usampler2DRect` in - * shader. - * @requires_gl31 %Extension @extension{ARB,texture_rectangle} - * @requires_gl Rectangle textures are not available in OpenGL ES. - */ + /** @deprecated Use @ref Magnum::RectangleTexture "RectangleTexture" class instead. */ Rectangle = GL_TEXTURE_RECTANGLE }; #else - typedef typename DataHelper::Target Target; /**< @brief %Texture target */ + typedef typename DataHelper::Target Target; + #endif #endif /** * @brief Constructor - * @param target %Texture target. If not set, default value - * is `Target::Texture1D`, `Target::Texture2D` or - * `Target::Texture3D` based on dimension count. * - * Creates new OpenGL texture. - * @see @fn_gl{GenTextures} + * Creates new OpenGL texture object. + * @see @fn_gl{GenTextures} with @def_gl{TEXTURE_1D}, @def_gl{TEXTURE_2D} + * or @def_gl{TEXTURE_3D} */ - explicit Texture(Target target = DataHelper::target()): AbstractTexture(GLenum(target)) {} - - /** @brief %Texture target */ - constexpr Target target() const { return static_cast(_target); } + explicit Texture(): AbstractTexture(Implementation::textureTarget()) {} + + #ifdef MAGNUM_BUILD_DEPRECATED + /** @copybrief Texture() + * @deprecated Use the parameterless @ref Magnum::Texture::Texture() "Texture()" + * constructor or dedicated @ref Magnum::TextureArray "TextureArray", + * @ref Magnum::MultisampleTexture "MultisampleTexture", + * @ref Magnum::RectangleTexture "RectangleTexture" classes + * instead. + */ + explicit CORRADE_DEPRECATED("use the parameterless constructor or dedicated TextureArray, MultisampleTexture, RectangleTexture classes instead") Texture(Target target): AbstractTexture(GLenum(target)) {} + + /** @brief %Texture target + * @deprecated Use dedicated @ref Magnum::Texture "Texture", + * @ref Magnum::TextureArray "TextureArray", + * @ref Magnum::MultisampleTexture "MultisampleTexture", + * @ref Magnum::RectangleTexture "RectangleTexture" classes + * instead. + */ + constexpr CORRADE_DEPRECATED("use dedicated Texture, TextureArray, MultisampleTexture, RectangleTexture classes instead") Target target() const { return static_cast(_target); } + #endif #ifndef MAGNUM_TARGET_GLES /** @@ -245,11 +179,50 @@ template class Texture: public AbstractTexture { * with @def_gl{TEXTURE_WIDTH}, @def_gl{TEXTURE_HEIGHT} or @def_gl{TEXTURE_DEPTH}. * @requires_gl %Texture image queries are not available in OpenGL ES. */ - typename DimensionTraits::VectorType imageSize(Int level) { - return DataHelper::imageSize(*this, _target, level); + typename DimensionTraits::VectorType imageSize(Int level) { + return DataHelper::imageSize(*this, _target, level); } #endif + /** + * @brief Set minification filter + * @param filter Filter + * @param mipmap Mipmap filtering. If set to anything else than + * @ref Sampler::Mipmap::Base, make sure textures for all mip + * levels are set or call @ref generateMipmap(). + * @return Reference to self (for method chaining) + * + * Sets filter used when the object pixel size is smaller than the + * texture size. If @extension{EXT,direct_state_access} is not + * available, the texture is bound to some layer before the operation. + * Initial value is (@ref Sampler::Filter::Nearest, @ref Sampler::Mipmap::Linear). + * @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} + */ + Texture& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { + AbstractTexture::setMinificationFilter(filter, mipmap); + return *this; + } + + /** + * @brief Set magnification filter + * @param filter Filter + * @return Reference to self (for method chaining) + * + * Sets filter used when the object pixel size is larger than largest + * texture size. If @extension{EXT,direct_state_access} is not + * available, the texture is bound to some layer before the operation. + * Initial value is @ref Sampler::Filter::Linear. + * @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} + */ + Texture& setMagnificationFilter(Sampler::Filter filter) { + AbstractTexture::setMagnificationFilter(filter); + return *this; + } + /** * @brief Set wrapping * @param wrapping Wrapping type for all texture dimensions @@ -260,15 +233,51 @@ template class Texture: public AbstractTexture { * textures. If @extension{EXT,direct_state_access} is not available, * the texture is bound to some layer before the operation. Initial * value is @ref Sampler::Wrapping::Repeat. - * @attention For rectangle textures only some modes are supported, - * see @ref Sampler::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} */ - Texture& setWrapping(const Array& wrapping) { - DataHelper::setWrapping(*this, wrapping); + Texture& setWrapping(const Array& wrapping) { + DataHelper::setWrapping(*this, wrapping); + return *this; + } + + /** + * @brief Set border color + * @return Reference to self (for method chaining) + * + * Border color when wrapping is set to @ref Sampler::Wrapping::ClampToBorder. + * If @extension{EXT,direct_state_access} is not available, the texture + * is bound to some layer before the operation. Initial value is + * `{0.0f, 0.0f, 0.0f, 0.0f}`. + * @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_es_extension %Extension @es_extension{NV,texture_border_clamp} + */ + Texture& setBorderColor(const Color4& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + + /** + * @brief Set max anisotropy + * @return Reference to self (for method chaining) + * + * Default value is `1.0f`, which means no anisotropy. Set to value + * greater than `1.0f` for anisotropic filtering. If extension + * @extension{EXT,texture_filter_anisotropic} (desktop or ES) is not + * available, this function does nothing. If + * @extension{EXT,direct_state_access} is not available, the texture is + * bound to some layer before the operation. + * @see @ref Sampler::maxMaxAnisotropy(), @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} + */ + Texture& setMaxAnisotropy(Float anisotropy) { + AbstractTexture::setMaxAnisotropy(anisotropy); return *this; } @@ -301,8 +310,8 @@ template class Texture: public AbstractTexture { * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureImage3D,EXT,direct_state_access}. */ - Texture& setStorage(Int levels, TextureFormat internalFormat, const typename DimensionTraits::VectorType& size) { - DataHelper::setStorage(*this, _target, levels, internalFormat, size); + Texture& setStorage(Int levels, TextureFormat internalFormat, const typename DimensionTraits::VectorType& size) { + DataHelper::setStorage(*this, _target, levels, internalFormat, size); return *this; } @@ -368,20 +377,20 @@ template class Texture: public AbstractTexture { * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureImage3D,EXT,direct_state_access} */ - Texture& setImage(Int level, TextureFormat internalFormat, const ImageReference& image) { - DataHelper::setImage(*this, _target, level, internalFormat, image); + Texture& setImage(Int level, TextureFormat internalFormat, const ImageReference& image) { + DataHelper::setImage(*this, _target, level, internalFormat, image); return *this; } #ifndef MAGNUM_TARGET_GLES2 /** @overload */ - Texture& setImage(Int level, TextureFormat internalFormat, BufferImage& image) { - DataHelper::setImage(*this, _target, level, internalFormat, image); + Texture& setImage(Int level, TextureFormat internalFormat, BufferImage& image) { + DataHelper::setImage(*this, _target, level, internalFormat, image); return *this; } /** @overload */ - Texture& setImage(Int level, TextureFormat internalFormat, BufferImage&& image) { + Texture& setImage(Int level, TextureFormat internalFormat, BufferImage&& image) { return setImage(level, internalFormat, image); } #endif @@ -403,24 +412,50 @@ template class Texture: public AbstractTexture { * @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} */ - Texture& setSubImage(Int level, const typename DimensionTraits::VectorType& offset, const ImageReference& image) { + Texture& setSubImage(Int level, const typename DimensionTraits::VectorType& offset, const ImageReference& image) { DataHelper::setSubImage(*this, _target, level, offset, image); return *this; } #ifndef MAGNUM_TARGET_GLES2 /** @overload */ - Texture& setSubImage(Int level, const typename DimensionTraits::VectorType& offset, BufferImage& image) { + Texture& setSubImage(Int level, const typename DimensionTraits::VectorType& offset, BufferImage& image) { DataHelper::setSubImage(*this, _target, level, offset, image); return *this; } /** @overload */ - Texture& setSubImage(Int level, const typename DimensionTraits::VectorType& offset, BufferImage&& image) { + Texture& setSubImage(Int level, const typename DimensionTraits::VectorType& offset, BufferImage&& image) { return setSubImage(level, offset, image); } #endif + /** + * @brief Generate mipmap + * @return Reference to self (for method chaining) + * + * 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{ARB,framebuffer_object} + */ + Texture& generateMipmap() { + AbstractTexture::generateMipmap(); + return *this; + } + + /** + * @brief Invalidate texture image + * @param level Mip level + * + * If running on OpenGL ES or extension @extension{ARB,invalidate_subdata} + * (part of OpenGL 4.3) is not available, this function does nothing. + * @see @ref invalidateSubImage(), @fn_gl{InvalidateTexImage} + */ + void invalidateImage(Int level) { AbstractTexture::invalidateImage(level); } + /** * @brief Invalidate texture subimage * @param level Mip level @@ -431,36 +466,16 @@ template class Texture: public AbstractTexture { * (part of OpenGL 4.3) is not available, this function does nothing. * @see @ref invalidateImage(), @fn_gl{InvalidateTexSubImage} */ - void invalidateSubImage(Int level, const typename DimensionTraits::VectorType& offset, const typename DimensionTraits::VectorType& size) { + void invalidateSubImage(Int level, const typename DimensionTraits::VectorType& offset, const typename DimensionTraits::VectorType& size) { DataHelper::invalidateSubImage(*this, level, offset, size); } /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT - Texture& setLabel(const std::string& label) { + Texture& setLabel(const std::string& label) { AbstractTexture::setLabel(label); return *this; } - Texture& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { - AbstractTexture::setMinificationFilter(filter, mipmap); - return *this; - } - Texture& setMagnificationFilter(Sampler::Filter filter) { - AbstractTexture::setMagnificationFilter(filter); - return *this; - } - Texture& setBorderColor(const Color4& color) { - AbstractTexture::setBorderColor(color); - return *this; - } - Texture& setMaxAnisotropy(Float anisotropy) { - AbstractTexture::setMaxAnisotropy(anisotropy); - return *this; - } - Texture& generateMipmap() { - AbstractTexture::generateMipmap(); - return *this; - } #endif }; diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h new file mode 100644 index 000000000..e4653dae6 --- /dev/null +++ b/src/Magnum/TextureArray.h @@ -0,0 +1,302 @@ +#ifndef Magnum_TextureArray_h +#define Magnum_TextureArray_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MAGNUM_TARGET_GLES2 +/** @file + * @brief Class @ref Magnum::TextureArray, typedef @ref Magnum::Texture1DArray, @ref Magnum::Texture2DArray + */ +#endif + +#include "Magnum/AbstractTexture.h" +#include "Magnum/Array.h" +#include "Magnum/DimensionTraits.h" +#include "Magnum/Math/Vector3.h" + +#ifndef MAGNUM_TARGET_GLES2 +namespace Magnum { + +namespace Implementation { + template constexpr GLenum textureArrayTarget(); + #ifndef MAGNUM_TARGET_GLES + template<> inline constexpr GLenum textureArrayTarget<1>() { return GL_TEXTURE_1D_ARRAY; } + #endif + template<> inline constexpr GLenum textureArrayTarget<2>() { return GL_TEXTURE_2D_ARRAY; } +} + +/** +@brief %Texture array + +Template class for one- and two-dimensional texture arrays. See also +@ref AbstractTexture documentation for more information. + +@section Texture-usage Usage + +Common usage is to fully configure all texture parameters and then set the +data. Example configuration: +@code +Texture2DArray texture; +texture.setMagnificationFilter(Sampler::Filter::Linear) + .setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) + .setWrapping(Sampler::Wrapping::ClampToEdge) + .setMaxAnisotropy(Sampler::maxMaxAnisotropy());; +@endcode + +It is often more convenient to first allocate the memory for all layers by +calling @ref setStorage() and then specify each layer separately using +@ref setSubImage(): +@code +texture.setStorage(levels, TextureFormat::RGBA8, {64, 64, 16}); + +for(std::size_t i = 0; i != 16; ++i) { + Image3D image(ColorFormat::RGBA, ColorType::UnsignedByte, {64, 64, 1}, ...); + texture.setSubImage(0, Vector3i::zAxis(i), image); +} +@endcode + +@attention Note that default configuration (if @ref setMinificationFilter() is + not called with another value) is to use mipmaps, so be sure to either call + @ref setMinificationFilter(), explicitly specify all mip levels with + @ref setStorage() and @ref setImage() or call @ref generateMipmap(). + +The texture is bound to layer specified by shader via @ref bind(). In shader, +the texture is used via `sampler1DArray`/`sampler2DArray`, +`sampler1DArrayShadow`/`sampler1DArrayShadow`, `isampler1DArray`/`isampler2DArray` +or `usampler1DArray`/`usampler2DArray`. See @ref AbstractShaderProgram +documentation for more information about usage in shaders. + +@requires_gl30 %Extension @extension{EXT,texture_array} +@requires_gles30 %Array textures are not available in OpenGL ES 2.0. +@requires_gl 1D array textures are not available in OpenGL ES, only 2D ones. + +@see @ref Texture1DArray, @ref Texture2DArray, @ref Texture, @ref BufferTexture, + @ref CubeMapTexture, @ref CubeMapTextureArray, @ref MultisampleTexture, + @ref RectangleTexture + */ +template class TextureArray: public AbstractTexture { + public: + static const UnsignedInt Dimensions = dimensions; /**< @brief %Texture dimension count */ + + /** + * @brief Constructor + * + * Creates new OpenGL texture object. + * @see @fn_gl{GenTextures} with @def_gl{TEXTURE_1D_ARRAY} or @def_gl{TEXTURE_2D_ARRAY} + */ + explicit TextureArray(): AbstractTexture(Implementation::textureArrayTarget()) {} + + /** @copydoc Texture::setMinificationFilter() */ + TextureArray& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { + AbstractTexture::setMinificationFilter(filter, mipmap); + return *this; + } + + /** @copydoc Texture::setMagnificationFilter() */ + TextureArray& setMagnificationFilter(Sampler::Filter filter) { + AbstractTexture::setMagnificationFilter(filter); + return *this; + } + + /** @copydoc Texture::setWrapping() */ + TextureArray& setWrapping(const Array& wrapping) { + DataHelper::setWrapping(*this, wrapping); + return *this; + } + + /** @copydoc Texture::setBorderColor() */ + TextureArray& setBorderColor(const Color4& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + + /** @copydoc Texture::setMaxAnisotropy() */ + TextureArray& setMaxAnisotropy(Float anisotropy) { + AbstractTexture::setMaxAnisotropy(anisotropy); + return *this; + } + + #ifndef MAGNUM_TARGET_GLES + /** @copydoc Texture::imageSize() */ + typename DimensionTraits::VectorType imageSize(Int level) { + return DataHelper::imageSize(*this, _target, level); + } + #endif + + /** + * @brief Set storage + * @param levels Mip level count + * @param internalFormat Internal format + * @param size Size of largest mip level + * @return Reference to self (for method chaining) + * + * Specifies entire structure of a texture at once, removing the need + * for additional consistency checks and memory reallocations when + * updating the data later. After calling this function the texture + * is immutable and calling @ref setStorage() or @ref setImage() is not + * allowed. + * + * If @extension{EXT,direct_state_access} is not available, the texture + * is bound to some layer before the operation. If + * @extension{ARB,texture_storage} (part of OpenGL 4.2) or OpenGL ES + * 3.0 is not available, the feature is emulated with sequence of + * @ref setImage() calls. + * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{TexStorage2D}/@fn_gl{TexStorage3D} or + * @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}/ + * @fn_gl_extension{TextureStorage3D,EXT,direct_state_access}, + * eventually @fn_gl{TexImage2D}/@fn_gl{TexImage3D} or + * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ + * @fn_gl_extension{TextureImage3D,EXT,direct_state_access}. + */ + TextureArray& setStorage(Int levels, TextureFormat internalFormat, const typename DimensionTraits::VectorType& size) { + DataHelper::setStorage(*this, _target, levels, internalFormat, size); + return *this; + } + + #ifndef MAGNUM_TARGET_GLES + /** @copydoc Texture::image(Int, Image&) */ + void image(Int level, Image& image) { + AbstractTexture::image(_target, level, image); + } + + /** @copydoc Texture::imate(Int, BufferImage&, BufferUsage) */ + void image(Int level, BufferImage& image, BufferUsage usage) { + AbstractTexture::image(_target, level, image, usage); + } + #endif + + /** + * @brief Set image data + * @param level Mip level + * @param internalFormat Internal format + * @param image @ref Image, @ref ImageReference or + * @ref Trade::ImageData of the same dimension count + * @return Reference to self (for method chaining) + * + * For better performance when generating mipmaps using + * @ref generateMipmap() or calling @ref setImage() more than once use + * @ref setStorage() and @ref setSubImage() instead. + * + * 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{TexImage2D}/@fn_gl{TexImage3D} or + * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ + * @fn_gl_extension{TextureImage3D,EXT,direct_state_access} + */ + TextureArray& setImage(Int level, TextureFormat internalFormat, const ImageReference& image) { + DataHelper::setImage(*this, _target, level, internalFormat, image); + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @overload */ + TextureArray& setImage(Int level, TextureFormat internalFormat, BufferImage& image) { + DataHelper::setImage(*this, _target, level, internalFormat, image); + return *this; + } + + /** @overload */ + TextureArray& setImage(Int level, TextureFormat internalFormat, BufferImage&& image) { + return setImage(level, internalFormat, image); + } + #endif + + /** + * @brief Set image subdata + * @param level Mip level + * @param offset Offset where to put data in the texture + * @param image @ref Image, @ref ImageReference or + * @ref Trade::ImageData of the same dimension count + * @return Reference to self (for method chaining) + * + * If @extension{EXT,direct_state_access} is not available, the + * texture is bound to some layer before the operation. + * @see @ref setStorage(), @ref setImage(), @fn_gl{ActiveTexture}, + * @fn_gl{BindTexture} and @fn_gl{TexSubImage2D}/@fn_gl{TexSubImage3D} + * or @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}/ + * @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} + */ + TextureArray& setSubImage(Int level, const typename DimensionTraits::VectorType& offset, const ImageReference& image) { + DataHelper::setSubImage(*this, _target, level, offset, image); + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @overload */ + TextureArray& setSubImage(Int level, const typename DimensionTraits::VectorType& offset, BufferImage& image) { + DataHelper::setSubImage(*this, _target, level, offset, image); + return *this; + } + + /** @overload */ + TextureArray& setSubImage(Int level, const typename DimensionTraits::VectorType& offset, BufferImage&& image) { + return setSubImage(level, offset, image); + } + #endif + + /** @copydoc Texture::generateMipmap() */ + TextureArray& generateMipmap() { + AbstractTexture::generateMipmap(); + return *this; + } + + /** @copydoc Texture::invalidateImage() */ + void invalidateImage(Int level) { AbstractTexture::invalidateImage(level); } + + /** @copydoc Texture::invalidateSubImage() */ + void invalidateSubImage(Int level, const typename DimensionTraits::VectorType& offset, const typename DimensionTraits::VectorType& size) { + DataHelper::invalidateSubImage(*this, level, offset, size); + } + + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + TextureArray& setLabel(const std::string& label) { + AbstractTexture::setLabel(label); + return *this; + } + #endif +}; + +#ifndef MAGNUM_TARGET_GLES +/** +@brief One-dimensional texture array + +@requires_gl Only @ref Magnum::Texture2DArray "Texture2DArray" is available in + OpenGL ES. +*/ +typedef TextureArray<1> Texture1DArray; +#endif + +/** @brief Two-dimensional texture array */ +typedef TextureArray<2> Texture2DArray; + +} +#else +#error this header is not available on OpenGL ES 2.0 build +#endif + +#endif From bcf1cf1c63f95f9c1e38286ecb516a9b66e5217c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 27 Jan 2014 15:45:05 +0100 Subject: [PATCH 33/86] Better texture attaching in Framebuffer. The previous way was half-working at best, as it handled array textures improperly. Now there is overload for each texture type. The old way with attachTexture*D() is marked as deprecated and will be removed in future release. --- doc/opengl-support.dox | 4 +- src/Magnum/Framebuffer.cpp | 98 ++++++++++++---- src/Magnum/Framebuffer.h | 110 +++++++++++++++--- .../Implementation/FramebufferState.cpp | 4 +- src/Magnum/Implementation/FramebufferState.h | 4 +- src/Magnum/Test/FramebufferGLTest.cpp | 88 ++++++++------ src/Magnum/TextureTools/DistanceField.cpp | 2 +- 7 files changed, 226 insertions(+), 84 deletions(-) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 938b75587..f0f515158 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -60,10 +60,10 @@ following: @extension{ARB,texture_float} | done @extension{ARB,depth_buffer_float} | done @extension{ARB,texture_rg} | done -@extension{ARB,framebuffer_object} | missing texture layer attachments +@extension{ARB,framebuffer_object} | done @extension{EXT,gpu_shader4} | done @extension{EXT,packed_float} | done -@extension{EXT,texture_array} | missing texture layer attachments +@extension{EXT,texture_array} | done @extension{EXT,texture_compression_rgtc} | done @extension{EXT,texture_shared_exponent} | done @extension{EXT,framebuffer_sRGB} | | diff --git a/src/Magnum/Framebuffer.cpp b/src/Magnum/Framebuffer.cpp index 141877e8a..4bb281504 100644 --- a/src/Magnum/Framebuffer.cpp +++ b/src/Magnum/Framebuffer.cpp @@ -27,15 +27,23 @@ #include -#ifndef MAGNUM_TARGET_GLES2 -#include "Magnum/BufferImage.h" -#endif #include "Magnum/Context.h" #include "Magnum/Extensions.h" #include "Magnum/Image.h" #include "Magnum/Renderbuffer.h" #include "Magnum/Texture.h" +#ifndef MAGNUM_TARGET_GLES2 +#include "Magnum/BufferImage.h" +#include "Magnum/TextureArray.h" +#endif + +#ifndef MAGNUM_TARGET_GLES +#include "Magnum/CubeMapTextureArray.h" +#include "Magnum/MultisampleTexture.h" +#include "Magnum/RectangleTexture.h" +#endif + #include "Implementation/DebugState.h" #include "Implementation/State.h" #include "Implementation/FramebufferState.h" @@ -152,28 +160,71 @@ Framebuffer& Framebuffer::attachRenderbuffer(const BufferAttachment attachment, } #ifndef MAGNUM_TARGET_GLES -Framebuffer& Framebuffer::attachTexture1D(const BufferAttachment attachment, Texture1D& texture, const Int level) { - (this->*Context::current()->state().framebuffer->texture1DImplementation)(attachment, texture, level); +Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, Texture1D& texture, const Int level) { + (this->*Context::current()->state().framebuffer->texture1DImplementation)(attachment, texture.id(), level); return *this; } #endif -Framebuffer& Framebuffer::attachTexture2D(BufferAttachment attachment, Texture2D& texture, Int mipLevel) { - /** @todo Check for texture target compatibility */ - (this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GLenum(texture.target()), texture.id(), mipLevel); +Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, Texture2D& texture, const Int level) { + (this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GL_TEXTURE_2D, texture.id(), level); + return *this; +} + +#ifndef MAGNUM_TARGET_GLES +Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, RectangleTexture& texture, const Int level) { + (this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GL_TEXTURE_RECTANGLE, texture.id(), level); return *this; } +Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, MultisampleTexture2D& texture, const Int level) { + (this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GL_TEXTURE_2D_MULTISAMPLE, texture.id(), level); + return *this; +} +#endif + Framebuffer& Framebuffer::attachCubeMapTexture(const BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, const Int level) { (this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GLenum(coordinate), texture.id(), level); return *this; } -Framebuffer& Framebuffer::attachTexture3D(Framebuffer::BufferAttachment attachment, Texture3D& texture, Int level, Int layer) { - /** @todo Check for texture target compatibility */ - (this->*Context::current()->state().framebuffer->texture3DImplementation)(attachment, texture, level, layer); +Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, Texture3D& texture, Int level, Int layer) { + (this->*Context::current()->state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); + return *this; +} + +#ifndef MAGNUM_TARGET_GLES +Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, Texture1DArray& texture, Int level, Int layer) { + (this->*Context::current()->state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); + return *this; +} +#endif + +#ifndef MAGNUM_TARGET_GLES2 +Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, Texture2DArray& texture, Int level, Int layer) { + (this->*Context::current()->state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); + return *this; +} +#endif + +#ifndef MAGNUM_TARGET_GLES +Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, CubeMapTextureArray& texture, Int level, Int layer) { + (this->*Context::current()->state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); + return *this; +} + +Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, MultisampleTexture2DArray& texture, Int level, Int layer) { + (this->*Context::current()->state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); return *this; } +#endif + +#ifdef MAGNUM_BUILD_DEPRECATED +Framebuffer& Framebuffer::attachTexture2D(BufferAttachment attachment, Texture2D& texture, Int mipLevel) { + (this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GLenum(texture.target()), texture.id(), mipLevel); + return *this; +} +#endif void Framebuffer::renderbufferImplementationDefault(BufferAttachment attachment, Renderbuffer& renderbuffer) { glFramebufferRenderbuffer(GLenum(bindInternal()), GLenum(attachment), GL_RENDERBUFFER, renderbuffer.id()); @@ -184,12 +235,12 @@ void Framebuffer::renderbufferImplementationDSA(BufferAttachment attachment, Ren glNamedFramebufferRenderbufferEXT(_id, GLenum(attachment), GL_RENDERBUFFER, renderbuffer.id()); } -void Framebuffer::texture1DImplementationDefault(BufferAttachment attachment, Texture1D& texture, GLint mipLevel) { - glFramebufferTexture1D(GLenum(bindInternal()), GLenum(attachment), GLenum(texture.target()), texture.id(), mipLevel); +void Framebuffer::texture1DImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint mipLevel) { + glFramebufferTexture1D(GLenum(bindInternal()), GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel); } -void Framebuffer::texture1DImplementationDSA(BufferAttachment attachment, Texture1D& texture, GLint mipLevel) { - glNamedFramebufferTexture1DEXT(_id, GLenum(attachment), GLenum(texture.target()), texture.id(), mipLevel); +void Framebuffer::texture1DImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint mipLevel) { + glNamedFramebufferTexture1DEXT(_id, GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel); } #endif @@ -203,24 +254,23 @@ void Framebuffer::texture2DImplementationDSA(BufferAttachment attachment, GLenum } #endif -void Framebuffer::texture3DImplementationDefault(BufferAttachment attachment, Texture3D& texture, GLint mipLevel, GLint layer) { - /** @todo Check for texture target compatibility */ - /** @todo Re-enable when extension loader is available for ES */ - #ifndef MAGNUM_TARGET_GLES - glFramebufferTexture3D(GLenum(bindInternal()), GLenum(attachment), GLenum(texture.target()), texture.id(), mipLevel, layer); +void Framebuffer::textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint mipLevel, GLint layer) { + /** @todo Re-enable when extension loader is available for ES 2.0 */ + #ifndef MAGNUM_TARGET_GLES2 + glFramebufferTextureLayer(GLenum(bindInternal()), GLenum(attachment), textureId, mipLevel, layer); #else static_cast(attachment); - static_cast(texture); + static_cast(textureId); static_cast(mipLevel); static_cast(layer); CORRADE_INTERNAL_ASSERT(false); - //glFramebufferTexture3DOES(GLenum(bindInternal()), GLenum(attachment), GLenum(texture.target()), texture.id(), mipLevel, layer); + //glFramebufferTexture3DOES(GLenum(bindInternal()), GLenum(attachment), GL_TEXTURE_3D_OES, texture.id(), mipLevel, layer); #endif } #ifndef MAGNUM_TARGET_GLES -void Framebuffer::texture3DImplementationDSA(BufferAttachment attachment, Texture3D& texture, GLint mipLevel, GLint layer) { - glNamedFramebufferTexture3DEXT(_id, GLenum(attachment), GLenum(texture.target()), texture.id(), mipLevel, layer); +void Framebuffer::textureLayerImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint mipLevel, GLint layer) { + glNamedFramebufferTextureLayerEXT(_id, GLenum(attachment), textureId, mipLevel, layer); } #endif diff --git a/src/Magnum/Framebuffer.h b/src/Magnum/Framebuffer.h index 20fbc65ae..24a71991a 100644 --- a/src/Magnum/Framebuffer.h +++ b/src/Magnum/Framebuffer.h @@ -474,26 +474,27 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje #ifndef MAGNUM_TARGET_GLES /** - * @brief Attach 1D texture to given buffer + * @brief Attach texture to given buffer * @param attachment %Buffer attachment - * @param texture 1D texture + * @param texture Texture * @param level Mip level * @return Reference to self (for method chaining) * * If @extension{EXT,direct_state_access} is not available and the * framebufferbuffer is not currently bound, it is bound before the * operation. - * @see @fn_gl{BindFramebuffer}, @fn_gl2{FramebufferTexture1D,FramebufferTexture} - * or @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access} + * @see @ref attachCubeMapTexture(), @fn_gl{BindFramebuffer}, + * @fn_gl2{FramebufferTexture1D,FramebufferTexture} or + * @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access} * @requires_gl Only 2D and 3D textures are available in OpenGL ES. */ - Framebuffer& attachTexture1D(BufferAttachment attachment, Texture1D& texture, Int level); + Framebuffer& attachTexture(BufferAttachment attachment, Texture1D& texture, Int level); #endif /** - * @brief Attach 2D texture to given buffer + * @brief Attach texture to given buffer * @param attachment %Buffer attachment - * @param texture 2D texture + * @param texture Texture * @param level Mip level * @return Reference to self (for method chaining) * @@ -504,7 +505,21 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @fn_gl2{FramebufferTexture2D,FramebufferTexture} or * @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access} */ - Framebuffer& attachTexture2D(BufferAttachment attachment, Texture2D& texture, Int level); + Framebuffer& attachTexture(BufferAttachment attachment, Texture2D& texture, Int level); + + #ifndef MAGNUM_TARGET_GLES + /** @overload + * @requires_gl31 %Extension @extension{ARB,texture_rectangle} + * @requires_gl Rectangle textures are not available in OpenGL ES. + */ + Framebuffer& attachTexture(BufferAttachment attachment, RectangleTexture& texture, Int level); + + /** @overload + * @requires_gl32 %Extension @extension{ARB,texture_multisample} + * @requires_gl Multisample textures are not available in OpenGL ES. + */ + Framebuffer& attachTexture(BufferAttachment attachment, MultisampleTexture2D& texture, Int level); + #endif /** * @brief Attach cube map texture to given buffer @@ -524,21 +539,78 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje Framebuffer& attachCubeMapTexture(BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, Int level); /** - * @brief Attach 3D texture to given buffer + * @brief Attach texture layer to given buffer * @param attachment %Buffer attachment - * @param texture 3D texture + * @param texture Texture * @param level Mip level - * @param layer Layer of 2D image within a 3D texture + * @param layer Layer * @return Reference to self (for method chaining) * * If @extension{EXT,direct_state_access} is not available and the * framebufferbuffer is not currently bound, it is bound before the * operation. - * @see @fn_gl{BindFramebuffer}, @fn_gl2{FramebufferTexture3D,FramebufferTexture} - * or @fn_gl_extension{NamedFramebufferTexture3D,EXT,direct_state_access} - * @requires_es_extension %Extension @es_extension{OES,texture_3D} + * @see @fn_gl{BindFramebuffer}, @fn_gl2{FramebufferTextureLayer,FramebufferTexture} + * or @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access}, + * @fn_gles_extension{FramebufferTexture3D,OES,texture_3D} in OpenGL ES 2.0 + * @requires_gles30 %Extension @es_extension{OES,texture_3D} + */ + Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture3D& texture, Int level, Int layer); + + #ifndef MAGNUM_TARGET_GLES + /** @overload + * @requires_gl30 %Extension @extension{EXT,texture_array} + * @requires_gl Only 2D array textures are available in OpenGL ES. + */ + Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture1DArray& texture, Int level, Int layer); + #endif + + #ifndef MAGNUM_TARGET_GLES2 + /** @overload + * @requires_gl30 %Extension @extension{EXT,texture_array} + * @requires_gles30 %Array textures are not available in OpenGL ES 2.0. + */ + Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture2DArray& texture, Int level, Int layer); + #endif + + #ifndef MAGNUM_TARGET_GLES + /** @overload + * @requires_gl40 %Extension @extension{ARB,texture_cube_map_array} + * @requires_gl Cube map texture arrays are not available in OpenGL ES. */ - Framebuffer& attachTexture3D(BufferAttachment attachment, Texture3D& texture, Int level, Int layer); + Framebuffer& attachTextureLayer(BufferAttachment attachment, CubeMapTextureArray& texture, Int level, Int layer); + + /** @overload + * @requires_gl32 %Extension @extension{ARB,texture_multisample} + * @requires_gl Multisample textures are not available in OpenGL ES. + */ + Framebuffer& attachTextureLayer(BufferAttachment attachment, MultisampleTexture2DArray& texture, Int level, Int layer); + #endif + + #ifdef MAGNUM_BUILD_DEPRECATED + #ifndef MAGNUM_TARGET_GLES + /** + * @copybrief attachTexture() + * @deprecated Use one of @ref Magnum::Framebuffer::attachTexture() "attachTexture()" overloads instead. + */ + Framebuffer& attachTexture1D(BufferAttachment attachment, Texture1D& texture, Int level) { + return attachTexture(attachment, texture, level); + } + #endif + + /** + * @copybrief attachTexture() + * @deprecated Use one of @ref Magnum::Framebuffer::attachTexture() "attachTexture()" overloads instead. + */ + Framebuffer& attachTexture2D(BufferAttachment attachment, Texture2D& texture, Int level); + + /** + * @copybrief attachTextureLayer() + * @deprecated Use one of @ref Magnum::Framebuffer::attachTextureLayer() "attachTextureLayer()" overloads instead. + */ + Framebuffer& attachTexture3D(BufferAttachment attachment, Texture3D& texture, Int level, Int layer) { + return attachTextureLayer(attachment, texture, level, layer); + } + #endif /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT @@ -555,8 +627,8 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje #endif #ifndef MAGNUM_TARGET_GLES - void MAGNUM_LOCAL texture1DImplementationDefault(BufferAttachment attachment, Texture1D& texture, GLint level); - void MAGNUM_LOCAL texture1DImplementationDSA(BufferAttachment attachment, Texture1D& texture, GLint level); + void MAGNUM_LOCAL texture1DImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level); + void MAGNUM_LOCAL texture1DImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint level); #endif void MAGNUM_LOCAL texture2DImplementationDefault(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level); @@ -564,9 +636,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje void MAGNUM_LOCAL texture2DImplementationDSA(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level); #endif - void MAGNUM_LOCAL texture3DImplementationDefault(BufferAttachment attachment, Texture3D& texture, GLint level, GLint layer); + void MAGNUM_LOCAL textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer); #ifndef MAGNUM_TARGET_GLES - void MAGNUM_LOCAL texture3DImplementationDSA(BufferAttachment attachment, Texture3D& texture, GLint level, GLint layer); + void MAGNUM_LOCAL textureLayerImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer); #endif }; diff --git a/src/Magnum/Implementation/FramebufferState.cpp b/src/Magnum/Implementation/FramebufferState.cpp index 5ef927e74..4b6a99803 100644 --- a/src/Magnum/Implementation/FramebufferState.cpp +++ b/src/Magnum/Implementation/FramebufferState.cpp @@ -49,7 +49,7 @@ FramebufferState::FramebufferState(Context& context, std::vector& e renderbufferImplementation = &Framebuffer::renderbufferImplementationDSA; texture1DImplementation = &Framebuffer::texture1DImplementationDSA; texture2DImplementation = &Framebuffer::texture2DImplementationDSA; - texture3DImplementation = &Framebuffer::texture3DImplementationDSA; + textureLayerImplementation = &Framebuffer::textureLayerImplementationDSA; renderbufferStorageImplementation = &Renderbuffer::storageImplementationDSA; } else @@ -65,7 +65,7 @@ FramebufferState::FramebufferState(Context& context, std::vector& e texture1DImplementation = &Framebuffer::texture1DImplementationDefault; #endif texture2DImplementation = &Framebuffer::texture2DImplementationDefault; - texture3DImplementation = &Framebuffer::texture3DImplementationDefault; + textureLayerImplementation = &Framebuffer::textureLayerImplementationDefault; renderbufferStorageImplementation = &Renderbuffer::storageImplementationDefault; } diff --git a/src/Magnum/Implementation/FramebufferState.h b/src/Magnum/Implementation/FramebufferState.h index 9df8a9bb3..f8ecde63c 100644 --- a/src/Magnum/Implementation/FramebufferState.h +++ b/src/Magnum/Implementation/FramebufferState.h @@ -42,10 +42,10 @@ struct FramebufferState { void(Framebuffer::*renderbufferImplementation)(Framebuffer::BufferAttachment, Renderbuffer&); #ifndef MAGNUM_TARGET_GLES - void(Framebuffer::*texture1DImplementation)(Framebuffer::BufferAttachment, Texture1D&, GLint); + void(Framebuffer::*texture1DImplementation)(Framebuffer::BufferAttachment, GLuint, GLint); #endif void(Framebuffer::*texture2DImplementation)(Framebuffer::BufferAttachment, GLenum, GLuint, GLint); - void(Framebuffer::*texture3DImplementation)(Framebuffer::BufferAttachment, Texture3D&, GLint, GLint); + void(Framebuffer::*textureLayerImplementation)(Framebuffer::BufferAttachment, GLuint, GLint, GLint); void(Renderbuffer::*renderbufferStorageImplementation)(RenderbufferFormat, const Vector2i&); void(Renderbuffer::*renderbufferStorageMultisampleImplementation)(GLsizei, RenderbufferFormat, const Vector2i&); diff --git a/src/Magnum/Test/FramebufferGLTest.cpp b/src/Magnum/Test/FramebufferGLTest.cpp index 217843e1a..f7e4be20e 100644 --- a/src/Magnum/Test/FramebufferGLTest.cpp +++ b/src/Magnum/Test/FramebufferGLTest.cpp @@ -24,9 +24,7 @@ */ #include "Magnum/configure.h" -#ifndef MAGNUM_TARGET_GLES2 -#include "Magnum/BufferImage.h" -#endif +#include "Magnum/Color.h" #include "Magnum/ColorFormat.h" #include "Magnum/Context.h" #include "Magnum/Extensions.h" @@ -38,6 +36,16 @@ #include "Magnum/TextureFormat.h" #include "Magnum/Test/AbstractOpenGLTester.h" +#ifndef MAGNUM_TARGET_GLES2 +#include "Magnum/BufferImage.h" +#include "Magnum/TextureArray.h" +#endif + +#ifndef MAGNUM_TARGET_GLES +#include "Magnum/CubeMapTextureArray.h" +#include "Magnum/RectangleTexture.h" +#endif + namespace Magnum { namespace Test { class FramebufferGLTest: public AbstractOpenGLTester { @@ -298,8 +306,8 @@ void FramebufferGLTest::attachTexture1D() { depthStencil.setStorage(1, TextureFormat::Depth24Stencil8, 128); Framebuffer framebuffer({{}, {128, 1}}); - framebuffer.attachTexture1D(Framebuffer::ColorAttachment(0), color, 0) - .attachTexture1D(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0); + framebuffer.attachTexture(Framebuffer::ColorAttachment(0), color, 0) + .attachTexture(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::ReadDraw), Framebuffer::Status::Complete); @@ -327,7 +335,7 @@ void FramebufferGLTest::attachTexture2D() { MAGNUM_VERIFY_NO_ERROR(); - framebuffer.attachTexture2D(Framebuffer::ColorAttachment(0), color, 0); + framebuffer.attachTexture(Framebuffer::ColorAttachment(0), color, 0); MAGNUM_VERIFY_NO_ERROR(); @@ -342,11 +350,11 @@ void FramebufferGLTest::attachTexture2D() { Texture2D depthStencil; #ifndef MAGNUM_TARGET_GLES2 depthStencil.setStorage(1, TextureFormat::Depth24Stencil8, Vector2i(128)); - framebuffer.attachTexture2D(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0); + framebuffer.attachTexture(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0); #else depthStencil.setStorage(1, TextureFormat::DepthStencil, Vector2i(128)); - framebuffer.attachTexture2D(Framebuffer::BufferAttachment::Depth, depthStencil, 0) - .attachTexture2D(Framebuffer::BufferAttachment::Stencil, depthStencil, 0); + framebuffer.attachTexture(Framebuffer::BufferAttachment::Depth, depthStencil, 0) + .attachTexture(Framebuffer::BufferAttachment::Stencil, depthStencil, 0); #endif } @@ -356,7 +364,7 @@ void FramebufferGLTest::attachTexture2D() { Texture2D depth; depth.setStorage(1, TextureFormat::DepthComponent16, Vector2i(128)); - framebuffer.attachTexture2D(Framebuffer::BufferAttachment::Depth, depth, 0); + framebuffer.attachTexture(Framebuffer::BufferAttachment::Depth, depth, 0); } #endif @@ -371,8 +379,6 @@ void FramebufferGLTest::attachTexture3D() { #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::OES::texture_3D::string() + std::string(" is not available.")); - #else - CORRADE_SKIP("Not properly implemented yet."); #endif Texture3D color; @@ -383,7 +389,7 @@ void FramebufferGLTest::attachTexture3D() { #endif Framebuffer framebuffer({{}, Vector2i(128)}); - framebuffer.attachTexture3D(Framebuffer::ColorAttachment(0), color, 0, 0); + framebuffer.attachTextureLayer(Framebuffer::ColorAttachment(0), color, 0, 0); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::ReadDraw), Framebuffer::Status::Complete); @@ -394,17 +400,16 @@ void FramebufferGLTest::attachTexture1DArray() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); - Texture2D color(Texture2D::Target::Texture1DArray); + Texture1DArray color; color.setStorage(1, TextureFormat::RGBA8, {128, 8}); - Texture2D depthStencil(Texture2D::Target::Texture1DArray); + Texture1DArray depthStencil; depthStencil.setStorage(1, TextureFormat::Depth24Stencil8, {128, 8}); Framebuffer framebuffer({{}, {128, 1}}); - framebuffer.attachTexture2D(Framebuffer::ColorAttachment(0), color, 0) - .attachTexture2D(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0); + framebuffer.attachTextureLayer(Framebuffer::ColorAttachment(0), color, 0, 3) + .attachTextureLayer(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0, 3); - CORRADE_EXPECT_FAIL("Not properly implemented yet."); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::ReadDraw), Framebuffer::Status::Complete); } @@ -415,21 +420,20 @@ void FramebufferGLTest::attachTexture2DArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); - #else - CORRADE_SKIP("Not properly implemented yet."); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not available.")); #endif - Texture3D color(Texture3D::Target::Texture2DArray); + Texture2DArray color; color.setStorage(1, TextureFormat::RGBA8, {128, 128, 8}); - Texture3D depthStencil(Texture3D::Target::Texture2DArray); + Texture2DArray depthStencil; depthStencil.setStorage(1, TextureFormat::Depth24Stencil8, {128, 128, 8}); Framebuffer framebuffer({{}, Vector2i(128)}); - framebuffer.attachTexture3D(Framebuffer::ColorAttachment(0), color, 0, 0) - .attachTexture3D(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0, 0); + framebuffer.attachTextureLayer(Framebuffer::ColorAttachment(0), color, 0, 3) + .attachTextureLayer(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0, 3); - CORRADE_EXPECT_FAIL("Not properly implemented yet."); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::ReadDraw), Framebuffer::Status::Complete); } @@ -450,15 +454,15 @@ void FramebufferGLTest::attachRectangleTexture() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not available.")); - Texture2D color(Texture2D::Target::Rectangle); - color.setStorage(1, TextureFormat::RGBA8, Vector2i(128)); + RectangleTexture color; + color.setStorage(TextureFormat::RGBA8, Vector2i(128)); - Texture2D depthStencil(Texture2D::Target::Rectangle); - depthStencil.setStorage(1, TextureFormat::Depth24Stencil8, Vector2i(128)); + RectangleTexture depthStencil; + depthStencil.setStorage(TextureFormat::Depth24Stencil8, Vector2i(128)); Framebuffer framebuffer({{}, Vector2i(128)}); - framebuffer.attachTexture2D(Framebuffer::ColorAttachment(0), color, 0) - .attachTexture2D(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0); + framebuffer.attachTexture(Framebuffer::ColorAttachment(0), color, 0) + .attachTexture(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::ReadDraw), Framebuffer::Status::Complete); @@ -516,7 +520,23 @@ void FramebufferGLTest::attachCubeMapTexture() { #ifndef MAGNUM_TARGET_GLES void FramebufferGLTest::attachCubeMapTextureArray() { - CORRADE_SKIP("Not implemented yet."); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not available.")); + + CubeMapTextureArray color; + color.setStorage(1, TextureFormat::RGBA8, {128, 128, 18}); + + CubeMapTextureArray depthStencil; + depthStencil.setStorage(1, TextureFormat::Depth24Stencil8, {128, 128, 18}); + + Framebuffer framebuffer({{}, Vector2i(128)}); + framebuffer.attachTextureLayer(Framebuffer::ColorAttachment(0), color, 0, 3) + .attachTextureLayer(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0, 3); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::ReadDraw), Framebuffer::Status::Complete); } #endif @@ -547,8 +567,8 @@ void FramebufferGLTest::multipleColorOutputs() { depth.setStorage(RenderbufferFormat::DepthComponent16, Vector2i(128)); Framebuffer framebuffer({{}, Vector2i(128)}); - framebuffer.attachTexture2D(Framebuffer::ColorAttachment(0), color1, 0) - .attachTexture2D(Framebuffer::ColorAttachment(1), color2, 0) + framebuffer.attachTexture(Framebuffer::ColorAttachment(0), color1, 0) + .attachTexture(Framebuffer::ColorAttachment(1), color2, 0) .attachRenderbuffer(Framebuffer::BufferAttachment::Depth, depth) .mapForDraw({{0, Framebuffer::ColorAttachment(1)}, {1, Framebuffer::ColorAttachment(0)}}); diff --git a/src/Magnum/TextureTools/DistanceField.cpp b/src/Magnum/TextureTools/DistanceField.cpp index b76bbd05e..b5ba59b17 100644 --- a/src/Magnum/TextureTools/DistanceField.cpp +++ b/src/Magnum/TextureTools/DistanceField.cpp @@ -149,7 +149,7 @@ void distanceField(Texture2D& input, Texture2D& output, const Range2Di& rectangl #endif Framebuffer framebuffer(rectangle); - framebuffer.attachTexture2D(Framebuffer::ColorAttachment(0), output, 0); + framebuffer.attachTexture(Framebuffer::ColorAttachment(0), output, 0); framebuffer.bind(FramebufferTarget::Draw); framebuffer.clear(FramebufferClear::Color); From b68843bf22c73131e9abe806a5ed4270177b3c38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 27 Jan 2014 15:48:51 +0100 Subject: [PATCH 34/86] Shader: ability to use version directive from shader source. --- src/Magnum/Shader.cpp | 6 +++--- src/Magnum/Shader.h | 6 ++++-- src/Magnum/Test/ShaderGLTest.cpp | 7 +++++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Shader.cpp b/src/Magnum/Shader.cpp index b547f2400..23a00651f 100644 --- a/src/Magnum/Shader.cpp +++ b/src/Magnum/Shader.cpp @@ -558,11 +558,11 @@ Shader::Shader(const Version version, const Type type): _type(type), _id(0) { case Version::GLES300: _sources.push_back("#version 300\n"); return; #endif - case Version::None: - CORRADE_ASSERT(false, "Shader::Shader(): unsupported version" << version, ); + /* The user is responsible for (not) adding #version directive */ + case Version::None: return; } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT(false, "Shader::Shader(): unsupported version" << version, ); } Shader::~Shader() { diff --git a/src/Magnum/Shader.h b/src/Magnum/Shader.h index 1a087adac..902b0f8fc 100644 --- a/src/Magnum/Shader.h +++ b/src/Magnum/Shader.h @@ -436,8 +436,10 @@ class MAGNUM_EXPORT Shader: public AbstractObject { * @param version Target version * @param type %Shader type * - * Creates empty OpenGL shader and adds @c \#version directive at the - * beginning. + * Creates empty OpenGL shader and adds @c \#version directive + * corresponding to @p version parameter at the beginning. If + * @ref Version::None is specified, (not) adding the @c \#version + * directive is left to the user. * @see @fn_gl{CreateShader} */ explicit Shader(Version version, Type type); diff --git a/src/Magnum/Test/ShaderGLTest.cpp b/src/Magnum/Test/ShaderGLTest.cpp index 70ef874a8..dc33d3fc8 100644 --- a/src/Magnum/Test/ShaderGLTest.cpp +++ b/src/Magnum/Test/ShaderGLTest.cpp @@ -39,6 +39,7 @@ class ShaderGLTest: public AbstractOpenGLTester { explicit ShaderGLTest(); void construct(); + void constructNoVersion(); void constructCopy(); void constructMove(); @@ -51,6 +52,7 @@ class ShaderGLTest: public AbstractOpenGLTester { ShaderGLTest::ShaderGLTest() { addTests({&ShaderGLTest::construct, + &ShaderGLTest::constructNoVersion, &ShaderGLTest::constructCopy, &ShaderGLTest::constructMove, @@ -82,6 +84,11 @@ void ShaderGLTest::construct() { MAGNUM_VERIFY_NO_ERROR(); } +void ShaderGLTest::constructNoVersion() { + const Shader shader(Version::None, Shader::Type::Fragment); + CORRADE_VERIFY(shader.sources().empty()); +} + void ShaderGLTest::constructCopy() { CORRADE_VERIFY(!(std::is_constructible{})); /* GCC 4.6 doesn't have std::is_assignable */ From 10cf24e15834b23ed6bb0e3891e8eac1331e7d12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 27 Jan 2014 18:53:03 +0100 Subject: [PATCH 35/86] Publicly inherit AbstractTexture in BufferTexture. There isn't anything to hide anymore. --- src/Magnum/BufferTexture.h | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/Magnum/BufferTexture.h b/src/Magnum/BufferTexture.h index 67d9931ee..46a5ae4be 100644 --- a/src/Magnum/BufferTexture.h +++ b/src/Magnum/BufferTexture.h @@ -200,13 +200,10 @@ and respective function documentation for more information. @requires_gl31 %Extension @extension{ARB,texture_buffer_object} @requires_gl Texture buffers are not available in OpenGL ES. */ -class MAGNUM_EXPORT BufferTexture: private AbstractTexture { +class MAGNUM_EXPORT BufferTexture: public AbstractTexture { friend struct Implementation::TextureState; public: - /** @copydoc AbstractTexture::maxLabelLength() */ - static Int maxLabelLength() { return AbstractTexture::maxLabelLength(); } - /** * @brief Minimum required alignment for texture buffer offsets * @@ -225,21 +222,6 @@ class MAGNUM_EXPORT BufferTexture: private AbstractTexture { */ explicit BufferTexture(): AbstractTexture(GL_TEXTURE_BUFFER) {} - /** @copydoc AbstractTexture::id() */ - Int id() const { return AbstractTexture::id(); } - - /** @copydoc AbstractTexture::label() */ - std::string label() const { return AbstractTexture::label(); } - - /** @copydoc AbstractTexture::setLabel() */ - BufferTexture& setLabel(const std::string& label) { - AbstractTexture::setLabel(label); - return *this; - } - - /** @copydoc AbstractTexture::bind() */ - void bind(Int layer) { AbstractTexture::bind(layer); } - /** * @brief Set texture buffer * @param internalFormat Internal format @@ -269,6 +251,14 @@ class MAGNUM_EXPORT BufferTexture: private AbstractTexture { */ void setBuffer(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size); + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + BufferTexture& setLabel(const std::string& label) { + AbstractTexture::setLabel(label); + return *this; + } + #endif + private: void MAGNUM_LOCAL setBufferImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer); void MAGNUM_LOCAL setBufferImplementationDSA(BufferTextureFormat internalFormat, Buffer& buffer); From 0e87886ac448fe9d8c0b7bb346bac96d6938bbf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 27 Jan 2014 18:55:05 +0100 Subject: [PATCH 36/86] Allow method chaining also on BufferTexture. There is only one configuring function now, but still, be consistent with the rest. --- src/Magnum/BufferTexture.cpp | 6 ++++-- src/Magnum/BufferTexture.h | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Magnum/BufferTexture.cpp b/src/Magnum/BufferTexture.cpp index 4fbc8af09..1c91f129e 100644 --- a/src/Magnum/BufferTexture.cpp +++ b/src/Magnum/BufferTexture.cpp @@ -48,12 +48,14 @@ Int BufferTexture::offsetAlignment() { return value; } -void BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer) { +BufferTexture& BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer) { (this->*Context::current()->state().texture->setBufferImplementation)(internalFormat, buffer); + return *this; } -void BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer, const GLintptr offset, const GLsizeiptr size) { +BufferTexture& BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer, const GLintptr offset, const GLsizeiptr size) { (this->*Context::current()->state().texture->setBufferRangeImplementation)(internalFormat, buffer, offset, size); + return *this; } void BufferTexture::setBufferImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer) { diff --git a/src/Magnum/BufferTexture.h b/src/Magnum/BufferTexture.h index 46a5ae4be..d80dd0722 100644 --- a/src/Magnum/BufferTexture.h +++ b/src/Magnum/BufferTexture.h @@ -226,6 +226,7 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture { * @brief Set texture buffer * @param internalFormat Internal format * @param buffer %Buffer with data + * @return Reference to self (for method chaining) * * Binds given buffer to this texture. The buffer itself can be then * filled with data of proper format at any time using @ref Buffer "Buffer"'s @@ -233,7 +234,7 @@ class MAGNUM_EXPORT BufferTexture: public 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); + BufferTexture& setBuffer(BufferTextureFormat internalFormat, Buffer& buffer); /** * @brief Set texture buffer @@ -241,6 +242,7 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture { * @param buffer %Buffer * @param offset Offset * @param size Data size + * @return Reference to self (for method chaining) * * Binds range of given buffer to this texture. The buffer itself can * be then filled with data of proper format at any time using @ref Buffer "Buffer"'s @@ -249,7 +251,7 @@ class MAGNUM_EXPORT BufferTexture: public 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); + BufferTexture& setBuffer(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size); /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT From 601913308b7afaf5d13f5e0fa51d08e91d223b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 27 Jan 2014 19:05:20 +0100 Subject: [PATCH 37/86] Removed now duplicate extension support status, added some TODOs. --- doc/opengl-support.dox | 6 ++- src/Magnum/Context.cpp | 110 +++++++++++++++++++---------------------- 2 files changed, 56 insertions(+), 60 deletions(-) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index f0f515158..41624536b 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -47,7 +47,8 @@ following: @subsection opengl-support-30 OpenGL 3.0 -@todo @extension{APPLE,flush_buffer_range} doesn't add anything to @extension{ARB,map_buffer_range} +@todo Replace @extension{APPLE,vertex_array_object} with ARB version (we use only ARB functions without APPLE fallback) +@todo @extension{APPLE,flush_buffer_range} doesn't add anything to @extension{ARB,map_buffer_range} (remove it and leave only ARB one) @todo @extension{EXT,texture_array} overlaps with @extension{ARB,framebuffer_object} %Extension | Status @@ -267,6 +268,9 @@ supported. Only extensions not already listed in above tables are included here. +@todo Support also IMG_multisampled_render_to_texture? It has different enum + values (!) + %Extension | Status -------------------------------------------- | ------ @es_extension{APPLE,texture_format_BGRA8888} | done diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index a428575fc..c11a579b0 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -54,126 +54,122 @@ const std::vector& Extension::extensions(Version version) { static const std::vector empty; #ifndef MAGNUM_TARGET_GLES static const std::vector extensions{ - _extension(GL,AMD,vertex_shader_layer), // done - _extension(GL,AMD,shader_trinary_minmax), // done - _extension(GL,ARB,robustness), // done + _extension(GL,AMD,vertex_shader_layer), + _extension(GL,AMD,shader_trinary_minmax), + _extension(GL,ARB,robustness), _extension(GL,ATI,texture_mirror_once), - _extension(GL,EXT,texture_filter_anisotropic), // done + _extension(GL,EXT,texture_filter_anisotropic), _extension(GL,EXT,texture_mirror_clamp), _extension(GL,EXT,direct_state_access), _extension(GL,EXT,debug_label), _extension(GL,EXT,debug_marker), - _extension(GL,GREMEDY,string_marker)}; // done + _extension(GL,GREMEDY,string_marker)}; static const std::vector extensions300{ - /** - * @todo Remove as it doesn't have all functionality present in GL 3.0 - * and leave only ARB_map_buffer_range? - */ - _extension(GL,APPLE,flush_buffer_range), // done - _extension(GL,APPLE,vertex_array_object), // done - _extension(GL,ARB,map_buffer_range), // done, replaces APPLE_flush_buffer_range + _extension(GL,APPLE,flush_buffer_range), + _extension(GL,APPLE,vertex_array_object), + _extension(GL,ARB,map_buffer_range), _extension(GL,ARB,color_buffer_float), - _extension(GL,ARB,half_float_pixel), // done - _extension(GL,ARB,texture_float), // done - _extension(GL,ARB,depth_buffer_float), // done - _extension(GL,ARB,texture_rg), // done + _extension(GL,ARB,half_float_pixel), + _extension(GL,ARB,texture_float), + _extension(GL,ARB,depth_buffer_float), + _extension(GL,ARB,texture_rg), _extension(GL,ARB,framebuffer_object), _extension(GL,EXT,gpu_shader4), - _extension(GL,EXT,packed_float), // done + _extension(GL,EXT,packed_float), _extension(GL,EXT,texture_array), - _extension(GL,EXT,texture_compression_rgtc), // done - _extension(GL,EXT,texture_shared_exponent), // done + _extension(GL,EXT,texture_compression_rgtc), + _extension(GL,EXT,texture_shared_exponent), _extension(GL,EXT,framebuffer_sRGB), _extension(GL,EXT,draw_buffers2), _extension(GL,EXT,texture_integer), _extension(GL,EXT,transform_feedback), - _extension(GL,NV,half_float), // done + _extension(GL,NV,half_float), _extension(GL,NV,depth_buffer_float), - _extension(GL,NV,conditional_render)}; // done + _extension(GL,NV,conditional_render)}; static const std::vector extensions310{ _extension(GL,ARB,texture_rectangle), _extension(GL,ARB,draw_instanced), _extension(GL,ARB,texture_buffer_object), _extension(GL,ARB,uniform_buffer_object), - _extension(GL,ARB,copy_buffer), // done - _extension(GL,EXT,texture_snorm), // done + _extension(GL,ARB,copy_buffer), + _extension(GL,EXT,texture_snorm), _extension(GL,NV,primitive_restart)}; static const std::vector extensions320{ _extension(GL,ARB,geometry_shader4), - _extension(GL,ARB,depth_clamp), // done + _extension(GL,ARB,depth_clamp), _extension(GL,ARB,draw_elements_base_vertex), - _extension(GL,ARB,fragment_coord_conventions), // done - _extension(GL,ARB,provoking_vertex), // done - _extension(GL,ARB,seamless_cube_map), // done + _extension(GL,ARB,fragment_coord_conventions), + _extension(GL,ARB,provoking_vertex), + _extension(GL,ARB,seamless_cube_map), _extension(GL,ARB,sync), _extension(GL,ARB,texture_multisample), - _extension(GL,ARB,vertex_array_bgra)}; // done + _extension(GL,ARB,vertex_array_bgra)}; static const std::vector extensions330{ _extension(GL,ARB,instanced_arrays), _extension(GL,ARB,blend_func_extended), - _extension(GL,ARB,explicit_attrib_location), // done - _extension(GL,ARB,occlusion_query2), // done + _extension(GL,ARB,explicit_attrib_location), + _extension(GL,ARB,occlusion_query2), _extension(GL,ARB,sampler_objects), - _extension(GL,ARB,shader_bit_encoding), // done - _extension(GL,ARB,texture_rgb10_a2ui), // done + _extension(GL,ARB,shader_bit_encoding), + _extension(GL,ARB,texture_rgb10_a2ui), _extension(GL,ARB,texture_swizzle), _extension(GL,ARB,timer_query), - _extension(GL,ARB,vertex_type_2_10_10_10_rev)}; // done + _extension(GL,ARB,vertex_type_2_10_10_10_rev)}; static const std::vector extensions400{ _extension(GL,ARB,draw_buffers_blend), _extension(GL,ARB,sample_shading), - _extension(GL,ARB,texture_cube_map_array), // done + _extension(GL,ARB,texture_cube_map_array), _extension(GL,ARB,texture_gather), - _extension(GL,ARB,texture_query_lod), // done + _extension(GL,ARB,texture_query_lod), _extension(GL,ARB,draw_indirect), _extension(GL,ARB,gpu_shader5), - _extension(GL,ARB,gpu_shader_fp64), // done + _extension(GL,ARB,gpu_shader_fp64), _extension(GL,ARB,shader_subroutine), _extension(GL,ARB,tessellation_shader), - _extension(GL,ARB,texture_buffer_object_rgb32), // done + _extension(GL,ARB,texture_buffer_object_rgb32), _extension(GL,ARB,transform_feedback2), _extension(GL,ARB,transform_feedback3)}; static const std::vector extensions410{ _extension(GL,ARB,ES2_compatibility), _extension(GL,ARB,get_program_binary), _extension(GL,ARB,separate_shader_objects), - _extension(GL,ARB,shader_precision), // done - _extension(GL,ARB,vertex_attrib_64bit), // done + _extension(GL,ARB,shader_precision), + _extension(GL,ARB,vertex_attrib_64bit), _extension(GL,ARB,viewport_array)}; static const std::vector extensions420{ - _extension(GL,ARB,texture_compression_bptc), // done + _extension(GL,ARB,texture_compression_bptc), _extension(GL,ARB,base_instance), - _extension(GL,ARB,shading_language_420pack), // done + _extension(GL,ARB,shading_language_420pack), _extension(GL,ARB,transform_feedback_instanced), _extension(GL,ARB,compressed_texture_pixel_storage), - _extension(GL,ARB,conservative_depth), // done + _extension(GL,ARB,conservative_depth), _extension(GL,ARB,internalformat_query), _extension(GL,ARB,map_buffer_alignment), _extension(GL,ARB,shader_atomic_counters), _extension(GL,ARB,shader_image_load_store), /* Mentioned in GLSL 4.20 specs as newly added */ - _extension(GL,ARB,shading_language_packing), // done + _extension(GL,ARB,shading_language_packing), _extension(GL,ARB,texture_storage)}; static const std::vector extensions430{ - _extension(GL,ARB,arrays_of_arrays), // done + _extension(GL,ARB,arrays_of_arrays), _extension(GL,ARB,ES3_compatibility), _extension(GL,ARB,clear_buffer_object), _extension(GL,ARB,compute_shader), _extension(GL,ARB,copy_image), _extension(GL,KHR,debug), _extension(GL,ARB,explicit_uniform_location), - _extension(GL,ARB,fragment_layer_viewport), // done + _extension(GL,ARB,fragment_layer_viewport), _extension(GL,ARB,framebuffer_no_attachments), _extension(GL,ARB,internalformat_query2), - _extension(GL,ARB,invalidate_subdata), // done + _extension(GL,ARB,invalidate_subdata), _extension(GL,ARB,multi_draw_indirect), _extension(GL,ARB,program_interface_query), - _extension(GL,ARB,robust_buffer_access_behavior), // done - _extension(GL,ARB,shader_image_size), // done + _extension(GL,ARB,robust_buffer_access_behavior), + _extension(GL,ARB,shader_image_size), _extension(GL,ARB,shader_storage_buffer_object), _extension(GL,ARB,stencil_texturing), - _extension(GL,ARB,texture_buffer_range), // done - _extension(GL,ARB,texture_query_levels), // done + _extension(GL,ARB,texture_buffer_range), + _extension(GL,ARB,texture_query_levels), _extension(GL,ARB,texture_storage_multisample), _extension(GL,ARB,texture_view), _extension(GL,ARB,vertex_attrib_binding)}; @@ -199,10 +195,6 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,EXT,disjoint_timer_query), _extension(GL,EXT,separate_shader_objects), _extension(GL,EXT,sRGB), - /** - * @todo Support also IMG_multisampled_render_to_texture? It has - * different enum values (!) - */ _extension(GL,EXT,multisampled_render_to_texture), _extension(GL,EXT,robustness), _extension(GL,KHR,debug), @@ -210,7 +202,7 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,NV,read_depth), _extension(GL,NV,read_stencil), _extension(GL,NV,read_depth_stencil), - _extension(GL,NV,texture_border_clamp), // done + _extension(GL,NV,texture_border_clamp), _extension(GL,OES,depth32), _extension(GL,OES,mapbuffer), _extension(GL,OES,stencil1), @@ -219,7 +211,7 @@ const std::vector& Extension::extensions(Version version) { static const std::vector extensionsES300{ _extension(GL,ANGLE,framebuffer_blit), _extension(GL,ANGLE,framebuffer_multisample), - _extension(GL,ANGLE,depth_texture), // done + _extension(GL,ANGLE,depth_texture), _extension(GL,APPLE,framebuffer_multisample), _extension(GL,ARM,rgba8), _extension(GL,EXT,texture_type_2_10_10_10_REV), @@ -232,7 +224,7 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,NV,draw_buffers), _extension(GL,NV,fbo_color_attachments), _extension(GL,NV,read_buffer), - _extension(GL,NV,framebuffer_blit), // done + _extension(GL,NV,framebuffer_blit), _extension(GL,NV,framebuffer_multisample), _extension(GL,OES,depth24), _extension(GL,OES,element_index_uint), @@ -245,10 +237,10 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,OES,vertex_half_float), _extension(GL,OES,packed_depth_stencil), _extension(GL,OES,depth_texture), - _extension(GL,OES,standard_derivatives), // done + _extension(GL,OES,standard_derivatives), _extension(GL,OES,vertex_array_object), _extension(GL,OES,required_internalformat), - _extension(GL,OES,surfaceless_context)}; // done + _extension(GL,OES,surfaceless_context)}; #endif #endif From 06f45d8674093f4e658f98909b8902f15321efe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 27 Jan 2014 20:40:11 +0100 Subject: [PATCH 38/86] Fix compilation on GCC 4.7. --- src/Magnum/Text/Test/GlyphCacheGLTest.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Magnum/Text/Test/GlyphCacheGLTest.cpp b/src/Magnum/Text/Test/GlyphCacheGLTest.cpp index 70c9e6117..1e06c79a3 100644 --- a/src/Magnum/Text/Test/GlyphCacheGLTest.cpp +++ b/src/Magnum/Text/Test/GlyphCacheGLTest.cpp @@ -23,6 +23,8 @@ DEALINGS IN THE SOFTWARE. */ +#include + #include "Magnum/Test/AbstractOpenGLTester.h" #include "Magnum/Text/GlyphCache.h" From 5373fdf3adbb56adc73d435884a0029d79491480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 28 Jan 2014 13:16:32 +0100 Subject: [PATCH 39/86] MeshTools: fix obvious out-of-range access in tipsify(). Spotted by MSVC compiler (which does range check on everything). This was probably harmless, as the out-of-range memory wasn't accessed afterwards (the for cycle would end right after that because vi == 3), but it was firing the assertion so it's better to have it fixed. --- src/Magnum/MeshTools/Tipsify.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Magnum/MeshTools/Tipsify.cpp b/src/Magnum/MeshTools/Tipsify.cpp index fba38cf16..e68402ca4 100644 --- a/src/Magnum/MeshTools/Tipsify.cpp +++ b/src/Magnum/MeshTools/Tipsify.cpp @@ -61,7 +61,9 @@ void Tipsify::operator()(std::size_t cacheSize) { emitted[t] = true; /* Write all vertices of the triangle to output buffer */ - for(UnsignedInt vi = 0, v = indices[t*3]; vi != 3; v = indices[++vi+t*3]) { + for(UnsignedInt vi = 0; vi != 3; ++vi) { + const UnsignedInt v = indices[vi + t*3]; + outputIndices.push_back(v); /* Add to dead end stack and candidates array */ From 8f9036104d3cd1fe7d0ed7c9a0b82faa147afbe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 29 Jan 2014 15:15:22 +0100 Subject: [PATCH 40/86] doc: explicitly mention that given extension is needed for ES2. ES2 extensions which have equivalent in ES3 are not available there. --- src/Magnum/AbstractFramebuffer.h | 12 ++++++----- src/Magnum/AbstractShaderProgram.h | 7 +++++-- src/Magnum/Buffer.h | 15 +++++++++----- src/Magnum/ColorFormat.h | 33 ++++++++++++++++++------------ src/Magnum/DefaultFramebuffer.h | 14 +++++++++---- src/Magnum/Framebuffer.h | 25 +++++++++++++--------- src/Magnum/Mesh.h | 1 + src/Magnum/Query.h | 3 ++- src/Magnum/Renderbuffer.h | 2 +- src/Magnum/RenderbufferFormat.h | 14 ++++++++----- src/Magnum/Renderer.h | 3 +++ src/Magnum/Sampler.h | 4 ++-- src/Magnum/Texture.h | 5 +++-- src/Magnum/TextureFormat.h | 24 +++++++++++++++------- 14 files changed, 105 insertions(+), 57 deletions(-) diff --git a/src/Magnum/AbstractFramebuffer.h b/src/Magnum/AbstractFramebuffer.h index c6f45c396..d74b0656a 100644 --- a/src/Magnum/AbstractFramebuffer.h +++ b/src/Magnum/AbstractFramebuffer.h @@ -62,7 +62,7 @@ typedef Containers::EnumSet FramebufferBlitMask; @@ -88,7 +88,7 @@ typedef Containers::EnumSet class AbstractShaderProgram::Attribute { * Half float. Only for float attribute types. * @requires_gl30 %Extension @extension{NV,half_float} * @requires_gles30 %Extension @es_extension{OES,vertex_half_float} + * in OpenGL ES 2.0 */ HalfFloat = GL_HALF_FLOAT, @@ -1005,7 +1006,8 @@ template class AbstractShaderProgram::Attribute { * float vector attribute type. * @todo How about (incompatible) @es_extension{OES,vertex_type_10_10_10_2}? * @requires_gl33 %Extension @extension{ARB,vertex_type_2_10_10_10_rev} - * @requires_gles30 (no extension providing this functionality) + * @requires_gles30 Packed attributes are not available in OpenGL + * ES 2.0 */ UnsignedInt2101010Rev = GL_UNSIGNED_INT_2_10_10_10_REV, @@ -1013,7 +1015,8 @@ template class AbstractShaderProgram::Attribute { * Signed 2.10.10.10 packed integer. Only for four-component float * vector attribute type. * @requires_gl33 %Extension @extension{ARB,vertex_type_2_10_10_10_rev} - * @requires_gles30 (no extension providing this functionality) + * @requires_gles30 Packed attributes are not available in OpenGL + * ES 2.0 */ Int2101010Rev = GL_INT_2_10_10_10_REV #endif diff --git a/src/Magnum/Buffer.h b/src/Magnum/Buffer.h index 73674d6ac..0ece23817 100644 --- a/src/Magnum/Buffer.h +++ b/src/Magnum/Buffer.h @@ -350,7 +350,8 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * * @see @ref MapFlags, @ref map(GLintptr, GLsizeiptr, MapFlags) * @requires_gl30 %Extension @extension{ARB,map_buffer_range} - * @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} + * @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} in + * OpenGL ES 2.0 */ enum class MapFlag: GLbitfield { /** Map buffer for reading. */ @@ -416,7 +417,8 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * * @see @ref map(GLintptr, GLsizeiptr, MapFlags) * @requires_gl30 %Extension @extension{ARB,map_buffer_range} - * @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} + * @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} in + * OpenGL ES 2.0 */ typedef Containers::EnumSet MapFlags; @@ -800,7 +802,8 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @ref map(MapAccess), @ref setTargetHint(), @fn_gl{BindBuffer} * and @fn_gl{MapBufferRange} or @fn_gl_extension{MapNamedBufferRange,EXT,direct_state_access} * @requires_gl30 %Extension @extension{ARB,map_buffer_range} - * @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} + * @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} in + * OpenGL ES 2.0 */ void* map(GLintptr offset, GLsizeiptr length, MapFlags flags); @@ -820,7 +823,8 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @see @ref setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{FlushMappedBufferRange} * or @fn_gl_extension{FlushMappedNamedBufferRange,EXT,direct_state_access} * @requires_gl30 %Extension @extension{ARB,map_buffer_range} - * @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} + * @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} in + * OpenGL ES 2.0 */ Buffer& flushMappedRange(GLintptr offset, GLsizeiptr length); @@ -836,7 +840,8 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * is bound to hinted target before the operation. * @see setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{UnmapBuffer} or * @fn_gl_extension{UnmapNamedBuffer,EXT,direct_state_access} - * @requires_gles30 %Extension @es_extension{OES,mapbuffer} + * @requires_gles30 %Extension @es_extension{OES,mapbuffer} in OpenGL + * ES 2.0 */ bool unmap(); diff --git a/src/Magnum/ColorFormat.h b/src/Magnum/ColorFormat.h index cf3272c08..67c6a1e9e 100644 --- a/src/Magnum/ColorFormat.h +++ b/src/Magnum/ColorFormat.h @@ -55,8 +55,9 @@ See documentation of these values for possible limitations when using OpenGL ES enum class ColorFormat: GLenum { /** * Floating-point red channel. - * @requires_gles30 For texture data only, extension @es_extension{EXT,texture_rg}. - * @requires_es_extension For framebuffer reading, extension @es_extension{EXT,texture_rg}. + * @requires_gles30 For texture data only, extension @es_extension{EXT,texture_rg} + * in OpenGL ES 2.0 + * @requires_es_extension For framebuffer reading, extension @es_extension{EXT,texture_rg} */ #ifndef MAGNUM_TARGET_GLES2 Red = GL_RED, @@ -95,7 +96,8 @@ enum class ColorFormat: GLenum { /** * Floating-point red and green channel. * @requires_gl30 %Extension @extension{ARB,texture_rg} and @extension{EXT,texture_integer} - * @requires_gles30 For texture data only, extension @es_extension{EXT,texture_rg}. + * @requires_gles30 For texture data only, extension @es_extension{EXT,texture_rg} + * in OpenGL ES 2.0 * @requires_es_extension For framebuffer reading, extension @es_extension{EXT,texture_rg}. */ #ifndef MAGNUM_TARGET_GLES2 @@ -223,7 +225,8 @@ enum class ColorFormat: GLenum { /** * Depth component. - * @requires_gles30 For texture data only, extension @es_extension{ANGLE,depth_texture}. + * @requires_gles30 For texture data only, extension @es_extension{OES,depth_texture} + * or @es_extension{ANGLE,depth_texture} in OpenGL ES 2.0 * @requires_es_extension For framebuffer reading only, extension * @es_extension2{NV,read_depth,GL_NV_read_depth_stencil}. */ @@ -246,9 +249,10 @@ enum class ColorFormat: GLenum { /** * Depth and stencil. * @requires_gl30 %Extension @extension{ARB,framebuffer_object} - * @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}. + * @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil} + * in OpenGL ES 2.0 * @requires_es_extension For framebuffer reading only, extension - * @es_extension2{NV,read_depth_stencil,GL_NV_read_depth_stencil}. + * @es_extension2{NV,read_depth_stencil,GL_NV_read_depth_stencil} */ #ifndef MAGNUM_TARGET_GLES2 DepthStencil = GL_DEPTH_STENCIL @@ -293,7 +297,7 @@ enum class ColorType: GLenum { * Each component unsigned short. * @requires_gl Can't be used for framebuffer reading in OpenGL ES. * @requires_gles30 For texture data only, extension @es_extension{OES,depth_texture} - * or @es_extension{ANGLE,depth_texture}. + * or @es_extension{ANGLE,depth_texture} in OpenGL ES 2.0 */ UnsignedShort = GL_UNSIGNED_SHORT, @@ -312,7 +316,7 @@ enum class ColorType: GLenum { * Each component unsigned int. * @requires_gles30 Can't be used for framebuffer reading in OpenGL ES 2.0. * @requires_gles30 For texture data only, extension @es_extension{OES,depth_texture} - * or @es_extension{ANGLE,depth_texture}. + * or @es_extension{ANGLE,depth_texture} in OpenGL ES 2.0 */ UnsignedInt = GL_UNSIGNED_INT, @@ -320,7 +324,7 @@ enum class ColorType: GLenum { /** * Each component signed int. * @requires_gles30 Only @ref Magnum::ColorType::UnsignedInt "ColorType::UnsignedInt" - * is available in OpenGL ES 2.0. + * is available in OpenGL ES 2.0 in OpenGL ES 2.0 */ Int = GL_INT, #endif @@ -329,7 +333,8 @@ enum class ColorType: GLenum { * Each component half float. * @requires_gl30 %Extension @extension{NV,half_float} / @extension{ARB,half_float_pixel} * @requires_gles30 For texture data only, extension - * @es_extension2{OES,texture_half_float,OES_texture_float}. + * @es_extension2{OES,texture_half_float,OES_texture_float} in OpenGL + * ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 HalfFloat = GL_HALF_FLOAT, @@ -339,7 +344,8 @@ enum class ColorType: GLenum { /** * Each component float. - * @requires_gles30 For texture data only, extension @es_extension{OES,texture_float}. + * @requires_gles30 For texture data only, extension @es_extension{OES,texture_float} + * in OpenGL ES 2.0 */ Float = GL_FLOAT, @@ -434,7 +440,7 @@ enum class ColorType: GLenum { * ABGR, unsigned int, each RGB component 10bit, alpha component 2bit. * @requires_gles30 Can't be used for framebuffer reading in OpenGL ES 2.0. * @requires_gles30 For texture data only, extension - * @es_extension{EXT,texture_type_2_10_10_10_REV}. + * @es_extension{EXT,texture_type_2_10_10_10_REV} in OpenGL ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 UnsignedInt2101010Rev = GL_UNSIGNED_INT_2_10_10_10_REV, @@ -463,7 +469,8 @@ enum class ColorType: GLenum { /** * Unsigned int, depth component 24bit, stencil index 8bit. * @requires_gl30 %Extension @extension{ARB,framebuffer_object} - * @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}. + * @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil} + * in OpenGL ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 UnsignedInt248 = GL_UNSIGNED_INT_24_8, diff --git a/src/Magnum/DefaultFramebuffer.h b/src/Magnum/DefaultFramebuffer.h index 61276f675..347d3e3dd 100644 --- a/src/Magnum/DefaultFramebuffer.h +++ b/src/Magnum/DefaultFramebuffer.h @@ -95,6 +95,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { /** * The default framebuffer does not exist. * @requires_gles30 %Extension @es_extension{OES,surfaceless_context} + * in OpenGL ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 Undefined = GL_FRAMEBUFFER_UNDEFINED @@ -170,6 +171,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * * @see @ref mapForRead() * @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} + * in OpenGL ES 2.0 */ enum class ReadAttachment: GLenum { /** Don't read from any buffer */ @@ -241,6 +243,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * @see @ref invalidate() * @requires_gl43 %Extension @extension{ARB,invalidate_subdata} * @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer} + * in OpenGL ES 2.0 */ enum class InvalidationAttachment: GLenum { #ifndef MAGNUM_TARGET_GLES @@ -374,6 +377,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * @see mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} or * @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access} * @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} + * in OpenGL ES 2.0 */ DefaultFramebuffer& mapForRead(ReadAttachment attachment); @@ -388,8 +392,9 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * @requires_gl43 %Extension @extension{ARB,invalidate_subdata}. Use * @ref Magnum::DefaultFramebuffer::clear() "clear()" instead * where the extension is not supported. - * @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}. - * Use @ref Magnum::DefaultFramebuffer::clear() "clear()" instead + * @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer} + * in OpenGL ES 2.0. Use + * @ref Magnum::DefaultFramebuffer::clear() "clear()" instead * where the extension is not supported. */ void invalidate(std::initializer_list attachments); @@ -406,8 +411,9 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * @requires_gl43 %Extension @extension{ARB,invalidate_subdata}. Use * @ref Magnum::DefaultFramebuffer::clear() "clear()" instead * where the extension is not supported. - * @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}. - * Use @ref Magnum::DefaultFramebuffer::clear() "clear()" instead + * @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer} + * in OpenGL ES 2.0. Use + * @ref Magnum::DefaultFramebuffer::clear() "clear()" instead * where the extension is not supported. */ void invalidate(std::initializer_list attachments, const Range2Di& rectangle); diff --git a/src/Magnum/Framebuffer.h b/src/Magnum/Framebuffer.h index 24a71991a..7076898ba 100644 --- a/src/Magnum/Framebuffer.h +++ b/src/Magnum/Framebuffer.h @@ -121,7 +121,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @param id Color attachment ID * * @requires_gles30 %Extension @es_extension{NV,fbo_color_attachments} - * is required for @p id greater than 0. + * is required for @p id greater than 0 in OpenGL ES 2.0 */ constexpr explicit ColorAttachment(UnsignedInt id): attachment(GL_COLOR_ATTACHMENT0 + id) {} @@ -204,6 +204,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @see @ref invalidate() * @requires_gl43 %Extension @extension{ARB,invalidate_subdata} * @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer} + * in OpenGL ES 2.0 */ class InvalidationAttachment { public: @@ -268,7 +269,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_multisample}, * @es_extension{APPLE,framebuffer_multisample}, * @es_extension{EXT,multisampled_render_to_texture} or - * @es_extension{NV,framebuffer_multisample} + * @es_extension{NV,framebuffer_multisample} in OpenGL ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 IncompleteMultisample = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, @@ -387,6 +388,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} or * @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} * @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers} + * in OpenGL ES 2.0 */ Framebuffer& mapForDraw(std::initializer_list> attachments); @@ -406,6 +408,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access}, * @fn_gl{DrawBuffers} in OpenGL ES 3.0 * @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers} + * in OpenGL ES 2.0 */ Framebuffer& mapForDraw(DrawAttachment attachment); @@ -420,6 +423,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @see @ref mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} * or @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access} * @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} + * in OpenGL ES 2.0 */ Framebuffer& mapForRead(ColorAttachment attachment); @@ -434,9 +438,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @requires_gl43 %Extension @extension{ARB,invalidate_subdata}. Use * @ref Magnum::Framebuffer::clear() "clear()" instead where the * extension is not supported. - * @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}. - * Use @ref Magnum::Framebuffer::clear() "clear()" instead where - * the extension is not supported. + * @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer} + * in OpenGL ES 2.0. Use @ref Magnum::Framebuffer::clear() "clear()" + * instead where the extension is not supported. */ void invalidate(std::initializer_list attachments); @@ -452,9 +456,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @requires_gl43 %Extension @extension{ARB,invalidate_subdata}. Use * @ref Magnum::Framebuffer::clear() "clear()" instead where the * extension is not supported. - * @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}. - * Use @ref Magnum::Framebuffer::clear() "clear()" instead where - * the extension is not supported. + * @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer} + * in OpenGL ES 2.0. Use @ref Magnum::Framebuffer::clear() "clear()" + * instead where the extension is not supported. */ void invalidate(std::initializer_list attachments, const Range2Di& rectangle); @@ -552,7 +556,8 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @see @fn_gl{BindFramebuffer}, @fn_gl2{FramebufferTextureLayer,FramebufferTexture} * or @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access}, * @fn_gles_extension{FramebufferTexture3D,OES,texture_3D} in OpenGL ES 2.0 - * @requires_gles30 %Extension @es_extension{OES,texture_3D} + * @requires_gles30 %Extension @es_extension{OES,texture_3D} in OpenGL + * ES 2.0 */ Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture3D& texture, Int level, Int layer); @@ -567,7 +572,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje #ifndef MAGNUM_TARGET_GLES2 /** @overload * @requires_gl30 %Extension @extension{EXT,texture_array} - * @requires_gles30 %Array textures are not available in OpenGL ES 2.0. + * @requires_gles30 %Array textures are not available in OpenGL ES 2.0 */ Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture2DArray& texture, Int level, Int layer); #endif diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index bb6158b2a..f6d6cc37b 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -339,6 +339,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { /** * Unsigned int * @requires_gles30 %Extension @es_extension{OES,element_index_uint} + * in OpenGL ES 2.0 */ UnsignedInt = GL_UNSIGNED_INT }; diff --git a/src/Magnum/Query.h b/src/Magnum/Query.h index bc15fad36..07a9bf3fe 100644 --- a/src/Magnum/Query.h +++ b/src/Magnum/Query.h @@ -252,8 +252,9 @@ q.beginConditionalRender(SampleQuery::ConditionalRenderMode::Wait); // render full version of the object only if the query returns nonzero result q.endConditionalRender(); @endcode -@requires_gles30 %Extension @es_extension{EXT,occlusion_query_boolean} +@requires_gles30 %Extension @es_extension{EXT,occlusion_query_boolean} in + OpenGL ES 2.0 @see @ref PrimitiveQuery, @ref TimeQuery */ class SampleQuery: public AbstractQuery { diff --git a/src/Magnum/Renderbuffer.h b/src/Magnum/Renderbuffer.h index c7be10d5c..07ad9fb97 100644 --- a/src/Magnum/Renderbuffer.h +++ b/src/Magnum/Renderbuffer.h @@ -162,7 +162,7 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject { * @see @ref maxSize(), @ref maxSamples(), @fn_gl{BindRenderbuffer}, * @fn_gl{RenderbufferStorageMultisample} or @fn_gl_extension{NamedRenderbufferStorageMultisample,EXT,direct_state_access} * @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_multisample} - * or @es_extension{NV,framebuffer_multisample} + * or @es_extension{NV,framebuffer_multisample} in OpenGL ES 2.0 * @todo How about @es_extension{APPLE,framebuffer_multisample}? * @todo NaCl has @fn_gl_extension{RenderbufferStorageMultisample,EXT,multisampled_render_to_texture} */ diff --git a/src/Magnum/RenderbufferFormat.h b/src/Magnum/RenderbufferFormat.h index 06dd008ca..8a417cb73 100644 --- a/src/Magnum/RenderbufferFormat.h +++ b/src/Magnum/RenderbufferFormat.h @@ -55,7 +55,8 @@ enum class RenderbufferFormat: GLenum { /** * Red component, normalized unsigned byte. * @requires_gl30 %Extension @extension{ARB,texture_rg} - * @requires_gles30 %Extension @es_extension{EXT,texture_rg} + * @requires_gles30 %Extension @es_extension{EXT,texture_rg} in OpenGL ES + * 2.0 */ #ifndef MAGNUM_TARGET_GLES2 R8 = GL_R8, @@ -78,7 +79,8 @@ enum class RenderbufferFormat: GLenum { /** * Red and green component, each normalized unsigned byte. * @requires_gl30 %Extension @extension{ARB,texture_rg} - * @requires_gles30 %Extension @es_extension{EXT,texture_rg} + * @requires_gles30 %Extension @es_extension{EXT,texture_rg} in OpenGL ES + * 2.0 */ #ifndef MAGNUM_TARGET_GLES2 RG8 = GL_RG8, @@ -99,6 +101,7 @@ enum class RenderbufferFormat: GLenum { /** * RGBA, each component normalized unsigned byte. * @requires_gles30 %Extension @es_extension{ARM,rgba8} or @es_extension{OES,rgb8_rgba8} + * in OpenGL ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 RGBA8 = GL_RGBA8, @@ -372,7 +375,7 @@ enum class RenderbufferFormat: GLenum { /** * sRGBA, each component normalized unsigned byte. - * @requires_gles30 %Extension @es_extension{EXT,sRGB} + * @requires_gles30 %Extension @es_extension{EXT,sRGB} in OpenGL ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 SRGB8Alpha8 = GL_SRGB8_ALPHA8, @@ -396,7 +399,7 @@ enum class RenderbufferFormat: GLenum { /** * Depth component, 24bit. - * @requires_gles30 %Extension @es_extension{OES,depth24} + * @requires_gles30 %Extension @es_extension{OES,depth24} in OpenGL ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 DepthComponent24 = GL_DEPTH_COMPONENT24, @@ -475,7 +478,8 @@ enum class RenderbufferFormat: GLenum { /** * 24bit depth and 8bit stencil component. - * @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} + * @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} in + * OpenGL ES 2.0 */ #ifdef MAGNUM_TARGET_GLES2 Depth24Stencil8 = GL_DEPTH24_STENCIL8_OES diff --git a/src/Magnum/Renderer.h b/src/Magnum/Renderer.h index 439fdd626..d36e956b5 100644 --- a/src/Magnum/Renderer.h +++ b/src/Magnum/Renderer.h @@ -233,6 +233,7 @@ class MAGNUM_EXPORT Renderer { /** * Accuracy of derivative calculation in fragment shader. * @requires_gles30 %Extension @es_extension{OES,standard_derivatives} + * in OpenGL ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 FragmentShaderDerivative = GL_FRAGMENT_SHADER_DERIVATIVE_HINT @@ -643,12 +644,14 @@ class MAGNUM_EXPORT Renderer { /** * `min(source, destination)` * @requires_gles30 %Extension @es_extension2{EXT,blend_minmax,blend_minmax} + * in OpenGL ES 2.0 */ Min = GL_MIN, /** * `max(source, destination)` * @requires_gles30 %Extension @es_extension2{EXT,blend_minmax,blend_minmax} + * in OpenGL ES 2.0 */ Max = GL_MAX #endif diff --git a/src/Magnum/Sampler.h b/src/Magnum/Sampler.h index cb0b1ed9c..b2c6e995a 100644 --- a/src/Magnum/Sampler.h +++ b/src/Magnum/Sampler.h @@ -57,7 +57,7 @@ class MAGNUM_EXPORT Sampler { * for linear interpolation of textures with * @ref Magnum::TextureFormat "TextureFormat::HalfFloat" / * @ref Magnum::TextureFormat "TextureFormat::Float" in OpenGL - * ES 2.0. + * ES 2.0 */ Linear = GL_LINEAR }; @@ -83,7 +83,7 @@ class MAGNUM_EXPORT Sampler { * for linear interpolation of textures with * @ref Magnum::TextureFormat "TextureFormat::HalfFloat" / * @ref Magnum::TextureFormat "TextureFormat::Float" in OpenGL - * ES 2.0. + * ES 2.0 */ Linear = GL_NEAREST_MIPMAP_LINEAR & ~GL_NEAREST }; diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 3beb01e88..b7fc72b68 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -89,7 +89,8 @@ the texture is used via `sampler1D`/`sampler2D`/`sampler3D`, See @ref AbstractShaderProgram documentation for more information about usage in shaders. -@requires_gles30 %Extension @es_extension{OES,texture_3D} for 3D textures. +@requires_gles30 %Extension @es_extension{OES,texture_3D} for 3D textures in + OpenGL ES 2.0 @requires_gl 1D textures are not available in OpenGL ES, only 2D and 3D ones. @see @ref Texture1D, @ref Texture2D, @ref Texture3D, @ref TextureArray, @@ -494,7 +495,7 @@ typedef Texture<2> Texture2D; /** @brief Three-dimensional texture -@requires_gles30 %Extension @es_extension{OES,texture_3D} +@requires_gles30 %Extension @es_extension{OES,texture_3D} in OpenGL ES 2.0 */ typedef Texture<3> Texture3D; diff --git a/src/Magnum/TextureFormat.h b/src/Magnum/TextureFormat.h index a9a358b7d..a1387b240 100644 --- a/src/Magnum/TextureFormat.h +++ b/src/Magnum/TextureFormat.h @@ -53,7 +53,8 @@ enum class TextureFormat: GLenum { * @deprecated_gl Prefer to use the exactly specified version of this * format, e.g. @ref Magnum::TextureFormat::R8 "TextureFormat::R8". * @requires_gl30 %Extension @extension{ARB,texture_rg} - * @requires_gles30 %Extension @es_extension{EXT,texture_rg} + * @requires_gles30 %Extension @es_extension{EXT,texture_rg} in OpenGL ES + * 2.0 */ #ifndef MAGNUM_TARGET_GLES2 Red = GL_RED, @@ -78,7 +79,8 @@ enum class TextureFormat: GLenum { * @deprecated_gl Prefer to use the exactly specified version of this * format, e.g. @ref Magnum::TextureFormat::RG8 "TextureFormat::RG8". * @requires_gl30 %Extension @extension{ARB,texture_rg} - * @requires_gles30 %Extension @es_extension{EXT,texture_rg} + * @requires_gles30 %Extension @es_extension{EXT,texture_rg} in OpenGL ES + * 2.0 */ #ifndef MAGNUM_TARGET_GLES2 RG = GL_RG, @@ -107,6 +109,7 @@ enum class TextureFormat: GLenum { /** * RGB, each component normalized unsigned byte. * @requires_gles30 %Extension @es_extension{OES,required_internalformat} + * in OpenGL ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 RGB8 = GL_RGB8, @@ -125,6 +128,7 @@ enum class TextureFormat: GLenum { /** * RGBA, each component normalized unsigned byte. * @requires_gles30 %Extension @es_extension{OES,required_internalformat} + * in OpenGL ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 RGBA8 = GL_RGBA8, @@ -532,6 +536,7 @@ enum class TextureFormat: GLenum { /** * RGB, normalized unsigned, red and blue component 5bit, green 6bit. * @requires_gles30 %Extension @es_extension{OES,required_internalformat} + * in OpenGL ES 2.0 */ RGB565 = GL_RGB565, @@ -605,19 +610,21 @@ enum class TextureFormat: GLenum { /** * RGBA, normalized unsigned, each component 4bit. * @requires_gles30 %Extension @es_extension{OES,required_internalformat} + * in OpenGL ES 2.0 */ RGBA4 = GL_RGBA4, /** * RGBA, normalized unsigned, each RGB component 5bit, alpha 1bit. * @requires_gles30 %Extension @es_extension{OES,required_internalformat} + * in OpenGL ES 2.0 */ RGB5A1 = GL_RGB5_A1, /** * RGBA, normalized unsigned, each RGB component 10bit, alpha 2bit. * @requires_gles30 %Extension @es_extension{OES,required_internalformat} - * and @es_extension{EXT,texture_type_2_10_10_10_REV} + * and @es_extension{EXT,texture_type_2_10_10_10_REV} in OpenGL ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 RGB10A2 = GL_RGB10_A2, @@ -756,7 +763,7 @@ enum class TextureFormat: GLenum { * @deprecated_gl Prefer to use the exactly specified version of this * format, e.g. @ref Magnum::TextureFormat::DepthComponent16 "TextureFormat::DepthComponent16". * @requires_gles30 %Extension @es_extension{OES,depth_texture} or - * @es_extension{ANGLE,depth_texture} + * @es_extension{ANGLE,depth_texture} in OpenGL ES 2.0 */ DepthComponent = GL_DEPTH_COMPONENT, @@ -764,14 +771,15 @@ enum class TextureFormat: GLenum { * Depth component, 16bit. Not supported in 3D textures. * @requires_gles30 %Extension (@es_extension{OES,required_internalformat} * and @es_extension{OES,depth_texture}) or (@es_extension{EXT,texture_storage} - * and @es_extension{ANGLE,depth_texture}) + * and @es_extension{ANGLE,depth_texture}) in OpenGL ES 2.0 */ DepthComponent16 = GL_DEPTH_COMPONENT16, /** * Depth component, 24bit. Not supported in 3D textures. * @requires_gles30 %Extension @es_extension{OES,required_internalformat}, - * @es_extension{OES,depth_texture} and @es_extension{OES,depth24} + * @es_extension{OES,depth_texture} and @es_extension{OES,depth24} in + * OpenGL ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 DepthComponent24 = GL_DEPTH_COMPONENT24, @@ -816,7 +824,8 @@ enum class TextureFormat: GLenum { * @ref Texture::setStorage() "*Texture::setStorage()" calls. * @deprecated_gl Prefer to use exactly specified version of this format, * e.g. @ref Magnum::TextureFormat::Depth24Stencil8 "TextureFormat::Depth24Stencil8". - * @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} + * @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} or + * @es_extension{ANGLE,depth_texture} in OpenGL ES 2.0 */ #ifndef MAGNUM_TARGET_GLES2 DepthStencil = GL_DEPTH_STENCIL, @@ -830,6 +839,7 @@ enum class TextureFormat: GLenum { * @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} and * (@es_extension{OES,required_internalformat} or * (@es_extension{EXT,texture_storage} and @es_extension{ANGLE,depth_texture})) + * in OpenGL ES 2.0 */ #ifdef MAGNUM_TARGET_GLES2 Depth24Stencil8 = GL_DEPTH24_STENCIL8_OES From 529513d5364185391451cf880c5a508e60b3a940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 29 Jan 2014 15:22:12 +0100 Subject: [PATCH 41/86] Removed redundant `Buffer` suffixes from FramebufferBlit enum. The old values are now aliases to new ones, are marked as deprecated and will be removed in future release. --- src/Magnum/AbstractFramebuffer.h | 30 ++++++++++++++++++++------- src/Magnum/Test/FramebufferGLTest.cpp | 2 +- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/Magnum/AbstractFramebuffer.h b/src/Magnum/AbstractFramebuffer.h index d74b0656a..f375e49a8 100644 --- a/src/Magnum/AbstractFramebuffer.h +++ b/src/Magnum/AbstractFramebuffer.h @@ -43,9 +43,9 @@ namespace Magnum { @see @ref AbstractFramebuffer, @ref FramebufferClearMask */ enum class FramebufferClear: GLbitfield { - Color = GL_COLOR_BUFFER_BIT, /**< Color */ - Depth = GL_DEPTH_BUFFER_BIT, /**< Depth value */ - Stencil = GL_STENCIL_BUFFER_BIT /**< Stencil value */ + Color = GL_COLOR_BUFFER_BIT, /**< Color buffer */ + Depth = GL_DEPTH_BUFFER_BIT, /**< Depth buffer */ + Stencil = GL_STENCIL_BUFFER_BIT /**< Stencil buffer */ }; /** @@ -63,12 +63,28 @@ typedef Containers::EnumSet()[0], Color4ub()); /* And have given color after */ - Framebuffer::blit(a, b, a.viewport(), FramebufferBlit::ColorBuffer); + Framebuffer::blit(a, b, a.viewport(), FramebufferBlit::Color); b.read({}, Vector2i(1), image); MAGNUM_VERIFY_NO_ERROR(); From 8b209a24ba005ffb00d8b6016bf5470dc229f1eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 30 Jan 2014 00:05:55 +0100 Subject: [PATCH 42/86] Audio: use std::reference_wrapper instead of pointers. I'm still learning. --- src/Magnum/Audio/Source.cpp | 53 ++++++++++++++---- src/Magnum/Audio/Source.h | 105 +++++++++++++++++++++++++----------- 2 files changed, 118 insertions(+), 40 deletions(-) diff --git a/src/Magnum/Audio/Source.cpp b/src/Magnum/Audio/Source.cpp index ab0fadf90..229b65dc6 100644 --- a/src/Magnum/Audio/Source.cpp +++ b/src/Magnum/Audio/Source.cpp @@ -40,15 +40,21 @@ Source& Source::setBuffer(Buffer* buffer) { namespace { -Containers::Array sourceIds(const std::initializer_list& sources) { +Containers::Array sourceIds(const std::initializer_list>& sources) { Containers::Array ids(sources.size()); - for(auto it = sources.begin(); it != sources.end(); ++it) { - CORRADE_INTERNAL_ASSERT(*it); - ids[it-sources.begin()] = (*it)->id(); - } + for(auto it = sources.begin(); it != sources.end(); ++it) + ids[it-sources.begin()] = it->get().id(); + return ids; +} + +Containers::Array sourceIds(const std::vector>& sources) { + Containers::Array ids(sources.size()); + for(auto it = sources.begin(); it != sources.end(); ++it) + ids[it-sources.begin()] = it->get().id(); return ids; } +#ifdef MAGNUM_BUILD_DEPRECATED Containers::Array sourceIds(const std::vector& sources) { Containers::Array ids(sources.size()); for(auto it = sources.begin(); it != sources.end(); ++it) { @@ -57,48 +63,77 @@ Containers::Array sourceIds(const std::vector& sources) { } return ids; } +#endif + +} +void Source::play(std::initializer_list> sources) { + const auto ids = sourceIds(sources); + alSourcePlayv(ids.size(), ids); } -void Source::play(std::initializer_list sources) { +void Source::play(const std::vector>& sources) { const auto ids = sourceIds(sources); alSourcePlayv(ids.size(), ids); } +#ifdef MAGNUM_BUILD_DEPRECATED void Source::play(const std::vector& sources) { const auto ids = sourceIds(sources); alSourcePlayv(ids.size(), ids); } +#endif -void Source::pause(std::initializer_list sources) { +void Source::pause(std::initializer_list> sources) { const auto ids = sourceIds(sources); alSourcePausev(ids.size(), ids); } +void Source::pause(const std::vector>& sources) { + const auto ids = sourceIds(sources); + alSourcePausev(ids.size(), ids); +} + +#ifdef MAGNUM_BUILD_DEPRECATED void Source::pause(const std::vector& sources) { const auto ids = sourceIds(sources); alSourcePausev(ids.size(), ids); } +#endif + +void Source::stop(std::initializer_list> sources) { + const auto ids = sourceIds(sources); + alSourceStopv(ids.size(), ids); +} -void Source::stop(std::initializer_list sources) { +void Source::stop(const std::vector>& sources) { const auto ids = sourceIds(sources); alSourceStopv(ids.size(), ids); } +#ifdef MAGNUM_BUILD_DEPRECATED void Source::stop(const std::vector& sources) { const auto ids = sourceIds(sources); alSourceStopv(ids.size(), ids); } +#endif + +void Source::rewind(std::initializer_list> sources) { + const auto ids = sourceIds(sources); + alSourceRewindv(ids.size(), ids); +} -void Source::rewind(std::initializer_list sources) { +void Source::rewind(const std::vector>& sources) { const auto ids = sourceIds(sources); alSourceRewindv(ids.size(), ids); } +#ifdef MAGNUM_BUILD_DEPRECATED void Source::rewind(const std::vector& sources) { const auto ids = sourceIds(sources); alSourceRewindv(ids.size(), ids); } +#endif Debug operator<<(Debug debug, const Source::State value) { switch(value) { diff --git a/src/Magnum/Audio/Source.h b/src/Magnum/Audio/Source.h index 5597fdd2a..33fe1d3e7 100644 --- a/src/Magnum/Audio/Source.h +++ b/src/Magnum/Audio/Source.h @@ -29,6 +29,7 @@ * @brief Class Magnum::Audio::Source */ +#include #include #include #include @@ -377,52 +378,90 @@ class MAGNUM_AUDIO_EXPORT Source { * * The operation is guaranteed to be done for all sources at the same * time. `nullptr` is not allowed. - * @see @ref play(), @ref pause(std::initializer_list), - * @ref stop(std::initializer_list), - * @ref rewind(std::initializer_list), + * @see @ref play(), @ref pause(std::initializer_list>), + * @ref stop(std::initializer_list>), + * @ref rewind(std::initializer_list>), * @fn_al{SourcePlayv} */ - static void play(std::initializer_list sources); - static void play(const std::vector& sources); /**< @overload */ + static void play(std::initializer_list> sources); + static void play(const std::vector>& sources); /**< @overload */ + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief play(const std::vector>&) + * @deprecated Use @ref Magnum::Audio::Source::play(const std::>&) "play(const std::vector>&)" instead. + */ + static CORRADE_DEPRECATED("use play(const std::vector>&) instead") void play(const std::vector& sources); + #endif /** * @brief Pause more sources at once * * The operation is guaranteed to be done for all sources at the same - * time. `nullptr` is not allowed. - * @see @ref pause(), @ref play(std::initializer_list), - * @ref stop(std::initializer_list), - * @ref rewind(std::initializer_list), + * time. + * @see @ref pause(), @ref play(std::initializer_list>), + * @ref stop(std::initializer_list>), + * @ref rewind(std::initializer_list>), * @fn_al{SourcePausev} */ - static void pause(std::initializer_list sources); - static void pause(const std::vector& sources); /**< @overload */ + static void pause(std::initializer_list> sources); + static void pause(const std::vector>& sources); /**< @overload */ + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief pause(const std::vector>&) + * @deprecated Use @ref Magnum::Audio::Source::pause(const std::>&) "pause(const std::vector>&)" instead. + */ + static CORRADE_DEPRECATED("use pause(const std::vector>&) instead") void pause(const std::vector& sources); + #endif /** * @brief Stop more sources at once * * The operation is guaranteed to be done for all sources at the same - * time. `nullptr` is not allowed. - * @see @ref stop(), @ref play(std::initializer_list), - * @ref pause(std::initializer_list), - * @ref rewind(std::initializer_list), + * time. + * @see @ref stop(), @ref play(std::initializer_list>), + * @ref pause(std::initializer_list>), + * @ref rewind(std::initializer_list>), * @fn_al{SourceStopv} */ - static void stop(std::initializer_list sources); - static void stop(const std::vector& sources); /**< @overload */ + static void stop(std::initializer_list> sources); + static void stop(const std::vector>& sources); /**< @overload */ + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief stop(const std::vector>&) + * @deprecated Use @ref Magnum::Audio::Source::stop(const std::>&) "stop(const std::vector>&)" instead. + */ + static CORRADE_DEPRECATED("use stop(const std::vector>&) instead") void stop(const std::vector& sources); + #endif /** * @brief Rewind more sources at once * * The operation is guaranteed to be done for all sources at the same - * time. `nullptr` is not allowed. - * @see @ref rewind(), @ref play(std::initializer_list), - * @ref pause(std::initializer_list), - * @ref stop(std::initializer_list), + * time. + * @see @ref rewind(), @ref play(std::initializer_list>), + * @ref pause(std::initializer_list>), + * @ref stop(std::initializer_list>), * @fn_al{SourceRewindv} */ - static void rewind(std::initializer_list sources); - static void rewind(const std::vector& sources); /**< @overload */ + static void rewind(std::initializer_list> sources); + static void rewind(const std::vector>& sources); /**< @overload */ + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief rewind(std::initializer_list>) + * @deprecated Use @ref Magnum::Audio::Source::rewind(std::initializer_list>) "rewind(std::initializer_list>)" instead. + */ + static CORRADE_DEPRECATED("use rewind(std::initializer_list>) instead") void rewind(std::initializer_list sources); + + /** + * @copybrief rewind(const std::vector>&) + * @deprecated Use @ref Magnum::Audio::Source::rewind(const std::>&) "rewind(const std::vector>&)" instead. + */ + static CORRADE_DEPRECATED("use rewind(const std::vector>&) instead") void rewind(const std::vector& sources); + #endif /** * @brief State @@ -435,32 +474,36 @@ class MAGNUM_AUDIO_EXPORT Source { /** * @brief Play * - * @see @ref play(std::initializer_list), @ref state(), - * @ref pause(), @ref stop(), @ref rewind(), @fn_al{SourcePlay} + * @see @ref play(std::initializer_list>), + * @ref state(), @ref pause(), @ref stop(), @ref rewind(), + * @fn_al{SourcePlay} */ void play() { alSourcePlay(_id); } /** * @brief Pause * - * @see @ref pause(std::initializer_list), @ref state(), - * @ref play(), @ref stop(), @ref rewind(), @fn_al{SourcePause} + * @see @ref pause(std::initializer_list>), + * @ref state(), @ref play(), @ref stop(), @ref rewind(), + * @fn_al{SourcePause} */ void pause() { alSourcePause(_id); } /** * @brief Stop * - * @see @ref stop(std::initializer_list), @ref state(), - * @ref play(), @ref pause(), @ref rewind(), @fn_al{SourceStop} + * @see @ref stop(std::initializer_list>), + * @ref state(), @ref play(), @ref pause(), @ref rewind(), + * @fn_al{SourceStop} */ void stop() { alSourceStop(_id); } /** * @brief Rewind * - * @see @ref rewind(std::initializer_list), @ref state(), - * @ref play(), @ref pause(), @ref stop(), @fn_al{SourceRewind} + * @see @ref rewind(std::initializer_list>), + * @ref state(), @ref play(), @ref pause(), @ref stop(), + * @fn_al{SourceRewind} */ void rewind() { alSourceRewind(_id); } From d19b3837fe3fbe701e9473926b6471b7f664e20e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 30 Jan 2014 00:34:13 +0100 Subject: [PATCH 43/86] MeshTools: reworked combineIndexedArrays(). Added combineIndexArrays() function, which can combine any number of indexarrays (i.e. number specified at runtime). The function originated in ColladaImporter plugin and is moved here to make it useful elsewhere. It is now used as base for combineIndexedArrays(), which is further simplified without unnecessary functor-like implementation. Also improved documentation. The combineIndexedArrays() function now takes std::pair instead of std::tuple, the previous version is alias to the new one, is marked as deprecated and will be removed in some future release. --- src/Magnum/MeshTools/CMakeLists.txt | 1 + src/Magnum/MeshTools/CombineIndexedArrays.cpp | 159 ++++++++++++++++ src/Magnum/MeshTools/CombineIndexedArrays.h | 173 +++++++++++------- src/Magnum/MeshTools/Test/CMakeLists.txt | 2 +- .../Test/CombineIndexedArraysTest.cpp | 36 ++-- 5 files changed, 294 insertions(+), 77 deletions(-) create mode 100644 src/Magnum/MeshTools/CombineIndexedArrays.cpp diff --git a/src/Magnum/MeshTools/CMakeLists.txt b/src/Magnum/MeshTools/CMakeLists.txt index 7a1033dfc..f4e9587e2 100644 --- a/src/Magnum/MeshTools/CMakeLists.txt +++ b/src/Magnum/MeshTools/CMakeLists.txt @@ -31,6 +31,7 @@ set(MagnumMeshTools_SRCS # Files compiled with different flags for main library and unit test library set(MagnumMeshTools_GracefulAssert_SRCS + CombineIndexedArrays.cpp FlipNormals.cpp GenerateFlatNormals.cpp) diff --git a/src/Magnum/MeshTools/CombineIndexedArrays.cpp b/src/Magnum/MeshTools/CombineIndexedArrays.cpp new file mode 100644 index 000000000..57e918e8b --- /dev/null +++ b/src/Magnum/MeshTools/CombineIndexedArrays.cpp @@ -0,0 +1,159 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "CombineIndexedArrays.h" + +#include +#include +#include +#include + +#include "Magnum/Magnum.h" + +namespace Magnum { namespace MeshTools { + +namespace Implementation { + +std::pair, std::vector> interleaveAndCombineIndexArrays(const std::reference_wrapper>* begin, const std::reference_wrapper>* end) { + /* Array stride and size */ + const UnsignedInt stride = end - begin; + const UnsignedInt inputSize = begin->get().size(); + #ifndef CORRADE_NO_ASSERT + for(auto it = begin; it != end; ++it) + CORRADE_ASSERT(it->get().size() == inputSize, "MeshTools::combineIndexArrays(): the arrays don't have the same size", {}); + #endif + + /* Interleave the arrays */ + std::vector interleavedArrays; + interleavedArrays.resize(inputSize*stride); + for(UnsignedInt offset = 0; offset != stride; ++offset) { + const auto& array = (begin+offset)->get(); + for(UnsignedInt i = 0; i != inputSize; ++i) + interleavedArrays[offset + i*stride] = array[i]; + } + + /* Combine them */ + std::vector combinedIndices; + std::tie(combinedIndices, interleavedArrays) = combineIndexArrays(interleavedArrays, stride); + return {combinedIndices, interleavedArrays}; +} + +} + +std::vector combineIndexArrays(const std::initializer_list>> arrays) { + /* Interleave and combine the arrays */ + std::vector combinedIndices; + std::vector interleavedCombinedArrays; + std::tie(combinedIndices, interleavedCombinedArrays) = Implementation::interleaveAndCombineIndexArrays( + /* This will bite me hard once. */ + reinterpret_cast>*>(arrays.begin()), + reinterpret_cast>*>(arrays.end())); + + /* Update the original indices */ + const UnsignedInt stride = arrays.size(); + const UnsignedInt outputSize = interleavedCombinedArrays.size()/stride; + for(UnsignedInt offset = 0; offset != stride; ++offset) { + auto& array = (arrays.begin()+offset)->get(); + CORRADE_INTERNAL_ASSERT(array.size() >= outputSize); + array.resize(outputSize); + for(UnsignedInt i = 0; i != outputSize; ++i) + array[i] = interleavedCombinedArrays[offset + i*stride]; + } + + return combinedIndices; +} + +namespace { + +class IndexHash { + public: + explicit IndexHash(const std::vector& indices, UnsignedInt stride): indices(indices), stride(stride) {} + + std::size_t operator()(UnsignedInt key) const { + return *reinterpret_cast(Utility::MurmurHash2()(reinterpret_cast(indices.data()+key*stride), sizeof(UnsignedInt)*stride).byteArray()); + } + + private: + const std::vector& indices; + UnsignedInt stride; +}; + +class IndexEqual { + public: + explicit IndexEqual(const std::vector& indices, UnsignedInt stride): indices(indices), stride(stride) {} + + bool operator()(UnsignedInt a, UnsignedInt b) const { + return std::memcmp(indices.data()+a*stride, indices.data()+b*stride, sizeof(UnsignedInt)*stride) == 0; + } + + private: + const std::vector& indices; + UnsignedInt stride; +}; + +} + +std::pair, std::vector> combineIndexArrays(const std::vector& interleavedArrays, const UnsignedInt stride) { + CORRADE_ASSERT(interleavedArrays.size() % stride == 0, "MeshTools::combineIndexArrays(): array size is not divisible by stride", {}); + + /* Hash map with index combinations, containing just indices into + interleavedArrays vector, hashing and comparison is done using IndexHash + and IndexEqual functors. Reserving more buckets than necessary (i.e. as + if each combination was unique). */ + std::unordered_map indexCombinations( + interleavedArrays.size()/stride, + IndexHash(interleavedArrays, stride), + IndexEqual(interleavedArrays, stride)); + + /* Make the index combinations unique. Original indices into original + `interleavedArrays` array were 0, 1, 2, 3, ..., `combinedIndices` + contains new ones into new (shorter) `newInterleavedArrays` array. */ + std::vector combinedIndices; + combinedIndices.reserve(interleavedArrays.size()/stride); + std::vector newInterleavedArrays; + for(std::size_t oldIndex = 0, end = interleavedArrays.size()/stride; oldIndex != end; ++oldIndex) { + /* Try to insert new index combination to the map */ + #ifndef CORRADE_GCC46_COMPATIBILITY + const auto result = indexCombinations.emplace(oldIndex, indexCombinations.size()); + #else + const auto result = indexCombinations.insert({oldIndex, indexCombinations.size()}); + #endif + + /* Add the (either new or already existing) index to resulting index array */ + combinedIndices.push_back(result.first->second); + + /* If this is new combination, copy it to new interleaved arrays */ + if(result.second) newInterleavedArrays.insert(newInterleavedArrays.end(), + interleavedArrays.begin()+oldIndex*stride, + interleavedArrays.begin()+(oldIndex+1)*stride); + } + + CORRADE_INTERNAL_ASSERT(combinedIndices.size() == interleavedArrays.size()/stride && + newInterleavedArrays.size() <= interleavedArrays.size()); + + return {std::move(combinedIndices), std::move(newInterleavedArrays)}; +} + +}} diff --git a/src/Magnum/MeshTools/CombineIndexedArrays.h b/src/Magnum/MeshTools/CombineIndexedArrays.h index 6af94c479..8c5ae946f 100644 --- a/src/Magnum/MeshTools/CombineIndexedArrays.h +++ b/src/Magnum/MeshTools/CombineIndexedArrays.h @@ -26,74 +26,105 @@ */ /** @file - * @brief Function Magnum::MeshTools::combineIndexedArrays() + * @brief Function @ref Magnum::MeshTools::combineIndexArrays(), @ref Magnum::MeshTools::combineIndexedArrays() */ -#include -#include +#include #include +#include -#include "Magnum/Math/Vector.h" -#include "Magnum/MeshTools/RemoveDuplicates.h" +#include "Magnum/Types.h" +#include "Magnum/MeshTools/visibility.h" + +#ifdef MAGNUM_BUILD_DEPRECATED +#include +#endif namespace Magnum { namespace MeshTools { -namespace Implementation { +/** +@brief Combine index arrays + +Creates new combined index array and updates the original ones with translation +to new ones. For example, when you have position and normal array, each indexed +with separate indices and you want to index both of them with single index +array: + + a b c d e f // positions + A B C D E F G // normals + + 0 2 5 0 0 1 3 2 2 // position indices + 1 3 4 1 4 6 1 3 1 // normal indices + +In particular, first triangle in the mesh will have positions `a c f` and +normals `B D E`. You can see that not all combinations are unique and also that +there are some vertices unused. When you pass the two index arrays above to +this function, the following combined index array is returned: + + 0 1 2 0 3 4 5 1 6 + +And the original arrays are cleaned up to have only unique combinations: + + 0 2 5 0 1 3 2 + 1 3 4 4 6 1 1 + +You can use these as translation table to create new vertex and normal arrays +which can be then indexed with the combined index array: + + a c f a b d c + B D E E G B B -class CombineIndexedArrays { - public: - template std::vector operator()(const std::tuple&, std::vector&>&... indexedArrays) { - /* Compute index count */ - std::size_t _indexCount = indexCount(std::get<0>(indexedArrays)...); +Again, first triangle in the mesh will have positions `a c f` and normals +`B D E`. - /* Resulting index array */ - std::vector result; - result.resize(_indexCount); - std::iota(result.begin(), result.end(), 0); +This function calls @ref combineIndexArrays(std::vector&, UnsignedInt) +internally. See also @ref combineIndexedArrays() which does the vertex data +reordering automatically. +*/ +MAGNUM_MESHTOOLS_EXPORT std::vector combineIndexArrays(std::initializer_list>> arrays); + +/** +@brief Combine index arrays + +Unlike above, this function takes one interleaved array instead of separate +index arrays. Continuing with the above example, you would call this function +with the following array (odd value is vertex index, even is normal index, +@p stride is thus 2): - /* All index combinations */ - std::vector > indexCombinations(_indexCount); - writeCombinedIndices(indexCombinations, std::get<0>(indexedArrays)...); + 0 1 2 3 5 4 0 1 0 4 1 6 3 1 2 3 2 1 - /* Make the combinations unique */ - MeshTools::removeDuplicates(result, indexCombinations); +Similarly to above this function will return the following combined index +array as first pair value: - /* Write combined arrays */ - writeCombinedArrays(indexCombinations, std::get<1>(indexedArrays)...); + 0 1 2 0 3 4 5 1 6 - return result; - } +And second pair value is the cleaned up interleaved array: - private: - template static std::size_t indexCount(const std::vector& first, const std::vector&... next) { - CORRADE_ASSERT(sizeof...(next) == 0 || indexCount(next...) == first.size(), "MeshTools::combineIndexedArrays(): index arrays don't have the same length, nothing done.", 0); + 0 1 2 3 5 4 0 4 1 6 3 1 2 1 - return first.size(); - } +@see @ref combineIndexedArrays() +*/ +MAGNUM_MESHTOOLS_EXPORT std::pair, std::vector> combineIndexArrays(const std::vector& interleavedArrays, UnsignedInt stride); - template static void writeCombinedIndices(std::vector>& output, const std::vector& first, const std::vector&... next) { - /* Copy the data to output */ - for(std::size_t i = 0; i != output.size(); ++i) - output[i][size-sizeof...(next)-1] = first[i]; +namespace Implementation { - writeCombinedIndices(output, next...); - } +MAGNUM_MESHTOOLS_EXPORT std::pair, std::vector> interleaveAndCombineIndexArrays(const std::reference_wrapper>* begin, const std::reference_wrapper>* end); - template static void writeCombinedArrays(const std::vector>& combinedIndices, std::vector& first, std::vector&... next) { - /* Rewrite output array */ - std::vector output; - for(std::size_t i = 0; i != combinedIndices.size(); ++i) - output.push_back(first[combinedIndices[i][size-sizeof...(next)-1]]); - std::swap(output, first); +template void writeCombinedArray(const UnsignedInt stride, const UnsignedInt offset, const std::vector& interleavedCombinedIndexArrays, std::vector& array) { + std::vector output; + output.reserve(interleavedCombinedIndexArrays.size()/stride); + for(std::size_t i = 0, max = interleavedCombinedIndexArrays.size()/stride; i != max; ++i) + output.push_back(array[interleavedCombinedIndexArrays[offset + i*stride]]); + std::swap(output, array); +} - writeCombinedArrays(combinedIndices, next...); - } +/* Terminator for recursive calls */ +inline void writeCombinedArrays(UnsignedInt, UnsignedInt, const std::vector&) {} - /* Terminator functions for recursive calls */ - static std::size_t indexCount() { return 0; } - template static void writeCombinedIndices(std::vector>&) {} - template static void writeCombinedArrays(const std::vector>&) {} -}; +template inline void writeCombinedArrays(UnsignedInt stride, UnsignedInt offset, const std::vector& interleavedCombinedIndexArrays, std::vector& first, std::vector&... next) { + writeCombinedArray(stride, offset, interleavedCombinedIndexArrays, first); + writeCombinedArrays(stride, offset + 1, interleavedCombinedIndexArrays, next...); +} } @@ -102,15 +133,13 @@ class CombineIndexedArrays { @param[in,out] indexedArrays Index and attribute arrays @return %Array with resulting indices -When you have e.g. vertex, normal and texture array, each indexed with -different indices, you can use this function to combine them to use the same -indices. The function returns array with resulting indices and replaces -original attribute arrays with combined ones. +Creates new combined index array and reorders original attribute arrays so they +can be indexed with the new single index array. The index array must be passed as const reference (to avoid copying) and attribute array as reference, so it can be replaced with combined data. To avoid explicit verbose specification of tuple type, you can write it with help -of some STL functions like shown below. Also if one index array is shader by +of some STL functions like shown below. Also if one index array is shared by more than one attribute array, just pass the index array more times. Example: @code std::vector vertexIndices; @@ -120,25 +149,43 @@ std::vector normals; std::vector textureCoordinates; std::vector indices = MeshTools::combineIndexedArrays( - std::make_tuple(std::cref(vertexIndices), std::ref(positions)), - std::make_tuple(std::cref(normalTextureIndices), std::ref(normals)), - std::make_tuple(std::cref(normalTextureIndices), std::ref(textureCoordinates)) + std::make_pair(std::cref(vertexIndices), std::ref(positions)), + std::make_pair(std::cref(normalTextureIndices), std::ref(normals)), + std::make_pair(std::cref(normalTextureIndices), std::ref(textureCoordinates)) ); @endcode -`positions`, `normals` and `textureCoordinates` will then contain combined -attributes indexed with `indices`. -@attention The function expects that all arrays have the same size. -@todo Use `std::pair` (to avoid `std::make_tuple`), make this usable also at - runtime +See @ref combineIndexArrays() documentation for more information about the +procedure. +@todo Invent a way which avoids these overly verbose parameters (`std::pair` + doesn't help) */ /* Implementation note: It's done using tuples because it is more clear which parameter is index array and which is attribute array, mainly when both are of the same type. */ -template std::vector combineIndexedArrays(const std::tuple&, std::vector&>&... indexedArrays) { - return Implementation::CombineIndexedArrays()(indexedArrays...); +template std::vector combineIndexedArrays(const std::pair&, std::vector&>&... indexedArrays) { + /* Interleave and combine index arrays */ + std::vector combinedIndices; + std::vector interleavedCombinedIndexArrays; + auto i = {std::ref(indexedArrays.first)...}; + std::tie(combinedIndices, interleavedCombinedIndexArrays) = Implementation::interleaveAndCombineIndexArrays(i.begin(), i.end()); + + /* Write combined arrays */ + Implementation::writeCombinedArrays(sizeof...(T), 0, interleavedCombinedIndexArrays, indexedArrays.second...); + + return combinedIndices; } +#ifdef MAGNUM_BUILD_DEPRECATED +/** + * @copybrief combineIndexedArrays(const std::pair&, std::vector&>&...) + * @deprecated Use @ref Magnum::MeshTools::combineIndexedArrays(const std::pair&, std::vector&>&...) "combineIndexedArrays(const std::pair&, std::vector&>&...)" instead. + */ +template inline CORRADE_DEPRECATED("use combineIndexedArrays(const std::pair&, std::vector&>&...) instead") std::vector combineIndexedArrays(const std::tuple&, std::vector&>&... indexedArrays) { + return combineIndexedArrays(std::make_pair(std::cref(std::get<0>(indexedArrays)), std::ref(std::get<1>(indexedArrays)))...); +} +#endif + }} #endif diff --git a/src/Magnum/MeshTools/Test/CMakeLists.txt b/src/Magnum/MeshTools/Test/CMakeLists.txt index b461a79b3..aec260cae 100644 --- a/src/Magnum/MeshTools/Test/CMakeLists.txt +++ b/src/Magnum/MeshTools/Test/CMakeLists.txt @@ -23,7 +23,7 @@ # DEALINGS IN THE SOFTWARE. # -corrade_add_test(MeshToolsCombineIndexedArraysTest CombineIndexedArraysTest.cpp) +corrade_add_test(MeshToolsCombineIndexedArraysTest CombineIndexedArraysTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsCompressIndicesTest CompressIndicesTest.cpp LIBRARIES MagnumMeshTools) corrade_add_test(MeshToolsDuplicateTest DuplicateTest.cpp) corrade_add_test(MeshToolsFlipNormalsTest FlipNormalsTest.cpp LIBRARIES MagnumMeshToolsTestLib) diff --git a/src/Magnum/MeshTools/Test/CombineIndexedArraysTest.cpp b/src/Magnum/MeshTools/Test/CombineIndexedArraysTest.cpp index d5903f519..a944328f8 100644 --- a/src/Magnum/MeshTools/Test/CombineIndexedArraysTest.cpp +++ b/src/Magnum/MeshTools/Test/CombineIndexedArraysTest.cpp @@ -27,7 +27,7 @@ #include #include -#include "Magnum/Types.h" +#include "Magnum/Magnum.h" #include "Magnum/MeshTools/CombineIndexedArrays.h" namespace Magnum { namespace MeshTools { namespace Test { @@ -37,12 +37,14 @@ class CombineIndexedArraysTest: public TestSuite::Tester { CombineIndexedArraysTest(); void wrongIndexCount(); - void combine(); + void indexArrays(); + void indexedArrays(); }; CombineIndexedArraysTest::CombineIndexedArraysTest() { addTests({&CombineIndexedArraysTest::wrongIndexCount, - &CombineIndexedArraysTest::combine}); + &CombineIndexedArraysTest::indexArrays, + &CombineIndexedArraysTest::indexedArrays}); } void CombineIndexedArraysTest::wrongIndexCount() { @@ -50,16 +52,24 @@ void CombineIndexedArraysTest::wrongIndexCount() { Error::setOutput(&ss); std::vector a{0, 1, 0}; std::vector b{3, 4}; - std::vector array; - std::vector result = MeshTools::combineIndexedArrays( - std::make_tuple(std::cref(a), std::ref(array)), - std::make_tuple(std::cref(b), std::ref(array))); + std::vector result = MeshTools::combineIndexArrays({a, b}); + + CORRADE_COMPARE(ss.str(), "MeshTools::combineIndexArrays(): the arrays don't have the same size\n"); +} + +void CombineIndexedArraysTest::indexArrays() { + std::vector a{0, 1, 0}; + std::vector b{3, 4, 3}; + std::vector c{6, 7, 6}; - CORRADE_COMPARE(result.size(), 0); - CORRADE_COMPARE(ss.str(), "MeshTools::combineIndexedArrays(): index arrays don't have the same length, nothing done.\n"); + std::vector result = MeshTools::combineIndexArrays({a, b, c}); + CORRADE_COMPARE(result, (std::vector{0, 1, 0})); + CORRADE_COMPARE(a, (std::vector{0, 1})); + CORRADE_COMPARE(b, (std::vector{3, 4})); + CORRADE_COMPARE(c, (std::vector{6, 7})); } -void CombineIndexedArraysTest::combine() { +void CombineIndexedArraysTest::indexedArrays() { std::vector a{0, 1, 0}; std::vector b{3, 4, 3}; std::vector c{6, 7, 6}; @@ -68,9 +78,9 @@ void CombineIndexedArraysTest::combine() { std::vector array3{ 0, 1, 2, 3, 4, 5, 6, 7 }; std::vector result = MeshTools::combineIndexedArrays( - std::make_tuple(std::cref(a), std::ref(array1)), - std::make_tuple(std::cref(b), std::ref(array2)), - std::make_tuple(std::cref(c), std::ref(array3))); + std::make_pair(std::cref(a), std::ref(array1)), + std::make_pair(std::cref(b), std::ref(array2)), + std::make_pair(std::cref(c), std::ref(array3))); CORRADE_COMPARE(result, (std::vector{0, 1, 0})); CORRADE_COMPARE(array1, (std::vector{0, 1})); From cc1142cc1761f2454b576ce71c15b45cea9242d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 30 Jan 2014 20:13:55 +0100 Subject: [PATCH 44/86] MeshTools: reworked removeDuplicates(). It now returns new index array instead of operating on already existing one and also custom vector size is removed. The internal implementation is now much simpler and cleaner. The old way (but still without custom vector size) is now alias to the new implementation, is marked as deprecated and will be removed in future release. Renamed the parameters and reworded the documentation so it doesn't talk about vertices, but rather about generic floating-point vector data. --- src/Magnum/MeshTools/GenerateFlatNormals.cpp | 3 +- src/Magnum/MeshTools/RemoveDuplicates.h | 209 ++++++++++-------- src/Magnum/MeshTools/Test/CMakeLists.txt | 2 +- .../MeshTools/Test/RemoveDuplicatesTest.cpp | 30 ++- src/Magnum/MeshTools/Test/SubdivideTest.cpp | 5 - src/Magnum/Primitives/Icosphere.cpp | 5 +- 6 files changed, 141 insertions(+), 113 deletions(-) diff --git a/src/Magnum/MeshTools/GenerateFlatNormals.cpp b/src/Magnum/MeshTools/GenerateFlatNormals.cpp index bbda7a9b8..c4b78db09 100644 --- a/src/Magnum/MeshTools/GenerateFlatNormals.cpp +++ b/src/Magnum/MeshTools/GenerateFlatNormals.cpp @@ -26,6 +26,7 @@ #include "GenerateFlatNormals.h" #include "Magnum/Math/Vector3.h" +#include "Magnum/MeshTools/Duplicate.h" #include "Magnum/MeshTools/RemoveDuplicates.h" namespace Magnum { namespace MeshTools { @@ -50,7 +51,7 @@ std::tuple, std::vector> generateFlatNormals(c } /* Remove duplicate normals and return */ - MeshTools::removeDuplicates(normalIndices, normals); + normalIndices = MeshTools::duplicate(normalIndices, MeshTools::removeDuplicates(normals)); return std::make_tuple(std::move(normalIndices), std::move(normals)); } diff --git a/src/Magnum/MeshTools/RemoveDuplicates.h b/src/Magnum/MeshTools/RemoveDuplicates.h index 7a226aa8a..b2c58a807 100644 --- a/src/Magnum/MeshTools/RemoveDuplicates.h +++ b/src/Magnum/MeshTools/RemoveDuplicates.h @@ -26,10 +26,11 @@ */ /** @file - * @brief Function Magnum::MeshTools::removeDuplicates() + * @brief Function @ref Magnum::MeshTools::removeDuplicates() */ #include +#include #include #include #include @@ -37,120 +38,142 @@ #include "Magnum/Magnum.h" #include "Magnum/Math/Functions.h" -namespace Magnum { namespace MeshTools { - -namespace Implementation { - -template class RemoveDuplicates { - public: - RemoveDuplicates(std::vector& indices, std::vector& vertices): indices(indices), vertices(vertices) {} - - void operator()(typename Vertex::Type epsilon = Math::TypeTraits::epsilon()); - - private: - class IndexHash { - public: - std::size_t operator()(const Math::Vector& data) const { - return *reinterpret_cast(Utility::MurmurHash2()(reinterpret_cast(&data), sizeof(data)).byteArray()); - } - }; +#ifdef MAGNUM_BUILD_DEPRECATED +#include - struct HashedVertex { - UnsignedInt oldIndex, newIndex; - - HashedVertex(UnsignedInt oldIndex, UnsignedInt newIndex): oldIndex(oldIndex), newIndex(newIndex) {} - }; +#include "Magnum/MeshTools/Duplicate.h" +#endif - std::vector& indices; - std::vector& vertices; -}; +namespace Magnum { namespace MeshTools { +namespace Implementation { + template class VectorHash { + public: + std::size_t operator()(const Math::Vector& data) const { + return *reinterpret_cast(Utility::MurmurHash2()(reinterpret_cast(&data), sizeof(data)).byteArray()); + } + }; } /** -@brief %Remove duplicate vertices from the mesh -@tparam Vertex Vertex data type -@tparam vertexSize How many initial vertex fields are important (for - example, when dealing with perspective in 3D space, only first three - fields of otherwise 4D vertex are important) -@param[in,out] indices Index array to operate on -@param[in,out] vertices Vertex array to operate on -@param[in] epsilon Epsilon value, vertices nearer than this distance will - be melt together. - -Removes duplicate vertices from the mesh. -@see duplicate() - -@todo Different (no cycle) implementation for integral vertices -@todo Interpolate vertices, not collapse them to first in the cell -@todo Ability to specify other attributes for interpolation +@brief %Remove duplicate floating-point vector data from given array +@param[in,out] data Input data array +@param[out] epsilon Epsilon value, vertices nearer than this distance will be + melt together +@return Index array and unique data + +Removes duplicate data from the array by collapsing them into buckets of size +@p epsilon. First vector in given bucket is used, other ones are thrown away, +no interpolation is done. Note that this function is meant to be used for +floating-point data (or generally with non-zero @p epsilon), for discrete data +the usual sorting method is much more efficient. + +If you want to remove duplicate data from already indexed array, first remove +duplicates as if the array wasn't indexed at all and then use @ref duplicate() +to combine the two index arrays: +@code +std::vector indices; +std::vector positions; + +indices = MeshTools::duplicate(indices, MeshTools::removeDuplicates(positions)); +@endcode + +Removing duplicates in multiple indcidental arrays is also possible -- first +remove duplicates in each array separately and then use @ref combineIndexedArrays() +to combine the resulting index arrays to single index array and reorder the +data accordingly: +@code +std::vector positions; +std::vector texCoords; + +std::vector positionIndices; +std::tie(positionIndices, positions) = MeshTools::removeDuplicates(positions); + +std::vector texCoordIndices; +std::tie(texCoordIndices, texCoords) = MeshTools::removeDuplicates(texCoords); + +std::vector indices = MeshTools::combineIndexedArrays( + std::make_pair(std::cref(positionIndices), std::ref(positions)), + std::make_pair(std::cref(texCoordIndices), std::ref(texCoords)) +); +@endcode */ -template inline void removeDuplicates(std::vector& indices, std::vector& vertices, typename Vertex::Type epsilon = Math::TypeTraits::epsilon()) { - Implementation::RemoveDuplicates(indices, vertices)(epsilon); -} - -namespace Implementation { - -template void RemoveDuplicates::operator()(typename Vertex::Type epsilon) { - if(indices.empty()) return; - - /* Get mesh bounds */ - Vertex min = vertices[0], max = vertices[0]; - for(const auto& v: vertices) { +template std::vector removeDuplicates(std::vector& data, typename Vector::Type epsilon = Math::TypeTraits::epsilon()) { + /* Get bounds */ + Vector min = data[0], max = data[0]; + for(const auto& v: data) { min = Math::min(v, min); max = Math::max(v, max); } - /* Make epsilon so large that std::size_t can index all vertices inside - mesh bounds. */ - epsilon = Math::max(epsilon, static_cast((max-min).max()/std::numeric_limits::max())); - - /* First go with original vertex coordinates, then move them by - epsilon/2 in each direction. */ - Vertex moved; - for(std::size_t moving = 0; moving <= vertexSize; ++moving) { - - /* Under each index is pointer to face which contains given vertex - and index of vertex in the face. */ - std::unordered_map, HashedVertex, IndexHash> table; - - /* Reserve space for all vertices */ - table.reserve(vertices.size()); - - /* Go through all faces' vertices */ - for(auto it = indices.begin(); it != indices.end(); ++it) { - /* Index of a vertex in vertexSize-dimensional table */ - std::size_t index[vertexSize]; - for(std::size_t ii = 0; ii != vertexSize; ++ii) - index[ii] = std::size_t((vertices[*it][ii]+moved[ii]-min[ii])/epsilon); - - /* Try inserting the vertex into table, if it already - exists, change vertex pointer of the face to already - existing vertex */ - HashedVertex v(*it, table.size()); + /* Make epsilon so large that std::size_t can index all vectors inside the + bounds. */ + epsilon = Math::max(epsilon, typename Vector::Type((max-min).max()/std::numeric_limits::max())); + + /* Resulting index array */ + std::vector resultIndices(data.size()); + std::iota(resultIndices.begin(), resultIndices.end(), 0); + + /* Table containing original vector index for each discretized vector. + Reserving more buckets than necessary (i.e. as if each vector was + unique). */ + std::unordered_map, UnsignedInt, Implementation::VectorHash> table(data.size()); + + /* Index array for each pass, new data array */ + std::vector indices; + indices.reserve(data.size()); + + /* First go with original coordinates, then move them by epsilon/2 in each + direction. */ + Vector moved; + for(std::size_t moving = 0; moving <= Vector::Size; ++moving) { + /* Go through all vectors */ + for(std::size_t i = 0; i != data.size(); ++i) { + /* Try to insert new vertex to the table */ + const Math::Vector v((data[i] + moved - min)/epsilon); #ifndef CORRADE_GCC46_COMPATIBILITY - auto result = table.emplace(Math::Vector::from(index), v); + const auto result = table.emplace(v, table.size()); #else - auto result = table.insert({Math::Vector::from(index), v}); + const auto result = table.insert({v, table.size()}); #endif - *it = result.first->second.newIndex; + + /* Add the (either new or already existing) index to index array */ + indices.push_back(result.first->second); + + /* If this is new combination, copy the data to new (earlier) + possition in the array */ + if(result.second && i != table.size()-1) data[table.size()-1] = data[i]; } - /* Shrink vertices array */ - std::vector newVertices(table.size()); - for(auto it = table.cbegin(); it != table.cend(); ++it) - newVertices[it->second.newIndex] = vertices[it->second.oldIndex]; - std::swap(newVertices, vertices); + /* Shrink the data array */ + CORRADE_INTERNAL_ASSERT(data.size() >= table.size()); + data.resize(table.size()); + + /* Remap the resulting index array */ + for(auto& i: resultIndices) i = indices[i]; + + /* Finished */ + if(moving == Vector::Size) continue; /* Move vertex coordinates by epsilon/2 in next direction */ - if(moving != Vertex::Size) { - moved = Vertex(); - moved[moving] = epsilon/2; - } + moved = Vector(); + moved[moving] = epsilon/2; + + /* Clear the structures for next pass */ + table.clear(); + indices.clear(); } + + return resultIndices; } +#ifdef MAGNUM_BUILD_DEPRECATED +template void removeDuplicates(std::vector& indices, std::vector& data, typename Vector::Type epsilon = Math::TypeTraits::epsilon()) { + std::vector uniqueIndices; + std::tie(uniqueIndices, data) = removeDuplicates(data); + indices = MeshTools::duplicate(indices, uniqueIndices); } +#endif }} diff --git a/src/Magnum/MeshTools/Test/CMakeLists.txt b/src/Magnum/MeshTools/Test/CMakeLists.txt index aec260cae..ec7cfe6b9 100644 --- a/src/Magnum/MeshTools/Test/CMakeLists.txt +++ b/src/Magnum/MeshTools/Test/CMakeLists.txt @@ -29,7 +29,7 @@ corrade_add_test(MeshToolsDuplicateTest DuplicateTest.cpp) corrade_add_test(MeshToolsFlipNormalsTest FlipNormalsTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsGenerateFlatNormalsTest GenerateFlatNormalsTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsInterleaveTest InterleaveTest.cpp) -corrade_add_test(MeshToolsRemoveDuplicatesTest RemoveDuplicatesTest.cpp) +corrade_add_test(MeshToolsRemoveDuplicatesTest RemoveDuplicatesTest.cpp LIBRARIES Magnum) corrade_add_test(MeshToolsSubdivideTest SubdivideTest.cpp) # corrade_add_test(MeshToolsSubdivideRemoveDuplicatesBenchmark SubdivideRemoveDuplicatesBenchmark.h SubdivideRemoveDuplicatesBenchmark.cpp MagnumPrimitives) corrade_add_test(MeshToolsTipsifyTest TipsifyTest.cpp LIBRARIES MagnumMeshTools) diff --git a/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp b/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp index b8733fa70..c6549b48a 100644 --- a/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp +++ b/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp @@ -25,6 +25,7 @@ #include +#include "Magnum/Math/Vector2.h" #include "Magnum/MeshTools/RemoveDuplicates.h" namespace Magnum { namespace MeshTools { namespace Test { @@ -33,23 +34,30 @@ class RemoveDuplicatesTest: public TestSuite::Tester { public: RemoveDuplicatesTest(); - void cleanMesh(); + void removeDuplicates(); }; -typedef Math::Vector<1, int> Vector1; - RemoveDuplicatesTest::RemoveDuplicatesTest() { - addTests({&RemoveDuplicatesTest::cleanMesh}); + addTests({&RemoveDuplicatesTest::removeDuplicates}); } -void RemoveDuplicatesTest::cleanMesh() { - std::vector positions{1, 2, 1, 4}; - std::vector indices{0, 1, 2, 1, 2, 3}; - MeshTools::removeDuplicates(indices, positions); +void RemoveDuplicatesTest::removeDuplicates() { + /* Numbers with distance 1 should be merged, numbers with distance 2 should + be kept. Testing both even-odd and odd-even sequence to verify that + half-epsilon translations are applied properly. */ + std::vector data{ + {1, 0}, + {2, 1}, + {0, 4}, + {1, 5} + }; - /* Verify cleanup */ - CORRADE_VERIFY(positions == (std::vector{1, 2, 4})); - CORRADE_COMPARE(indices, (std::vector{0, 1, 0, 1, 0, 2})); + const std::vector indices = MeshTools::removeDuplicates(data, 2); + CORRADE_COMPARE(indices, (std::vector{0, 0, 1, 1})); + CORRADE_COMPARE(data, (std::vector{ + {1, 0}, + {0, 4} + })); } }}} diff --git a/src/Magnum/MeshTools/Test/SubdivideTest.cpp b/src/Magnum/MeshTools/Test/SubdivideTest.cpp index da5bdb7db..c4c3b928d 100644 --- a/src/Magnum/MeshTools/Test/SubdivideTest.cpp +++ b/src/Magnum/MeshTools/Test/SubdivideTest.cpp @@ -71,11 +71,6 @@ void SubdivideTest::subdivide() { CORRADE_VERIFY(positions == (std::vector{0, 2, 6, 8, 1, 4, 3, 4, 7, 5})); CORRADE_COMPARE(indices, (std::vector{4, 5, 6, 7, 8, 9, 0, 4, 6, 4, 1, 5, 6, 5, 2, 1, 7, 9, 7, 2, 8, 9, 8, 3})); - - MeshTools::removeDuplicates(indices, positions); - - /* Positions 0, 1, 2, 3, 4, 5, 6, 7, 8 */ - CORRADE_COMPARE(positions.size(), 9); } }}} diff --git a/src/Magnum/Primitives/Icosphere.cpp b/src/Magnum/Primitives/Icosphere.cpp index 0c3911331..83a3d7496 100644 --- a/src/Magnum/Primitives/Icosphere.cpp +++ b/src/Magnum/Primitives/Icosphere.cpp @@ -27,8 +27,9 @@ #include "Magnum/Mesh.h" #include "Magnum/Math/Vector3.h" -#include "Magnum/MeshTools/Subdivide.h" +#include "Magnum/MeshTools/Duplicate.h" #include "Magnum/MeshTools/RemoveDuplicates.h" +#include "Magnum/MeshTools/Subdivide.h" #include "Magnum/Trade/MeshData3D.h" namespace Magnum { namespace Primitives { @@ -77,7 +78,7 @@ Trade::MeshData3D Icosphere::solid(const UnsignedInt subdivisions) { return (a+b).normalized(); }); - MeshTools::removeDuplicates(indices, positions); + indices = MeshTools::duplicate(indices, MeshTools::removeDuplicates(positions)); std::vector normals(positions); return Trade::MeshData3D(MeshPrimitive::Triangles, std::move(indices), {std::move(positions)}, {std::move(normals)}, std::vector>{}); From 409153380ef9e9bb8a9a6d0497efe75e24b7fbf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 30 Jan 2014 20:16:22 +0100 Subject: [PATCH 45/86] MeshTools: cleaned up duplicate(). --- src/Magnum/MeshTools/Duplicate.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Magnum/MeshTools/Duplicate.h b/src/Magnum/MeshTools/Duplicate.h index 8cf5c1ebd..4d67ab583 100644 --- a/src/Magnum/MeshTools/Duplicate.h +++ b/src/Magnum/MeshTools/Duplicate.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Function Magnum::MeshTools::duplicate() + * @brief Function @ref Magnum::MeshTools::duplicate() */ #include @@ -36,18 +36,18 @@ namespace Magnum { namespace MeshTools { /** -@brief Duplicate vertices using index array +@brief Duplicate data using index array -Converts indexed array to non-indexed, for example vertices `{a, b, c, d}` with +Converts indexed array to non-indexed, for example data `{a, b, c, d}` with index array `{1, 1, 0, 3, 2, 2}` will be converted to `{b, b, a, d, c, c}`. -@see removeDuplicates() +@see @ref removeDuplicates(), @ref combineIndexedArrays() */ -template std::vector duplicate(const std::vector& indices, const std::vector& vertices) { +template std::vector duplicate(const std::vector& indices, const std::vector& data) { std::vector out; out.reserve(indices.size()); for(const UnsignedInt index: indices) - out.push_back(vertices[index]); - return std::move(out); + out.push_back(data[index]); + return out; } }} From 0ed21034119240ed64a53c218c8b4092925af9ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 30 Jan 2014 20:17:53 +0100 Subject: [PATCH 46/86] package: enable everything possible in ArchLinux PKGBUILD. Not enabling optional Platform classes, as they would introduce additional dependencies. --- package/archlinux/magnum-git/PKGBUILD | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/package/archlinux/magnum-git/PKGBUILD b/package/archlinux/magnum-git/PKGBUILD index f48968bd3..e3ca44e5f 100644 --- a/package/archlinux/magnum-git/PKGBUILD +++ b/package/archlinux/magnum-git/PKGBUILD @@ -39,9 +39,17 @@ build() { cmake ../$_gitname \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr \ + -DWITH_AUDIO=ON \ -DWITH_GLUTAPPLICATION=ON \ -DWITH_GLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \ + -DWITH_MAGNUMFONT=ON \ + -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_TGAIMAGECONVERTER=ON \ + -DWITH_TGAIMPORTER=ON \ + -DWITH_WAVAUDIOIMPORTER=ON \ + -DWITH_DISTANCEFIELDCONVERTER=ON \ + -DWITH_FONTCONVERTER=ON \ -DWITH_MAGNUMINFO=ON make } From 123a850f4bc0e4d1bdb0fb61e21f96a3ef9ff9da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 30 Jan 2014 20:21:14 +0100 Subject: [PATCH 47/86] doc: moved GL-related TODOs where they belong. --- doc/opengl-support.dox | 8 ++++++++ src/Magnum/AbstractFramebuffer.h | 1 - src/Magnum/Buffer.h | 3 --- src/Magnum/Context.h | 2 -- src/Magnum/Mesh.h | 1 - src/Magnum/Query.h | 1 - 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 41624536b..708dc15b7 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -50,6 +50,8 @@ following: @todo Replace @extension{APPLE,vertex_array_object} with ARB version (we use only ARB functions without APPLE fallback) @todo @extension{APPLE,flush_buffer_range} doesn't add anything to @extension{ARB,map_buffer_range} (remove it and leave only ARB one) @todo @extension{EXT,texture_array} overlaps with @extension{ARB,framebuffer_object} +@todo Replace @extension{NV,depth_buffer_float} with @extension{ARB,depth_buffer_float} and implement the missing @fn_gl{DepthRange} function +@todo @extension{ARB,half_float_pixel}, @extension{ARB,half_float_vertex}? %Extension | Status -------------------------------------------- | ------ @@ -191,6 +193,8 @@ following: @subsection opengl-support-44 OpenGL 4.4 +@todo Also fallback to @extension{AMD,query_buffer_object} + %Extension | Status -------------------------------------------- | ------ @extension{ARB,buffer_storage} | | @@ -204,6 +208,10 @@ following: @subsection opengl-support-extensions OpenGL extensions +@todo @extension{ARB,sparse_texture}, @extension{ARB,bindless_texture} + their vendor equivalents +@todo @extension{ATI,meminfo}, @extension{NVX,gpu_memory_info}, GPU temperature +@todo @extension{AMD,performance_monitor}, @extension{INTEL,performance_query} + %Extension | Status -------------------------------------------- | ------ @extension{AMD,vertex_shader_layer} | done (shading language only) diff --git a/src/Magnum/AbstractFramebuffer.h b/src/Magnum/AbstractFramebuffer.h index f375e49a8..1f279f9a9 100644 --- a/src/Magnum/AbstractFramebuffer.h +++ b/src/Magnum/AbstractFramebuffer.h @@ -162,7 +162,6 @@ in repeated @fn_gl{Get} calls. If @extension{ARB,robustness} is available, @ref read() operations are protected from buffer overflow. -@todo @extension{ARB,viewport_array} (and `GL_MAX_VIEWPORTS`) */ class MAGNUM_EXPORT AbstractFramebuffer { friend struct Implementation::FramebufferState; diff --git a/src/Magnum/Buffer.h b/src/Magnum/Buffer.h index 0ece23817..faed9eae9 100644 --- a/src/Magnum/Buffer.h +++ b/src/Magnum/Buffer.h @@ -187,9 +187,6 @@ don't need buffer data anymore to avoid unnecessary memory operations performed by OpenGL in order to preserve the data. If running on OpenGL ES or extension @extension{ARB,invalidate_subdata} is not available, these functions do nothing. - -@todo Support for AMD/ARB's query buffer (@extension{AMD,query_buffer_object}, @extension{ARB,query_buffer_object}) -@todo BindBufferRange/BindBufferOffset/BindBufferBase for transform feedback (3.0, @extension{EXT,transform_feedback}) */ class MAGNUM_EXPORT Buffer: public AbstractObject { friend struct Implementation::BufferState; diff --git a/src/Magnum/Context.h b/src/Magnum/Context.h index 29a806b3f..60afb96ae 100644 --- a/src/Magnum/Context.h +++ b/src/Magnum/Context.h @@ -91,8 +91,6 @@ through @ref Context::current() is automatically created during construction of *Application classes in @ref Platform namespace. You can safely assume that the instance is available during whole lifetime of *Application object. See @ref platform documentation for more information about engine setup. -@todo @extension{ATI,meminfo}, @extension{NVX,gpu_memory_info}, GPU temperature? - (here or where?) */ class MAGNUM_EXPORT Context { Context(const Context&) = delete; diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index f6d6cc37b..0d65c4151 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -310,7 +310,6 @@ If index range is specified in @ref setIndexBuffer(), range-based version of drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also @ref draw() for more information. -@todo Support for indirect draw buffer (OpenGL 4.0, @extension{ARB,draw_indirect}) @todo Redo in a way that allows glMultiDrawArrays, glDrawArraysInstanced etc. @todo How to glDrawElementsBaseVertex()/vertex offset -- in draw()? */ diff --git a/src/Magnum/Query.h b/src/Magnum/Query.h index 07a9bf3fe..4062c0513 100644 --- a/src/Magnum/Query.h +++ b/src/Magnum/Query.h @@ -41,7 +41,6 @@ namespace Magnum { See @ref PrimitiveQuery, @ref SampleQuery and @ref TimeQuery documentation for more information. -@todo Support for AMD's query buffer (@extension{AMD,query_buffer_object}) @todo `QUERY_COUNTER_BITS` (not sure since when this is supported) */ class MAGNUM_EXPORT AbstractQuery: public AbstractObject { From 3a1c776557353123e1c7affcd17a9bf712806801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 30 Jan 2014 20:45:16 +0100 Subject: [PATCH 48/86] Adapted to Corrade::PluginManager changes. --- doc/plugins.dox | 4 ---- src/Magnum/Text/fontconverter.cpp | 14 ++++---------- .../TextureTools/distancefieldconverter.cpp | 18 ++++++------------ 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/doc/plugins.dox b/doc/plugins.dox index ddc64c1db..95ab27ca7 100644 --- a/doc/plugins.dox +++ b/doc/plugins.dox @@ -120,10 +120,6 @@ lifetime of all plugin instances created from it. std::exit(1); } std::unique_ptr tgaImporter = manager.instance("TgaImporter"); - if(!tgaImporter) { - Error() << "Cannot instantiate TgaImporter plugin"; - std::exit(2); - } // Use the plugin... diff --git a/src/Magnum/Text/fontconverter.cpp b/src/Magnum/Text/fontconverter.cpp index fb7b6782b..df510b7aa 100644 --- a/src/Magnum/Text/fontconverter.cpp +++ b/src/Magnum/Text/fontconverter.cpp @@ -72,21 +72,15 @@ int FontConverter::exec() { /* Load font */ PluginManager::Manager fontManager(Utility::Directory::join(MAGNUM_PLUGINS_DIR, "fonts/")); - std::unique_ptr font; - if(!(fontManager.load(args.value("font")) & PluginManager::LoadState::Loaded) || - !(font = fontManager.instance(args.value("font")))) { - Error() << "Cannot load plugin" << args.value("font") << "from" << fontManager.pluginDirectory(); + if(!(fontManager.load(args.value("font")) & PluginManager::LoadState::Loaded)) std::exit(1); - } + std::unique_ptr font = fontManager.instance(args.value("font")); /* Load font converter */ PluginManager::Manager converterManager(Utility::Directory::join(MAGNUM_PLUGINS_DIR, "fontconverters/")); - std::unique_ptr converter; - if(!(converterManager.load(args.value("converter")) & PluginManager::LoadState::Loaded) || - !(converter = converterManager.instance(args.value("converter")))) { - Error() << "Cannot load plugin" << args.value("converter") << "from" << converterManager.pluginDirectory(); + if(!(converterManager.load(args.value("converter")) & PluginManager::LoadState::Loaded)) std::exit(1); - } + std::unique_ptr converter = converterManager.instance(args.value("converter")); /* Open font */ if(!font->openFile(args.value("input"), args.value("font-size"))) { diff --git a/src/Magnum/TextureTools/distancefieldconverter.cpp b/src/Magnum/TextureTools/distancefieldconverter.cpp index 073b6bd0a..bc386bb31 100644 --- a/src/Magnum/TextureTools/distancefieldconverter.cpp +++ b/src/Magnum/TextureTools/distancefieldconverter.cpp @@ -66,23 +66,17 @@ DistanceFieldConverter::DistanceFieldConverter(const Arguments& arguments): Wind } int DistanceFieldConverter::exec() { - /* Load plugins */ + /* Load importer plugin */ PluginManager::Manager importerManager(MAGNUM_IMPORTER_PLUGIN_DIR); - if(!(importerManager.load(args.value("importer")) & PluginManager::LoadState::Loaded)) { - Error() << "Cannot load importer plugin" << args.value("importer") << "from" << MAGNUM_IMPORTER_PLUGIN_DIR; + if(!(importerManager.load(args.value("importer")) & PluginManager::LoadState::Loaded)) return 1; - } + std::unique_ptr importer = importerManager.instance(args.value("importer")); + + /* Load converter plugin */ PluginManager::Manager converterManager(MAGNUM_IMAGECONVERTER_PLUGIN_DIR); - if(!(converterManager.load(args.value("converter")) & PluginManager::LoadState::Loaded)) { - Error() << "Cannot load converter plugin" << args.value("converter") << "from" << MAGNUM_IMAGECONVERTER_PLUGIN_DIR; + if(!(converterManager.load(args.value("converter")) & PluginManager::LoadState::Loaded)) return 1; - } - - /* Instance plugins */ - std::unique_ptr importer = importerManager.instance(args.value("importer")); - CORRADE_INTERNAL_ASSERT(importer); std::unique_ptr converter = converterManager.instance(args.value("converter")); - CORRADE_INTERNAL_ASSERT(converter); /* Open input file */ std::optional image; From 30aae1bd48e640cd2532ab9ce79b5c66b48d310d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 30 Jan 2014 21:47:06 +0100 Subject: [PATCH 49/86] modules: actually detect the MAGNUM_PLUGINS_DIR. It now defaults to magnum/ subdirectory of dir where main Magnum library was found. It was *annoying* to change /usr/local/lib/magnum to /usr/lib/magnum _every time_. --- doc/cmake.dox | 9 +++++---- modules/FindMagnum.cmake | 11 +++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/doc/cmake.dox b/doc/cmake.dox index 07cd6fc26..21e776f4d 100644 --- a/doc/cmake.dox +++ b/doc/cmake.dox @@ -44,10 +44,11 @@ variables: - `MAGNUM_FOUND` -- Whether the library was found - `MAGNUM_LIBRARIES` -- %Magnum library and dependent libraries - `MAGNUM_INCLUDE_DIRS` -- Root include dir and include dirs of dependencies -- `MAGNUM_PLUGINS_DIR` -- Base directory with plugins. You can modify it - (e.g. set it to `.` when deploying on Windows with plugins stored - relatively to the executable), the following `MAGNUM_PLUGINS_*_DIR` - variables depend on it. +- `MAGNUM_PLUGINS_DIR` -- Base directory with plugins, defaults to `magnum/` + subdirectory of dir where Magnum library was found. You can modify it (e.g. + set it to `.` when deploying on Windows with plugins stored relatively to + the executable), the following `MAGNUM_PLUGINS_*_DIR` variables depend on + it. - `MAGNUM_PLUGINS_FONT_DIR` -- Directory with font plugins - `MAGNUM_PLUGINS_FONTCONVERTER_DIR` -- Directory with font converter plugins - `MAGNUM_PLUGINS_IMAGECONVERTER_DIR` -- Directory with image converter diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 6b8a2f99b..c742edceb 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -7,9 +7,10 @@ # MAGNUM_LIBRARIES - Magnum library and dependent libraries # MAGNUM_INCLUDE_DIRS - Root include dir and include dirs of # dependencies -# MAGNUM_PLUGINS_DIR - Base directory with plugins. You can modify -# it (e.g. set it to `.` when deploying on Windows with plugins stored -# relatively to the executable), the following MAGNUM_PLUGINS_*_DIR +# MAGNUM_PLUGINS_DIR - Base directory with plugins, defaults to +# `magnum/` subdirectory of dir where Magnum library was found. You can +# modify it (e.g. set it to `.` when deploying on Windows with plugins +# stored relatively to the executable), the following MAGNUM_PLUGINS_*_DIR # variables depend on it. # MAGNUM_PLUGINS_FONT_DIR - Directory with font plugins # MAGNUM_PLUGINS_FONTCONVERTER_DIR - Directory with font converter plugins @@ -404,7 +405,9 @@ if(MAGNUM_BUILD_DEPRECATED) set(MAGNUM_PLUGINS_INCLUDE_DIR ${MAGNUM_INCLUDE_DIR}/MagnumPlugins) endif() -set(MAGNUM_PLUGINS_DIR ${MAGNUM_PLUGINS_INSTALL_DIR} +# Get base plugin directory from main library location +get_filename_component(_MAGNUM_LIBRARY_PATH ${MAGNUM_LIBRARY} PATH) +set(MAGNUM_PLUGINS_DIR ${_MAGNUM_LIBRARY_PATH}/magnum CACHE PATH "Base directory where to look for Magnum plugins") # Plugin directories From 6fb04dcdfe3373e1ccc7715fec5925a8c50f7f6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 30 Jan 2014 21:52:24 +0100 Subject: [PATCH 50/86] modules: work around GLUT_Xi_LIBRARY-related CMake errors on Ubuntu. These libraries are not needed for GlutApplication, thus we link only to GLUT_glut_LIBRARY now. Hopefully this won't break linking somewhere else. --- modules/FindMagnum.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index c742edceb..998911a3a 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -245,7 +245,7 @@ foreach(component ${Magnum_FIND_COMPONENTS}) if(${component} STREQUAL GlutApplication) find_package(GLUT) if(GLUT_FOUND) - set(_MAGNUM_${_COMPONENT}_LIBRARIES ${GLUT_LIBRARIES} ${_WINDOWCONTEXT_MAGNUM_LIBRARIES_DEPENDENCY}) + set(_MAGNUM_${_COMPONENT}_LIBRARIES ${GLUT_glut_LIBRARY} ${_WINDOWCONTEXT_MAGNUM_LIBRARIES_DEPENDENCY}) else() unset(MAGNUM_${_COMPONENT}_LIBRARY) endif() From 29deb70f2324ce567723443c5adca0a0c0c14384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 30 Jan 2014 22:17:56 +0100 Subject: [PATCH 51/86] doc: mention also OpenGL version for optionally used extensions. --- src/Magnum/AbstractObject.h | 6 +++--- src/Magnum/AbstractShaderProgram.h | 12 ++++++------ src/Magnum/AbstractTexture.h | 16 ++++++++-------- src/Magnum/Buffer.h | 16 ++++++++-------- src/Magnum/Framebuffer.h | 12 ++++++------ src/Magnum/Mesh.h | 12 ++++++------ src/Magnum/Query.h | 12 ++++++------ src/Magnum/RectangleTexture.h | 8 ++++---- src/Magnum/Renderbuffer.h | 12 ++++++------ src/Magnum/Shader.h | 12 ++++++------ src/Magnum/Texture.h | 9 ++++----- 11 files changed, 63 insertions(+), 64 deletions(-) diff --git a/src/Magnum/AbstractObject.h b/src/Magnum/AbstractObject.h index d18a119e5..54a220673 100644 --- a/src/Magnum/AbstractObject.h +++ b/src/Magnum/AbstractObject.h @@ -50,9 +50,9 @@ class MAGNUM_EXPORT AbstractObject { * @brief Max object label length * * The result is cached, repeated queries don't result in repeated - * OpenGL calls. If @extension{KHR,debug} desktop or ES extension is - * not available, returns `0`. Note that @extension2{EXT,debug_label} - * has no such limit. + * OpenGL calls. If OpenGL 4.3 is not supported and @extension{KHR,debug} + * desktop or ES extension is not available, returns `0`. Note that + * @extension2{EXT,debug_label} has no such limit. * @see @ref AbstractQuery::setLabel(), @ref AbstractShaderProgram::setLabel(), * @ref AbstractTexture::setLabel(), @ref Buffer::setLabel(), * @ref BufferTexture::setLabel(), @ref Framebuffer::setLabel(), diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index c4473629e..7186b692e 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -517,9 +517,9 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { * @brief %Shader program label * * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function returns empty string. + * OpenGL calls. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function returns empty string. * @see @fn_gl{GetObjectLabel} with @def_gl{PROGRAM} or * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @def_gl{PROGRAM_OBJECT_EXT} @@ -530,9 +530,9 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { * @brief Set shader program label * @return Reference to self (for method chaining) * - * Default is empty string. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function does nothing. + * Default is empty string. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function does nothing. * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with * @def_gl{PROGRAM} or @fn_gl_extension2{LabelObject,EXT,debug_label} * with @def_gl{PROGRAM_OBJECT_EXT} diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 8a10eede1..5e41dc1d3 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -83,8 +83,8 @@ You can use functions @ref Texture::invalidateImage() and @ref Texture::invalidateSubImage() "invalidateSubImage()" if you don't need texture data anymore to avoid unnecessary memory operations performed by OpenGL in order to preserve the data. If running on OpenGL ES or extension -@extension{ARB,invalidate_subdata} is not available, these functions do -nothing. +@extension{ARB,invalidate_subdata} (part of OpenGL 4.3) is not available, these +functions do nothing. @todo all texture [level] parameters, global texture parameters @todo Add glPixelStore encapsulation @@ -180,9 +180,9 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { * @brief %Texture label * * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function returns empty string. + * OpenGL calls. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function returns empty string. * @see @fn_gl{GetObjectLabel} or * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @def_gl{TEXTURE} @@ -193,9 +193,9 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { * @brief Set texture label * @return Reference to self (for method chaining) * - * Default is empty string. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function does nothing. + * Default is empty string. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function does nothing. * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} or * @fn_gl_extension2{LabelObject,EXT,debug_label} with * @def_gl{TEXTURE} diff --git a/src/Magnum/Buffer.h b/src/Magnum/Buffer.h index faed9eae9..35d5d1e5d 100644 --- a/src/Magnum/Buffer.h +++ b/src/Magnum/Buffer.h @@ -185,8 +185,8 @@ and @ref unmap() use DSA functions to avoid unnecessary calls to You can use functions @ref invalidateData() and @ref invalidateSubData() if you don't need buffer data anymore to avoid unnecessary memory operations performed by OpenGL in order to preserve the data. If running on OpenGL ES or extension -@extension{ARB,invalidate_subdata} is not available, these functions do -nothing. +@extension{ARB,invalidate_subdata} (part of OpenGL 4.3) is not available, these +functions do nothing. */ class MAGNUM_EXPORT Buffer: public AbstractObject { friend struct Implementation::BufferState; @@ -544,9 +544,9 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @brief %Buffer label * * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function returns empty string. + * OpenGL calls. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function returns empty string. * @see @fn_gl{GetObjectLabel} with @def_gl{BUFFER} or * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @def_gl{BUFFER_OBJECT_EXT} @@ -557,9 +557,9 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @brief Set buffer label * @return Reference to self (for method chaining) * - * Default is empty string. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function does nothing. + * Default is empty string. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function does nothing. * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with @def_gl{BUFFER} * or @fn_gl_extension2{LabelObject,EXT,debug_label} with * @def_gl{BUFFER_OBJECT_EXT} diff --git a/src/Magnum/Framebuffer.h b/src/Magnum/Framebuffer.h index 7076898ba..7d6f27091 100644 --- a/src/Magnum/Framebuffer.h +++ b/src/Magnum/Framebuffer.h @@ -333,9 +333,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @brief %Framebuffer label * * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function returns empty string. + * OpenGL calls. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function returns empty string. * @see @fn_gl{GetObjectLabel} or * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @def_gl{FRAMEBUFFER} @@ -346,9 +346,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @brief Set framebuffer label * @return Reference to self (for method chaining) * - * Default is empty string. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function does nothing. + * Default is empty string. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function does nothing. * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} or * @fn_gl_extension2{LabelObject,EXT,debug_label} with * @def_gl{FRAMEBUFFER} diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 0d65c4151..243efe699 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -426,9 +426,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @brief %Mesh label * * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function returns empty string. + * OpenGL calls. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function returns empty string. * @see @fn_gl{GetObjectLabel} with @def_gl{VERTEX_ARRAY} or * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @def_gl{VERTEX_ARRAY_OBJECT_EXT} @@ -439,9 +439,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @brief Set mesh label * @return Reference to self (for method chaining) * - * Default is empty string. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function does nothing. + * Default is empty string. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function does nothing. * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with * @def_gl{VERTEX_ARRAY} or @fn_gl_extension2{LabelObject,EXT,debug_label} * with @def_gl{VERTEX_ARRAY_OBJECT_EXT} diff --git a/src/Magnum/Query.h b/src/Magnum/Query.h index 4062c0513..3a55772f3 100644 --- a/src/Magnum/Query.h +++ b/src/Magnum/Query.h @@ -64,9 +64,9 @@ class MAGNUM_EXPORT AbstractQuery: public AbstractObject { * @brief %Query label * * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function returns empty string. + * OpenGL calls. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function returns empty string. * @see @fn_gl{GetObjectLabel} with @def_gl{QUERY} or * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @def_gl{QUERY_OBJECT_EXT} @@ -77,9 +77,9 @@ class MAGNUM_EXPORT AbstractQuery: public AbstractObject { * @brief Set query label * @return Reference to self (for method chaining) * - * Default is empty string. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function does nothing. + * Default is empty string. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function does nothing. * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with * @def_gl{QUERY} or @fn_gl_extension2{LabelObject,EXT,debug_label} * with @def_gl{QUERY_OBJECT_EXT} diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index d226bc9c8..d31f4d02f 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -166,10 +166,10 @@ class RectangleTexture: public AbstractTexture { * allowed. * * If @extension{EXT,direct_state_access} is not available, the texture - * is bound to some layer before the operation. If OpenGL 4.2, - * @extension{ARB,texture_storage}, OpenGL ES 3.0 or - * @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not - * available, the feature is emulated with @ref setImage() call. + * is bound to some layer before the operation. If @extension{ARB,texture_storage} + * (part of OpenGL 4.2), OpenGL ES 3.0 or @es_extension{EXT,texture_storage} + * in OpenGL ES 2.0 is not available, the feature is emulated with + * @ref setImage() call. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexStorage2D} * or @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, * eventually @fn_gl{TexImage2D} or diff --git a/src/Magnum/Renderbuffer.h b/src/Magnum/Renderbuffer.h index 07ad9fb97..febb72670 100644 --- a/src/Magnum/Renderbuffer.h +++ b/src/Magnum/Renderbuffer.h @@ -115,9 +115,9 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject { * @brief %Renderbuffer label * * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function returns empty string. + * OpenGL calls. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function returns empty string. * @see @fn_gl{GetObjectLabel} or * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @def_gl{RENDERBUFFER} @@ -128,9 +128,9 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject { * @brief Set renderbuffer label * @return Reference to self (for method chaining) * - * Default is empty string. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function does nothing. + * Default is empty string. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function does nothing. * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} or * @fn_gl_extension2{LabelObject,EXT,debug_label} with * @def_gl{RENDERBUFFER} diff --git a/src/Magnum/Shader.h b/src/Magnum/Shader.h index 902b0f8fc..e7768948a 100644 --- a/src/Magnum/Shader.h +++ b/src/Magnum/Shader.h @@ -471,9 +471,9 @@ class MAGNUM_EXPORT Shader: public AbstractObject { * @brief %Shader label * * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function returns empty string. + * OpenGL calls. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function returns empty string. * @see @fn_gl{GetObjectLabel} with @def_gl{SHADER} or * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @def_gl{SHADER_OBJECT_EXT} @@ -484,9 +484,9 @@ class MAGNUM_EXPORT Shader: public AbstractObject { * @brief Set shader label * @return Reference to self (for method chaining) * - * Default is empty string. If neither @extension{KHR,debug} nor - * @extension2{EXT,debug_label} desktop or ES extension is available, - * this function does nothing. + * Default is empty string. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function does nothing. * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with * @def_gl{SHADER} or @fn_gl_extension2{LabelObject,EXT,debug_label} * with @def_gl{SHADER_OBJECT_EXT} diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index b7fc72b68..e4e5d8169 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -296,11 +296,10 @@ template class Texture: public AbstractTexture { * allowed. * * If @extension{EXT,direct_state_access} is not available, the texture - * is bound to some layer before the operation. If OpenGL 4.2, - * @extension{ARB,texture_storage}, OpenGL ES 3.0 or - * @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not - * available, the feature is emulated with sequence of @ref setImage() - * calls. + * is bound to some layer before the operation. If @extension{ARB,texture_storage} + * (part of OpenGL 4.2), OpenGL ES 3.0 or @es_extension{EXT,texture_storage} + * in OpenGL ES 2.0 is not available, the feature is emulated with + * sequence of @ref setImage() calls. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{TexStorage1D}/@fn_gl{TexStorage2D}/@fn_gl{TexStorage3D} * or @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}/ From 69225bf8c112cc2ca9b5363ba8ed6d67014e77d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 30 Jan 2014 22:25:24 +0100 Subject: [PATCH 52/86] doc: clearly mention all possibly needed CMake module files. Also note that the files should be kept up-to-date. --- doc/cmake.dox | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/cmake.dox b/doc/cmake.dox index 21e776f4d..c1b60c6e9 100644 --- a/doc/cmake.dox +++ b/doc/cmake.dox @@ -29,10 +29,17 @@ namespace Magnum { %Magnum uses CMake build system for both building and integration into your projects. The logic is in module `FindMagnum.cmake` distributed with the engine -in `modules/` directory, you are encouraged to copy it (and its dependencies) -into your project and add path to the files to `CMAKE_MODULE_PATH`. Otherwise, -if CMake won't be able to find this file in predefined locations, it will error -out even if %Magnum might be installed on the system. +in `modules/` directory, you are encouraged to copy it along with +`FindCorrade.cmake` into your project and add path to the files to +`CMAKE_MODULE_PATH`. Otherwise, if CMake won't be able to find this file in +predefined locations, it will error out even if %Magnum might be installed on +the system. If you plan to use Magnum on OpenGL ES, you may also need +`FindOpenGLES2.cmake` or `FindOpenGLES3.cmake` and in some cases also +`FindEGL.cmake`. + +Note that the module files are updated as the library evolves, you are +encouraged to update your copies from time to time to avoid strange building +issues. Basic usage is: From 6ce7466b21030b85e68f46ae1c56e00d667b9732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 30 Jan 2014 22:39:17 +0100 Subject: [PATCH 53/86] Use UnsignedInt instead of std::size_t for attribute sizes/offsets. --- src/Magnum/AbstractShaderProgram.cpp | 8 ++++---- src/Magnum/AbstractShaderProgram.h | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Magnum/AbstractShaderProgram.cpp b/src/Magnum/AbstractShaderProgram.cpp index 5ffcaa358..b3bc39a7e 100644 --- a/src/Magnum/AbstractShaderProgram.cpp +++ b/src/Magnum/AbstractShaderProgram.cpp @@ -806,7 +806,7 @@ void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const namespace Implementation { -std::size_t FloatAttribute::size(GLint components, DataType dataType) { +UnsignedInt FloatAttribute::size(GLint components, DataType dataType) { switch(dataType) { case DataType::UnsignedByte: case DataType::Byte: @@ -829,7 +829,7 @@ std::size_t FloatAttribute::size(GLint components, DataType dataType) { } #ifndef MAGNUM_TARGET_GLES2 -std::size_t IntAttribute::size(GLint components, DataType dataType) { +UnsignedInt IntAttribute::size(GLint components, DataType dataType) { switch(dataType) { case DataType::UnsignedByte: case DataType::Byte: @@ -847,7 +847,7 @@ std::size_t IntAttribute::size(GLint components, DataType dataType) { #endif #ifndef MAGNUM_TARGET_GLES -std::size_t DoubleAttribute::size(GLint components, DataType dataType) { +UnsignedInt DoubleAttribute::size(GLint components, DataType dataType) { switch(dataType) { case DataType::Double: return 8*components; @@ -857,7 +857,7 @@ std::size_t DoubleAttribute::size(GLint components, DataType dataType) { } #endif -std::size_t Attribute>::size(GLint components, DataType dataType) { +UnsignedInt Attribute>::size(GLint components, DataType dataType) { #ifndef MAGNUM_TARGET_GLES if(components == GL_BGRA) components = 4; #endif diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index 7186b692e..fcf00d4bf 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -1195,7 +1195,7 @@ struct FloatAttribute { }; typedef Containers::EnumSet DataOptions; - static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType); + static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType); }; CORRADE_ENUMSET_OPERATORS(FloatAttribute::DataOptions) @@ -1220,7 +1220,7 @@ struct IntAttribute { enum class DataOption: UnsignedByte {}; typedef Containers::EnumSet DataOptions; - static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType); + static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType); }; Debug MAGNUM_EXPORT operator<<(Debug debug, IntAttribute::DataType value); @@ -1235,7 +1235,7 @@ struct UnsignedIntAttribute { typedef IntAttribute::DataOption DataOption; typedef Containers::EnumSet DataOptions; - static std::size_t size(GLint components, DataType dataType) { + static UnsignedInt size(GLint components, DataType dataType) { return IntAttribute::size(components, dataType); } }; @@ -1254,7 +1254,7 @@ struct DoubleAttribute { enum class DataOption: UnsignedByte {}; typedef Containers::EnumSet DataOptions; - static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType); + static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType); }; Debug MAGNUM_EXPORT operator<<(Debug debug, DoubleAttribute::DataType value); @@ -1308,7 +1308,7 @@ template<> struct Attribute> { enum: UnsignedInt { VectorCount = 1 }; - static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType); + static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType); }; typedef Math::Vector<4, Float> _Vector4; From e7159c52ae8da4a846bd649e49fafe59739eda66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 31 Jan 2014 12:50:45 +0100 Subject: [PATCH 54/86] package: added debian package. Thanks to Costas Hatzis for the help. --- doc/building.dox | 14 ++++++++++++++ package/debian/changelog | 5 +++++ package/debian/compat | 1 + package/debian/control | 25 +++++++++++++++++++++++++ package/debian/copyright | 25 +++++++++++++++++++++++++ package/debian/magnum-dev.install | 6 ++++++ package/debian/magnum.install | 3 +++ package/debian/rules | 19 +++++++++++++++++++ package/debian/source/format | 1 + 9 files changed, 99 insertions(+) create mode 100644 package/debian/changelog create mode 100644 package/debian/compat create mode 100644 package/debian/control create mode 100644 package/debian/copyright create mode 100644 package/debian/magnum-dev.install create mode 100644 package/debian/magnum.install create mode 100755 package/debian/rules create mode 100644 package/debian/source/format diff --git a/doc/building.dox b/doc/building.dox index 5bef9436f..71edec083 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -269,6 +269,20 @@ project root: makepkg -p package/archlinux/ +@subsection building-packages-deb DEB packages + +There is also `package/debian/` directory with all files needed for building +Debian packages. You need to have `corrade-dev` DEB packages installed and in +addition also `dpkg-dev` package. Building is easy, just change directory to +package root, copy `package/debian` directory there and run `dpkg-buildpackage`: + + cp -r package/debian . + dpkg-buildpackage + +This will compile binary and development packages, which will then appear in +parent directory. If you need to modify CMake flags (enabling/disabling some +features, for example), modify the last entry in `debian/rules`. + @section building-crosscompiling Crosscompiling For crosscompiling you need to have *both* target and native version of diff --git a/package/debian/changelog b/package/debian/changelog new file mode 100644 index 000000000..796c69eba --- /dev/null +++ b/package/debian/changelog @@ -0,0 +1,5 @@ +magnum (1.0-1) UNRELEASED; urgency=low + + * Latest upstream version + + -- Vladimír Vondruš Fri, 31 Jan 2014 12:20:58 +0100 diff --git a/package/debian/compat b/package/debian/compat new file mode 100644 index 000000000..ec635144f --- /dev/null +++ b/package/debian/compat @@ -0,0 +1 @@ +9 diff --git a/package/debian/control b/package/debian/control new file mode 100644 index 000000000..38669b8aa --- /dev/null +++ b/package/debian/control @@ -0,0 +1,25 @@ +Source: magnum +Priority: optional +Maintainer: Vladimír Vondruš +Build-Depends: debhelper (>= 9), cmake (>= 2.8.8) +Standards-Version: 3.9.2 +Section: libs +Homepage: http://mosra.cz/blog/magnum.php +Vcs-Git: git://github.com/mosra/magnum.git +Vcs-Browser: https://github.com/mosra/magnum + +Package: magnum-dev +Section: libdevel +Architecture: any +Depends: magnum (= ${binary:Version}), corrade-dev, libgl-dev, freeglut3-dev, libopenal-dev +Description: Magnum development files + Headers and tools needed for developing with Magnum. + +Package: magnum +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, corrage, libgl1, freeglut3, libopenal1 +Description: C++11 and OpenGL 2D/3D graphics engine + Magnum is 2D/3D graphics engine written in C++11 and modern OpenGL. Its goal + is to simplify low-level graphics development and interaction with OpenGL + using recent C++11 features and to abstract away platform-specific issues. diff --git a/package/debian/copyright b/package/debian/copyright new file mode 100644 index 000000000..a9eaab973 --- /dev/null +++ b/package/debian/copyright @@ -0,0 +1,25 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: Magnum +Upstream-Contact: Vladimír Vondruš +Source: https://github.com/mosra/magnum + +Files: * +Copyright: 2010-2014 Vladimír Vondruš +License: Expat + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. diff --git a/package/debian/magnum-dev.install b/package/debian/magnum-dev.install new file mode 100644 index 000000000..dccc382dd --- /dev/null +++ b/package/debian/magnum-dev.install @@ -0,0 +1,6 @@ +usr/include/Magnum/* +usr/include/MagnumExternal/* +usr/include/MagnumPlugins/* +usr/lib*/lib*.so +usr/lib*/lib*.a +usr/share/cmake* diff --git a/package/debian/magnum.install b/package/debian/magnum.install new file mode 100644 index 000000000..27b2ed6b2 --- /dev/null +++ b/package/debian/magnum.install @@ -0,0 +1,3 @@ +usr/bin/* +usr/lib*/magnum/* +usr/lib*/lib*.so.* diff --git a/package/debian/rules b/package/debian/rules new file mode 100755 index 000000000..3723072df --- /dev/null +++ b/package/debian/rules @@ -0,0 +1,19 @@ +#!/usr/bin/make -f + +%: + dh $@ --parallel + +override_dh_auto_configure: + dh_auto_configure -- \ + -DWITH_AUDIO=ON \ + -DWITH_GLUTAPPLICATION=ON \ + -DWITH_GLXAPPLICATION=ON \ + -DWITH_WINDOWLESSGLXAPPLICATION=ON \ + -DWITH_MAGNUMFONT=ON \ + -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_TGAIMAGECONVERTER=ON \ + -DWITH_TGAIMPORTER=ON \ + -DWITH_WAVAUDIOIMPORTER=ON \ + -DWITH_DISTANCEFIELDCONVERTER=ON \ + -DWITH_FONTCONVERTER=ON \ + -DWITH_MAGNUMINFO=ON diff --git a/package/debian/source/format b/package/debian/source/format new file mode 100644 index 000000000..89ae9db8f --- /dev/null +++ b/package/debian/source/format @@ -0,0 +1 @@ +3.0 (native) From 40c8548db7acfc0a8c8e184d75e17365f54031d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 31 Jan 2014 13:02:02 +0100 Subject: [PATCH 55/86] package: no CMake files are installed by Magnum. --- package/debian/magnum-dev.install | 1 - 1 file changed, 1 deletion(-) diff --git a/package/debian/magnum-dev.install b/package/debian/magnum-dev.install index dccc382dd..86958e901 100644 --- a/package/debian/magnum-dev.install +++ b/package/debian/magnum-dev.install @@ -3,4 +3,3 @@ usr/include/MagnumExternal/* usr/include/MagnumPlugins/* usr/lib*/lib*.so usr/lib*/lib*.a -usr/share/cmake* From e3248bf524fea6367f803d7764ae23e69e4703eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 31 Jan 2014 13:59:35 +0100 Subject: [PATCH 56/86] package: fix typo. Blind coding FTW! --- package/debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/debian/control b/package/debian/control index 38669b8aa..c8889b81c 100644 --- a/package/debian/control +++ b/package/debian/control @@ -18,7 +18,7 @@ Description: Magnum development files Package: magnum Section: libs Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, corrage, libgl1, freeglut3, libopenal1 +Depends: ${shlibs:Depends}, ${misc:Depends}, corrade, libgl1, freeglut3, libopenal1 Description: C++11 and OpenGL 2D/3D graphics engine Magnum is 2D/3D graphics engine written in C++11 and modern OpenGL. Its goal is to simplify low-level graphics development and interaction with OpenGL From 4a289c9df59b2512c5aa9c9c9b4b1b259e8c0369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 31 Jan 2014 13:59:59 +0100 Subject: [PATCH 57/86] package: Magnum doesn't have versioned libraries. Yet. --- package/debian/magnum-dev.install | 1 - package/debian/magnum.install | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/package/debian/magnum-dev.install b/package/debian/magnum-dev.install index 86958e901..b76bb83af 100644 --- a/package/debian/magnum-dev.install +++ b/package/debian/magnum-dev.install @@ -1,5 +1,4 @@ usr/include/Magnum/* usr/include/MagnumExternal/* usr/include/MagnumPlugins/* -usr/lib*/lib*.so usr/lib*/lib*.a diff --git a/package/debian/magnum.install b/package/debian/magnum.install index 27b2ed6b2..a6d60262c 100644 --- a/package/debian/magnum.install +++ b/package/debian/magnum.install @@ -1,3 +1,3 @@ usr/bin/* usr/lib*/magnum/* -usr/lib*/lib*.so.* +usr/lib*/lib*.so From 4c21e10e5759cca3a984bf3150d4dd569af695d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 31 Jan 2014 22:55:04 +0100 Subject: [PATCH 58/86] Support both DSA and SSO variants of glProgramUniform*(). Also added (currently disabled) ES implementation (provided by EXT_separate_shader_objects). Unfortunately it's not possible to reduce the function count, because ARB_separate_shader_objects and EXT_direct_state_access are completely independent. Also double uniforms are supported since GL 4.0 and SSO are since 4.1, so we can't omit old glUniform*() calls for doubles either. --- doc/opengl-support.dox | 4 +- src/Magnum/AbstractShaderProgram.cpp | 393 ++++++++++++++++-- src/Magnum/AbstractShaderProgram.h | 46 ++ .../Implementation/ShaderProgramState.cpp | 71 +++- 4 files changed, 467 insertions(+), 47 deletions(-) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 708dc15b7..6d6a0d8f2 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -142,7 +142,7 @@ following: -------------------------------------------- | ------ @extension{ARB,ES2_compatibility} | only float depth clear @extension{ARB,get_program_binary} | | -@extension{ARB,separate_shader_objects} | | +@extension{ARB,separate_shader_objects} | only direct uniform binding @extension{ARB,shader_precision} | done (shading language only) @extension{ARB,vertex_attrib_64bit} | done @extension{ARB,viewport_array} | | @@ -286,7 +286,7 @@ Only extensions not already listed in above tables are included here. @es_extension{EXT,texture_format_BGRA8888} | done @es_extension{EXT,read_format_bgra} | done @es_extension{EXT,disjoint_timer_query} | only time elapsed query -@es_extension{EXT,separate_shader_objects} | | +@es_extension{EXT,separate_shader_objects} | only direct uniform binding @es_extension{EXT,sRGB} | done @es_extension{EXT,multisampled_render_to_texture} | only renderbuffer storage @es_extension{EXT,robustness} | done diff --git a/src/Magnum/AbstractShaderProgram.cpp b/src/Magnum/AbstractShaderProgram.cpp index b3bc39a7e..4d1e966cf 100644 --- a/src/Magnum/AbstractShaderProgram.cpp +++ b/src/Magnum/AbstractShaderProgram.cpp @@ -321,9 +321,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform1fv(location, count, values); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLfloat* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniform1fv(_id, location, count, values); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniform1fvEXT(_id, location, count, values); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLfloat* const values) { - glProgramUniform1fv(_id, location, count, values); + glProgramUniform1fvEXT(_id, location, count, values); } #endif @@ -336,9 +349,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform2fv(location, count, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniform2fv(_id, location, count, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniform2fvEXT(_id, location, count, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) { - glProgramUniform2fv(_id, location, count, values[0].data()); + glProgramUniform2fvEXT(_id, location, count, values[0].data()); } #endif @@ -351,9 +377,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform3fv(location, count, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniform3fv(_id, location, count, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniform3fvEXT(_id, location, count, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) { - glProgramUniform3fv(_id, location, count, values[0].data()); + glProgramUniform3fvEXT(_id, location, count, values[0].data()); } #endif @@ -366,9 +405,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform4fv(location, count, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniform4fv(_id, location, count, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniform4fvEXT(_id, location, count, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) { - glProgramUniform4fv(_id, location, count, values[0].data()); + glProgramUniform4fvEXT(_id, location, count, values[0].data()); } #endif @@ -381,9 +433,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform1iv(location, count, values); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLint* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniform1iv(_id, location, count, values); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniform1ivEXT(_id, location, count, values); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLint* const values) { - glProgramUniform1iv(_id, location, count, values); + glProgramUniform1ivEXT(_id, location, count, values); } #endif @@ -396,9 +461,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform2iv(location, count, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniform2iv(_id, location, count, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniform2ivEXT(_id, location, count, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) { - glProgramUniform2iv(_id, location, count, values[0].data()); + glProgramUniform2ivEXT(_id, location, count, values[0].data()); } #endif @@ -411,9 +489,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform3iv(location, count, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniform3iv(_id, location, count, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniform3ivEXT(_id, location, count, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) { - glProgramUniform3iv(_id, location, count, values[0].data()); + glProgramUniform3ivEXT(_id, location, count, values[0].data()); } #endif @@ -426,9 +517,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform4iv(location, count, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniform4iv(_id, location, count, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniform4ivEXT(_id, location, count, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) { - glProgramUniform4iv(_id, location, count, values[0].data()); + glProgramUniform4ivEXT(_id, location, count, values[0].data()); } #endif @@ -442,9 +546,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform1uiv(location, count, values); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLuint* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniform1uiv(_id, location, count, values); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniform1uivEXT(_id, location, count, values); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLuint* const values) { - glProgramUniform1uiv(_id, location, count, values); + glProgramUniform1uivEXT(_id, location, count, values); } #endif @@ -457,9 +574,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform2uiv(location, count, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniform2uiv(_id, location, count, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniform2uivEXT(_id, location, count, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) { - glProgramUniform2uiv(_id, location, count, values[0].data()); + glProgramUniform2uivEXT(_id, location, count, values[0].data()); } #endif @@ -472,9 +602,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform3uiv(location, count, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniform3uiv(_id, location, count, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniform3uivEXT(_id, location, count, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) { - glProgramUniform3uiv(_id, location, count, values[0].data()); + glProgramUniform3uivEXT(_id, location, count, values[0].data()); } #endif @@ -487,9 +630,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform4uiv(location, count, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniform4uiv(_id, location, count, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniform4uivEXT(_id, location, count, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) { - glProgramUniform4uiv(_id, location, count, values[0].data()); + glProgramUniform4uivEXT(_id, location, count, values[0].data()); } #endif #endif @@ -504,10 +660,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform1dv(location, count, values); } -void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLdouble* const values) { +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLdouble* const values) { glProgramUniform1dv(_id, location, count, values); } +void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLdouble* const values) { + glProgramUniform1dvEXT(_id, location, count, values); +} + void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<2, Double>* const values) { (this->*Context::current()->state().shaderProgram->uniform2dvImplementation)(location, count, values); } @@ -517,10 +677,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform2dv(location, count, values[0].data()); } -void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLdouble>* const values) { +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLdouble>* const values) { glProgramUniform2dv(_id, location, count, values[0].data()); } +void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLdouble>* const values) { + glProgramUniform2dvEXT(_id, location, count, values[0].data()); +} + void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<3, Double>* const values) { (this->*Context::current()->state().shaderProgram->uniform3dvImplementation)(location, count, values); } @@ -530,10 +694,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform3dv(location, count, values[0].data()); } -void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLdouble>* const values) { +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLdouble>* const values) { glProgramUniform3dv(_id, location, count, values[0].data()); } +void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLdouble>* const values) { + glProgramUniform3dvEXT(_id, location, count, values[0].data()); +} + void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<4, Double>* const values) { (this->*Context::current()->state().shaderProgram->uniform4dvImplementation)(location, count, values); } @@ -543,9 +711,13 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniform4dv(location, count, values[0].data()); } -void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLdouble>* const values) { +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLdouble>* const values) { glProgramUniform4dv(_id, location, count, values[0].data()); } + +void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLdouble>* const values) { + glProgramUniform4dvEXT(_id, location, count, values[0].data()); +} #endif void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 2, Float>* const values) { @@ -557,9 +729,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix2fv(location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniformMatrix2fv(_id, location, count, GL_FALSE, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniformMatrix2fvEXT(_id, location, count, GL_FALSE, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) { - glProgramUniformMatrix2fv(_id, location, count, GL_FALSE, values[0].data()); + glProgramUniformMatrix2fvEXT(_id, location, count, GL_FALSE, values[0].data()); } #endif @@ -572,9 +757,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix3fv(location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniformMatrix3fv(_id, location, count, GL_FALSE, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniformMatrix3fvEXT(_id, location, count, GL_FALSE, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) { - glProgramUniformMatrix3fv(_id, location, count, GL_FALSE, values[0].data()); + glProgramUniformMatrix3fvEXT(_id, location, count, GL_FALSE, values[0].data()); } #endif @@ -587,9 +785,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix4fv(location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniformMatrix4fv(_id, location, count, GL_FALSE, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniformMatrix4fvEXT(_id, location, count, GL_FALSE, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) { - glProgramUniformMatrix4fv(_id, location, count, GL_FALSE, values[0].data()); + glProgramUniformMatrix4fvEXT(_id, location, count, GL_FALSE, values[0].data()); } #endif @@ -603,9 +814,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix2x3fv(location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniformMatrix2x3fv(_id, location, count, GL_FALSE, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniformMatrix2x3fvEXT(_id, location, count, GL_FALSE, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) { - glProgramUniformMatrix2x3fv(_id, location, count, GL_FALSE, values[0].data()); + glProgramUniformMatrix2x3fvEXT(_id, location, count, GL_FALSE, values[0].data()); } #endif @@ -618,9 +842,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix3x2fv(location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniformMatrix3x2fv(_id, location, count, GL_FALSE, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniformMatrix3x2fv(_id, location, count, GL_FALSE, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) { - glProgramUniformMatrix3x2fv(_id, location, count, GL_FALSE, values[0].data()); + glProgramUniformMatrix3x2fvEXT(_id, location, count, GL_FALSE, values[0].data()); } #endif @@ -633,9 +870,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix2x4fv(location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniformMatrix2x4fv(_id, location, count, GL_FALSE, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniformMatrix2x4fvEXT(_id, location, count, GL_FALSE, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) { - glProgramUniformMatrix2x4fv(_id, location, count, GL_FALSE, values[0].data()); + glProgramUniformMatrix2x4fvEXT(_id, location, count, GL_FALSE, values[0].data()); } #endif @@ -648,9 +898,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix4x2fv(location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniformMatrix4x2fv(_id, location, count, GL_FALSE, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniformMatrix4x2fvEXT(_id, location, count, GL_FALSE, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) { - glProgramUniformMatrix4x2fv(_id, location, count, GL_FALSE, values[0].data()); + glProgramUniformMatrix4x2fvEXT(_id, location, count, GL_FALSE, values[0].data()); } #endif @@ -663,9 +926,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix3x4fv(location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniformMatrix3x4fv(_id, location, count, GL_FALSE, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniformMatrix3x4fvEXT(_id, location, count, GL_FALSE, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) { - glProgramUniformMatrix3x4fv(_id, location, count, GL_FALSE, values[0].data()); + glProgramUniformMatrix3x4fvEXT(_id, location, count, GL_FALSE, values[0].data()); } #endif @@ -678,9 +954,22 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix4x3fv(location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) { + /** @todo Enable when extension loader for ES is available */ + #ifndef MAGNUM_TARGET_GLES + glProgramUniformMatrix4x3fv(_id, location, count, GL_FALSE, values[0].data()); + #else + CORRADE_INTERNAL_ASSERT(false); + //glProgramUniformMatrix4x3fvEXT(_id, location, count, GL_FALSE, values[0].data()); + static_cast(location); + static_cast(count); + static_cast(values); + #endif +} + #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) { - glProgramUniformMatrix4x3fv(_id, location, count, GL_FALSE, values[0].data()); + glProgramUniformMatrix4x3fvEXT(_id, location, count, GL_FALSE, values[0].data()); } #endif #endif @@ -695,10 +984,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix2dv(location, count, GL_FALSE, values[0].data()); } -void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* const values) { +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* const values) { glProgramUniformMatrix2dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* const values) { + glProgramUniformMatrix2dvEXT(_id, location, count, GL_FALSE, values[0].data()); +} + void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 3, Double>* const values) { (this->*Context::current()->state().shaderProgram->uniformMatrix3dvImplementation)(location, count, values); } @@ -708,10 +1001,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix3dv(location, count, GL_FALSE, values[0].data()); } -void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* const values) { +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* const values) { glProgramUniformMatrix3dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* const values) { + glProgramUniformMatrix3dvEXT(_id, location, count, GL_FALSE, values[0].data()); +} + void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 4, Double>* const values) { (this->*Context::current()->state().shaderProgram->uniformMatrix4dvImplementation)(location, count, values); } @@ -721,10 +1018,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix4dv(location, count, GL_FALSE, values[0].data()); } -void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* const values) { +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* const values) { glProgramUniformMatrix4dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* const values) { + glProgramUniformMatrix4dvEXT(_id, location, count, GL_FALSE, values[0].data()); +} + void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 3, Double>* const values) { (this->*Context::current()->state().shaderProgram->uniformMatrix2x3dvImplementation)(location, count, values); } @@ -734,10 +1035,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix2x3dv(location, count, GL_FALSE, values[0].data()); } -void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* const values) { +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* const values) { glProgramUniformMatrix2x3dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* const values) { + glProgramUniformMatrix2x3dvEXT(_id, location, count, GL_FALSE, values[0].data()); +} + void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 2, Double>* const values) { (this->*Context::current()->state().shaderProgram->uniformMatrix3x2dvImplementation)(location, count, values); } @@ -747,10 +1052,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix3x2dv(location, count, GL_FALSE, values[0].data()); } -void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* const values) { +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* const values) { glProgramUniformMatrix3x2dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* const values) { + glProgramUniformMatrix3x2dvEXT(_id, location, count, GL_FALSE, values[0].data()); +} + void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 4, Double>* const values) { (this->*Context::current()->state().shaderProgram->uniformMatrix2x4dvImplementation)(location, count, values); } @@ -760,10 +1069,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix2x4dv(location, count, GL_FALSE, values[0].data()); } -void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* const values) { +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* const values) { glProgramUniformMatrix2x4dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* const values) { + glProgramUniformMatrix2x4dvEXT(_id, location, count, GL_FALSE, values[0].data()); +} + void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 2, Double>* const values) { (this->*Context::current()->state().shaderProgram->uniformMatrix4x2dvImplementation)(location, count, values); } @@ -773,10 +1086,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix4x2dv(location, count, GL_FALSE, values[0].data()); } -void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* const values) { +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* const values) { glProgramUniformMatrix4x2dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* const values) { + glProgramUniformMatrix4x2dvEXT(_id, location, count, GL_FALSE, values[0].data()); +} + void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 4, Double>* const values) { (this->*Context::current()->state().shaderProgram->uniformMatrix3x4dvImplementation)(location, count, values); } @@ -786,10 +1103,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix3x4dv(location, count, GL_FALSE, values[0].data()); } -void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* const values) { +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* const values) { glProgramUniformMatrix3x4dv(_id, location, count, GL_FALSE, values[0].data()); } +void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* const values) { + glProgramUniformMatrix3x4dvEXT(_id, location, count, GL_FALSE, values[0].data()); +} + void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 3, Double>* const values) { (this->*Context::current()->state().shaderProgram->uniformMatrix4x3dvImplementation)(location, count, values); } @@ -799,9 +1120,13 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c glUniformMatrix4x3dv(location, count, GL_FALSE, values[0].data()); } -void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* const values) { +void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* const values) { glProgramUniformMatrix4x3dv(_id, location, count, GL_FALSE, values[0].data()); } + +void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* const values) { + glProgramUniformMatrix4x3dvEXT(_id, location, count, GL_FALSE, values[0].data()); +} #endif namespace Implementation { diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index fcf00d4bf..09bc42fd9 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -809,6 +809,28 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLdouble>* values); void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLdouble>* values); void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values); + #endif + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLfloat* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLfloat>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLint* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLint>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLint>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLint>* values); + #ifndef MAGNUM_TARGET_GLES2 + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLuint* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLuint>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLuint>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLuint>* values); + #endif + #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLdouble* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLdouble>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLdouble>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values); + #endif + #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const GLfloat* values); void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values); @@ -848,6 +870,30 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* values); void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* values); void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values); + #endif + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values); + #ifndef MAGNUM_TARGET_GLES2 + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* values); + #endif + #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* values); + void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values); + #endif + #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values); diff --git a/src/Magnum/Implementation/ShaderProgramState.cpp b/src/Magnum/Implementation/ShaderProgramState.cpp index 9ef01e4b6..3e375e8c0 100644 --- a/src/Magnum/Implementation/ShaderProgramState.cpp +++ b/src/Magnum/Implementation/ShaderProgramState.cpp @@ -39,13 +39,66 @@ ShaderProgramState::ShaderProgramState(Context& context, std::vector() || - context.isExtensionSupported()) + if(context.isExtensionSupported()) + #else + if(context.isExtensionSupported()) + #endif { - extensions.push_back(context.isExtensionSupported() ? - Extensions::GL::ARB::separate_shader_objects::string() : Extensions::GL::EXT::direct_state_access::string()); + #ifndef MAGNUM_TARGET_GLES + extensions.push_back(Extensions::GL::ARB::separate_shader_objects::string()); + #else + extensions.push_back(Extensions::GL::EXT::separate_shader_objects::string()); + #endif + + uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationSSO; + #ifndef MAGNUM_TARGET_GLES2 + uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationSSO; + #endif + #ifndef MAGNUM_TARGET_GLES + uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + #endif + + uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + #ifndef MAGNUM_TARGET_GLES2 + uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + #endif + #ifndef MAGNUM_TARGET_GLES + uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + #endif + } + + #ifndef MAGNUM_TARGET_GLES + else if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; @@ -82,14 +135,10 @@ ShaderProgramState::ShaderProgramState(Context& context, std::vector(context); - static_cast(extensions); - #endif + else { uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; From 2ba69b2c2b1b9b485519e612e97b207dafc40e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 1 Feb 2014 11:37:06 +0100 Subject: [PATCH 59/86] doc: added Visual Studio building instructions. --- doc/building.dox | 62 ++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/doc/building.dox b/doc/building.dox index 71edec083..49823eba2 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -78,37 +78,53 @@ can be built and installed using these four commands: See @ref building-features "below" for additional configuration options. -@subsection building-windows Using QtCreator and CMake GUI (on Windows) +@subsection building-windows Building on Windows -On Windows, if you don't want to touch the command-line, the easiest way is to -install QtCreator (just QtCreator, you don't need the full Qt SDK) and -configure it to use MinGW and CMake. +On Windows you can use either MinGW or MSVC 2013 compiler. It's then up to you +whether you will use QtCreator, Visual Studio or do the build from command- +line. Note that for most convenient usage it's best use some dedicated +directory (e.g. `C:/Sys`) for installing dependencies instead of putting each +dependency to its own directory in `C:/Program Files`. Then add its `bin/` +subdir (e.g. `C:/Sys/bin`) to PATH so all the DLLs are found when running the +executables. If you are using MinGW, the `C:/MinGW` directory is in most cases +already prepared for exactly this. -For most convenient usage it's best to install (or copy/paste) all library -dependencies into directory where MinGW is installed (e.g. `C:/MinGW/`), -following proper filesystem hierarchy, i.e. headers into `include/` and -binaries into `bin/` or `lib/`. CMake will then have no problem finding them -and you won't need to explicitly specify path to each one. +When running CMake, set `CMAKE_FIND_ROOT_PATH` and `CMAKE_INSTALL_PREFIX` +parameters to that directory so CMake knows where to look for installed +libraries and where to install new ones. -Then just open project's root `CMakeLists.txt` file within QtCreator. It then +@subsubsection building-windows-msvc Using Visual Studio + +On Windows CMake by default creates Visual Studio project files. You need to +use `compatibility` branch to compile with MSVC 2013, as said above. + +The most straightforward way to build and install the library is again via the +command-line. The bonus point is that you don't even need to wait for Visual +Studio to load: + + mkdir build + cd build + cmake -DCMAKE_FIND_ROOT_PATH="C:/Sys" -DCMAKE_INSTALL_PREFIX="C:/Sys" .. + cmake --build . + cmake --build --target install . + +If you want to build and install from Visual Studio, just open the `Magnum.sln` +project file generated by CMake in the build directory. + +@subsubsection building-windows-qtcreator Using QtCreator + +On Windows you can also use QtCreator (just QtCreator, you don't need the full +Qt SDK). Configure it to use CMake and either MSVC compiler or MinGW and and +then just open project's root `CMakeLists.txt` file within it. QtCreator then asks you where to create build directory, allows you to specify initial CMake -parameters and then you can just press *Configure* and everything is be ready -to be built. +parameters (e.g. `CMAKE_FIND_ROOT_PATH` and `CMAKE_INSTALL_PREFIX`) and then +you can just press *Configure* and everything is ready to be built. After the initial import you might want to reconfigure some CMake variables, see @ref building-features "below" for more information. -For most convenient usage it's best to set `CMAKE_INSTALL_PREFIX` to directory -where MinGW is installed (e.g. `C:/MinGW/`) and add `C:/MinGW/bin` and -`C:/MinGW/lib` to `PATH`. Installation to given prefix can be then done from -within QtCreator by adding new `make install` build rule. - -@subsubsection building-windows-troubleshooting Windows troubleshooting - -If CMake isn't able to find dependencies (e.g. %Corrade is not found), point -`CMAKE_FIND_ROOT_PATH` and `CMAKE_INSTALL_PREFIX` to installation prefix of -dependency libraries, e.g. specify `-DCMAKE_FIND_ROOT_PATH=C:/MinGW/` CMake -parameter. +Installation to given prefix can be done from within QtCreator by adding new +`make install` build rule. @subsection building-features Enabling or disabling features From 3a3830098b926934b1e9964978b5081bb8fd866e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 2 Feb 2014 09:56:08 +0100 Subject: [PATCH 60/86] doc: mention that it might be easier to use SDL2 on newer systems. --- doc/getting-started.dox | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/getting-started.dox b/doc/getting-started.dox index 722235f03..4b271c8c5 100644 --- a/doc/getting-started.dox +++ b/doc/getting-started.dox @@ -34,7 +34,9 @@ namespace Magnum { Get latest version from GitHub and install it. Read full guide on @ref building "how to download, build and install Magnum" on platform of your choice. For our first project we will use GLUT toolkit, don't forget to enable -it for building using `WITH_GLUTAPPLICATION` CMake parameter. +it for building using `WITH_GLUTAPPLICATION` CMake parameter. On newer systems, +Mac OS X and Windows you might want to use SDL2 toolkit instead, it is enabled +using `WITH_SDL2APPLICATION` CMake parameter. @section getting-started-bootstrap Download bootstrap project @@ -52,6 +54,12 @@ extract it somewhere. Do it rather than cloning the full repository, as it's better to init your own repository from scratch to avoid having the history polluted. +If you want to use SDL2 instead of GLUT, download the `base-sdl2` branch +[archive](https://github.com/mosra/magnum-bootstrap/archive/base-sdl2.zip). +The code will be slightly different from what is presented below, but the +changes are only minor (two modified lines and one additional file) and the +main principles are the same. + @section getting-started-review Review project structure The base project consists of just six files in two subfolders. %Magnum uses From a93774eeb29620e3585ef4ba19432b4c51d35a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 2 Feb 2014 10:14:32 +0100 Subject: [PATCH 61/86] doc: update Getting Started for MSVC too. --- doc/getting-started.dox | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/doc/getting-started.dox b/doc/getting-started.dox index 4b271c8c5..adcdd39a7 100644 --- a/doc/getting-started.dox +++ b/doc/getting-started.dox @@ -152,14 +152,26 @@ of build dir: make ./src/MyApplication -On Windows, if you don't want to touch the command-line, the easiest way is to -open root `CMakeLists.txt` in QtCreator, let it import the project and then -just build and run the application. If CMake isn't able to find the -dependencies or the building fails for some reason, you might want to look at -@ref building-windows-troubleshooting. - -If CMake complains about `GlutApplication` missing, you forgot to enable -`WITH_GLUTAPPLICATION` when building %Magnum, @ref getting-started-download "go back and fix it". +On Windows you can use either MinGW or MSVC 2013 compiler. It's then up to you +whether you will use QtCreator or Visual Studio. With Visual Studio the most +straightforward way to create the project file is via the command-line: + + mkdir build + cd build + cmake -DCMAKE_FIND_ROOT_PATH="C:/Sys" .. + +You can also use CMake GUI. Then open the `MyApplication.sln` project file +generated by CMake in the build directory. + +With QtCreator just open project's root `CMakeLists.txt` file. It then asks you +where to create build directory, allows you to specify initial CMake parameters +(e.g. `CMAKE_FIND_ROOT_PATH`) and then you can just press *Configure* and +everything is ready to be built. + +If CMake isn't able to find the dependencies on Windows, you might want to look +at @ref building-windows. If CMake complains about `GlutApplication` missing, +you forgot to enable `WITH_GLUTAPPLICATION` when building %Magnum, +@ref getting-started-download "go back and fix it". @image html getting-started.png @image latex getting-started.png From 2713d0f725006e68e648be2cf5560bf7a364afb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 2 Feb 2014 10:14:59 +0100 Subject: [PATCH 62/86] Doc++ --- src/Magnum/Audio/Source.h | 8 ++++---- src/Magnum/MeshTools/CombineIndexedArrays.h | 2 +- src/Magnum/MeshTools/RemoveDuplicates.h | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Audio/Source.h b/src/Magnum/Audio/Source.h index 33fe1d3e7..e80a63bb8 100644 --- a/src/Magnum/Audio/Source.h +++ b/src/Magnum/Audio/Source.h @@ -389,7 +389,7 @@ class MAGNUM_AUDIO_EXPORT Source { #ifdef MAGNUM_BUILD_DEPRECATED /** * @copybrief play(const std::vector>&) - * @deprecated Use @ref Magnum::Audio::Source::play(const std::>&) "play(const std::vector>&)" instead. + * @deprecated Use @ref Magnum::Audio::Source::play(const std::vector>&) "play(const std::vector>&)" instead. */ static CORRADE_DEPRECATED("use play(const std::vector>&) instead") void play(const std::vector& sources); #endif @@ -410,7 +410,7 @@ class MAGNUM_AUDIO_EXPORT Source { #ifdef MAGNUM_BUILD_DEPRECATED /** * @copybrief pause(const std::vector>&) - * @deprecated Use @ref Magnum::Audio::Source::pause(const std::>&) "pause(const std::vector>&)" instead. + * @deprecated Use @ref Magnum::Audio::Source::pause(const std::vector>&) "pause(const std::vector>&)" instead. */ static CORRADE_DEPRECATED("use pause(const std::vector>&) instead") void pause(const std::vector& sources); #endif @@ -431,7 +431,7 @@ class MAGNUM_AUDIO_EXPORT Source { #ifdef MAGNUM_BUILD_DEPRECATED /** * @copybrief stop(const std::vector>&) - * @deprecated Use @ref Magnum::Audio::Source::stop(const std::>&) "stop(const std::vector>&)" instead. + * @deprecated Use @ref Magnum::Audio::Source::stop(const std::vector>&) "stop(const std::vector>&)" instead. */ static CORRADE_DEPRECATED("use stop(const std::vector>&) instead") void stop(const std::vector& sources); #endif @@ -458,7 +458,7 @@ class MAGNUM_AUDIO_EXPORT Source { /** * @copybrief rewind(const std::vector>&) - * @deprecated Use @ref Magnum::Audio::Source::rewind(const std::>&) "rewind(const std::vector>&)" instead. + * @deprecated Use @ref Magnum::Audio::Source::rewind(const std::vector>&) "rewind(const std::vector>&)" instead. */ static CORRADE_DEPRECATED("use rewind(const std::vector>&) instead") void rewind(const std::vector& sources); #endif diff --git a/src/Magnum/MeshTools/CombineIndexedArrays.h b/src/Magnum/MeshTools/CombineIndexedArrays.h index 8c5ae946f..c52b72199 100644 --- a/src/Magnum/MeshTools/CombineIndexedArrays.h +++ b/src/Magnum/MeshTools/CombineIndexedArrays.h @@ -77,7 +77,7 @@ which can be then indexed with the combined index array: Again, first triangle in the mesh will have positions `a c f` and normals `B D E`. -This function calls @ref combineIndexArrays(std::vector&, UnsignedInt) +This function calls @ref combineIndexArrays(const std::vector&, UnsignedInt) internally. See also @ref combineIndexedArrays() which does the vertex data reordering automatically. */ diff --git a/src/Magnum/MeshTools/RemoveDuplicates.h b/src/Magnum/MeshTools/RemoveDuplicates.h index b2c58a807..6b5b40715 100644 --- a/src/Magnum/MeshTools/RemoveDuplicates.h +++ b/src/Magnum/MeshTools/RemoveDuplicates.h @@ -168,6 +168,10 @@ template std::vector removeDuplicates(std::vector&, typename Vector::Type) +@deprecated Use @ref Magnum::MeshTools::removeDuplicates(std::vector&, typename Vector::Type) "removeDuplicates(std::vector&, typename Vector::Type)" instead. +*/ template void removeDuplicates(std::vector& indices, std::vector& data, typename Vector::Type epsilon = Math::TypeTraits::epsilon()) { std::vector uniqueIndices; std::tie(uniqueIndices, data) = removeDuplicates(data); From 3c64b371ac5f508565140655e04662c541f4f1b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 2 Feb 2014 10:16:33 +0100 Subject: [PATCH 63/86] Audio: remove useless deprecated function. The std::vector overload is enough. I removed it everywhere else but not here? Was I drunk or what. --- src/Magnum/Audio/Source.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Magnum/Audio/Source.h b/src/Magnum/Audio/Source.h index e80a63bb8..2c9402f15 100644 --- a/src/Magnum/Audio/Source.h +++ b/src/Magnum/Audio/Source.h @@ -450,12 +450,6 @@ class MAGNUM_AUDIO_EXPORT Source { static void rewind(const std::vector>& sources); /**< @overload */ #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @copybrief rewind(std::initializer_list>) - * @deprecated Use @ref Magnum::Audio::Source::rewind(std::initializer_list>) "rewind(std::initializer_list>)" instead. - */ - static CORRADE_DEPRECATED("use rewind(std::initializer_list>) instead") void rewind(std::initializer_list sources); - /** * @copybrief rewind(const std::vector>&) * @deprecated Use @ref Magnum::Audio::Source::rewind(const std::vector>&) "rewind(const std::vector>&)" instead. From 5a7919322750abdfece8b0bdcf50280efa6584b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 3 Feb 2014 23:08:07 +0100 Subject: [PATCH 64/86] Trade: allow objects without materials. --- src/Magnum/Trade/MeshObjectData2D.cpp | 2 +- src/Magnum/Trade/MeshObjectData2D.h | 14 +++++++++----- src/Magnum/Trade/MeshObjectData3D.cpp | 2 +- src/Magnum/Trade/MeshObjectData3D.h | 14 +++++++++----- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Magnum/Trade/MeshObjectData2D.cpp b/src/Magnum/Trade/MeshObjectData2D.cpp index ba2c6d806..f0b5c283c 100644 --- a/src/Magnum/Trade/MeshObjectData2D.cpp +++ b/src/Magnum/Trade/MeshObjectData2D.cpp @@ -27,6 +27,6 @@ namespace Magnum { namespace Trade { -MeshObjectData2D::MeshObjectData2D(std::vector children, const Matrix3& transformation, UnsignedInt instance, UnsignedInt material): ObjectData2D(std::move(children), transformation, ObjectInstanceType2D::Mesh, instance), _material(material) {} +MeshObjectData2D::MeshObjectData2D(std::vector children, const Matrix3& transformation, UnsignedInt instance, Int material): ObjectData2D(std::move(children), transformation, ObjectInstanceType2D::Mesh, instance), _material(material) {} }} diff --git a/src/Magnum/Trade/MeshObjectData2D.h b/src/Magnum/Trade/MeshObjectData2D.h index 4708da31f..4a59eee30 100644 --- a/src/Magnum/Trade/MeshObjectData2D.h +++ b/src/Magnum/Trade/MeshObjectData2D.h @@ -46,11 +46,11 @@ class MAGNUM_EXPORT MeshObjectData2D: public ObjectData2D { * @param children Child objects * @param transformation Transformation (relative to parent) * @param instance Instance ID - * @param material Material ID + * @param material Material ID or `-1` * * Creates object with mesh instance type. */ - explicit MeshObjectData2D(std::vector children, const Matrix3& transformation, UnsignedInt instance, UnsignedInt material); + explicit MeshObjectData2D(std::vector children, const Matrix3& transformation, UnsignedInt instance, Int material); /** @brief Copying is not allowed */ MeshObjectData2D(const MeshObjectData2D&) = delete; @@ -64,11 +64,15 @@ class MAGNUM_EXPORT MeshObjectData2D: public ObjectData2D { /** @brief Move assignment */ MeshObjectData2D& operator=(MeshObjectData2D&&) = default; - /** @brief Material ID */ - UnsignedInt material() const { return _material; } + /** + * @brief Material ID + * + * Returns `-1` if the object has no material assigned. + */ + Int material() const { return _material; } private: - UnsignedInt _material; + Int _material; }; }} diff --git a/src/Magnum/Trade/MeshObjectData3D.cpp b/src/Magnum/Trade/MeshObjectData3D.cpp index 2b5812f76..84f0333b1 100644 --- a/src/Magnum/Trade/MeshObjectData3D.cpp +++ b/src/Magnum/Trade/MeshObjectData3D.cpp @@ -27,6 +27,6 @@ namespace Magnum { namespace Trade { -MeshObjectData3D::MeshObjectData3D(std::vector children, const Matrix4& transformation, UnsignedInt instance, UnsignedInt material): ObjectData3D(std::move(children), transformation, ObjectInstanceType3D::Mesh, instance), _material(material) {} +MeshObjectData3D::MeshObjectData3D(std::vector children, const Matrix4& transformation, UnsignedInt instance, Int material): ObjectData3D(std::move(children), transformation, ObjectInstanceType3D::Mesh, instance), _material(material) {} }} diff --git a/src/Magnum/Trade/MeshObjectData3D.h b/src/Magnum/Trade/MeshObjectData3D.h index df8b5095e..dafe97632 100644 --- a/src/Magnum/Trade/MeshObjectData3D.h +++ b/src/Magnum/Trade/MeshObjectData3D.h @@ -46,11 +46,11 @@ class MAGNUM_EXPORT MeshObjectData3D: public ObjectData3D { * @param children Child objects * @param transformation Transformation (relative to parent) * @param instance Instance ID - * @param material Material ID + * @param material Material ID or `-1` * * Creates object with mesh instance type. */ - explicit MeshObjectData3D(std::vector children, const Matrix4& transformation, UnsignedInt instance, UnsignedInt material); + explicit MeshObjectData3D(std::vector children, const Matrix4& transformation, UnsignedInt instance, Int material); /** @brief Copying is not allowed */ MeshObjectData3D(const MeshObjectData3D&) = delete; @@ -64,11 +64,15 @@ class MAGNUM_EXPORT MeshObjectData3D: public ObjectData3D { /** @brief Move assignment */ MeshObjectData3D& operator=(MeshObjectData3D&&) = default; - /** @brief Material ID */ - UnsignedInt material() const { return _material; } + /** + * @brief Material ID + * + * Returns `-1` if the object has no material assigned. + */ + Int material() const { return _material; } private: - UnsignedInt _material; + Int _material; }; }} From c70f037add32a11ce444b02cb84d3ddbdea234bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 4 Feb 2014 12:03:33 +0100 Subject: [PATCH 65/86] Deprecate implicit conversion of Resource to U&. We are allowing implicit conversions only if they are harmless and this is *not* harmless, as it might fire an assertion. The user should use operator*() or operator->() instead, which will make these conversions stand out more in the code. Also reduced code duplication. --- .../Implementation/CapsuleRenderer.cpp | 12 +++---- src/Magnum/Resource.h | 31 +++++++++++++------ 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp b/src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp index c897e9d97..5007e1e81 100644 --- a/src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp +++ b/src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp @@ -45,21 +45,21 @@ AbstractCapsuleRenderer<2>::AbstractCapsuleRenderer(): AbstractShapeRenderer<2>( /* Bottom hemisphere */ if(!(bottom = ResourceManager::instance().get("capsule2d-bottom"))) { - auto view = new MeshView(wireframeMesh); + auto view = new MeshView(*wireframeMesh); view->setIndexRange(0, rings*4, 0, rings*2+1); ResourceManager::instance().set(bottom.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); } /* Cylinder */ if(!(cylinder = ResourceManager::instance().get("capsule2d-cylinder"))) { - auto view = new MeshView(wireframeMesh); + auto view = new MeshView(*wireframeMesh); view->setIndexRange(rings*4, 4, rings*2+1, rings*2+3); ResourceManager::instance().set(cylinder.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); } /* Top hemisphere */ if(!(top = ResourceManager::instance().get("capsule2d-top"))) { - auto view = new MeshView(wireframeMesh); + auto view = new MeshView(*wireframeMesh); view->setIndexRange(rings*4+4, rings*4, rings*2+3, rings*4+4); ResourceManager::instance().set(top.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); } @@ -72,21 +72,21 @@ AbstractCapsuleRenderer<3>::AbstractCapsuleRenderer(): AbstractShapeRenderer<3>( /* Bottom hemisphere */ if(!(bottom = ResourceManager::instance().get("capsule3d-bottom"))) { - auto view = new MeshView(wireframeMesh); + auto view = new MeshView(*wireframeMesh); view->setIndexRange(0, rings*8, 0, rings*4+1); ResourceManager::instance().set(bottom.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); } /* Cylinder */ if(!(cylinder = ResourceManager::instance().get("capsule3d-cylinder"))) { - auto view = new MeshView(wireframeMesh); + auto view = new MeshView(*wireframeMesh); view->setIndexRange(rings*8, segments*4+8, rings*4+1, rings*4+segments*2+5); ResourceManager::instance().set(cylinder.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); } /* Top */ if(!(top = ResourceManager::instance().get("capsule3d-top"))) { - auto view = new MeshView(wireframeMesh); + auto view = new MeshView(*wireframeMesh); view->setIndexRange(rings*8+segments*4+8, rings*8, rings*4+segments*2+5, rings*8+segments*2+6); ResourceManager::instance().set(top.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); } diff --git a/src/Magnum/Resource.h b/src/Magnum/Resource.h index 77f472722..57d701a03 100644 --- a/src/Magnum/Resource.h +++ b/src/Magnum/Resource.h @@ -191,28 +191,39 @@ class Resource { * @brief Reference to resource data * * The resource must be loaded before accessing it. Use boolean - * conversion operator or state() for testing whether it is loaded. + * conversion operator or @ref state() for testing whether it is + * loaded. */ - operator U&() { + U& operator*() { acquire(); CORRADE_ASSERT(data, "Resource: accessing not loaded data with key" << key(), *static_cast(data)); return *static_cast(data); } - /** @overload */ + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @overload + * @deprecated Use the explicit @ref Magnum::Resource::operator*() "operator*()" or + * @ref Magnum::Resource::operator->() "operator->()" instead. + * Implicit conversion is no longer allowed if it might throw an + * assertion. + */ + CORRADE_DEPRECATED("use operator*() or operator->() instead") operator U&() { return **this; } + #endif + + /** + * @brief Access to resource data + * + * The resource must be loaded before accessing it. Use boolean + * conversion operator or @ref state() for testing whether it is + * loaded. + */ U* operator->() { acquire(); CORRADE_ASSERT(data, "Resource: accessing not loaded data with key" << key(), nullptr); return static_cast(data); } - /** @overload */ - U& operator*() { - acquire(); - CORRADE_ASSERT(data, "Resource: accessing not loaded data with key" << key(), *static_cast(data)); - return *static_cast(data); - } - private: Resource(Implementation::ResourceManagerData* manager, ResourceKey key): manager(manager), _key(key), lastCheck(0), _state(ResourceState::NotLoaded), data(nullptr) { manager->incrementReferenceCount(key); From 703ce0bd89fbf02ec42c46a1de9bd8cdb3cf6c15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 4 Feb 2014 12:18:56 +0100 Subject: [PATCH 66/86] Explicitly passing shader to Mesh*::draw(). Previously the API didn't encourage the user to set up and activate shader before drawing the meshes, leading to unintuitive behavior: // Can I just call draw() or do I have to fully understand the // meaning of the universe before? mesh.draw(); Now the draw() needs the shader passed explicitly as parameter, which should hint that the shader must be set up somehow: // Right, so this needs just a shader and that's all. Expecting this // I fortunately *did* configure all the uniforms before this call. mesh.draw(shader); It is also possible to pass the shader as rvalue, in case the drawing is just a one-off thing and is already fully configured. mesh.draw(MyShader{}); As usual, the original API is kept, is marked as deprecated and will be removed in some future release. --- doc/opengl-mapping.dox | 2 +- src/Magnum/AbstractShaderProgram.h | 28 +++++++------ src/Magnum/DebugTools/ForceRenderer.cpp | 5 +-- .../Implementation/AxisAlignedBoxRenderer.cpp | 5 +-- .../DebugTools/Implementation/BoxRenderer.cpp | 5 +-- .../Implementation/CapsuleRenderer.cpp | 9 ++--- .../Implementation/CylinderRenderer.cpp | 5 +-- .../Implementation/LineSegmentRenderer.cpp | 5 +-- .../Implementation/PointRenderer.cpp | 5 +-- .../Implementation/SphereRenderer.cpp | 5 +-- src/Magnum/DebugTools/ObjectRenderer.cpp | 6 +-- src/Magnum/Mesh.h | 40 ++++++++++++++----- src/Magnum/MeshView.cpp | 12 ++++++ src/Magnum/MeshView.h | 11 ++++- src/Magnum/ResourceManager.h | 3 +- src/Magnum/Shaders/Generic.h | 3 +- .../Test/AbstractShaderProgramGLTest.cpp | 12 ------ src/Magnum/Test/MeshGLTest.cpp | 7 +--- src/Magnum/Test/PrimitiveQueryGLTest.cpp | 3 +- src/Magnum/Test/SampleQueryGLTest.cpp | 10 ++--- src/Magnum/Text/Renderer.h | 6 +-- src/Magnum/TextureTools/DistanceField.cpp | 5 +-- 22 files changed, 103 insertions(+), 89 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 98d1c6a4a..c855e4bb8 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -248,7 +248,7 @@ OpenGL function | Matching API @fn_gl{Uniform}, \n @fn_gl{ProgramUniform}, \n @fn_gl_extension{ProgramUniform,EXT,direct_state_access} | @ref AbstractShaderProgram::setUniform() @fn_gl{UniformBlockBinding} | | @fn_gl{UniformSubroutines} | | -@fn_gl{UseProgram} | @ref AbstractShaderProgram::use() +@fn_gl{UseProgram} | @ref Mesh::draw(), @ref MeshView::draw() @fn_gl{UseProgramStages} | | @fn_gl{ValidateProgram} | @ref AbstractShaderProgram::validate() @fn_gl{ValidateProgramPipeline} | | diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index 09bc42fd9..7cdd763ae 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -248,19 +248,17 @@ Basic workflow with %AbstractShaderProgram subclasses is: instance shader class, configure attribute binding in meshes (see @ref Mesh-configuration "Mesh documentation" for more information) and map shader outputs to framebuffer attachments if needed (see @ref Framebuffer-usage "Framebuffer documentation" for more -information). In each draw event set uniforms, mark the shader for use, bind -specific framebuffer (if needed) and bind required textures to their -respective layers using @ref AbstractTexture::bind(Int). Then call -@ref Mesh::draw(). Example: +information). In each draw event set uniforms, bind specific framebuffer (if +needed) and bind required textures to their respective layers using +@ref AbstractTexture::bind(Int). Then call @ref Mesh::draw(). Example: @code shader.setTransformation(transformation) - .setProjection(projection) - .use(); + .setProjection(projection); diffuseTexture.bind(MyShader::DiffuseTextureLayer); specularTexture.bind(MyShader::SpecularTextureLayer); -mesh.draw(); +mesh.draw(shader); @endcode @section AbstractShaderProgram-types Mapping between GLSL and Magnum types @@ -303,9 +301,8 @@ also @ref Attribute::DataType enum for additional type options. @section AbstractShaderProgram-performance-optimization Performance optimizations -The engine tracks currently used shader program to avoid unnecessary calls to -@fn_gl{UseProgram}. %Shader limits (such as @ref maxVertexAttributes()) -are cached, so repeated queries don't result in repeated @fn_gl{Get} calls. +%Shader limits (such as @ref maxVertexAttributes()) are cached, so repeated +queries don't result in repeated @fn_gl{Get} calls. If extension @extension{ARB,separate_shader_objects} (part of OpenGL 4.1) or @extension{EXT,direct_state_access} is available, uniform setting functions @@ -323,6 +320,8 @@ comes in handy. @todo `GL_NUM_{PROGRAM,SHADER}_BINARY_FORMATS` + `GL_{PROGRAM,SHADER}_BINARY_FORMATS` (vector), (@extension{ARB,ES2_compatibility}) */ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { + friend class Mesh; + friend class MeshView; friend struct Implementation::ShaderProgramState; public: @@ -549,12 +548,13 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { */ std::pair validate(); + #ifdef MAGNUM_BUILD_DEPRECATED /** * @brief Use shader for rendering - * - * @see @fn_gl{UseProgram} + * @deprecated Use @ref Magnum::Mesh::draw(AbstractShaderProgram&) "Mesh::draw(AbstractShaderProgram&)" instead. */ void use(); + #endif protected: #ifndef MAGNUM_TARGET_GLES2 @@ -790,6 +790,10 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { #endif private: + #ifndef MAGNUM_BUILD_DEPRECATED + void use(); + #endif + void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLfloat* values); void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values); diff --git a/src/Magnum/DebugTools/ForceRenderer.cpp b/src/Magnum/DebugTools/ForceRenderer.cpp index 825c2406c..e763955a7 100644 --- a/src/Magnum/DebugTools/ForceRenderer.cpp +++ b/src/Magnum/DebugTools/ForceRenderer.cpp @@ -97,9 +97,8 @@ template ForceRenderer::ForceRenderer(SceneG template void ForceRenderer::draw(const typename DimensionTraits::MatrixType& transformationMatrix, SceneGraph::AbstractCamera& camera) { shader->setTransformationProjectionMatrix(camera.projectionMatrix()*Implementation::forceRendererTransformation(transformationMatrix.transformPoint(forcePosition), force)*DimensionTraits::MatrixType::scaling(typename DimensionTraits::VectorType(options->scale()))) - .setColor(options->color()) - .use(); - mesh->draw(); + .setColor(options->color()); + mesh->draw(*shader); } template class ForceRenderer<2>; diff --git a/src/Magnum/DebugTools/Implementation/AxisAlignedBoxRenderer.cpp b/src/Magnum/DebugTools/Implementation/AxisAlignedBoxRenderer.cpp index c84f1c810..33e014ca5 100644 --- a/src/Magnum/DebugTools/Implementation/AxisAlignedBoxRenderer.cpp +++ b/src/Magnum/DebugTools/Implementation/AxisAlignedBoxRenderer.cpp @@ -38,9 +38,8 @@ template void AxisAlignedBoxRenderer::draw(R AbstractBoxRenderer::wireframeShader->setTransformationProjectionMatrix(projectionMatrix* DimensionTraits::MatrixType::translation((axisAlignedBox.min()+axisAlignedBox.max())/2)* DimensionTraits::MatrixType::scaling(axisAlignedBox.max()-axisAlignedBox.min())) - .setColor(options->color()) - .use(); - AbstractBoxRenderer::wireframeMesh->draw(); + .setColor(options->color()); + AbstractBoxRenderer::wireframeMesh->draw(*AbstractBoxRenderer::wireframeShader); } template class AxisAlignedBoxRenderer<2>; diff --git a/src/Magnum/DebugTools/Implementation/BoxRenderer.cpp b/src/Magnum/DebugTools/Implementation/BoxRenderer.cpp index b47ef553d..e070188c9 100644 --- a/src/Magnum/DebugTools/Implementation/BoxRenderer.cpp +++ b/src/Magnum/DebugTools/Implementation/BoxRenderer.cpp @@ -36,9 +36,8 @@ template BoxRenderer::BoxRenderer(const Shap template void BoxRenderer::draw(Resource& options, const typename DimensionTraits::MatrixType& projectionMatrix) { AbstractBoxRenderer::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*box.transformation()) - .setColor(options->color()) - .use(); - AbstractBoxRenderer::wireframeMesh->draw(); + .setColor(options->color()); + AbstractBoxRenderer::wireframeMesh->draw(*AbstractBoxRenderer::wireframeShader); } template class BoxRenderer<2>; diff --git a/src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp b/src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp index 5007e1e81..2c46cd430 100644 --- a/src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp +++ b/src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp @@ -100,20 +100,19 @@ template CapsuleRenderer::CapsuleRenderer(co template void CapsuleRenderer::draw(Resource& options, const typename DimensionTraits::MatrixType& projectionMatrix) { std::array::MatrixType, 3> transformations = Implementation::capsuleRendererTransformation(capsule.a(), capsule.b(), capsule.radius()); - AbstractShapeRenderer::wireframeShader->setColor(options->color()) - .use(); + AbstractShapeRenderer::wireframeShader->setColor(options->color()); /* Bottom */ AbstractShapeRenderer::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*transformations[0]); - AbstractCapsuleRenderer::bottom->draw(); + AbstractCapsuleRenderer::bottom->draw(*AbstractShapeRenderer::wireframeShader); /* Cylinder */ AbstractShapeRenderer::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*transformations[1]); - AbstractCapsuleRenderer::cylinder->draw(); + AbstractCapsuleRenderer::cylinder->draw(*AbstractShapeRenderer::wireframeShader); /* Top */ AbstractShapeRenderer::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*transformations[2]); - AbstractCapsuleRenderer::top->draw(); + AbstractCapsuleRenderer::top->draw(*AbstractShapeRenderer::wireframeShader); } template class CapsuleRenderer<2>; diff --git a/src/Magnum/DebugTools/Implementation/CylinderRenderer.cpp b/src/Magnum/DebugTools/Implementation/CylinderRenderer.cpp index 7e6e14e6d..20f3e1798 100644 --- a/src/Magnum/DebugTools/Implementation/CylinderRenderer.cpp +++ b/src/Magnum/DebugTools/Implementation/CylinderRenderer.cpp @@ -51,9 +51,8 @@ template CylinderRenderer::CylinderRenderer( template void CylinderRenderer::draw(Resource& options, const typename DimensionTraits::MatrixType& projectionMatrix) { AbstractShapeRenderer::wireframeShader->setTransformationProjectionMatrix(projectionMatrix* Implementation::cylinderRendererTransformation(cylinder.a(), cylinder.b(), cylinder.radius())) - .setColor(options->color()) - .use(); - AbstractShapeRenderer::wireframeMesh->draw(); + .setColor(options->color()); + AbstractShapeRenderer::wireframeMesh->draw(*AbstractShapeRenderer::wireframeShader); } template class CylinderRenderer<2>; diff --git a/src/Magnum/DebugTools/Implementation/LineSegmentRenderer.cpp b/src/Magnum/DebugTools/Implementation/LineSegmentRenderer.cpp index be8ef4a46..956bbae84 100644 --- a/src/Magnum/DebugTools/Implementation/LineSegmentRenderer.cpp +++ b/src/Magnum/DebugTools/Implementation/LineSegmentRenderer.cpp @@ -58,9 +58,8 @@ template LineSegmentRenderer::LineSegmentRen template void LineSegmentRenderer::draw(Resource& options, const typename DimensionTraits::MatrixType& projectionMatrix) { AbstractShapeRenderer::wireframeShader->setTransformationProjectionMatrix(projectionMatrix* Implementation::lineSegmentRendererTransformation(line.a(), line.b())) - .setColor(options->color()) - .use(); - AbstractShapeRenderer::wireframeMesh->draw(); + .setColor(options->color()); + AbstractShapeRenderer::wireframeMesh->draw(*AbstractShapeRenderer::wireframeShader); } template class LineSegmentRenderer<2>; diff --git a/src/Magnum/DebugTools/Implementation/PointRenderer.cpp b/src/Magnum/DebugTools/Implementation/PointRenderer.cpp index f5434c2ef..29614f3da 100644 --- a/src/Magnum/DebugTools/Implementation/PointRenderer.cpp +++ b/src/Magnum/DebugTools/Implementation/PointRenderer.cpp @@ -58,9 +58,8 @@ template void PointRenderer::draw(Resource::wireframeShader->setTransformationProjectionMatrix(projectionMatrix* DimensionTraits::MatrixType::translation(point.position())* DimensionTraits::MatrixType::scaling(typename DimensionTraits::VectorType(options->pointSize()/2))) - .setColor(options->color()) - .use(); - AbstractShapeRenderer::wireframeMesh->draw(); + .setColor(options->color()); + AbstractShapeRenderer::wireframeMesh->draw(*AbstractShapeRenderer::wireframeShader); } template class PointRenderer<2>; diff --git a/src/Magnum/DebugTools/Implementation/SphereRenderer.cpp b/src/Magnum/DebugTools/Implementation/SphereRenderer.cpp index 58b454712..dbdf66ab4 100644 --- a/src/Magnum/DebugTools/Implementation/SphereRenderer.cpp +++ b/src/Magnum/DebugTools/Implementation/SphereRenderer.cpp @@ -50,9 +50,8 @@ template void SphereRenderer::draw(Resource< AbstractShapeRenderer::wireframeShader->setTransformationProjectionMatrix(projectionMatrix* DimensionTraits::MatrixType::translation(sphere.position())* DimensionTraits::MatrixType::scaling(typename DimensionTraits::VectorType(sphere.radius()))) - .setColor(options->color()) - .use(); - AbstractShapeRenderer::wireframeMesh->draw(); + .setColor(options->color()); + AbstractShapeRenderer::wireframeMesh->draw(*AbstractShapeRenderer::wireframeShader); } template class SphereRenderer<2>; diff --git a/src/Magnum/DebugTools/ObjectRenderer.cpp b/src/Magnum/DebugTools/ObjectRenderer.cpp index 618a2064c..669f8806a 100644 --- a/src/Magnum/DebugTools/ObjectRenderer.cpp +++ b/src/Magnum/DebugTools/ObjectRenderer.cpp @@ -175,10 +175,8 @@ template ObjectRenderer::ObjectRenderer(Scen } template void ObjectRenderer::draw(const typename DimensionTraits::MatrixType& transformationMatrix, SceneGraph::AbstractCamera& camera) { - shader->setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix*DimensionTraits::MatrixType::scaling(typename DimensionTraits::VectorType(options->size()))) - .use(); - - mesh->draw(); + shader->setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix*DimensionTraits::MatrixType::scaling(typename DimensionTraits::VectorType(options->size()))); + mesh->draw(*shader); } template class ObjectRenderer<2>; diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 243efe699..87b6e25c6 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -296,10 +296,11 @@ for more infromation) and call @ref Mesh::draw(). If @extension{APPLE,vertex_array_object} (part of OpenGL 3.0), OpenGL ES 3.0 or @es_extension{OES,vertex_array_object} on OpenGL ES 2.0 is supported, VAOs are used instead of binding the buffers and specifying vertex attribute pointers -in each @ref draw() call. The engine tracks currently bound VAO to avoid -unnecessary calls to @fn_gl{BindVertexArray}. %Mesh limits and -implementation-defined values (such as @ref maxVertexAttributes()) are cached, -so repeated queries don't result in repeated @fn_gl{Get} calls. +in each @ref draw() call. The engine tracks currently bound VAO and currently +active shader program to avoid unnecessary calls to @fn_gl{BindVertexArray} and +@fn_gl{UseProgram}. %Mesh limits and implementation-defined values (such as +@ref maxVertexAttributes()) are cached, so repeated queries don't result in +repeated @fn_gl{Get} calls. If extension @extension{EXT,direct_state_access} and VAOs are available, DSA functions are used for specifying attribute locations to avoid unnecessary @@ -607,14 +608,34 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { /** * @brief Draw the mesh + * @param shader Shader to use for drawing * - * Expects an active shader with all uniforms set. See + * Expects that the shader is compatible with this mesh and is fully + * set up. See also * @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" * for more information. - * @see @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer}, - * @fn_gl{VertexAttribPointer}, @fn_gl{DisableVertexAttribArray} - * or @fn_gl{BindVertexArray} (if @extension{APPLE,vertex_array_object} - * is available), @fn_gl{DrawArrays} or @fn_gl{DrawElements}/@fn_gl{DrawRangeElements}. + * @see @fn_gl{UseProgram}, @fn_gl{EnableVertexAttribArray}, + * @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer}, + * @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray} (if + * @extension{APPLE,vertex_array_object} is available), @fn_gl{DrawArrays} + * or @fn_gl{DrawElements}/@fn_gl{DrawRangeElements}. + */ + void draw(AbstractShaderProgram& shader) { + shader.use(); + + #ifndef MAGNUM_TARGET_GLES2 + drawInternal(0, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd); + #else + drawInternal(0, _vertexCount, _indexOffset, _indexCount); + #endif + } + + void draw(AbstractShaderProgram&& shader) { draw(shader); } /**< @overload */ + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief draw(AbstractShaderProgram&) + * @deprecated Use @ref Magnum::Mesh::draw(AbstractShaderProgram&) instead. */ void draw() { #ifndef MAGNUM_TARGET_GLES2 @@ -623,6 +644,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { drawInternal(0, _vertexCount, _indexOffset, _indexCount); #endif } + #endif private: #ifndef DOXYGEN_GENERATING_OUTPUT diff --git a/src/Magnum/MeshView.cpp b/src/Magnum/MeshView.cpp index ac8ea04a4..893b50c02 100644 --- a/src/Magnum/MeshView.cpp +++ b/src/Magnum/MeshView.cpp @@ -44,6 +44,17 @@ MeshView& MeshView::setIndexRange(Int first, Int count, UnsignedInt, UnsignedInt return *this; } +void MeshView::draw(AbstractShaderProgram& shader) { + shader.use(); + + #ifndef MAGNUM_TARGET_GLES2 + _original->drawInternal(_firstVertex, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd); + #else + _original->drawInternal(_firstVertex, _vertexCount, _indexOffset, _indexCount); + #endif +} + +#ifdef MAGNUM_BUILD_DEPRECATED void MeshView::draw() { #ifndef MAGNUM_TARGET_GLES2 _original->drawInternal(_firstVertex, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd); @@ -51,5 +62,6 @@ void MeshView::draw() { _original->drawInternal(_firstVertex, _vertexCount, _indexOffset, _indexCount); #endif } +#endif } diff --git a/src/Magnum/MeshView.h b/src/Magnum/MeshView.h index cde4452fc..4b137ea17 100644 --- a/src/Magnum/MeshView.h +++ b/src/Magnum/MeshView.h @@ -120,7 +120,16 @@ class MAGNUM_EXPORT MeshView { * * See @ref Mesh::draw() for more information. */ - void draw(); + void draw(AbstractShaderProgram& shader); + void draw(AbstractShaderProgram&& shader) { draw(shader); } /**< @overload */ + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief draw(AbstractShaderProgram&) + * @deprecated Use + */ + CORRADE_DEPRECATED("use draw(AbstractShaderProgram&) instead") void draw(); + #endif private: Mesh* _original; diff --git a/src/Magnum/ResourceManager.h b/src/Magnum/ResourceManager.h index 6fa15a672..56e7479f4 100644 --- a/src/Magnum/ResourceManager.h +++ b/src/Magnum/ResourceManager.h @@ -212,9 +212,8 @@ if(!cube) { @endcode - Using the resource data. @code -shader->use(); texture->bind(layer); -cube->draw(); +cube->draw(*shader); @endcode - Destroying resource references and deleting manager instance when nothing references the resources anymore. diff --git a/src/Magnum/Shaders/Generic.h b/src/Magnum/Shaders/Generic.h index f3090256e..315a0e851 100644 --- a/src/Magnum/Shaders/Generic.h +++ b/src/Magnum/Shaders/Generic.h @@ -54,8 +54,7 @@ mesh.addVertexBuffer(vertexBuffer, 0, Shaders::Phong phong; // ... -phong.use(); -mesh.draw(); +mesh.draw(phong); @endcode @see @ref Generic2D, @ref Generic3D diff --git a/src/Magnum/Test/AbstractShaderProgramGLTest.cpp b/src/Magnum/Test/AbstractShaderProgramGLTest.cpp index 6e64fa06a..153dd8ba6 100644 --- a/src/Magnum/Test/AbstractShaderProgramGLTest.cpp +++ b/src/Magnum/Test/AbstractShaderProgramGLTest.cpp @@ -199,10 +199,6 @@ void AbstractShaderProgramGLTest::create() { CORRADE_VERIFY(multiplierUniform >= 0); CORRADE_VERIFY(colorUniform >= 0); CORRADE_VERIFY(additionsUniform >= 0); - - program.use(); - - MAGNUM_VERIFY_NO_ERROR(); } void AbstractShaderProgramGLTest::createMultipleOutputs() { @@ -236,10 +232,6 @@ void AbstractShaderProgramGLTest::createMultipleOutputs() { MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(linked); CORRADE_VERIFY(valid); - - program.use(); - - MAGNUM_VERIFY_NO_ERROR(); #elif !defined(MAGNUM_TARGET_GLES2) CORRADE_SKIP("Only explicit location specification supported in ES 3.0."); #else @@ -278,10 +270,6 @@ void AbstractShaderProgramGLTest::createMultipleOutputsIndexed() { MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(linked); CORRADE_VERIFY(valid); - - program.use(); - - MAGNUM_VERIFY_NO_ERROR(); } #endif diff --git a/src/Magnum/Test/MeshGLTest.cpp b/src/Magnum/Test/MeshGLTest.cpp index 8ec197adf..f9a608780 100644 --- a/src/Magnum/Test/MeshGLTest.cpp +++ b/src/Magnum/Test/MeshGLTest.cpp @@ -393,12 +393,11 @@ Checker::Checker(AbstractShaderProgram&& shader, RenderbufferFormat format, Mesh framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer); framebuffer.bind(FramebufferTarget::ReadDraw); - shader.use(); mesh.setVertexCount(2) .setPrimitive(MeshPrimitive::Points); /* Skip first vertex so we test also offsets */ - MeshView(mesh).setVertexRange(1, 1).draw(); + MeshView(mesh).setVertexRange(1, 1).draw(shader); } template T Checker::get(ColorFormat format, ColorType type) { @@ -1148,13 +1147,11 @@ IndexChecker::IndexChecker(Mesh& mesh): framebuffer({{}, Vector2i(1)}) { framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer); framebuffer.bind(FramebufferTarget::ReadDraw); - MultipleShader shader; - shader.use(); mesh.setIndexCount(2) .setPrimitive(MeshPrimitive::Points); /* Skip first vertex so we test also offsets */ - MeshView(mesh).setIndexRange(1, 1).draw(); + MeshView(mesh).setIndexRange(1, 1).draw(MultipleShader{}); } Color4ub IndexChecker::get() { diff --git a/src/Magnum/Test/PrimitiveQueryGLTest.cpp b/src/Magnum/Test/PrimitiveQueryGLTest.cpp index cd017599b..d2509454e 100644 --- a/src/Magnum/Test/PrimitiveQueryGLTest.cpp +++ b/src/Magnum/Test/PrimitiveQueryGLTest.cpp @@ -97,8 +97,7 @@ void PrimitiveQueryGLTest::query() { q.begin(PrimitiveQuery::Target::PrimitivesGenerated); framebuffer.bind(FramebufferTarget::ReadDraw); - shader.use(); - mesh.draw(); + mesh.draw(shader); q.end(); const bool availableBefore = q.resultAvailable(); diff --git a/src/Magnum/Test/SampleQueryGLTest.cpp b/src/Magnum/Test/SampleQueryGLTest.cpp index cb62b80b5..39b6ffdd6 100644 --- a/src/Magnum/Test/SampleQueryGLTest.cpp +++ b/src/Magnum/Test/SampleQueryGLTest.cpp @@ -127,8 +127,7 @@ void SampleQueryGLTest::querySamplesPassed() { #endif framebuffer.bind(FramebufferTarget::ReadDraw); - shader.use(); - mesh.draw(); + mesh.draw(shader); q.end(); const bool availableBefore = q.resultAvailable(); @@ -167,7 +166,6 @@ void SampleQueryGLTest::conditionalRender() { MyShader shader; framebuffer.bind(FramebufferTarget::ReadDraw); - shader.use(); MAGNUM_VERIFY_NO_ERROR(); @@ -175,13 +173,13 @@ void SampleQueryGLTest::conditionalRender() { /* This should generate some samples */ qYes.begin(SampleQuery::Target::SamplesPassed); - mesh.draw(); + mesh.draw(shader); qYes.end(); /* Thus this should be rendered */ qYes.beginConditionalRender(SampleQuery::ConditionalRenderMode::Wait); q.begin(SampleQuery::Target::SamplesPassed); - mesh.draw(); + mesh.draw(shader); q.end(); qYes.endConditionalRender(); @@ -196,7 +194,7 @@ void SampleQueryGLTest::conditionalRender() { /* Thus this should not be rendered */ qNo.beginConditionalRender(SampleQuery::ConditionalRenderMode::Wait); q.begin(SampleQuery::Target::SamplesPassed); - mesh.draw(); + mesh.draw(shader); q.end(); qNo.endConditionalRender(); diff --git a/src/Magnum/Text/Renderer.h b/src/Magnum/Text/Renderer.h index 0ca6f2a8c..58dad37ab 100644 --- a/src/Magnum/Text/Renderer.h +++ b/src/Magnum/Text/Renderer.h @@ -191,9 +191,8 @@ std::tie(mesh, rectangle) = Text::Renderer2D::render(*font, cache, 0.15f, // Draw white text centered on the screen shader.setTransformationProjectionMatrix(projection*Matrix3::translation(-rectangle.width()/2.0f)) .setColor(Color3(1.0f)); - .use(); glyphCache->texture()->bind(Shaders::VectorShader2D::FontTextureLayer); -mesh.draw(); +mesh.draw(shader); @endcode See @ref render(AbstractFont&, const GlyphCache&, Float, const std::string&, Alignment) and @ref render(AbstractFont&, const GlyphCache&, Float, const std::string&, Buffer&, Buffer&, BufferUsage, Alignment) @@ -217,9 +216,8 @@ renderer.render("Hello World Countdown: 10"); // Draw the text centered on the screen shader.setTransformationProjectionMatrix(projection*Matrix3::translation(-renderer.rectangle().width()/2.0f)) .setColor(Color3(1.0f)); - .use(); glyphCache->texture()->bind(Shaders::VectorShader2D::FontTextureLayer); -renderer.mesh().draw(); +renderer.mesh().draw(shader); @endcode @section Renderer-extensions Required OpenGL functionality diff --git a/src/Magnum/TextureTools/DistanceField.cpp b/src/Magnum/TextureTools/DistanceField.cpp index b5ba59b17..21d9d247b 100644 --- a/src/Magnum/TextureTools/DistanceField.cpp +++ b/src/Magnum/TextureTools/DistanceField.cpp @@ -162,8 +162,7 @@ void distanceField(Texture2D& input, Texture2D& output, const Range2Di& rectangl DistanceFieldShader shader; shader.setRadius(radius) - .setScaling(Vector2(imageSize)/Vector2(rectangle.size())) - .use(); + .setScaling(Vector2(imageSize)/Vector2(rectangle.size())); input.bind(DistanceFieldShader::TextureLayer); @@ -198,7 +197,7 @@ void distanceField(Texture2D& input, Texture2D& output, const Range2Di& rectangl } /* Draw the mesh */ - mesh.draw(); + mesh.draw(shader); } }} From cef4fde3985d08a3529d5c42441ede7f411d438f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 4 Feb 2014 12:28:54 +0100 Subject: [PATCH 67/86] DebugTools: fix obsolete reference in documentation. --- src/Magnum/DebugTools/Profiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/DebugTools/Profiler.h b/src/Magnum/DebugTools/Profiler.h index 6de886d6e..85b2070df 100644 --- a/src/Magnum/DebugTools/Profiler.h +++ b/src/Magnum/DebugTools/Profiler.h @@ -76,7 +76,7 @@ void MyApplication::drawEvent() { p.start(sections.draw); - scene.draw() + camera.draw(drawables); p.start(sections.bufferSwap); From b1be44845342df615619b5c68e841cf24cddd647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 4 Feb 2014 12:29:25 +0100 Subject: [PATCH 68/86] doc: hint that these function actually take some parameters. This looked like valid code, which is not. --- doc/scenegraph.dox | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/scenegraph.dox b/doc/scenegraph.dox index 877d48704..85ec71c42 100644 --- a/doc/scenegraph.dox +++ b/doc/scenegraph.dox @@ -165,10 +165,10 @@ class Bomb: public Object3D, SceneGraph::Drawable3D, SceneGraph::Animable3D { protected: // drawing implementation for Drawable feature - void draw() override; + void draw(...) override; // animation step for Animable feature - void animationStep() override; + void animationStep(...) override; }; @endcode From 7376e8f36d5e024ce99465f461c99e64eac2629c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 4 Feb 2014 16:07:00 +0100 Subject: [PATCH 69/86] Use functions to bind textures to shader rather than *Texture::bind(). Why did I do this: * It is more clean, shorter and nice looking with method chaining, i.e. instead of: shader.setColor(...) .setOtherParam(5); texture1.bind(MyShader::Texture1Layer); texture2.bind(MyShader::Texture2Layer); We now have this: shader.setColor(...) .setOtherParam(5) .setTexture1(texture1) .setTexture2(texture2); * It is now also clear which texture type is expected, the layer constant did not say anything about type. * Also it is possible to use new features (multi bind, bindless textures etc.) while preserving the same public API. The only potential disadvantage is that the textures don't stay bound like uniform values do, but this become a non-issue with bindless textures. As usual, the old way is now deprecated and will be removed in some future release. --- src/Magnum/AbstractShaderProgram.h | 36 ++++++++-------- src/Magnum/AbstractTexture.h | 11 +++-- src/Magnum/BufferTexture.h | 9 ++-- src/Magnum/CubeMapTexture.h | 11 +++-- src/Magnum/CubeMapTextureArray.h | 5 +-- src/Magnum/MultisampleTexture.h | 3 +- src/Magnum/RectangleTexture.h | 7 ++-- src/Magnum/ResourceManager.h | 2 +- src/Magnum/Shaders/AbstractVector.cpp | 43 +++++++++++++++++++ src/Magnum/Shaders/AbstractVector.h | 18 +++++++- src/Magnum/Shaders/CMakeLists.txt | 1 + src/Magnum/Shaders/DistanceFieldVector.h | 8 ++++ src/Magnum/Shaders/Flat.cpp | 8 ++++ src/Magnum/Shaders/Flat.h | 33 +++++++++------ src/Magnum/Shaders/Phong.cpp | 24 +++++++++++ src/Magnum/Shaders/Phong.h | 51 ++++++++++++++++++----- src/Magnum/Shaders/Vector.h | 8 ++++ src/Magnum/Text/Renderer.h | 12 +++--- src/Magnum/Texture.h | 3 +- src/Magnum/TextureArray.h | 3 +- src/Magnum/TextureTools/DistanceField.cpp | 16 +++---- 21 files changed, 230 insertions(+), 82 deletions(-) create mode 100644 src/Magnum/Shaders/AbstractVector.cpp diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index 7cdd763ae..925345bc0 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -63,14 +63,6 @@ enum: UnsignedInt { NormalOutput = 1 }; @endcode -- **Layers for texture uniforms** to which the textures will be bound before - rendering, for example: -@code -enum: Int { - DiffuseTextureLayer = 0, - SpecularTextureLayer = 1 -}; -@endcode - **Uniform locations** for setting uniform data (see below) (private variables), for example: @code @@ -111,6 +103,18 @@ MyShader& setProjection(const Matrix4& matrix) { return *this; } @endcode +- **Texture setting functions** in which you bind the textures to particular + layers using @ref AbstractTexture::bind() and equivalent, for example: +@code +MyShader& setDiffuseTexture(Texture2D& texture) { + texture->bind(0); + return *this; +} +MyShader& setSpecularTexture(Texture2D& texture) { + texture->bind(1); + return *this; +} +@endcode @subsection AbstractShaderProgram-attribute-location Binding attribute location @@ -230,8 +234,8 @@ uniform sampler2D diffuseTexture; uniform sampler2D specularTexture; @endcode @code -setUniform(DiffuseTextureUniform, DiffuseTextureLayer); -setUniform(SpecularTextureUniform, SpecularTextureLayer); +setUniform(DiffuseTextureUniform, 0); +setUniform(SpecularTextureUniform, 1); @endcode @see @ref Shader::maxTextureImageUnits() @@ -248,15 +252,13 @@ Basic workflow with %AbstractShaderProgram subclasses is: instance shader class, configure attribute binding in meshes (see @ref Mesh-configuration "Mesh documentation" for more information) and map shader outputs to framebuffer attachments if needed (see @ref Framebuffer-usage "Framebuffer documentation" for more -information). In each draw event set uniforms, bind specific framebuffer (if -needed) and bind required textures to their respective layers using -@ref AbstractTexture::bind(Int). Then call @ref Mesh::draw(). Example: +information). In each draw event set all required shader parameters, bind +specific framebuffer (if needed) and then call @ref Mesh::draw(). Example: @code shader.setTransformation(transformation) - .setProjection(projection); - -diffuseTexture.bind(MyShader::DiffuseTextureLayer); -specularTexture.bind(MyShader::SpecularTextureLayer); + .setProjection(projection) + .setDiffuseTexture(diffuseTexture) + .setSpecularTexture(specularTexture); mesh.draw(shader); @endcode diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 5e41dc1d3..a13211979 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -208,10 +208,13 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { /** * @brief Bind texture for rendering * - * Sets current texture as active in given layer. The layer must be - * 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. + * 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. + * @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 * @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} */ diff --git a/src/Magnum/BufferTexture.h b/src/Magnum/BufferTexture.h index d80dd0722..a8a891d26 100644 --- a/src/Magnum/BufferTexture.h +++ b/src/Magnum/BufferTexture.h @@ -181,11 +181,10 @@ constexpr static Vector3 data[] = { buffer.setData(data, BufferUsage::StaticDraw); @endcode -The texture is bound to layer specified by shader via @ref bind(). In shader, -the texture is used via `samplerBuffer`, `isamplerBuffer` or `usamplerBuffer`. -Unlike in classic textures, coordinates for buffer textures are integer -coordinates passed to `texelFetch()`. See also @ref AbstractShaderProgram -documentation for more information. +In shader, the texture is used via `samplerBuffer`, `isamplerBuffer` or +`usamplerBuffer`. Unlike in classic textures, coordinates for buffer textures +are integer coordinates passed to `texelFetch()`. See @ref AbstractShaderProgram +documentation for more information about usage in shaders. @section BufferTexture-performance-optimization Performance optimizations diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index 8db6acaf7..7b2ce1363 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -69,12 +69,11 @@ texture.setMagnificationFilter(Sampler::Filter::Linear) // ... @endcode -The texture is bound to layer specified by shader via @ref bind(). In shader, -the texture is used via `samplerCube`, `samplerCubeShadow`, `isamplerCube` or -`usamplerCube`. Unlike in classic textures, coordinates for cube map textures -is signed three-part vector from the center of the cube, which intersects one -of the six sides of the cube map. See also @ref AbstractShaderProgram for more -information about usage in shaders. +In shader, the texture is used via `samplerCube`, `samplerCubeShadow`, +`isamplerCube` or `usamplerCube`. Unlike in classic textures, coordinates for +cube map textures is signed three-part vector from the center of the cube, +which intersects one of the six sides of the cube map. See +@ref AbstractShaderProgram for more information about usage in shaders. @see @ref Renderer::Feature::SeamlessCubeMapTexture, @ref CubeMapTextureArray, @ref Texture, @ref BufferTexture diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index a22b89ece..22cc837cc 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -67,12 +67,11 @@ for(std::size_t i = 0; i != 4; i += 6) { texture.generateMipmap(); @endcode -The texture is bound to layer specified by shader via @ref bind(). In shader, -the texture is used via `samplerCubeArray`, `samplerCubeArrayShadow`, +In shader, the texture is used via `samplerCubeArray`, `samplerCubeArrayShadow`, `isamplerCubeArray` or `usamplerCubeArray`. Unlike in classic textures, coordinates for cube map texture arrays is signed four-part vector. First three parts define vector from the center of the cube which intersects with one of -the six sides of the cube map, fourth part is layer in the array. See also +the six sides of the cube map, fourth part is layer in the array. See @ref AbstractShaderProgram for more information about usage in shaders. @see @ref Renderer::Feature::SeamlessCubeMapTexture, @ref CubeMapTexture, diff --git a/src/Magnum/MultisampleTexture.h b/src/Magnum/MultisampleTexture.h index cff1c1d2b..97c986b6d 100644 --- a/src/Magnum/MultisampleTexture.h +++ b/src/Magnum/MultisampleTexture.h @@ -52,8 +52,7 @@ also @ref AbstractTexture documentation for more information. @todoc Finish when fully implemented -The texture is bound to layer specified by shader via @ref bind(). In shader, -the texture is used via `sampler2DMS`/`sampler2DMSArray`, +In shader, the texture is used via `sampler2DMS`/`sampler2DMSArray`, `isampler2DMS`/`isampler2DMSArray` or `usampler2DMS`/`usampler2DMSArray`. See @ref AbstractShaderProgram documentation for more information about usage in shaders. diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index d31f4d02f..2d8c76c6c 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -59,10 +59,9 @@ texture.setMagnificationFilter(Sampler::Filter::Linear) .setSubImage({}, image); @endcode -The texture is bound to layer specified by shader via @ref bind(). In shader, -the texture is used via sampler2DRect`, `sampler2DRectShadow`, `isampler2DRect` -or `usampler2DRect`. See @ref AbstractShaderProgram documentation for more -information about usage in shaders. +In shader, the texture is used via sampler2DRect`, `sampler2DRectShadow`, +`isampler2DRect` or `usampler2DRect`. See @ref AbstractShaderProgram +documentation for more information about usage in shaders. @requires_gl31 %Extension @extension{ARB,texture_rectangle} @requires_gl Rectangle textures are not available in OpenGL ES. diff --git a/src/Magnum/ResourceManager.h b/src/Magnum/ResourceManager.h index 56e7479f4..1030abc0f 100644 --- a/src/Magnum/ResourceManager.h +++ b/src/Magnum/ResourceManager.h @@ -212,7 +212,7 @@ if(!cube) { @endcode - Using the resource data. @code -texture->bind(layer); +shader->setTexture(layer); cube->draw(*shader); @endcode - Destroying resource references and deleting manager instance when nothing diff --git a/src/Magnum/Shaders/AbstractVector.cpp b/src/Magnum/Shaders/AbstractVector.cpp new file mode 100644 index 000000000..e06d09cc9 --- /dev/null +++ b/src/Magnum/Shaders/AbstractVector.cpp @@ -0,0 +1,43 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "AbstractVector.h" + +#include "Magnum/Texture.h" +#include "Magnum/Shaders/visibility.h" + +namespace Magnum { namespace Shaders { + +template AbstractVector& AbstractVector::setVectorTexture(Texture2D& texture) { + texture.bind(VectorTextureLayer); + return *this; +} + +#ifndef DOXYGEN_GENERATING_OUTPUT +template class MAGNUM_SHADERS_EXPORT AbstractVector<2>; +template class MAGNUM_SHADERS_EXPORT AbstractVector<3>; +#endif + +}} diff --git a/src/Magnum/Shaders/AbstractVector.h b/src/Magnum/Shaders/AbstractVector.h index b32be523b..fea2df38f 100644 --- a/src/Magnum/Shaders/AbstractVector.h +++ b/src/Magnum/Shaders/AbstractVector.h @@ -46,13 +46,29 @@ template class AbstractVector: public AbstractShaderProg /** @brief Texture coordinates */ typedef typename Generic::TextureCoordinates TextureCoordinates; + #ifdef MAGNUM_BUILD_DEPRECATED enum: Int { - VectorTextureLayer = 16 /**< Layer for vector texture */ + /** + * Layer for vector texture + * @deprecated Use @ref Magnum::Shaders::AbstractVector::setVectorTexture() "setVectorTexture()" instead. + */ + VectorTextureLayer = 16 }; + #endif + + /** + * @brief Set vector texture + * @return Reference to self (for method chaining) + */ + AbstractVector& setVectorTexture(Texture2D& texture); protected: explicit AbstractVector() = default; ~AbstractVector() = default; + + #ifndef MAGNUM_BUILD_DEPRECATED + enum: Int { VectorTextureLayer = 16 }; + #endif }; /** @brief Base for two-dimensional text shaders */ diff --git a/src/Magnum/Shaders/CMakeLists.txt b/src/Magnum/Shaders/CMakeLists.txt index 90714d0b4..0405f7529 100644 --- a/src/Magnum/Shaders/CMakeLists.txt +++ b/src/Magnum/Shaders/CMakeLists.txt @@ -26,6 +26,7 @@ corrade_add_resource(MagnumShaders_RCS resources.conf) set(MagnumShaders_SRCS + AbstractVector.cpp DistanceFieldVector.cpp Flat.cpp MeshVisualizer.cpp diff --git a/src/Magnum/Shaders/DistanceFieldVector.h b/src/Magnum/Shaders/DistanceFieldVector.h index de8316074..f81ce05b4 100644 --- a/src/Magnum/Shaders/DistanceFieldVector.h +++ b/src/Magnum/Shaders/DistanceFieldVector.h @@ -116,6 +116,14 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector return *this; } + #ifndef DOXYGEN_GENERATING_OUTPUT + /* Overloads to remove WTF-factor from method chaining order */ + DistanceFieldVector& setVectorTexture(Texture2D& texture) { + AbstractVector::setVectorTexture(texture); + return *this; + } + #endif + private: Int transformationProjectionMatrixUniform, colorUniform, diff --git a/src/Magnum/Shaders/Flat.cpp b/src/Magnum/Shaders/Flat.cpp index 0fab460cb..b70085413 100644 --- a/src/Magnum/Shaders/Flat.cpp +++ b/src/Magnum/Shaders/Flat.cpp @@ -30,10 +30,13 @@ #include "Magnum/Context.h" #include "Magnum/Extensions.h" #include "Magnum/Shader.h" +#include "Magnum/Texture.h" namespace Magnum { namespace Shaders { namespace { + enum: Int { TextureLayer = 0 }; + template constexpr const char* vertexShaderName(); template<> constexpr const char* vertexShaderName<2>() { return "Flat2D.vert"; } template<> constexpr const char* vertexShaderName<3>() { return "Flat3D.vert"; } @@ -96,6 +99,11 @@ template Flat::Flat(const Flags flags): tran #endif } +template Flat& Flat::setTexture(Texture2D& texture) { + if(_flags & Flag::Textured) texture.bind(TextureLayer); + return *this; +} + template class Flat<2>; template class Flat<3>; diff --git a/src/Magnum/Shaders/Flat.h b/src/Magnum/Shaders/Flat.h index ffbc7c4d6..e64afdd2a 100644 --- a/src/Magnum/Shaders/Flat.h +++ b/src/Magnum/Shaders/Flat.h @@ -52,15 +52,9 @@ need to provide @ref Position attribute in your triangle mesh and call at least If you want to use texture instead of color, you need to provide also @ref TextureCoordinates attribute. Pass @ref Flag::Textured to constructor and -then at render time bind the texture to its respective layer instead of calling -@ref setColor(). Example: -@code -Shaders::Flat2D shader(Shaders::Flat2D::Flag::Textured); - -// ... - -myTexture.bind(Shaders::Flat2D::TextureLayer); -@endcode +then at render time don't forget to set also the texture via @ref setTexture(). +The texture will be multiplied with the color (which is white by default, thus +it doesn't change texture color). For coloring the texture based on intensity you can use the @ref Vector shader. @see @ref Flat2D, @ref Flat3D @@ -77,10 +71,15 @@ template class MAGNUM_SHADERS_EXPORT Flat: public Abstra */ typedef typename Generic::TextureCoordinates TextureCoordinates; + #ifdef MAGNUM_BUILD_DEPRECATED enum: Int { - /** Layer for color texture. Used only if @ref Flag::Textured is set. */ + /** + * Layer for color texture. Used only if @ref Flag::Textured is set. + * @deprecated use @ref Magnum::Shaders::Flat::setTexture() "setTexture()" instead. + */ TextureLayer = 0 }; + #endif #ifdef DOXYGEN_GENERATING_OUTPUT /** @@ -125,11 +124,21 @@ template class MAGNUM_SHADERS_EXPORT Flat: public Abstra * @brief Set color * @return Reference to self (for method chaining) * - * Color will be multiplied with texture - * if @ref Flag::Textured is set. + * If not set, default value is fully opaque white. Color will be + * multiplied with texture if @ref Flag::Textured is set. + * @see @ref setTexture() */ Flat& setColor(const Color4& color); + /** + * @brief Set texture + * @return Reference to self (for method chaining) + * + * Has effect only if @ref Flag::Textured is set. + * @see @ref setColor() + */ + Flat& setTexture(Texture2D& texture); + private: Int transformationProjectionMatrixUniform, colorUniform; diff --git a/src/Magnum/Shaders/Phong.cpp b/src/Magnum/Shaders/Phong.cpp index feb810a6c..bb88002c3 100644 --- a/src/Magnum/Shaders/Phong.cpp +++ b/src/Magnum/Shaders/Phong.cpp @@ -30,9 +30,18 @@ #include "Magnum/Context.h" #include "Magnum/Extensions.h" #include "Magnum/Shader.h" +#include "Magnum/Texture.h" namespace Magnum { namespace Shaders { +namespace { + enum: Int { + AmbientTextureLayer = 0, + DiffuseTextureLayer = 1, + SpecularTextureLayer = 2 + }; +} + Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatrixUniform(1), normalMatrixUniform(2), lightUniform(3), diffuseColorUniform(4), ambientColorUniform(5), specularColorUniform(6), lightColorUniform(7), shininessUniform(8), _flags(flags) { Utility::Resource rs("MagnumShaders"); @@ -105,4 +114,19 @@ Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatri #endif } +Phong& Phong::setAmbientTexture(Texture2D& texture) { + if(_flags & Flag::AmbientTexture) texture.bind(AmbientTextureLayer); + return *this; +} + +Phong& Phong::setDiffuseTexture(Texture2D& texture) { + if(_flags & Flag::DiffuseTexture) texture.bind(DiffuseTextureLayer); + return *this; +} + +Phong& Phong::setSpecularTexture(Texture2D& texture) { + if(_flags & Flag::SpecularTexture) texture.bind(SpecularTextureLayer); + return *this; +} + }} diff --git a/src/Magnum/Shaders/Phong.h b/src/Magnum/Shaders/Phong.h index 42bff2819..d864c2aad 100644 --- a/src/Magnum/Shaders/Phong.h +++ b/src/Magnum/Shaders/Phong.h @@ -46,15 +46,8 @@ call at least @ref setTransformationMatrix(), @ref setNormalMatrix(), If you want to use texture instead of color, you need to provide also @ref TextureCoordinates attribute. Pass appropriate flags to constructor and -then at render time bind the texture to its respective layer instead of setting -the color. Example: -@code -Shaders::Phong shader(Shaders::Phong::Flag::DiffuseTexture); - -// ... - -myDiffuseTexture.bind(Shaders::Phong::DiffuseTextureLayer); -@endcode +then at render time don't forget to also call appropriate subset of +@ref setAmbientTexture(), @ref setDiffuseTexture() and @ref setSpecularTexture(). */ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { public: @@ -69,25 +62,33 @@ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { */ typedef Generic3D::TextureCoordinates TextureCoordinates; + #ifdef MAGNUM_BUILD_DEPRECATED enum: Int { /** * Layer for ambient texture. Used only if @ref Flag::AmbientTexture * is set. + * @deprecated Use @ref Magnum::Shaders::Phong::setAmbientTexture() "setAmbientTexture()" + * instead. */ AmbientTextureLayer = 0, /** * Layer for diffuse texture. Used only if @ref Flag::DiffuseTexture * is set. + * @deprecated Use @ref Magnum::Shaders::Phong::setDiffuseTexture() "setDiffuseTexture()" + * instead. */ DiffuseTextureLayer = 1, /** * Layer for specular texture. Used only if @ref Flag::SpecularTexture * is set. + * @deprecated Use @ref Magnum::Shaders::Phong::setSpecularTexture() "setSpecularTexture()" + * instead. */ SpecularTextureLayer = 2 }; + #endif /** * @brief Shader flag @@ -122,26 +123,56 @@ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { * * If not set, default value is `(0.0f, 0.0f, 0.0f)`. Has no effect if * @ref Flag::AmbientTexture is set. + * @see @ref setAmbientTexture() */ Phong& setAmbientColor(const Color3& color); + /** + * @brief Set ambient texture + * @return Reference to self (for method chaining) + * + * Has effect only if @ref Flag::AmbientTexture is set. + * @see @ref setAmbientColor() + */ + Phong& setAmbientTexture(Texture2D& texture); + /** * @brief Set diffuse color * @return Reference to self (for method chaining) * - * Has no effect if @ref Flag::AmbientTexture is used. + * Has no effect if @ref Flag::DiffuseTexture is used. + * @see @ref setDiffuseTexture() */ Phong& setDiffuseColor(const Color3& color); + /** + * @brief Set diffuse texture + * @return Reference to self (for method chaining) + * + * Has effect only if @ref Flag::DiffuseTexture is set. + * @see @ref setDiffuseColor() + */ + Phong& setDiffuseTexture(Texture2D& texture); + /** * @brief Set specular color * @return Reference to self (for method chaining) * * If not set, default value is `(1.0f, 1.0f, 1.0f)`. Has no effect if * @ref Flag::SpecularTexture is set. + * @see @ref setSpecularTexture() */ Phong& setSpecularColor(const Color3& color); + /** + * @brief Set specular texture + * @return Reference to self (for method chaining) + * + * Has effect only if @ref Flag::SpecularTexture is set. + * @see @ref setSpecularColor() + */ + Phong& setSpecularTexture(Texture2D& texture); + /** * @brief Set shininess * @return Reference to self (for method chaining) diff --git a/src/Magnum/Shaders/Vector.h b/src/Magnum/Shaders/Vector.h index 72d934183..ae73cf8d0 100644 --- a/src/Magnum/Shaders/Vector.h +++ b/src/Magnum/Shaders/Vector.h @@ -82,6 +82,14 @@ template class MAGNUM_SHADERS_EXPORT Vector: public Abst return *this; } + #ifndef DOXYGEN_GENERATING_OUTPUT + /* Overloads to remove WTF-factor from method chaining order */ + Vector& setVectorTexture(Texture2D& texture) { + AbstractVector::setVectorTexture(texture); + return *this; + } + #endif + private: Int transformationProjectionMatrixUniform, backgroundColorUniform, diff --git a/src/Magnum/Text/Renderer.h b/src/Magnum/Text/Renderer.h index 58dad37ab..d9bdcc6ae 100644 --- a/src/Magnum/Text/Renderer.h +++ b/src/Magnum/Text/Renderer.h @@ -173,8 +173,8 @@ depends on features supported by particular font and its layouter. Immutable text (e.g. menu items, credits) can be simply rendered using static methods, returning result either as data arrays or as fully configured mesh. -The text can be then drawn by configuring text shader, binding font texture -and drawing the mesh: +The text can be then drawn as usual by configuring the shader and drawing the +mesh: @code Text::AbstractFont* font; Text::GlyphCache cache; @@ -190,8 +190,8 @@ std::tie(mesh, rectangle) = Text::Renderer2D::render(*font, cache, 0.15f, // Draw white text centered on the screen shader.setTransformationProjectionMatrix(projection*Matrix3::translation(-rectangle.width()/2.0f)) - .setColor(Color3(1.0f)); -glyphCache->texture()->bind(Shaders::VectorShader2D::FontTextureLayer); + .setColor(Color3(1.0f)) + .setVectorTexture(glyphCache->texture()); mesh.draw(shader); @endcode See @ref render(AbstractFont&, const GlyphCache&, Float, const std::string&, Alignment) and @@ -215,8 +215,8 @@ renderer.render("Hello World Countdown: 10"); // Draw the text centered on the screen shader.setTransformationProjectionMatrix(projection*Matrix3::translation(-renderer.rectangle().width()/2.0f)) - .setColor(Color3(1.0f)); -glyphCache->texture()->bind(Shaders::VectorShader2D::FontTextureLayer); + .setColor(Color3(1.0f)) + .setVectorTexture(glyphCache->texture()); renderer.mesh().draw(shader); @endcode diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index e4e5d8169..5551e8f88 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -82,8 +82,7 @@ texture.setMagnificationFilter(Sampler::Filter::Linear) @ref setMinificationFilter(), explicitly specify all mip levels with @ref setStorage() and @ref setImage() or call @ref generateMipmap(). -The texture is bound to layer specified by shader via @ref bind(). In shader, -the texture is used via `sampler1D`/`sampler2D`/`sampler3D`, +In shader, the texture is used via `sampler1D`/`sampler2D`/`sampler3D`, `sampler1DShadow`/`sampler2DShadow`/`sampler3DShadow`, `isampler1D`/`isampler2D`/`isampler3D` or `usampler1D`/`usampler2D`/`usampler3D`. See @ref AbstractShaderProgram documentation for more information about usage diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index e4653dae6..412bf6503 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -82,8 +82,7 @@ for(std::size_t i = 0; i != 16; ++i) { @ref setMinificationFilter(), explicitly specify all mip levels with @ref setStorage() and @ref setImage() or call @ref generateMipmap(). -The texture is bound to layer specified by shader via @ref bind(). In shader, -the texture is used via `sampler1DArray`/`sampler2DArray`, +In shader, the texture is used via `sampler1DArray`/`sampler2DArray`, `sampler1DArrayShadow`/`sampler1DArrayShadow`, `isampler1DArray`/`isampler2DArray` or `usampler1DArray`/`usampler2DArray`. See @ref AbstractShaderProgram documentation for more information about usage in shaders. diff --git a/src/Magnum/TextureTools/DistanceField.cpp b/src/Magnum/TextureTools/DistanceField.cpp index 21d9d247b..a68959db2 100644 --- a/src/Magnum/TextureTools/DistanceField.cpp +++ b/src/Magnum/TextureTools/DistanceField.cpp @@ -45,10 +45,6 @@ class DistanceFieldShader: public AbstractShaderProgram { public: typedef Attribute<0, Vector2> Position; - enum: Int { - TextureLayer = 8 - }; - explicit DistanceFieldShader(); DistanceFieldShader& setRadius(Int radius) { @@ -66,7 +62,14 @@ class DistanceFieldShader: public AbstractShaderProgram { return *this; } + DistanceFieldShader& setTexture(Texture2D& texture) { + texture.bind(TextureLayer); + return *this; + } + private: + enum: Int { TextureLayer = 8 }; + Int radiusUniform, scalingUniform, imageSizeInvertedUniform; @@ -162,9 +165,8 @@ void distanceField(Texture2D& input, Texture2D& output, const Range2Di& rectangl DistanceFieldShader shader; shader.setRadius(radius) - .setScaling(Vector2(imageSize)/Vector2(rectangle.size())); - - input.bind(DistanceFieldShader::TextureLayer); + .setScaling(Vector2(imageSize)/Vector2(rectangle.size())) + .setTexture(input); #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isVersionSupported(Version::GL300)) From e55ee11b6af3322b28307971ea0b05d5c74a7494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 4 Feb 2014 16:14:08 +0100 Subject: [PATCH 70/86] Deprecate AbstractTexture::maxLayers() altogether. *Texture::bind() is now meant to be used only internally from shaders, thus this function is not needed at all, as we should query directly the particular shader type for the limits. The name also somehow clashes with layered textures, which should be avoided. --- src/Magnum/AbstractTexture.cpp | 11 +++++++++-- src/Magnum/AbstractTexture.h | 19 +++++++++---------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 4d2dd9d40..5594093c5 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -34,16 +34,22 @@ #include "Magnum/Context.h" #include "Magnum/Extensions.h" #include "Magnum/Image.h" -#include "Magnum/Shader.h" #include "Magnum/TextureFormat.h" +#ifdef MAGNUM_BUILD_DEPRECATED +#include "Magnum/Shader.h" +#endif + #include "Implementation/DebugState.h" #include "Implementation/State.h" #include "Implementation/TextureState.h" namespace Magnum { +#ifdef MAGNUM_BUILD_DEPRECATED Int AbstractTexture::maxLayers() { return Shader::maxCombinedTextureImageUnits(); } +Int AbstractTexture::maxSupportedLayerCount() { return Shader::maxCombinedTextureImageUnits(); } +#endif #ifndef MAGNUM_TARGET_GLES Int AbstractTexture::maxColorSamples() { @@ -183,7 +189,8 @@ void AbstractTexture::bindInternal() { return; /* Set internal layer as active if not already */ - const GLint internalLayer = maxLayers()-1; + CORRADE_INTERNAL_ASSERT(textureState->maxLayers > 1); + const GLint internalLayer = textureState->maxLayers-1; if(textureState->currentLayer != internalLayer) glActiveTexture(GL_TEXTURE0 + (textureState->currentLayer = internalLayer)); diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index a13211979..7062fbd64 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -102,23 +102,22 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { friend struct Implementation::TextureState; public: + #ifdef MAGNUM_BUILD_DEPRECATED /** - * @brief Max supported layer count - * - * The result is cached, repeated queries don't result in repeated - * OpenGL calls. This function is in fact alias to - * @ref Shader::maxCombinedTextureImageUnits(). - * @see @ref bind(Int) + * @copybrief Shader::maxCombinedTextureImageUnits() + * @deprecated Use @ref Magnum::Shader::maxCombinedTextureImageUnits() "Shader::maxCombinedTextureImageUnits()" + * instead. */ - static Int maxLayers(); + static CORRADE_DEPRECATED("use Shader::maxCombinedTextureImageUnits() instead") Int maxLayers(); + #endif #ifdef MAGNUM_BUILD_DEPRECATED /** - * @copybrief maxLayers() - * @deprecated Use @ref Magnum::AbstractTexture::maxLayers() "maxLayers()" + * @copybrief Shader::maxCombinedTextureImageUnits() + * @deprecated Use @ref Magnum::Shader::maxCombinedTextureImageUnits() "Shader::maxCombinedTextureImageUnits()" * instead. */ - static CORRADE_DEPRECATED("use maxLayers() instead") Int maxSupportedLayerCount() { return maxLayers(); } + static CORRADE_DEPRECATED("use Shader::maxCombinedTextureImageUnits() instead") Int maxSupportedLayerCount(); #endif #ifndef MAGNUM_TARGET_GLES From ae9462b4c8647c5bf13fb37beb733cfc1b880983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Feb 2014 19:49:32 +0100 Subject: [PATCH 71/86] Shaders: documentation improvements. --- src/Magnum/Shaders/AbstractVector.h | 4 ++-- src/Magnum/Shaders/DistanceFieldVector.h | 20 ++++++++++---------- src/Magnum/Shaders/MeshVisualizer.h | 15 ++++++++------- src/Magnum/Shaders/Phong.h | 2 +- src/Magnum/Shaders/Shaders.h | 2 +- src/Magnum/Shaders/VertexColor.h | 4 ++-- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/Magnum/Shaders/AbstractVector.h b/src/Magnum/Shaders/AbstractVector.h index fea2df38f..720de0714 100644 --- a/src/Magnum/Shaders/AbstractVector.h +++ b/src/Magnum/Shaders/AbstractVector.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shaders::AbstractVector, typedef Magnum::Shaders::AbstractVector2D, Magnum::Shaders::AbstractVector3D + * @brief Class @ref Magnum::Shaders::AbstractVector, typedef @ref Magnum::Shaders::AbstractVector2D, @ref Magnum::Shaders::AbstractVector3D */ #include "Magnum/Shaders/Generic.h" @@ -36,7 +36,7 @@ namespace Magnum { namespace Shaders { /** @brief Base for vector shaders -@see AbstractVector2D, AbstractVector3D +@see @ref AbstractVector2D, @ref AbstractVector3D */ template class AbstractVector: public AbstractShaderProgram { public: diff --git a/src/Magnum/Shaders/DistanceFieldVector.h b/src/Magnum/Shaders/DistanceFieldVector.h index f81ce05b4..9512c212b 100644 --- a/src/Magnum/Shaders/DistanceFieldVector.h +++ b/src/Magnum/Shaders/DistanceFieldVector.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shaders::DistanceFieldVector, typedef Magnum::Shaders::DistanceFieldVector2D, Magnum::Shaders::DistanceFieldVector3D + * @brief Class @ref Magnum::Shaders::DistanceFieldVector, typedef @ref Magnum::Shaders::DistanceFieldVector2D, @ref Magnum::Shaders::DistanceFieldVector3D */ #include "Magnum/Color.h" @@ -41,10 +41,10 @@ namespace Magnum { namespace Shaders { /** @brief Distance field vector shader -Renders vector art in form of signed distance field. See TextureTools::distanceField() +Renders vector art in form of signed distance field. See @ref TextureTools::distanceField() for more information. Note that the final rendered outlook will greatly depend -on radius of input distance field and value passed to setSmoothness(). -@see DistanceFieldVector2D, DistanceFieldVector3D +on radius of input distance field and value passed to @ref setSmoothness(). +@see @ref DistanceFieldVector2D, @ref DistanceFieldVector3D @todo Use fragment shader derivations to have proper smoothness in perspective/ large zoom levels, make it optional as it might have negative performance impact @@ -66,7 +66,7 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector * @brief Set fill color * @return Reference to self (for method chaining) * - * @see setOutlineColor() + * @see @ref setOutlineColor() */ DistanceFieldVector& setColor(const Color4& color) { AbstractShaderProgram::setUniform(colorUniform, color); @@ -77,7 +77,7 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector * @brief Set outline color * @return Reference to self (for method chaining) * - * @see setOutlineRange(), setColor() + * @see @ref setOutlineRange(), @ref setColor() */ DistanceFieldVector& setOutlineColor(const Color4& color) { AbstractShaderProgram::setUniform(outlineColorUniform, color); @@ -96,7 +96,7 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector * larger than @p start the outline is not drawn. Initial value is * `1.0f`. * - * @see setOutlineColor() + * @see @ref setOutlineColor() */ DistanceFieldVector& setOutlineRange(Float start, Float end) { AbstractShaderProgram::setUniform(outlineRangeUniform, Vector2(start, end)); @@ -107,9 +107,9 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector * @brief Set smoothness radius * @return Reference to self (for method chaining) * - * Larger values will make edges look less aliased (but blurry), smaller - * values will make them look more crisp (but possibly aliased). Initial - * value is `0.04f`. + * Larger values will make edges look less aliased (but blurry), + * smaller values will make them look more crisp (but possibly + * aliased). Initial value is `0.04f`. */ DistanceFieldVector& setSmoothness(Float value) { AbstractShaderProgram::setUniform(smoothnessUniform, value); diff --git a/src/Magnum/Shaders/MeshVisualizer.h b/src/Magnum/Shaders/MeshVisualizer.h index 867165b8f..7239e7caa 100644 --- a/src/Magnum/Shaders/MeshVisualizer.h +++ b/src/Magnum/Shaders/MeshVisualizer.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shaders::MeshVisualizer + * @brief Class @ref Magnum::Shaders::MeshVisualizer */ #include "Magnum/Math/Matrix4.h" @@ -56,9 +56,9 @@ If you have geometry shaders available, you don't need to do anything else. If you don't have geometry shaders, you need to set @ref Flag::NoGeometryShader (it's enabled by default in OpenGL ES) and use only **non-indexed** triangle -meshes (see MeshTools::duplicate() for possible solution). Additionaly, if you -have OpenGL < 3.1 or OpenGL ES 2.0, you need to provide also @ref VertexIndex -attribute. +meshes (see @ref MeshTools::duplicate() for possible solution). Additionaly, if +you have OpenGL < 3.1 or OpenGL ES 2.0, you need to provide also +@ref VertexIndex attribute. @requires_es_extension %Extension @extension{OES,standard_derivatives} for wireframe rendering. @@ -83,7 +83,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizer: public AbstractShaderProgram { /** * @brief %Flag * - * @see Flags, MeshVisualizer() + * @see @ref Flags, @ref MeshVisualizer() */ enum class Flag: UnsignedByte { /** @@ -98,8 +98,9 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizer: public AbstractShaderProgram { /** * Don't use geometry shader for wireframe visualization. If - * enabled, you might need to provide also VertexIndex attribute in - * the mesh. In OpenGL ES enabled alongside @ref Flag::Wireframe. + * enabled, you might need to provide also @ref VertexIndex + * attribute in the mesh. In OpenGL ES enabled alongside + * @ref Flag::Wireframe. */ NoGeometryShader = 1 << 1 }; diff --git a/src/Magnum/Shaders/Phong.h b/src/Magnum/Shaders/Phong.h index d864c2aad..f07967cfc 100644 --- a/src/Magnum/Shaders/Phong.h +++ b/src/Magnum/Shaders/Phong.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shaders::Phong + * @brief Class @ref Magnum::Shaders::Phong */ #include "Magnum/Color.h" diff --git a/src/Magnum/Shaders/Shaders.h b/src/Magnum/Shaders/Shaders.h index af355f7dd..d3fd54b2f 100644 --- a/src/Magnum/Shaders/Shaders.h +++ b/src/Magnum/Shaders/Shaders.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Forward declarations for Magnum::Shaders namespace + * @brief Forward declarations for @ref Magnum::Shaders namespace */ #include "Magnum/Types.h" diff --git a/src/Magnum/Shaders/VertexColor.h b/src/Magnum/Shaders/VertexColor.h index 1cbc4d0f1..4cb7cc865 100644 --- a/src/Magnum/Shaders/VertexColor.h +++ b/src/Magnum/Shaders/VertexColor.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shaders::VertexColor + * @brief Class @ref Magnum::Shaders::VertexColor */ #include "Magnum/Color.h" @@ -42,7 +42,7 @@ namespace Magnum { namespace Shaders { @brief Vertex color shader Draws vertex-colored mesh. -@see VertexColor2D, VertexColor3D +@see @ref VertexColor2D, @ref VertexColor3D */ template class MAGNUM_SHADERS_EXPORT VertexColor: public AbstractShaderProgram { public: From 8acd03778e1c8af507d6854f6fcb6027b37718b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Feb 2014 19:54:09 +0100 Subject: [PATCH 72/86] SceneGraph: documentation updates and fixes. --- src/Magnum/SceneGraph/AbstractObject.h | 50 +++++++++---------- .../SceneGraph/AbstractTransformation.h | 8 +-- src/Magnum/SceneGraph/AbstractTranslation.h | 7 +-- .../AbstractTranslationRotation2D.h | 4 +- .../AbstractTranslationRotation3D.h | 33 +++++++----- .../AbstractTranslationRotationScaling2D.h | 6 +-- .../AbstractTranslationRotationScaling3D.h | 7 +-- .../SceneGraph/DualComplexTransformation.h | 21 ++++---- .../SceneGraph/DualQuaternionTransformation.h | 21 ++++---- .../SceneGraph/MatrixTransformation2D.h | 15 +++--- .../SceneGraph/MatrixTransformation3D.h | 18 +++---- src/Magnum/SceneGraph/Object.h | 37 ++++++++++---- .../SceneGraph/RigidMatrixTransformation2D.h | 30 +++++------ .../SceneGraph/RigidMatrixTransformation3D.h | 39 ++++++++------- src/Magnum/SceneGraph/Scene.h | 4 +- src/Magnum/SceneGraph/SceneGraph.h | 2 +- .../SceneGraph/TranslationTransformation.h | 5 +- 17 files changed, 169 insertions(+), 138 deletions(-) diff --git a/src/Magnum/SceneGraph/AbstractObject.h b/src/Magnum/SceneGraph/AbstractObject.h index 11600ded7..cc204eb36 100644 --- a/src/Magnum/SceneGraph/AbstractObject.h +++ b/src/Magnum/SceneGraph/AbstractObject.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::AbstractObject, alias Magnum::SceneGraph::AbstractBasicObject2D, Magnum::SceneGraph::AbstractBasicObject3D, typedef Magnum::SceneGraph::AbstractObject2D, Magnum::SceneGraph::AbstractObject3D + * @brief Class @ref Magnum::SceneGraph::AbstractObject, alias @ref Magnum::SceneGraph::AbstractBasicObject2D, @ref Magnum::SceneGraph::AbstractBasicObject3D, typedef @ref Magnum::SceneGraph::AbstractObject2D, @ref Magnum::SceneGraph::AbstractObject3D */ #include @@ -129,7 +129,8 @@ template class AbstractObject /** * @brief Transformation matrix * - * @see Object::transformation() + * See also `transformation()` function of various transformation + * classes. */ MatrixType transformationMatrix() const { return doTransformationMatrix(); @@ -138,7 +139,7 @@ template class AbstractObject /** * @brief Transformation matrix relative to root object * - * @see Object::absoluteTransformation() + * @see @ref Object::absoluteTransformation() */ MatrixType absoluteTransformationMatrix() const { return doAbsoluteTransformationMatrix(); @@ -150,8 +151,8 @@ template class AbstractObject * All transformations are premultiplied with @p initialTransformationMatrix, * if specified. * @warning This function cannot check if all objects are of the same - * Object type, use typesafe Object::transformationMatrices() when - * possible. + * @ref Object type, use typesafe @ref Object::transformationMatrices() + * when possible. */ std::vector transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const { return doTransformationMatrices(objects, initialTransformationMatrix); @@ -170,7 +171,8 @@ template class AbstractObject * * Only dirty objects in the list are cleaned. * @warning This function cannot check if all objects are of the same - * Object type, use typesafe Object::setClean() when possible. + * @ref Object type, use typesafe @ref Object::setClean() when + * possible. */ static void setClean(const std::vector*>& objects) { if(objects.empty()) return; @@ -181,10 +183,8 @@ template class AbstractObject * @brief Whether absolute transformation is dirty * * Returns `true` if transformation of the object or any parent has - * changed since last call to setClean(), `false` otherwise. - * - * All objects are dirty by default. - * + * changed since last call to @ref setClean(), `false` otherwise. All + * objects are dirty by default. * @see @ref scenegraph-caching */ bool isDirty() const { return doIsDirty(); } @@ -192,26 +192,26 @@ template class AbstractObject /** * @brief Set object absolute transformation as dirty * - * Calls AbstractFeature::markDirty() on all object features and - * recursively calls setDirty() on every child object which is not + * Calls @ref AbstractFeature::markDirty() on all object features and + * recursively calls @ref setDirty() on every child object which is not * already dirty. If the object is already marked as dirty, the * function does nothing. - * @see @ref scenegraph-caching, setClean(), isDirty() + * @see @ref scenegraph-caching, @ref setClean(), @ref isDirty() */ void setDirty() { doSetDirty(); } /** * @brief Clean object absolute transformation * - * Calls AbstractFeature::clean() and/or AbstractFeature::cleanInverted() + * Calls @ref AbstractFeature::clean() and/or @ref AbstractFeature::cleanInverted() * on all object features which have caching enabled and recursively - * calls setClean() on every parent which is not already clean. If the - * object is already clean, the function does nothing. + * calls @ref setClean() on every parent which is not already clean. If + * the object is already clean, the function does nothing. * - * See also setClean(const std::vector& objects), which cleans given - * set of objects more efficiently than when calling setClean() on - * each object individually. - * @see @ref scenegraph-caching, setDirty(), isDirty() + * See also @ref setClean(const std::vector*>&), + * which cleans given set of objects more efficiently than when calling + * @ref setClean() on each object individually. + * @see @ref scenegraph-caching, @ref setDirty(), @ref isDirty() */ void setClean() { doSetClean(); } @@ -235,8 +235,8 @@ template class AbstractObject /** @brief Base object for two-dimensional scenes -Convenience alternative to %AbstractObject<2, T>. See AbstractObject -for more information. +Convenience alternative to %AbstractObject<2, T>. See +@ref AbstractObject for more information. @note Not available on GCC < 4.7. Use %AbstractObject<2, T> instead. @see @ref AbstractObject2D, @ref AbstractBasicObject3D */ @@ -258,10 +258,10 @@ typedef AbstractObject<2, Float> AbstractObject2D; /** @brief Base object for three-dimensional scenes -Convenience alternative to %AbstractObject<3, T>. See AbstractObject -for more information. +Convenience alternative to %AbstractObject<3, T>. See +@ref AbstractObject for more information. @note Not available on GCC < 4.7. Use %AbstractObject<3, T> instead. -@see AbstractObject2D +@see @ref AbstractObject3D, @ref AbstractBasicObject2D */ template using AbstractBasicObject3D = AbstractObject<3, T>; #endif diff --git a/src/Magnum/SceneGraph/AbstractTransformation.h b/src/Magnum/SceneGraph/AbstractTransformation.h index d6034052e..45c4236f4 100644 --- a/src/Magnum/SceneGraph/AbstractTransformation.h +++ b/src/Magnum/SceneGraph/AbstractTransformation.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::AbstractTransformation, alias Magnum::SceneGraph::AbstractBasicTransformation2D, Magnum::SceneGraph::AbstractBasicTransformation3D, typedef Magnum::SceneGraph::AbstractTransformation2D, Magnum::SceneGraph::AbstractTransformation3D, enum Magnum::SceneGraph::TransformationType + * @brief Class @ref Magnum::SceneGraph::AbstractTransformation, alias @ref Magnum::SceneGraph::AbstractBasicTransformation2D, @ref Magnum::SceneGraph::AbstractBasicTransformation3D, typedef @ref Magnum::SceneGraph::AbstractTransformation2D, @ref Magnum::SceneGraph::AbstractTransformation3D, enum @ref Magnum::SceneGraph::TransformationType */ #include "Magnum/SceneGraph/SceneGraph.h" @@ -80,7 +80,7 @@ template class AbstractTransformation { #else private: #endif - /** @brief Polymorphic implementation for resetTransformation() */ + /** @brief Polymorphic implementation for @ref resetTransformation() */ virtual void doResetTransformation() = 0; }; @@ -102,7 +102,7 @@ enum class TransformationType: UnsignedByte { @brief Base transformation for two-dimensional scenes Convenience alternative to %AbstractTransformation<2, T>. See -AbstractTransformation for more information. +@ref AbstractTransformation for more information. @note Not available on GCC < 4.7. Use %AbstractTransformation<2, T> instead. @see @ref AbstractTransformation2D, @ref AbstractBasicTransformation3D @@ -126,7 +126,7 @@ typedef AbstractTransformation<2, Float> AbstractTransformation2D; @brief Base transformation for three-dimensional scenes Convenience alternative to %AbstractTransformation<3, T>. See -AbstractTransformation for more information. +@ref AbstractTransformation for more information. @note Not available on GCC < 4.7. Use %AbstractTransformation<3, T> instead. @see @ref AbstractTransformation3D, @ref AbstractBasicTransformation2D diff --git a/src/Magnum/SceneGraph/AbstractTranslation.h b/src/Magnum/SceneGraph/AbstractTranslation.h index 91877a597..b7aff465b 100644 --- a/src/Magnum/SceneGraph/AbstractTranslation.h +++ b/src/Magnum/SceneGraph/AbstractTranslation.h @@ -60,8 +60,9 @@ class AbstractTranslation: public AbstractTransformation { * @param type Transformation type * @return Reference to self (for method chaining) * - * @see @ref Vector2::xAxis(), @ref Vector2::yAxis(), @ref Vector3::xAxis(), - * @ref Vector3::yAxis(), @ref Vector3::zAxis() + * @see @ref Math::Vector2::xAxis(), @ref Math::Vector2::yAxis(), + * @ref Math::Vector3::xAxis(), @ref Math::Vector3::yAxis(), + * @ref Math::Vector3::zAxis() */ AbstractTranslation& translate(const typename DimensionTraits::VectorType& vector, TransformationType type = TransformationType::Global) { doTranslate(vector, type); @@ -76,7 +77,7 @@ class AbstractTranslation: public AbstractTransformation { #else private: #endif - /** @brief Polymorphic implementation for translate() */ + /** @brief Polymorphic implementation for @ref translate() */ virtual void doTranslate(const typename DimensionTraits::VectorType& vector, TransformationType type) = 0; }; diff --git a/src/Magnum/SceneGraph/AbstractTranslationRotation2D.h b/src/Magnum/SceneGraph/AbstractTranslationRotation2D.h index efff4b4ba..91db68c0c 100644 --- a/src/Magnum/SceneGraph/AbstractTranslationRotation2D.h +++ b/src/Magnum/SceneGraph/AbstractTranslationRotation2D.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::AbstractBasicTranslationRotation2D, typedef Magnum::SceneGraph::AbstractTranslationRotation2D + * @brief Class @ref Magnum::SceneGraph::AbstractBasicTranslationRotation2D, typedef @ref Magnum::SceneGraph::AbstractTranslationRotation2D */ #include "Magnum/SceneGraph/AbstractTranslation.h" @@ -70,7 +70,7 @@ template class AbstractBasicTranslationRotation2D: public AbstractTrans #else private: #endif - /** @brief Polymorphic implementation for rotate() */ + /** @brief Polymorphic implementation for @ref rotate() */ virtual void doRotate(Math::Rad angle, TransformationType type) = 0; }; diff --git a/src/Magnum/SceneGraph/AbstractTranslationRotation3D.h b/src/Magnum/SceneGraph/AbstractTranslationRotation3D.h index d06f01ebc..e03d9b3b9 100644 --- a/src/Magnum/SceneGraph/AbstractTranslationRotation3D.h +++ b/src/Magnum/SceneGraph/AbstractTranslationRotation3D.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::AbstractBasicTranslationRotation3D, typedef Magnum::SceneGraph::AbstractTranslationRotation3D + * @brief Class @ref Magnum::SceneGraph::AbstractBasicTranslationRotation3D, typedef @ref Magnum::SceneGraph::AbstractTranslationRotation3D */ #include "Magnum/SceneGraph/AbstractTranslation.h" @@ -50,8 +50,9 @@ template class AbstractBasicTranslationRotation3D: public AbstractTrans * @param type Transformation type * @return Reference to self (for method chaining) * - * @see rotateX(), rotateY(), rotateZ(), Vector3::xAxis(), - * Vector3::yAxis(), Vector3::zAxis() + * @see @ref rotateX(), @ref rotateY(), @ref rotateZ(), + * @ref Math::Vector3::xAxis(), @ref Math::Vector3::yAxis(), + * @ref Math::Vector3::zAxis() */ AbstractBasicTranslationRotation3D& rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) { doRotate(angle, normalizedAxis, type); @@ -65,7 +66,8 @@ template class AbstractBasicTranslationRotation3D: public AbstractTrans * @return Reference to self (for method chaining) * * In some implementations faster than calling - * `rotate(angle, Vector3::xAxis())`. + * `rotate(angle, Vector3::xAxis())`, see subclasses for more + * information. */ AbstractBasicTranslationRotation3D& rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) { doRotateX(angle, type); @@ -79,7 +81,8 @@ template class AbstractBasicTranslationRotation3D: public AbstractTrans * @return Reference to self (for method chaining) * * In some implementations faster than calling - * `rotate(angle, Vector3::yAxis())`. + * `rotate(angle, Vector3::yAxis())`, see subclasses for more + * information. */ AbstractBasicTranslationRotation3D& rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) { doRotateX(angle, type); @@ -93,7 +96,8 @@ template class AbstractBasicTranslationRotation3D: public AbstractTrans * @return Reference to self (for method chaining) * * In some implementations faster than calling - * `rotate(angle, Vector3::zAxis())`. + * `rotate(angle, Vector3::zAxis())`, see subclasses for more + * information. */ AbstractBasicTranslationRotation3D& rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) { doRotateZ(angle, type); @@ -116,31 +120,34 @@ template class AbstractBasicTranslationRotation3D: public AbstractTrans #else private: #endif - /** @brief Polymorphic implementation for rotate() */ + /** @brief Polymorphic implementation for @ref rotate() */ virtual void doRotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type) = 0; /** - * @brief Polymorphic implementation for rotateX() + * @brief Polymorphic implementation for @ref rotateX() * - * Default implementation calls rotate() with Math::Vector3::xAxis(). + * Default implementation calls @ref rotate() with + * @ref Math::Vector3::xAxis(). */ virtual void doRotateX(Math::Rad angle, TransformationType type) { rotate(angle, Math::Vector3::xAxis(), type); } /** - * @brief Polymorphic implementation for rotateY() + * @brief Polymorphic implementation for @ref rotateY() * - * Default implementation calls rotate() with Math::Vector3::yAxis(). + * Default implementation calls @ref rotate() with + * @ref Math::Vector3::yAxis(). */ virtual void doRotateY(Math::Rad angle, TransformationType type) { rotate(angle, Math::Vector3::yAxis(), type); } /** - * @brief Polymorphic implementation for rotateZ() + * @brief Polymorphic implementation for @ref rotateZ() * - * Default implementation calls rotate() with Math::Vector3::zAxis(). + * Default implementation calls @ref rotate() with + * @ref Math::Vector3::zAxis(). */ virtual void doRotateZ(Math::Rad angle, TransformationType type) { rotate(angle, Math::Vector3::zAxis(), type); diff --git a/src/Magnum/SceneGraph/AbstractTranslationRotationScaling2D.h b/src/Magnum/SceneGraph/AbstractTranslationRotationScaling2D.h index fb8d1019c..1d3d988d8 100644 --- a/src/Magnum/SceneGraph/AbstractTranslationRotationScaling2D.h +++ b/src/Magnum/SceneGraph/AbstractTranslationRotationScaling2D.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::AbstractBasicTranslationRotationScaling2D, typedef Magnum::SceneGraph::AbstractTranslationRotationScaling2D + * @brief Class @ref Magnum::SceneGraph::AbstractBasicTranslationRotationScaling2D, typedef @ref Magnum::SceneGraph::AbstractTranslationRotationScaling2D */ #include "Magnum/SceneGraph/AbstractTranslationRotation2D.h" @@ -48,7 +48,7 @@ template class AbstractBasicTranslationRotationScaling2D: public Abstra * @param type Transformation type * @return Reference to self (for method chaining) * - * @see Vector2::xScale(), Vector2::yScale() + * @see @ref Math::Vector2::xScale(), @ref Math::Vector2::yScale() */ AbstractBasicTranslationRotationScaling2D& scale(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { doScale(vector, type); @@ -79,7 +79,7 @@ template class AbstractBasicTranslationRotationScaling2D: public Abstra #else private: #endif - /** @brief Polymorphic implementation for scale() */ + /** @brief Polymorphic implementation for @ref scale() */ virtual void doScale(const Math::Vector2& vector, TransformationType type) = 0; }; diff --git a/src/Magnum/SceneGraph/AbstractTranslationRotationScaling3D.h b/src/Magnum/SceneGraph/AbstractTranslationRotationScaling3D.h index 8b2104d7b..80e1bf0ef 100644 --- a/src/Magnum/SceneGraph/AbstractTranslationRotationScaling3D.h +++ b/src/Magnum/SceneGraph/AbstractTranslationRotationScaling3D.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::AbstractBasicTranslationRotationScaling3D, typedef Magnum::SceneGraph::AbstractTranslationRotationScaling3D + * @brief Class @ref Magnum::SceneGraph::AbstractBasicTranslationRotationScaling3D, typedef @ref Magnum::SceneGraph::AbstractTranslationRotationScaling3D */ #include "Magnum/SceneGraph/AbstractTranslationRotation3D.h" @@ -48,7 +48,8 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra * @param type Transformation type * @return Reference to self (for method chaining) * - * @see Vector3::xScale(), Vector3::yScale(), Vector3::zScale() + * @see @ref Math::Vector3::xScale(), @ref Math::Vector3::yScale(), + * @ref Math::Vector3::zScale() */ AbstractBasicTranslationRotationScaling3D& scale(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { doScale(vector, type); @@ -91,7 +92,7 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra #else private: #endif - /** @brief Polymorphic implementation for scale() */ + /** @brief Polymorphic implementation for @ref scale() */ virtual void doScale(const Math::Vector3& vector, TransformationType type) = 0; }; diff --git a/src/Magnum/SceneGraph/DualComplexTransformation.h b/src/Magnum/SceneGraph/DualComplexTransformation.h index f82584bed..974c29cb2 100644 --- a/src/Magnum/SceneGraph/DualComplexTransformation.h +++ b/src/Magnum/SceneGraph/DualComplexTransformation.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::BasicDualComplexTransformation, typedef Magnum::SceneGraph::DualComplexTransformation + * @brief Class @ref Magnum::SceneGraph::BasicDualComplexTransformation, typedef @ref Magnum::SceneGraph::DualComplexTransformation */ #include "Magnum/Math/DualComplex.h" @@ -39,12 +39,13 @@ namespace Magnum { namespace SceneGraph { @brief Two-dimensional transformation implemented using dual complex numbers This class allows only rigid transformation (i.e. only rotation and -translation). -@see @ref DualComplexTransformation, @ref scenegraph, Math::DualComplex, @ref BasicDualQuaternionTransformation +translation). Uses @ref Math::DualComplex as underlying transformation type. +@see @ref DualComplexTransformation, @ref scenegraph, + @ref BasicDualQuaternionTransformation */ template class BasicDualComplexTransformation: public AbstractBasicTranslationRotation2D { public: - /** @brief Transformation type */ + /** @brief Underlying transformation type */ typedef Math::DualComplex DataType; /** @brief Object transformation */ @@ -55,7 +56,7 @@ template class BasicDualComplexTransformation: public AbstractBasicTran * @return Reference to self (for method chaining) * * Expects that the dual complex number is normalized. - * @see DualComplex::isNormalized() + * @see @ref Math::DualComplex::isNormalized() */ Object>& setTransformation(const Math::DualComplex& transformation) { CORRADE_ASSERT(transformation.isNormalized(), @@ -75,7 +76,7 @@ template class BasicDualComplexTransformation: public AbstractBasicTran * * Normalizes the rotation part to prevent rounding errors when rotating * the object subsequently. - * @see DualComplex::normalized() + * @see @ref Math::DualComplex::normalized() */ Object>& normalizeRotation() { return setTransformationInternal(_transformation.normalized()); @@ -88,7 +89,7 @@ template class BasicDualComplexTransformation: public AbstractBasicTran * @return Reference to self (for method chaining) * * Expects that the dual complex number is normalized. - * @see DualComplex::isNormalized() + * @see @ref Math::DualComplex::isNormalized() */ Object>& transform(const Math::DualComplex& transformation, TransformationType type = TransformationType::Global) { CORRADE_ASSERT(transformation.isNormalized(), @@ -99,7 +100,7 @@ template class BasicDualComplexTransformation: public AbstractBasicTran /** * @copydoc AbstractTranslationRotationScaling2D::translate() - * Same as calling transform() with DualComplex::translation(). + * Same as calling @ref transform() with @ref Math::DualComplex::translation(). */ Object>& translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { return transformInternal(Math::DualComplex::translation(vector), type); @@ -111,8 +112,8 @@ template class BasicDualComplexTransformation: public AbstractBasicTran * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with DualComplex::rotation(). - * @see normalizeRotation() + * Same as calling @ref transform() with @ref Math::DualComplex::rotation(). + * @see @ref normalizeRotation() */ Object>& rotate(Math::Rad angle, TransformationType type = TransformationType::Global) { return transformInternal(Math::DualComplex::rotation(angle), type); diff --git a/src/Magnum/SceneGraph/DualQuaternionTransformation.h b/src/Magnum/SceneGraph/DualQuaternionTransformation.h index 5b2837c8e..d424ae0f8 100644 --- a/src/Magnum/SceneGraph/DualQuaternionTransformation.h +++ b/src/Magnum/SceneGraph/DualQuaternionTransformation.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::BasicDualQuaternionTransformation, typedef Magnum::SceneGraph::DualQuaternionTransformation + * @brief Class @ref Magnum::SceneGraph::BasicDualQuaternionTransformation, typedef @ref Magnum::SceneGraph::DualQuaternionTransformation */ #include "Magnum/Math/DualQuaternion.h" @@ -39,8 +39,9 @@ namespace Magnum { namespace SceneGraph { @brief Three-dimensional transformation implemented using dual quaternions This class allows only rigid transformation (i.e. only rotation and -translation). -@see @ref DualQuaternionTransformation @ref scenegraph, Math::DualQuaternion, @ref BasicDualComplexTransformation +translation). Uses @ref Math::DualQuaternion as underlying transformation type. +@see @ref DualQuaternionTransformation @ref scenegraph, + @ref BasicDualComplexTransformation */ template class BasicDualQuaternionTransformation: public AbstractBasicTranslationRotation3D { public: @@ -55,7 +56,7 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT * @return Reference to self (for method chaining) * * Expects that the dual quaternion is normalized. - * @see DualQuaternion::isNormalized() + * @see @ref Math::DualQuaternion::isNormalized() */ Object>& setTransformation(const Math::DualQuaternion& transformation) { CORRADE_ASSERT(transformation.isNormalized(), @@ -75,7 +76,7 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT * * Normalizes the rotation part to prevent rounding errors when rotating * the object subsequently. - * @see DualQuaternion::normalized() + * @see @ref Math::DualQuaternion::normalized() */ Object>& normalizeRotation() { return setTransformationInternal(_transformation.normalized()); @@ -88,7 +89,7 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT * @return Reference to self (for method chaining) * * Expects that the dual quaternion is normalized. - * @see DualQuaternion::isNormalized() + * @see @ref Math::DualQuaternion::isNormalized() */ Object>& transform(const Math::DualQuaternion& transformation, TransformationType type = TransformationType::Global) { CORRADE_ASSERT(transformation.isNormalized(), @@ -99,7 +100,7 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT /** * @copydoc AbstractTranslationRotationScaling3D::translate() - * Same as calling transform() with DualQuaternion::translation(). + * Same as calling @ref transform() with @ref Math::DualQuaternion::translation(). */ Object>& translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { return transformInternal(Math::DualQuaternion::translation(vector), type); @@ -112,9 +113,9 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with DualQuaternion::rotation(). - * @see Vector3::xAxis(), Vector3::yAxis(), Vector3::zAxis(), - * normalizeRotation() + * Same as calling @ref transform() with @ref Math::DualQuaternion::rotation(). + * @see @ref Math::Vector3::xAxis(), @ref Math::Vector3::yAxis(), + * @ref Math::Vector3::zAxis(), @ref normalizeRotation() */ Object>& rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) { return transformInternal(Math::DualQuaternion::rotation(angle, normalizedAxis), type); diff --git a/src/Magnum/SceneGraph/MatrixTransformation2D.h b/src/Magnum/SceneGraph/MatrixTransformation2D.h index 943801086..5401736ef 100644 --- a/src/Magnum/SceneGraph/MatrixTransformation2D.h +++ b/src/Magnum/SceneGraph/MatrixTransformation2D.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::BasicMatrixTransformation2D, typedef Magnum::SceneGraph::MatrixTransformation2D + * @brief Class @ref Magnum::SceneGraph::BasicMatrixTransformation2D, typedef @ref Magnum::SceneGraph::MatrixTransformation2D */ #include "Magnum/Math/Matrix3.h" @@ -38,8 +38,9 @@ namespace Magnum { namespace SceneGraph { /** @brief Two-dimensional transformation implemented using matrices -Uses Math::Matrix3 as underlying type. -@see @ref MatrixTransformation2D, @ref scenegraph, @ref BasicRigidMatrixTransformation2D, @ref BasicMatrixTransformation3D +Uses @ref Math::Matrix3 as underlying transformation type. +@see @ref MatrixTransformation2D, @ref scenegraph, + @ref BasicRigidMatrixTransformation2D, @ref BasicMatrixTransformation3D */ template class BasicMatrixTransformation2D: public AbstractBasicTranslationRotationScaling2D { public: @@ -83,7 +84,7 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla /** * @copydoc AbstractTranslationRotationScaling2D::translate() - * Same as calling transform() with Matrix3::translation(). + * Same as calling @ref transform() with @ref Math::Matrix3::translation(). */ Object>& translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { return transform(Math::Matrix3::translation(vector), type); @@ -91,7 +92,7 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla /** * @copydoc AbstractTranslationRotationScaling2D::rotate() - * Same as calling transform() with Matrix3::rotation(). + * Same as calling @ref transform() with @ref Math::Matrix3::rotation(). */ Object>& rotate(Math::Rad angle, TransformationType type = TransformationType::Global) { return transform(Math::Matrix3::rotation(angle), type); @@ -99,7 +100,7 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla /** * @copydoc AbstractTranslationRotationScaling2D::scale() - * Same as calling transform() with Matrix3::scaling(). + * Same as calling @ref transform() with @ref Math::Matrix3::scaling(). */ Object>& scale(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { return transform(Math::Matrix3::scaling(vector), type); @@ -112,7 +113,7 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with Matrix3::reflection(). + * Same as calling @ref transform() with @ref Math::Matrix3::reflection(). */ Object>& reflect(const Math::Vector2& normal, TransformationType type = TransformationType::Global) { return transform(Math::Matrix3::reflection(normal), type); diff --git a/src/Magnum/SceneGraph/MatrixTransformation3D.h b/src/Magnum/SceneGraph/MatrixTransformation3D.h index 0251a1d6a..970ed0bfe 100644 --- a/src/Magnum/SceneGraph/MatrixTransformation3D.h +++ b/src/Magnum/SceneGraph/MatrixTransformation3D.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::BasicMatrixTransformation3D, typedef Magnum::SceneGraph::MatrixTransformation3D + * @brief Class @ref Magnum::SceneGraph::BasicMatrixTransformation3D, typedef @ref Magnum::SceneGraph::MatrixTransformation3D */ #include "Magnum/Math/Matrix4.h" @@ -38,7 +38,7 @@ namespace Magnum { namespace SceneGraph { /** @brief Three-dimensional transformation implemented using matrices -Uses Math::Matrix4 as underlying type. +Uses @ref Math::Matrix4 as underlying transformation type. @see @ref MatrixTransformation3D, @ref scenegraph, @ref BasicRigidMatrixTransformation3D, @ref BasicMatrixTransformation2D */ template class BasicMatrixTransformation3D: public AbstractBasicTranslationRotationScaling3D { @@ -83,7 +83,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla /** * @copydoc AbstractTranslationRotationScaling3D::translate() - * Same as calling transform() with Matrix4::translation(). + * Same as calling @ref transform() with @ref Math::Matrix4::translation(). */ Object>& translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { return transform(Math::Matrix4::translation(vector), type); @@ -91,7 +91,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla /** * @copydoc AbstractTranslationRotationScaling3D::rotate() - * Same as calling transform() with Matrix4::rotation(). + * Same as calling @ref transform() with @ref Math::Matrix4::rotation(). */ Object>& rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) { return transform(Math::Matrix4::rotation(angle, normalizedAxis), type); @@ -103,7 +103,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with Matrix4::rotationX(). + * Same as calling @ref transform() with @ref Math::Matrix4::rotationX(). */ Object>& rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) { return transform(Math::Matrix4::rotationX(angle), type); @@ -115,7 +115,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with Matrix4::rotationY(). + * Same as calling @ref transform() with @ref Math::Matrix4::rotationY(). */ Object>& rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) { return transform(Math::Matrix4::rotationY(angle), type); @@ -127,7 +127,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with Matrix4::rotationZ(). + * Same as calling @ref transform() with @ref Math::Matrix4::rotationZ(). */ Object>& rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) { return transform(Math::Matrix4::rotationZ(angle), type); @@ -135,7 +135,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla /** * @copydoc AbstractTranslationRotationScaling3D::scale() - * Same as calling transform() with Matrix4::scaling(). + * Same as calling @ref transform() with @ref Math::Matrix4::scaling(). */ Object>& scale(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { return transform(Math::Matrix4::scaling(vector), type); @@ -148,7 +148,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with Matrix4::reflection(). + * Same as calling @ref transform() with @ref Math::Matrix4::reflection(). */ Object>& reflect(const Math::Vector3& normal, TransformationType type = TransformationType::Global) { return transform(Math::Matrix4::reflection(normal), type); diff --git a/src/Magnum/SceneGraph/Object.h b/src/Magnum/SceneGraph/Object.h index 4d4563c63..634b50597 100644 --- a/src/Magnum/SceneGraph/Object.h +++ b/src/Magnum/SceneGraph/Object.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::Object + * @brief Class @ref Magnum::SceneGraph::Object */ #include @@ -196,7 +196,7 @@ template class Object: public AbstractObject& setParent(Object* parent); @@ -204,8 +204,9 @@ template class Object: public AbstractObject& setParentKeepTransformation(Object* parent); @@ -216,7 +217,8 @@ template class Object: public AbstractObject::toMatrix(Transformation::transformation()); @@ -225,7 +227,7 @@ template class Object: public AbstractObject::toMatrix(absoluteTransformation()); @@ -234,7 +236,7 @@ template class Object: public AbstractObject class Object: public AbstractObject transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; @@ -252,7 +254,7 @@ template class Object: public AbstractObject class Object: public AbstractObject*> objects); @@ -281,7 +283,20 @@ template class Object: public AbstractObject*>), + * which cleans given set of objects more efficiently than when calling + * @ref setClean() on each object individually. + * @see @ref scenegraph-caching, @ref setDirty(), @ref isDirty() + */ + /* note: doc verbatim copied from AbstractObject::setClean() */ void setClean(); /*@}*/ diff --git a/src/Magnum/SceneGraph/RigidMatrixTransformation2D.h b/src/Magnum/SceneGraph/RigidMatrixTransformation2D.h index bb492e4db..f34a0de5e 100644 --- a/src/Magnum/SceneGraph/RigidMatrixTransformation2D.h +++ b/src/Magnum/SceneGraph/RigidMatrixTransformation2D.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::BasicRigidMatrixTransformation2D, typedef Magnum::SceneGraph::RigidMatrixTransformation2D + * @brief Class @ref Magnum::SceneGraph::BasicRigidMatrixTransformation2D, typedef @ref Magnum::SceneGraph::RigidMatrixTransformation2D */ #include "Magnum/Math/Matrix3.h" @@ -39,11 +39,12 @@ namespace Magnum { namespace SceneGraph { /** @brief Two-dimensional rigid transformation implemented using matrices -Unlike BasicMatrixTransformation2D this class allows only rotation, reflection -and translation (no scaling or setting arbitrary transformations). This allows -to use Matrix3::invertedRigid() for faster computation of inverse -transformations. -@see @ref RigidMatrixTransformation2D, @ref scenegraph, @ref BasicRigidMatrixTransformation3D +Unlike @ref BasicMatrixTransformation2D this class allows only rotation, +reflection and translation (no scaling or setting arbitrary transformations). +This allows to use @ref Math::Matrix3::invertedRigid() for faster computation +of inverse transformations. +@see @ref RigidMatrixTransformation2D, @ref scenegraph, + @ref BasicRigidMatrixTransformation3D */ template class BasicRigidMatrixTransformation2D: public AbstractBasicTranslationRotation2D { public: @@ -58,7 +59,7 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr * @return Reference to self (for method chaining) * * Expects that the matrix represents rigid transformation. - * @see Matrix3::isRigidTransformation() + * @see @ref Math::Matrix3::isRigidTransformation() */ Object>& setTransformation(const Math::Matrix3& transformation) { CORRADE_ASSERT(transformation.isRigidTransformation(), @@ -76,8 +77,9 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr * @brief Normalize rotation part * @return Reference to self (for method chaining) * - * Normalizes the rotation part using Math::Algorithms::gramSchmidt() - * to prevent rounding errors when rotating the object subsequently. + * Normalizes the rotation part using + * @ref Math::Algorithms::gramSchmidtOrthonormalize() to prevent + * rounding errors when rotating the object subsequently. */ Object>& normalizeRotation() { return setTransformationInternal(Math::Matrix3::from( @@ -92,7 +94,7 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr * @return Reference to self (for method chaining) * * Expects that the matrix represents rigid transformation. - * @see Matrix3::isRigidTransformation() + * @see @ref Math::Matrix3::isRigidTransformation() */ Object>& transform(const Math::Matrix3& transformation, TransformationType type = TransformationType::Global) { CORRADE_ASSERT(transformation.isRigidTransformation(), @@ -103,7 +105,7 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr /** * @copydoc AbstractTranslationRotationScaling2D::translate() - * Same as calling transform() with Matrix3::translation(). + * Same as calling @ref transform() with @ref Math::Matrix3::translation(). */ Object>& translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { return transformInternal(Math::Matrix3::translation(vector), type); @@ -115,8 +117,8 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with Matrix3::rotation(). - * @see normalizeRotation() + * Same as calling @ref transform() with @ref Math::Matrix3::rotation(). + * @see @ref normalizeRotation() */ Object>& rotate(Math::Rad angle, TransformationType type = TransformationType::Global) { return transformInternal(Math::Matrix3::rotation(angle), type); @@ -129,7 +131,7 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with Matrix3::reflection(). + * Same as calling @ref transform() with @ref Math::Matrix3::reflection(). */ Object>& reflect(const Math::Vector2& normal, TransformationType type = TransformationType::Global) { return transformInternal(Math::Matrix3::reflection(normal), type); diff --git a/src/Magnum/SceneGraph/RigidMatrixTransformation3D.h b/src/Magnum/SceneGraph/RigidMatrixTransformation3D.h index 53d68903b..a96b6ecb9 100644 --- a/src/Magnum/SceneGraph/RigidMatrixTransformation3D.h +++ b/src/Magnum/SceneGraph/RigidMatrixTransformation3D.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::BasicRigidMatrixTransformation3D, typedef Magnum::SceneGraph::RigidMatrixTransformation3D + * @brief Class @ref Magnum::SceneGraph::BasicRigidMatrixTransformation3D, typedef @ref Magnum::SceneGraph::RigidMatrixTransformation3D */ #include "Magnum/Math/Matrix4.h" @@ -39,10 +39,10 @@ namespace Magnum { namespace SceneGraph { /** @brief Three-dimensional rigid transformation implemented using matrices -Unlike BasicMatrixTransformation3D this class allows only rotation, reflection -and translation (no scaling or setting arbitrary transformations). This allows -to use Matrix4::invertedRigid() for faster computation of inverse -transformations. +Unlike @ref BasicMatrixTransformation3D this class allows only rotation, +reflection and translation (no scaling or setting arbitrary transformations). +This allows to use @ref Math::Matrix4::invertedRigid() for faster computation +of inverse transformations. @see @ref RigidMatrixTransformation3D, @ref scenegraph, @ref BasicRigidMatrixTransformation2D */ template class BasicRigidMatrixTransformation3D: public AbstractBasicTranslationRotation3D { @@ -58,7 +58,7 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * @return Reference to self (for method chaining) * * Expects that the matrix represents rigid transformation. - * @see Matrix4::isRigidTransformation() + * @see @ref Matrix4::isRigidTransformation() */ Object>& setTransformation(const Math::Matrix4& transformation) { CORRADE_ASSERT(transformation.isRigidTransformation(), @@ -76,7 +76,7 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * @brief Normalize rotation part * @return Reference to self (for method chaining) * - * Normalizes the rotation part using Math::Algorithms::gramSchmidt() + * Normalizes the rotation part using @ref Math::Algorithms::gramSchmidtOrthonormalize() * to prevent rounding errors when rotating the object subsequently. */ Object>& normalizeRotation() { @@ -92,7 +92,7 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * @return Reference to self (for method chaining) * * Expects that the matrix represents rigid transformation. - * @see Matrix4::isRigidTransformation() + * @see @ref Math::Matrix4::isRigidTransformation() */ Object>& transform(const Math::Matrix4& transformation, TransformationType type = TransformationType::Global) { CORRADE_ASSERT(transformation.isRigidTransformation(), @@ -103,7 +103,7 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr /** * @copydoc AbstractTranslationRotationScaling3D::translate() - * Same as calling transform() with Matrix4::translation(). + * Same as calling @ref transform() with @ref Math::Matrix4::translation(). */ Object>& translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { return transformInternal(Math::Matrix4::translation(vector), type); @@ -116,9 +116,10 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with Matrix4::rotation(). - * @see rotateX(), rotateY(), rotateZ(), Vector3::xAxis(), - * Vector3::yAxis(), Vector3::zAxis(), normalizeRotation() + * Same as calling @ref transform() with @ref Math::Matrix4::rotation(). + * @see @ref rotateX(), @ref rotateY(), @ref rotateZ(), + * @ref normalizeRotation(), @ref Math::Vector3::xAxis(), + * @ref Math::Vector3::yAxis(), @ref Math::Vector3::zAxis() */ Object>& rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) { return transformInternal(Math::Matrix4::rotation(angle, normalizedAxis), type); @@ -130,8 +131,8 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with Matrix4::rotationX(). - * @see normalizeRotation() + * Same as calling @ref transform() with @ref Math::Matrix4::rotationX(). + * @see @ref normalizeRotation() */ Object>& rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) { return transformInternal(Math::Matrix4::rotationX(angle), type); @@ -143,8 +144,8 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with Matrix4::rotationY(). - * @see normalizeRotation() + * Same as calling @ref transform() with @ref Math::Matrix4::rotationY(). + * @see @ref normalizeRotation() */ Object>& rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) { return transformInternal(Math::Matrix4::rotationY(angle), type); @@ -156,8 +157,8 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with Matrix4::rotationZ(). - * @see normalizeRotation() + * Same as calling @ref transform() with @ref Math::Matrix4::rotationZ(). + * @see @ref normalizeRotation() */ Object>& rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) { return transformInternal(Math::Matrix4::rotationZ(angle), type); @@ -170,7 +171,7 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * @param type Transformation type * @return Reference to self (for method chaining) * - * Same as calling transform() with Matrix4::reflection(). + * Same as calling @ref transform() with @ref Math::Matrix4::reflection(). */ Object>& reflect(const Math::Vector3& normal, TransformationType type = TransformationType::Global) { return transformInternal(Math::Matrix4::reflection(normal), type); diff --git a/src/Magnum/SceneGraph/Scene.h b/src/Magnum/SceneGraph/Scene.h index e1b375a6a..2153fa1e6 100644 --- a/src/Magnum/SceneGraph/Scene.h +++ b/src/Magnum/SceneGraph/Scene.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::Scene + * @brief Class @ref Magnum::SceneGraph::Scene */ #include "Magnum/SceneGraph/Object.h" @@ -36,7 +36,7 @@ namespace Magnum { namespace SceneGraph { /** @brief %Scene -Basically Object which cannot have parent or non-default transformation. +Basically @ref Object which cannot have parent or non-default transformation. See @ref scenegraph for introduction. */ template class Scene: public Object { diff --git a/src/Magnum/SceneGraph/SceneGraph.h b/src/Magnum/SceneGraph/SceneGraph.h index 67a7b4f52..ba8573537 100644 --- a/src/Magnum/SceneGraph/SceneGraph.h +++ b/src/Magnum/SceneGraph/SceneGraph.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Forward declarations for Magnum::SceneGraph namespace + * @brief Forward declarations for @ref Magnum::SceneGraph namespace */ #include diff --git a/src/Magnum/SceneGraph/TranslationTransformation.h b/src/Magnum/SceneGraph/TranslationTransformation.h index b3d36fe72..db07491e4 100644 --- a/src/Magnum/SceneGraph/TranslationTransformation.h +++ b/src/Magnum/SceneGraph/TranslationTransformation.h @@ -103,8 +103,9 @@ class TranslationTransformation: public AbstractTranslation>& translate(const typename DimensionTraits::VectorType& vector, TransformationType = TransformationType::Global) { _transformation += vector; From aa49008358fbedd6607cdaad2c54d0eecfa913cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Feb 2014 21:00:53 +0100 Subject: [PATCH 73/86] SceneGraph: using std::reference_wrapper instead of pointers. Currently all the functions taking vectors of objects (e.g. setClean(), transformations() and transformationMatrices()) were taking pointers, which lead to additional (and often forgotten) nullptr checks. The internals are now much more clean, as the parts where we are dealing with pointers are reduced to bare minimum. Also renamed private Object::setClean() function to Object::setCleanInternal() to avoid overload clash with the public one. The old way is now an nullptr-checked alias to the new one, is marked as deprecated and will be removed in some future release. --- src/Magnum/SceneGraph/AbstractCamera.hpp | 5 +- src/Magnum/SceneGraph/AbstractObject.h | 27 +++- src/Magnum/SceneGraph/Object.h | 40 ++++-- src/Magnum/SceneGraph/Object.hpp | 166 +++++++++++++++------- src/Magnum/SceneGraph/Test/ObjectTest.cpp | 31 ++-- src/Magnum/Shapes/ShapeGroup.cpp | 5 +- 6 files changed, 189 insertions(+), 85 deletions(-) diff --git a/src/Magnum/SceneGraph/AbstractCamera.hpp b/src/Magnum/SceneGraph/AbstractCamera.hpp index 994729c60..b3128484a 100644 --- a/src/Magnum/SceneGraph/AbstractCamera.hpp +++ b/src/Magnum/SceneGraph/AbstractCamera.hpp @@ -93,9 +93,10 @@ template void AbstractCamera::dr AbstractFeature::object().setClean(); /* Compute transformations of all objects in the group relative to the camera */ - std::vector*> objects(group.size()); + std::vector>> objects; + objects.reserve(group.size()); for(std::size_t i = 0; i != group.size(); ++i) - objects[i] = &group[i].object(); + objects.push_back(group[i].object()); std::vector::MatrixType> transformations = scene->transformationMatrices(objects, _cameraMatrix); diff --git a/src/Magnum/SceneGraph/AbstractObject.h b/src/Magnum/SceneGraph/AbstractObject.h index cc204eb36..f02872d09 100644 --- a/src/Magnum/SceneGraph/AbstractObject.h +++ b/src/Magnum/SceneGraph/AbstractObject.h @@ -29,6 +29,7 @@ * @brief Class @ref Magnum::SceneGraph::AbstractObject, alias @ref Magnum::SceneGraph::AbstractBasicObject2D, @ref Magnum::SceneGraph::AbstractBasicObject3D, typedef @ref Magnum::SceneGraph::AbstractObject2D, @ref Magnum::SceneGraph::AbstractObject3D */ +#include #include #include @@ -154,10 +155,18 @@ template class AbstractObject * @ref Object type, use typesafe @ref Object::transformationMatrices() * when possible. */ - std::vector transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const { + std::vector transformationMatrices(const std::vector>>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const { return doTransformationMatrices(objects, initialTransformationMatrix); } + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief transformationMatrices(const std::vector>>&, const MatrixType&) + * @deprecated Use @ref Magnum::SceneGraph::AbstractObject::transformationMatrices(const std::vector>>&, const MatrixType&) "transformationMatrices(const std::vector>>&, const MatrixType&)" instead. + */ + CORRADE_DEPRECATED("use transformationMatrices(const std::vector>>&, const MatrixType&) instead") std::vector transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; + #endif + /*@}*/ /** @@ -174,11 +183,19 @@ template class AbstractObject * @ref Object type, use typesafe @ref Object::setClean() when * possible. */ - static void setClean(const std::vector*>& objects) { + static void setClean(const std::vector>>& objects) { if(objects.empty()) return; - objects.front()->doSetClean(objects); + objects.front().get().doSetClean(objects); } + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief setClean(const std::vector>>&) + * @deprecated Use @ref Magnum::SceneGraph::AbstractObject::setClean(const std::vector>>&) "setClean(const std::vector>>&)" instead. + */ + static CORRADE_DEPRECATED("use setClean(const std::vector>>&) instead") void setClean(const std::vector*>& objects); + #endif + /** * @brief Whether absolute transformation is dirty * @@ -223,12 +240,12 @@ template class AbstractObject virtual MatrixType doTransformationMatrix() const = 0; virtual MatrixType doAbsoluteTransformationMatrix() const = 0; - virtual std::vector doTransformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const = 0; + virtual std::vector doTransformationMatrices(const std::vector>>& objects, const MatrixType& initialTransformationMatrix) const = 0; virtual bool doIsDirty() const = 0; virtual void doSetDirty() = 0; virtual void doSetClean() = 0; - virtual void doSetClean(const std::vector*>& objects) = 0; + virtual void doSetClean(const std::vector>>& objects) = 0; }; #ifndef CORRADE_GCC46_COMPATIBILITY diff --git a/src/Magnum/SceneGraph/Object.h b/src/Magnum/SceneGraph/Object.h index 634b50597..09911ae5c 100644 --- a/src/Magnum/SceneGraph/Object.h +++ b/src/Magnum/SceneGraph/Object.h @@ -247,7 +247,15 @@ template class Object: public AbstractObject transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; + std::vector transformationMatrices(const std::vector>>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief transformationMatrices(const std::vector>>&, const MatrixType&) + * @deprecated Use @ref Magnum::SceneGraph::Object::transformationMatrices(const std::vector>>&, const MatrixType&) "transformationMatrices(const std::vector>>&, const MatrixType&)" instead. + */ + CORRADE_DEPRECATED("use transformationMatrices(const std::vector>>&, const MatrixType&) instead") std::vector transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; + #endif /** * @brief Transformations of given group of objects relative to this object @@ -258,7 +266,15 @@ template class Object: public AbstractObject transformations(std::vector*> objects, const typename Transformation::DataType& initialTransformation = typename Transformation::DataType()) const; + std::vector transformations(std::vector>> objects, const typename Transformation::DataType& initialTransformation = typename Transformation::DataType()) const; + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief transformations(std::vector>>, const typename Transformation::DataType&) + * @deprecated Use @ref Magnum::SceneGraph::Object::transformations(std::vector>>, const typename Transformation::DataType&) "transformations(std::vector>>, const typename Transformation::DataType&)" instead. + */ + CORRADE_DEPRECATED("use transformations(std::vector>>, const typename Transformation::DataType&) instead") std::vector transformations(std::vector*> objects, const typename Transformation::DataType& initialTransformation = typename Transformation::DataType()) const; + #endif /*@}*/ @@ -275,7 +291,15 @@ template class Object: public AbstractObject*> objects); + static void setClean(std::vector>> objects); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief setClean(std::vector>>) + * @deprecated Use @ref Magnum::SceneGraph::Object::setClean(std::vector>> "setClean(std::vector>>" instead. + */ + CORRADE_DEPRECATED("use setClean(std::vector>>) instead") static void setClean(std::vector*> objects); + #endif /** @copydoc AbstractObject::isDirty() */ bool isDirty() const { return !!(flags & Flag::Dirty); } @@ -291,7 +315,7 @@ template class Object: public AbstractObject*>), + * See also @ref setClean(std::vector>>), * which cleans given set of objects more efficiently than when calling * @ref setClean() on each object individually. * @see @ref scenegraph-caching, @ref setDirty(), @ref isDirty() @@ -317,16 +341,16 @@ template class Object: public AbstractObject doTransformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const override final; + std::vector doTransformationMatrices(const std::vector>>& objects, const MatrixType& initialTransformationMatrix) const override final; - typename Transformation::DataType MAGNUM_SCENEGRAPH_LOCAL computeJointTransformation(const std::vector*>& jointObjects, std::vector& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const; + typename Transformation::DataType MAGNUM_SCENEGRAPH_LOCAL computeJointTransformation(const std::vector>>& jointObjects, std::vector& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const; bool MAGNUM_SCENEGRAPH_LOCAL doIsDirty() const override final { return isDirty(); } void MAGNUM_SCENEGRAPH_LOCAL doSetDirty() override final { setDirty(); } void MAGNUM_SCENEGRAPH_LOCAL doSetClean() override final { setClean(); } - void doSetClean(const std::vector*>& objects) override final; + void doSetClean(const std::vector>>& objects) override final; - void MAGNUM_SCENEGRAPH_LOCAL setClean(const typename Transformation::DataType& absoluteTransformation); + void MAGNUM_SCENEGRAPH_LOCAL setCleanInternal(const typename Transformation::DataType& absoluteTransformation); typedef Implementation::ObjectFlag Flag; typedef Implementation::ObjectFlags Flags; diff --git a/src/Magnum/SceneGraph/Object.hpp b/src/Magnum/SceneGraph/Object.hpp index d0dafa267..2f6cbcd55 100644 --- a/src/Magnum/SceneGraph/Object.hpp +++ b/src/Magnum/SceneGraph/Object.hpp @@ -38,9 +38,35 @@ namespace Magnum { namespace SceneGraph { +#ifdef MAGNUM_BUILD_DEPRECATED +template void AbstractObject::setClean(const std::vector*>& objects) { + std::vector>> references; + references.reserve(objects.size()); + for(auto o: objects) { + CORRADE_INTERNAL_ASSERT(o != nullptr); + references.push_back(*o); + } + + setClean(references); +} +#endif + template AbstractObject::AbstractObject() {} template AbstractObject::~AbstractObject() {} +#ifdef MAGNUM_BUILD_DEPRECATED +template auto AbstractObject::transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { + std::vector>> references; + references.reserve(objects.size()); + for(auto o: objects) { + CORRADE_INTERNAL_ASSERT(o != nullptr); + references.push_back(*o); + } + + return transformationMatrices(references, initialTransformationMatrix); +} +#endif + template AbstractTransformation::AbstractTransformation() {} template Object::Object(Object* parent): counter(0xFFFFu), flags(Flag::Dirty) { @@ -159,22 +185,21 @@ template void Object::setClean() { /* Compose transformation and clean object */ absoluteTransformation = Implementation::Transformation::compose(absoluteTransformation, o->transformation()); CORRADE_INTERNAL_ASSERT(o->isDirty()); - o->setClean(absoluteTransformation); + o->setCleanInternal(absoluteTransformation); CORRADE_ASSERT(!o->isDirty(), "SceneGraph::Object::setClean(): original implementation was not called", ); } } -template auto Object::doTransformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { - std::vector*> castObjects(objects.size()); - for(std::size_t i = 0; i != objects.size(); ++i) - /* Non-null is checked in transformations() */ - /** @todo Ensure this doesn't crash, somehow */ - castObjects[i] = static_cast*>(objects[i]); +template auto Object::doTransformationMatrices(const std::vector>>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { + std::vector>> castObjects; + castObjects.reserve(objects.size()); + /** @todo Ensure this doesn't crash, somehow */ + for(auto o: objects) castObjects.push_back(static_cast&>(o.get())); return transformationMatrices(std::move(castObjects), initialTransformationMatrix); } -template auto Object::transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { +template auto Object::transformationMatrices(const std::vector>>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { std::vector transformations = this->transformations(std::move(objects), Implementation::Transformation::fromMatrix(initialTransformationMatrix)); std::vector transformationMatrices(transformations.size()); for(std::size_t i = 0; i != objects.size(); ++i) @@ -183,6 +208,19 @@ template auto Object::transformationMatric return transformationMatrices; } +#ifdef MAGNUM_BUILD_DEPRECATED +template auto Object::transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { + std::vector>> references; + references.reserve(objects.size()); + for(auto o: objects) { + CORRADE_INTERNAL_ASSERT(o != nullptr); + references.push_back(*o); + } + + return transformationMatrices(references, initialTransformationMatrix); +} +#endif + /* Computing absolute transformations for given list of objects @@ -197,7 +235,7 @@ Then for all joints their transformation (relative to parent joint) is computed and recursively concatenated together. Resulting transformations for joints which were originally in `object` list is then returned. */ -template std::vector Object::transformations(std::vector*> objects, const typename Transformation::DataType& initialTransformation) const { +template std::vector Object::transformations(std::vector>> objects, const typename Transformation::DataType& initialTransformation) const { CORRADE_ASSERT(objects.size() < 0xFFFFu, "SceneGraph::Object::transformations(): too large scene", std::vector{}); /* Remember object count for later */ @@ -206,16 +244,14 @@ template std::vector Ob /* Mark all original objects as joints and create initial list of joints from them */ for(std::size_t i = 0; i != objects.size(); ++i) { - CORRADE_INTERNAL_ASSERT(objects[i]); - /* Multiple occurences of one object in the array, don't overwrite it with different counter */ - if(objects[i]->counter != 0xFFFFu) continue; + if(objects[i].get().counter != 0xFFFFu) continue; - objects[i]->counter = UnsignedShort(i); - objects[i]->flags |= Flag::Joint; + objects[i].get().counter = UnsignedShort(i); + objects[i].get().flags |= Flag::Joint; } - std::vector*> jointObjects(objects); + std::vector>> jointObjects(objects); /* Scene object */ const Scene* scene = this->scene(); @@ -227,19 +263,19 @@ template std::vector Ob auto it = objects.begin(); while(!objects.empty()) { /* Already visited, remove and continue to next (duplicate occurence) */ - if((*it)->flags & Flag::Visited) { + if(it->get().flags & Flag::Visited) { it = objects.erase(it); continue; } /* Mark the object as visited */ - (*it)->flags |= Flag::Visited; + it->get().flags |= Flag::Visited; - Object* parent = (*it)->parent(); + Object* parent = it->get().parent(); /* If this is root object, remove from list */ if(!parent) { - CORRADE_ASSERT(*it == scene, "SceneGraph::Object::transformations(): the objects are not part of the same tree", std::vector{}); + CORRADE_ASSERT(&it->get() == scene, "SceneGraph::Object::transformations(): the objects are not part of the same tree", std::vector{}); it = objects.erase(it); /* Parent is an joint or already visited - remove current from list */ @@ -254,11 +290,11 @@ template std::vector Ob CORRADE_INTERNAL_ASSERT(parent->counter == 0xFFFFu); parent->counter = UnsignedShort(jointObjects.size()); parent->flags |= Flag::Joint; - jointObjects.push_back(parent); + jointObjects.push_back(*parent); } /* Else go up the hierarchy */ - } else *it = parent; + } else *it = *parent; /* Cycle if reached end */ if(it == objects.end()) it = objects.begin(); @@ -274,17 +310,17 @@ template std::vector Ob /* Copy transformation for second or next occurences from first occurence of duplicate object */ for(std::size_t i = 0; i != objectCount; ++i) { - if(jointObjects[i]->counter != i) - jointTransformations[i] = jointTransformations[jointObjects[i]->counter]; + if(jointObjects[i].get().counter != i) + jointTransformations[i] = jointTransformations[jointObjects[i].get().counter]; } /* All visited marks are now cleaned, clean joint marks and counters */ for(auto i: jointObjects) { /* All not-already cleaned objects (...duplicate occurences) should have joint mark */ - CORRADE_INTERNAL_ASSERT(i->counter == 0xFFFFu || i->flags & Flag::Joint); - i->flags &= ~Flag::Joint; - i->counter = 0xFFFFu; + CORRADE_INTERNAL_ASSERT(i.get().counter == 0xFFFFu || i.get().flags & Flag::Joint); + i.get().flags &= ~Flag::Joint; + i.get().counter = 0xFFFFu; } /* Shrink the array to contain only transformations of requested objects and return */ @@ -292,27 +328,40 @@ template std::vector Ob return jointTransformations; } -template typename Transformation::DataType Object::computeJointTransformation(const std::vector*>& jointObjects, std::vector& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const { - Object* o = jointObjects[joint]; +#ifdef MAGNUM_BUILD_DEPRECATED +template std::vector Object::transformations(std::vector*> objects, const typename Transformation::DataType& initialTransformation) const { + std::vector>> references; + references.reserve(objects.size()); + for(auto o: objects) { + CORRADE_INTERNAL_ASSERT(o != nullptr); + references.push_back(*o); + } + + return transformations(references, initialTransformation); +} +#endif + +template typename Transformation::DataType Object::computeJointTransformation(const std::vector>>& jointObjects, std::vector& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const { + std::reference_wrapper> o = jointObjects[joint]; /* Transformation already computed ("unvisited" by this function before either due to recursion or duplicate object occurences), done */ - if(!(o->flags & Flag::Visited)) return jointTransformations[joint]; + if(!(o.get().flags & Flag::Visited)) return jointTransformations[joint]; /* Initialize transformation */ - jointTransformations[joint] = o->transformation(); + jointTransformations[joint] = o.get().transformation(); /* Go up until next joint or root */ for(;;) { /* Clean visited mark */ - CORRADE_INTERNAL_ASSERT(o->flags & Flag::Visited); - o->flags &= ~Flag::Visited; + CORRADE_INTERNAL_ASSERT(o.get().flags & Flag::Visited); + o.get().flags &= ~Flag::Visited; - Object* parent = o->parent(); + Object* parent = o.get().parent(); /* Root object, compose transformation with initial, done */ if(!parent) { - CORRADE_INTERNAL_ASSERT(o->isScene()); + CORRADE_INTERNAL_ASSERT(o.get().isScene()); return (jointTransformations[joint] = Implementation::Transformation::compose(initialTransformation, jointTransformations[joint])); @@ -324,23 +373,23 @@ template typename Transformation::DataType Object::compose(parent->transformation(), jointTransformations[joint]); - o = parent; + o = *parent; } } } -template void Object::doSetClean(const std::vector*>& objects) { - std::vector*> castObjects(objects.size()); - for(std::size_t i = 0; i != objects.size(); ++i) - /** @todo Ensure this doesn't crash, somehow */ - castObjects[i] = static_cast*>(objects[i]); +template void Object::doSetClean(const std::vector>>& objects) { + std::vector>> castObjects; + castObjects.reserve(objects.size()); + /** @todo Ensure this doesn't crash, somehow */ + for(auto o: objects) castObjects.push_back(static_cast&>(o.get())); setClean(std::move(castObjects)); } -template void Object::setClean(std::vector*> objects) { +template void Object::setClean(std::vector>> objects) { /* Remove all clean objects from the list */ - auto firstClean = std::remove_if(objects.begin(), objects.end(), [](Object* o) { return !o->isDirty(); }); + auto firstClean = std::remove_if(objects.begin(), objects.end(), [](Object& o) { return !o.isDirty(); }); objects.erase(firstClean, objects.end()); /* No dirty objects left, done */ @@ -349,35 +398,48 @@ template void Object::setClean(std::vector /* Add non-clean parents to the list. Mark each added object as visited, so they aren't added more than once */ for(std::size_t end = objects.size(), i = 0; i != end; ++i) { - Object* o = objects[i]; - o->flags |= Flag::Visited; + Object& o = objects[i]; + o.flags |= Flag::Visited; - Object* parent = o->parent(); + Object* parent = o.parent(); while(parent && !(parent->flags & Flag::Visited) && parent->isDirty()) { - objects.push_back(parent); + objects.push_back(*parent); parent = parent->parent(); } } /* Cleanup all marks */ - for(auto o: objects) o->flags &= ~Flag::Visited; + for(auto o: objects) o.get().flags &= ~Flag::Visited; /* Compute absolute transformations */ - Scene* scene = objects[0]->scene(); + Scene* scene = objects[0].get().scene(); CORRADE_ASSERT(scene, "Object::setClean(): objects must be part of some scene", ); std::vector transformations(scene->transformations(objects)); /* Go through all objects and clean them */ for(std::size_t i = 0; i != objects.size(); ++i) { /* The object might be duplicated in the list, don't clean it more than once */ - if(!objects[i]->isDirty()) continue; + if(!objects[i].get().isDirty()) continue; + + objects[i].get().setCleanInternal(transformations[i]); + CORRADE_ASSERT(!objects[i].get().isDirty(), "SceneGraph::Object::setClean(): original implementation was not called", ); + } +} - objects[i]->setClean(transformations[i]); - CORRADE_ASSERT(!objects[i]->isDirty(), "SceneGraph::Object::setClean(): original implementation was not called", ); +#ifdef MAGNUM_BUILD_DEPRECATED +template void Object::setClean(std::vector*> objects) { + std::vector>> references; + references.reserve(objects.size()); + for(auto o: objects) { + CORRADE_INTERNAL_ASSERT(o != nullptr); + references.push_back(*o); } + + return setClean(objects); } +#endif -template void Object::setClean(const typename Transformation::DataType& absoluteTransformation) { +template void Object::setCleanInternal(const typename Transformation::DataType& absoluteTransformation) { /* "Lazy storage" for transformation matrix and inverted transformation matrix */ CachedTransformations cached; MatrixType matrix, invertedMatrix; diff --git a/src/Magnum/SceneGraph/Test/ObjectTest.cpp b/src/Magnum/SceneGraph/Test/ObjectTest.cpp index 401f9accb..c031b3d02 100644 --- a/src/Magnum/SceneGraph/Test/ObjectTest.cpp +++ b/src/Magnum/SceneGraph/Test/ObjectTest.cpp @@ -174,22 +174,22 @@ void ObjectTest::transformations() { Matrix4 initial = Matrix4::rotationX(Deg(90.0f)).inverted(); /* Empty list */ - CORRADE_COMPARE(s.transformations(std::vector(), initial), std::vector()); + CORRADE_COMPARE(s.transformations({}, initial), std::vector()); /* Scene alone */ - CORRADE_COMPARE(s.transformations({&s}, initial), std::vector{initial}); + CORRADE_COMPARE(s.transformations({s}, initial), std::vector{initial}); /* One object */ Object3D first(&s); first.rotateZ(Deg(30.0f)); Object3D second(&first); second.scale(Vector3(0.5f)); - CORRADE_COMPARE(s.transformations({&second}, initial), std::vector{ + CORRADE_COMPARE(s.transformations({second}, initial), std::vector{ initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::scaling(Vector3(0.5f)) }); /* One object and scene */ - CORRADE_COMPARE(s.transformations({&second, &s}, initial), (std::vector{ + CORRADE_COMPARE(s.transformations({second, s}, initial), (std::vector{ initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::scaling(Vector3(0.5f)), initial })); @@ -197,13 +197,13 @@ void ObjectTest::transformations() { /* Two objects with foreign joint */ Object3D third(&first); third.translate(Vector3::xAxis(5.0f)); - CORRADE_COMPARE(s.transformations({&second, &third}, initial), (std::vector{ + CORRADE_COMPARE(s.transformations({second, third}, initial), (std::vector{ initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::scaling(Vector3(0.5f)), initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::translation(Vector3::xAxis(5.0f)), })); /* Three objects with joint as one of them */ - CORRADE_COMPARE(s.transformations({&second, &third, &first}, initial), (std::vector{ + CORRADE_COMPARE(s.transformations({second, third, first}, initial), (std::vector{ initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::scaling(Vector3(0.5f)), initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::translation(Vector3::xAxis(5.0f)), initial*Matrix4::rotationZ(Deg(30.0f)), @@ -222,7 +222,7 @@ void ObjectTest::transformationsRelative() { third.translate(Vector3::xAxis(5.0f)); /* Transformation relative to another object */ - CORRADE_COMPARE(second.transformations({&third}), std::vector{ + CORRADE_COMPARE(second.transformations({third}), std::vector{ Matrix4::scaling(Vector3(0.5f)).inverted()*Matrix4::translation(Vector3::xAxis(5.0f)) }); @@ -234,7 +234,7 @@ void ObjectTest::transformationsRelative() { orphan1.scale(Vector3::xScale(3.0f)); Object3D orphan2(&orphanParent); orphan2.translate(Vector3::zAxis(5.0f)); - CORRADE_COMPARE(orphan1.transformations({&orphan2}), std::vector{ + CORRADE_COMPARE(orphan1.transformations({orphan2}), std::vector{ Matrix4::scaling(Vector3::xScale(3.0f)).inverted()*Matrix4::translation(Vector3::zAxis(5.0f)) }); } @@ -246,7 +246,7 @@ void ObjectTest::transformationsOrphan() { /* Transformation of objects not part of the same scene */ Scene3D s; Object3D orphan; - CORRADE_COMPARE(s.transformations({&orphan}), std::vector()); + CORRADE_COMPARE(s.transformations({orphan}), std::vector()); CORRADE_COMPARE(o.str(), "SceneGraph::Object::transformations(): the objects are not part of the same tree\n"); } @@ -262,7 +262,7 @@ void ObjectTest::transformationsDuplicate() { Matrix4 firstExpected = Matrix4::rotationZ(Deg(30.0f)); Matrix4 secondExpected = Matrix4::rotationZ(Deg(30.0f))*Matrix4::scaling(Vector3(0.5f)); Matrix4 thirdExpected = Matrix4::rotationZ(Deg(30.0f))*Matrix4::translation(Vector3::xAxis(5.0f)); - CORRADE_COMPARE(s.transformations({&second, &third, &second, &first, &third}), (std::vector{ + CORRADE_COMPARE(s.transformations({second, third, second, first, third}), (std::vector{ secondExpected, thirdExpected, secondExpected, firstExpected, thirdExpected })); } @@ -392,7 +392,7 @@ void ObjectTest::setCleanListHierarchy() { childThree->rotate(Deg(90.0f), Vector3::yAxis()); /* Clean the object and all its dirty parents (but not children) */ - Scene3D::setClean(std::vector{childTwo}); + Scene3D::setClean({*childTwo}); CORRADE_VERIFY(!scene.isDirty()); CORRADE_VERIFY(!childOne->isDirty()); CORRADE_VERIFY(!childTwo->isDirty()); @@ -406,19 +406,19 @@ void ObjectTest::setCleanListHierarchy() { /* If the object itself is already clean, it shouldn't clean it again */ childOne->cleanedAbsoluteTransformation = Matrix4(Matrix4::Zero); CORRADE_VERIFY(!childOne->isDirty()); - Scene3D::setClean(std::vector{childOne}); + Scene3D::setClean({*childOne}); CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero)); /* If any object in the hierarchy is already clean, it shouldn't clean it again */ CORRADE_VERIFY(!childOne->isDirty()); childTwo->setDirty(); - Scene3D::setClean(std::vector{childTwo}); + Scene3D::setClean({*childTwo}); CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero)); } void ObjectTest::setCleanListBulk() { /* Verify it doesn't crash when passed empty list */ - Object3D::setClean(std::vector()); + Object3D::setClean({}); Scene3D scene; Object3D a(&scene); @@ -429,7 +429,6 @@ void ObjectTest::setCleanListBulk() { CachingObject d(&c); d.scale(Vector3(-2.0f)); Object3D e(&scene); - std::vector cleanAll{&a, &b, &c, &d, &e}; /* All objects should be cleaned */ CORRADE_VERIFY(a.isDirty()); @@ -437,7 +436,7 @@ void ObjectTest::setCleanListBulk() { CORRADE_VERIFY(c.isDirty()); CORRADE_VERIFY(d.isDirty()); CORRADE_VERIFY(e.isDirty()); - Object3D::setClean(cleanAll); + Object3D::setClean({a, b, c, d, e}); CORRADE_VERIFY(!a.isDirty()); CORRADE_VERIFY(!b.isDirty()); CORRADE_VERIFY(!c.isDirty()); diff --git a/src/Magnum/Shapes/ShapeGroup.cpp b/src/Magnum/Shapes/ShapeGroup.cpp index 64648f9db..aebee420d 100644 --- a/src/Magnum/Shapes/ShapeGroup.cpp +++ b/src/Magnum/Shapes/ShapeGroup.cpp @@ -32,9 +32,10 @@ namespace Magnum { namespace Shapes { template void ShapeGroup::setClean() { /* Clean all objects */ if(!this->isEmpty()) { - std::vector*> objects(this->size()); + std::vector>> objects; + objects.reserve(this->size()); for(std::size_t i = 0; i != this->size(); ++i) - objects[i] = &(*this)[i].object(); + objects.push_back((*this)[i].object()); SceneGraph::AbstractObject::setClean(objects); } From 650fd6766b60c29fc3f70fcdf5e6505f0180f083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Feb 2014 21:14:42 +0100 Subject: [PATCH 74/86] SceneGraph: use std::reference_wrapper in FeatureGroup internals. --- src/Magnum/SceneGraph/FeatureGroup.h | 8 ++++---- src/Magnum/SceneGraph/FeatureGroup.hpp | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Magnum/SceneGraph/FeatureGroup.h b/src/Magnum/SceneGraph/FeatureGroup.h index 1670d06b2..46982149c 100644 --- a/src/Magnum/SceneGraph/FeatureGroup.h +++ b/src/Magnum/SceneGraph/FeatureGroup.h @@ -51,7 +51,7 @@ template class AbstractFeatureGroup { void add(AbstractFeature& feature); void remove(AbstractFeature& feature); - std::vector*> features; + std::vector>> features; }; /** @@ -86,12 +86,12 @@ template class FeatureGroup: pub /** @brief Feature at given index */ Feature& operator[](std::size_t index) { - return *static_cast(AbstractFeatureGroup::features[index]); + return static_cast(AbstractFeatureGroup::features[index].get()); } /** @overload */ const Feature& operator[](std::size_t index) const { - return *static_cast(AbstractFeatureGroup::features[index]); + return static_cast(AbstractFeatureGroup::features[index].get()); } /** @@ -160,7 +160,7 @@ template using FeatureGroup3D = BasicFeatureGroup3D FeatureGroup::~FeatureGroup() { - for(auto i: AbstractFeatureGroup::features) static_cast(i)->_group = nullptr; + for(auto i: AbstractFeatureGroup::features) static_cast(i.get())._group = nullptr; } template FeatureGroup& FeatureGroup::add(Feature& feature) { diff --git a/src/Magnum/SceneGraph/FeatureGroup.hpp b/src/Magnum/SceneGraph/FeatureGroup.hpp index 2b61092c7..9ad9f3dc7 100644 --- a/src/Magnum/SceneGraph/FeatureGroup.hpp +++ b/src/Magnum/SceneGraph/FeatureGroup.hpp @@ -39,11 +39,12 @@ template AbstractFeatureGroup::A template AbstractFeatureGroup::~AbstractFeatureGroup() = default; template void AbstractFeatureGroup::add(AbstractFeature& feature) { - features.push_back(&feature); + features.push_back(feature); } template void AbstractFeatureGroup::remove(AbstractFeature& feature) { - features.erase(std::find(features.begin(), features.end(), &feature)); + features.erase(std::find_if(features.begin(), features.end(), + [&feature](AbstractFeature& f) { return &f == &feature; })); } }} From a16963276ba408228b3150ab6361500167cf5ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Feb 2014 21:36:53 +0100 Subject: [PATCH 75/86] SceneGraph: fix deprecated build. Thank you, Jenkins. --- src/Magnum/SceneGraph/Object.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/SceneGraph/Object.hpp b/src/Magnum/SceneGraph/Object.hpp index 2f6cbcd55..c2fe34830 100644 --- a/src/Magnum/SceneGraph/Object.hpp +++ b/src/Magnum/SceneGraph/Object.hpp @@ -40,7 +40,7 @@ namespace Magnum { namespace SceneGraph { #ifdef MAGNUM_BUILD_DEPRECATED template void AbstractObject::setClean(const std::vector*>& objects) { - std::vector>> references; + std::vector>> references; references.reserve(objects.size()); for(auto o: objects) { CORRADE_INTERNAL_ASSERT(o != nullptr); @@ -56,7 +56,7 @@ template AbstractObject::~Abstra #ifdef MAGNUM_BUILD_DEPRECATED template auto AbstractObject::transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { - std::vector>> references; + std::vector>> references; references.reserve(objects.size()); for(auto o: objects) { CORRADE_INTERNAL_ASSERT(o != nullptr); From b6f8ad4fa1cdd5e826c0aa266f11244f3e402b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Feb 2014 21:42:23 +0100 Subject: [PATCH 76/86] SceneGraph: fix Object test on deprecated build. --- src/Magnum/SceneGraph/Test/ObjectTest.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Magnum/SceneGraph/Test/ObjectTest.cpp b/src/Magnum/SceneGraph/Test/ObjectTest.cpp index c031b3d02..cb5aefe57 100644 --- a/src/Magnum/SceneGraph/Test/ObjectTest.cpp +++ b/src/Magnum/SceneGraph/Test/ObjectTest.cpp @@ -174,7 +174,11 @@ void ObjectTest::transformations() { Matrix4 initial = Matrix4::rotationX(Deg(90.0f)).inverted(); /* Empty list */ + #ifndef MAGNUM_BUILD_DEPRECATED CORRADE_COMPARE(s.transformations({}, initial), std::vector()); + #else + CORRADE_COMPARE(s.transformations(std::vector>{}, initial), std::vector()); + #endif /* Scene alone */ CORRADE_COMPARE(s.transformations({s}, initial), std::vector{initial}); @@ -418,7 +422,11 @@ void ObjectTest::setCleanListHierarchy() { void ObjectTest::setCleanListBulk() { /* Verify it doesn't crash when passed empty list */ + #ifndef MAGNUM_BUILD_DEPRECATED Object3D::setClean({}); + #else + Object3D::setClean(std::vector>{}); + #endif Scene3D scene; Object3D a(&scene); From b9ca5f11a8e63206a7014372288a7ad222c36f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Feb 2014 21:42:52 +0100 Subject: [PATCH 77/86] MeshTools: actually use the epsilon parameter. Thanks, Clang. Fortunately this affected only deprecated build. --- src/Magnum/MeshTools/RemoveDuplicates.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/MeshTools/RemoveDuplicates.h b/src/Magnum/MeshTools/RemoveDuplicates.h index 6b5b40715..4107420cd 100644 --- a/src/Magnum/MeshTools/RemoveDuplicates.h +++ b/src/Magnum/MeshTools/RemoveDuplicates.h @@ -174,7 +174,7 @@ template std::vector removeDuplicates(std::vector void removeDuplicates(std::vector& indices, std::vector& data, typename Vector::Type epsilon = Math::TypeTraits::epsilon()) { std::vector uniqueIndices; - std::tie(uniqueIndices, data) = removeDuplicates(data); + std::tie(uniqueIndices, data) = removeDuplicates(data, epsilon); indices = MeshTools::duplicate(indices, uniqueIndices); } #endif From 12a2bb81bac6558e868d6a089ca5d891e73fb84f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Feb 2014 21:43:59 +0100 Subject: [PATCH 78/86] Doc++, added some TODOs. --- doc/best-practices.dox | 4 ++++ doc/opengl-support.dox | 4 +++- doc/troubleshooting.dox | 2 +- src/Magnum/AbstractShaderProgram.h | 3 +++ src/Magnum/SceneGraph/Object.h | 2 ++ 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/best-practices.dox b/doc/best-practices.dox index 723f27868..b1f17c9a0 100644 --- a/doc/best-practices.dox +++ b/doc/best-practices.dox @@ -80,6 +80,10 @@ vertex and index buffers in both Native Client and Emscripten. - [PowerVR Performance Recommendations](https://github.com/burningsun/pecker_framework/blob/master/参考资料/PowerVR.Performance%20Recommendations.pdf?raw=true) [PDF] +@subsection best-practices-amd AMD hardware + +- [ATI Radeon HD 2000 programming guide](http://developer.amd.com/wordpress/media/2012/10/ATI_Radeon_HD_2000_programming_guide.pdf) + @subsection best-practices-tegra NVidia Tegra hardware - [Optimize OpenGL ES 2.0 Performance for Tegra](http://docs.nvidia.com/tegra/index.html#GLES2_Perf_Main.html) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 6d6a0d8f2..f103f292b 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -50,7 +50,7 @@ following: @todo Replace @extension{APPLE,vertex_array_object} with ARB version (we use only ARB functions without APPLE fallback) @todo @extension{APPLE,flush_buffer_range} doesn't add anything to @extension{ARB,map_buffer_range} (remove it and leave only ARB one) @todo @extension{EXT,texture_array} overlaps with @extension{ARB,framebuffer_object} -@todo Replace @extension{NV,depth_buffer_float} with @extension{ARB,depth_buffer_float} and implement the missing @fn_gl{DepthRange} function +@todo Add @extension{ARB,depth_buffer_float} and implement the missing @fn_gl{DepthRange} function, but keep (and implement) @extension{NV,depth_buffer_float} for non-linear depth buffer @todo @extension{ARB,half_float_pixel}, @extension{ARB,half_float_vertex}? %Extension | Status @@ -194,6 +194,7 @@ following: @subsection opengl-support-44 OpenGL 4.4 @todo Also fallback to @extension{AMD,query_buffer_object} +@todo @extension{AMD,pinned_memory} "fallback" for @extension{ARB,buffer_storage} %Extension | Status -------------------------------------------- | ------ @@ -276,6 +277,7 @@ supported. Only extensions not already listed in above tables are included here. +@todo @es_extension{NV,non_square_matrices} @todo Support also IMG_multisampled_render_to_texture? It has different enum values (!) diff --git a/doc/troubleshooting.dox b/doc/troubleshooting.dox index 114d7d280..f9a096240 100644 --- a/doc/troubleshooting.dox +++ b/doc/troubleshooting.dox @@ -26,7 +26,7 @@ namespace Magnum { /** @page troubleshooting Troubleshooting -@brief Various tricks to overcome to common building and rendering issues. +@brief Various tricks to overcome common building and rendering issues. @section troubleshooting-building Building issues diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index 925345bc0..4dc6409a8 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -181,6 +181,9 @@ bindFragmentDataLocationIndexed(NormalOutput, 1, "normal"); ES 2.0, similar functionality is available in extension @es_extension{NV,draw_buffers}. +@todo @es_extension{EXT,separate_shader_objects} supports explicit attrib + location + @subsection AbstractShaderProgram-uniform-location Uniform locations The preferred workflow is to specify uniform locations directly in the shader diff --git a/src/Magnum/SceneGraph/Object.h b/src/Magnum/SceneGraph/Object.h index 09911ae5c..74fcdd6e1 100644 --- a/src/Magnum/SceneGraph/Object.h +++ b/src/Magnum/SceneGraph/Object.h @@ -93,6 +93,8 @@ class documentation or @ref compilation-speedup-hpp for more information. @see @ref Scene, @ref AbstractFeature, @ref AbstractTransformation, @ref DebugTools::ObjectRenderer +@todo Consider using `mutable` for flags to make transformation computation + available on const refs */ template class Object: public AbstractObject, public Transformation #ifndef DOXYGEN_GENERATING_OUTPUT From 70a4909ed0d07feb513b7bcad984e21da2776834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Feb 2014 21:48:08 +0100 Subject: [PATCH 79/86] SceneGraph: don't do infinite recursion on deprecated Object::setClean(). Found thanks to (probably otherwise useless) GCC warning about usage of deprecated function . Clang didn't emit such warning, because even deprecated function should be able to call itself recursively. --- src/Magnum/SceneGraph/Object.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/SceneGraph/Object.hpp b/src/Magnum/SceneGraph/Object.hpp index c2fe34830..9c2ea5c12 100644 --- a/src/Magnum/SceneGraph/Object.hpp +++ b/src/Magnum/SceneGraph/Object.hpp @@ -435,7 +435,7 @@ template void Object::setClean(std::vector references.push_back(*o); } - return setClean(objects); + return setClean(references); } #endif From ceb150f6d6ea445795e76c5239036a579ba2e487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Feb 2014 22:39:40 +0100 Subject: [PATCH 80/86] SceneGraph: workaround ambiguous overloads on deprecated GCC < 4.7 build. GCC 4.7 cannot detect proper overload based on arguments in initializer list constructor of some type, thus we need to provide explicit overload taking std::initializer_lists. --- src/Magnum/SceneGraph/AbstractObject.h | 18 ++++++++++++++++ src/Magnum/SceneGraph/Object.h | 27 +++++++++++++++++++++++ src/Magnum/SceneGraph/Object.hpp | 30 ++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/src/Magnum/SceneGraph/AbstractObject.h b/src/Magnum/SceneGraph/AbstractObject.h index f02872d09..d464e2702 100644 --- a/src/Magnum/SceneGraph/AbstractObject.h +++ b/src/Magnum/SceneGraph/AbstractObject.h @@ -165,6 +165,15 @@ template class AbstractObject * @deprecated Use @ref Magnum::SceneGraph::AbstractObject::transformationMatrices(const std::vector>>&, const MatrixType&) "transformationMatrices(const std::vector>>&, const MatrixType&)" instead. */ CORRADE_DEPRECATED("use transformationMatrices(const std::vector>>&, const MatrixType&) instead") std::vector transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; + + #ifdef CORRADE_GCC47_COMPATIBILITY + /* Workarounds to avoid ambiguous overload errors on GCC < 4.8. And I + thought 4.7 was bug-free. */ + std::vector transformationMatrices(std::initializer_list>>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) { + return transformationMatrices(std::vector>>{objects}, initialTransformationMatrix); + } + CORRADE_DEPRECATED("use transformationMatrices(const std::vector>>&, const MatrixType&) instead") std::vector transformationMatrices(std::initializer_list*> objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; + #endif #endif /*@}*/ @@ -194,6 +203,15 @@ template class AbstractObject * @deprecated Use @ref Magnum::SceneGraph::AbstractObject::setClean(const std::vector>>&) "setClean(const std::vector>>&)" instead. */ static CORRADE_DEPRECATED("use setClean(const std::vector>>&) instead") void setClean(const std::vector*>& objects); + + #ifdef CORRADE_GCC47_COMPATIBILITY + /* Workarounds to avoid ambiguous overload errors on GCC < 4.8. And I + thought 4.7 was bug-free. */ + static void setClean(std::initializer_list>> objects) { + return setClean(std::vector>>{objects}); + } + static CORRADE_DEPRECATED("use setClean(const std::vector>>&) instead") void setClean(std::initializer_list*> objects); + #endif #endif /** diff --git a/src/Magnum/SceneGraph/Object.h b/src/Magnum/SceneGraph/Object.h index 74fcdd6e1..027d8b8f9 100644 --- a/src/Magnum/SceneGraph/Object.h +++ b/src/Magnum/SceneGraph/Object.h @@ -257,6 +257,15 @@ template class Object: public AbstractObject>>&, const MatrixType&) "transformationMatrices(const std::vector>>&, const MatrixType&)" instead. */ CORRADE_DEPRECATED("use transformationMatrices(const std::vector>>&, const MatrixType&) instead") std::vector transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; + + #ifdef CORRADE_GCC47_COMPATIBILITY + /* Workarounds to avoid ambiguous overload errors on GCC < 4.8. And I + thought 4.7 was bug-free. */ + std::vector transformationMatrices(std::initializer_list>> objects, const MatrixType& initialTransformationMatrix = MatrixType()) const { + return transformationMatrices(std::vector>>{objects}, initialTransformationMatrix); + } + CORRADE_DEPRECATED("use transformationMatrices(const std::vector>>&, const MatrixType&) instead") std::vector transformationMatrices(std::initializer_list*> objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; + #endif #endif /** @@ -276,6 +285,15 @@ template class Object: public AbstractObject>>, const typename Transformation::DataType&) "transformations(std::vector>>, const typename Transformation::DataType&)" instead. */ CORRADE_DEPRECATED("use transformations(std::vector>>, const typename Transformation::DataType&) instead") std::vector transformations(std::vector*> objects, const typename Transformation::DataType& initialTransformation = typename Transformation::DataType()) const; + + #ifdef CORRADE_GCC47_COMPATIBILITY + /* Workarounds to avoid ambiguous overload errors on GCC < 4.8. And I + thought 4.7 was bug-free. */ + std::vector transformations(std::initializer_list>> objects, const typename Transformation::DataType& initialTransformation = typename Transformation::DataType()) const { + return transformations(std::vector>>{objects}, initialTransformation); + } + CORRADE_DEPRECATED("use transformations(std::vector>>, const typename Transformation::DataType&) instead") std::vector transformations(std::initializer_list*> objects, const typename Transformation::DataType& initialTransformation = typename Transformation::DataType()) const; + #endif #endif /*@}*/ @@ -301,6 +319,15 @@ template class Object: public AbstractObject>> "setClean(std::vector>>" instead. */ CORRADE_DEPRECATED("use setClean(std::vector>>) instead") static void setClean(std::vector*> objects); + + #ifdef CORRADE_GCC47_COMPATIBILITY + /* Workarounds to avoid ambiguous overload errors on GCC < 4.8. And I + thought 4.7 was bug-free. */ + static void setClean(std::initializer_list>> objects) { + setClean(std::vector>>{objects}); + } + static CORRADE_DEPRECATED("use setClean(std::vector>>) instead") void setClean(std::initializer_list*> objects); + #endif #endif /** @copydoc AbstractObject::isDirty() */ diff --git a/src/Magnum/SceneGraph/Object.hpp b/src/Magnum/SceneGraph/Object.hpp index 9c2ea5c12..633124f50 100644 --- a/src/Magnum/SceneGraph/Object.hpp +++ b/src/Magnum/SceneGraph/Object.hpp @@ -49,6 +49,12 @@ template void AbstractObject::se setClean(references); } + +#ifdef CORRADE_GCC47_COMPATIBILITY +template void AbstractObject::setClean(std::initializer_list*> objects) { + return setClean(std::vector*>{objects}); +} +#endif #endif template AbstractObject::AbstractObject() {} @@ -65,6 +71,12 @@ template auto AbstractObject::tr return transformationMatrices(references, initialTransformationMatrix); } + +#ifdef CORRADE_GCC47_COMPATIBILITY +template auto AbstractObject::transformationMatrices(std::initializer_list*> objects, const MatrixType& initialTransformationMatrix) const -> std::vector { + return transformationMatrices(std::vector*>{objects}, initialTransformationMatrix); +} +#endif #endif template AbstractTransformation::AbstractTransformation() {} @@ -219,6 +231,12 @@ template auto Object::transformationMatric return transformationMatrices(references, initialTransformationMatrix); } + +#ifdef CORRADE_GCC47_COMPATIBILITY +template auto Object::transformationMatrices(std::initializer_list*> objects, const MatrixType& initialTransformationMatrix) const -> std::vector { + return transformationMatrices(std::vector*>{objects}, initialTransformationMatrix); +} +#endif #endif /* @@ -339,6 +357,12 @@ template std::vector Ob return transformations(references, initialTransformation); } + +#ifdef CORRADE_GCC47_COMPATIBILITY +template std::vector Object::transformations(std::initializer_list*> objects, const typename Transformation::DataType& initialTransformation) const { + return transformations(std::vector*>{objects}, initialTransformation); +} +#endif #endif template typename Transformation::DataType Object::computeJointTransformation(const std::vector>>& jointObjects, std::vector& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const { @@ -437,6 +461,12 @@ template void Object::setClean(std::vector return setClean(references); } + +#ifdef CORRADE_GCC47_COMPATIBILITY +template void Object::setClean(std::initializer_list*> objects) { + setClean(std::vector*>{objects}); +} +#endif #endif template void Object::setCleanInternal(const typename Transformation::DataType& absoluteTransformation) { From 388db5ae009aedbc2d3c6e1dca6c4c127c71e4d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Feb 2014 22:42:25 +0100 Subject: [PATCH 81/86] SceneGraph: no need to return void. --- src/Magnum/SceneGraph/Object.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/SceneGraph/Object.hpp b/src/Magnum/SceneGraph/Object.hpp index 633124f50..9b26614c3 100644 --- a/src/Magnum/SceneGraph/Object.hpp +++ b/src/Magnum/SceneGraph/Object.hpp @@ -459,7 +459,7 @@ template void Object::setClean(std::vector references.push_back(*o); } - return setClean(references); + setClean(references); } #ifdef CORRADE_GCC47_COMPATIBILITY From b64a50c821b779a9ce99e9f7668cf9f49cb46ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Feb 2014 22:46:24 +0100 Subject: [PATCH 82/86] SceneGraph: avoid unnecessary copies in deprecated functions. Optimizations of deprecated API? What the hell am I doing? --- src/Magnum/SceneGraph/Object.h | 4 ++-- src/Magnum/SceneGraph/Object.hpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Magnum/SceneGraph/Object.h b/src/Magnum/SceneGraph/Object.h index 027d8b8f9..dfa95b132 100644 --- a/src/Magnum/SceneGraph/Object.h +++ b/src/Magnum/SceneGraph/Object.h @@ -284,7 +284,7 @@ template class Object: public AbstractObject>>, const typename Transformation::DataType&) * @deprecated Use @ref Magnum::SceneGraph::Object::transformations(std::vector>>, const typename Transformation::DataType&) "transformations(std::vector>>, const typename Transformation::DataType&)" instead. */ - CORRADE_DEPRECATED("use transformations(std::vector>>, const typename Transformation::DataType&) instead") std::vector transformations(std::vector*> objects, const typename Transformation::DataType& initialTransformation = typename Transformation::DataType()) const; + CORRADE_DEPRECATED("use transformations(std::vector>>, const typename Transformation::DataType&) instead") std::vector transformations(const std::vector*>& objects, const typename Transformation::DataType& initialTransformation = typename Transformation::DataType()) const; #ifdef CORRADE_GCC47_COMPATIBILITY /* Workarounds to avoid ambiguous overload errors on GCC < 4.8. And I @@ -318,7 +318,7 @@ template class Object: public AbstractObject>>) * @deprecated Use @ref Magnum::SceneGraph::Object::setClean(std::vector>> "setClean(std::vector>>" instead. */ - CORRADE_DEPRECATED("use setClean(std::vector>>) instead") static void setClean(std::vector*> objects); + CORRADE_DEPRECATED("use setClean(std::vector>>) instead") static void setClean(const std::vector*>& objects); #ifdef CORRADE_GCC47_COMPATIBILITY /* Workarounds to avoid ambiguous overload errors on GCC < 4.8. And I diff --git a/src/Magnum/SceneGraph/Object.hpp b/src/Magnum/SceneGraph/Object.hpp index 9b26614c3..6716902e2 100644 --- a/src/Magnum/SceneGraph/Object.hpp +++ b/src/Magnum/SceneGraph/Object.hpp @@ -347,7 +347,7 @@ template std::vector Ob } #ifdef MAGNUM_BUILD_DEPRECATED -template std::vector Object::transformations(std::vector*> objects, const typename Transformation::DataType& initialTransformation) const { +template std::vector Object::transformations(const std::vector*>& objects, const typename Transformation::DataType& initialTransformation) const { std::vector>> references; references.reserve(objects.size()); for(auto o: objects) { @@ -355,7 +355,7 @@ template std::vector Ob references.push_back(*o); } - return transformations(references, initialTransformation); + return transformations(std::move(references), initialTransformation); } #ifdef CORRADE_GCC47_COMPATIBILITY @@ -451,7 +451,7 @@ template void Object::setClean(std::vector } #ifdef MAGNUM_BUILD_DEPRECATED -template void Object::setClean(std::vector*> objects) { +template void Object::setClean(const std::vector*>& objects) { std::vector>> references; references.reserve(objects.size()); for(auto o: objects) { @@ -459,7 +459,7 @@ template void Object::setClean(std::vector references.push_back(*o); } - setClean(references); + setClean(std::move(references)); } #ifdef CORRADE_GCC47_COMPATIBILITY From e8aa600a342769f29b498c553fe9abfc43baa95b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 10 Feb 2014 12:22:01 +0100 Subject: [PATCH 83/86] Polished docs of ResourceManager API. --- src/Magnum/AbstractResourceLoader.h | 71 ++++++++++--------- src/Magnum/Resource.h | 22 +++--- src/Magnum/ResourceManager.h | 106 ++++++++++++++-------------- 3 files changed, 101 insertions(+), 98 deletions(-) diff --git a/src/Magnum/AbstractResourceLoader.h b/src/Magnum/AbstractResourceLoader.h index 4430dff5c..8eedaefcd 100644 --- a/src/Magnum/AbstractResourceLoader.h +++ b/src/Magnum/AbstractResourceLoader.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::AbstractResourceLoader + * @brief Class @ref Magnum::AbstractResourceLoader */ #include @@ -38,28 +38,30 @@ namespace Magnum { /** @brief Base for resource loaders -Provides (a)synchronous resource loading for ResourceManager. +Provides (a)synchronous resource loading for @ref ResourceManager. @section AbstractResourceLoader-usage Usage and subclassing Usage is done by subclassing. Subclass instances can be added to -ResourceManager using ResourceManager::setLoader(). After adding the loader, -each call to ResourceManager::get() will call load() implementation unless the -resource is already loaded (or loading is in progress). Note that resources -requested before the loader was added are not be affected by the loader. - -Subclassing is done by implementing at least doLoad() function. The loading can -be done synchronously or asynchronously (i.e., in another thread). The base -implementation provides interface to ResourceManager and manages loading -progress (which is then available through functions requestedCount(), -loadedCount() and notFoundCount()). You shouldn't access the ResourceManager -directly when loading the data. - -In your doLoad() implementation, after your resources are loaded, call set() to -pass them to ResourceManager or call setNotFound() to indicate that the -resource was not found. - -You can also implement name() to provide meaningful names for resource keys. +@ref ResourceManager using @ref ResourceManager::setLoader(). After adding the +loader, each call to @ref ResourceManager::get() will call @ref load() +implementation unless the resource is already loaded (or loading is in +progress). Note that resources requested before the loader was added are not +affected by the loader. + +Subclassing is done by implementing at least @ref doLoad() function. The +loading can be done synchronously or asynchronously (i.e., in another thread). +The base implementation provides interface to @ref ResourceManager and manages +loading progress (which is then available through functions @ref requestedCount(), +@ref loadedCount() and @ref notFoundCount()). You shouldn't access the +@ref ResourceManager directly when loading the data. + +In your @ref doLoad() implementation, after your resources are loaded, call +@ref set() to pass them to @ref ResourceManager or call @ref setNotFound() to +indicate that the resource was not found. + +You can also implement @ref name() to provide meaningful names for resource +keys. Example implementation for synchronous mesh loader: @code @@ -109,23 +111,23 @@ template class AbstractResourceLoader { /** * @brief Count of requested resources * - * Count of resources requested by calling load(). + * Count of resources requested by calling @ref load(). */ std::size_t requestedCount() const { return _requestedCount; } /** * @brief Count of not found resources * - * Count of resources requested by calling load(), but not found by - * the loader. + * Count of resources requested by calling @ref load(), but not found + * by the loader. */ std::size_t notFoundCount() const { return _notFoundCount; } /** * @brief Count of loaded resources * - * Count of resources requested by calling load(), but not found by - * the loader. + * Count of resources requested by calling @ref load(), but not found + * by the loader. */ std::size_t loadedCount() const { return _loadedCount; } @@ -145,8 +147,8 @@ template class AbstractResourceLoader { * features is incremented. Depending on implementation the resource * might be loaded synchronously or asynchronously. * - * @see ResourceManager::state(), requestedCount(), notFoundCount(), - * loadedCount() + * @see @ref ResourceManager::state(), @ref requestedCount(), + * @ref notFoundCount(), @ref loadedCount() */ void load(ResourceKey key); @@ -155,9 +157,10 @@ template class AbstractResourceLoader { * @brief Set loaded resource to resource manager * * Also increments count of loaded resources. Parameter @p state must - * be either @ref ResourceDataState::Mutable or @ref ResourceDataState::Final. - * See @ref ResourceManager::set() for more information. - * @see loadedCount() + * be either @ref ResourceDataState::Mutable or + * @ref ResourceDataState::Final. See @ref ResourceManager::set() for + * more information. + * @see @ref loadedCount() */ void set(ResourceKey key, T* data, ResourceDataState state, ResourcePolicy policy); @@ -184,9 +187,9 @@ template class AbstractResourceLoader { /** * @brief Mark resource as not found * - * Also increments count of not found resources. See - * ResourceManager::setNotFound() for more information. - * @see notFountCount() + * Also increments count of not found resources. See also + * @ref ResourceManager::set() for more information. + * @see @ref notFoundCount() */ void setNotFound(ResourceKey key); @@ -196,14 +199,14 @@ template class AbstractResourceLoader { protected: #endif /** - * @brief Implementation for name() + * @brief Implementation for @ref name() * * Default implementation returns empty string. */ virtual std::string doName(ResourceKey key) const; /** - * @brief Implementation for load() + * @brief Implementation for @ref load() * * See class documentation for reimplementation guide. */ diff --git a/src/Magnum/Resource.h b/src/Magnum/Resource.h index 57d701a03..787e39f90 100644 --- a/src/Magnum/Resource.h +++ b/src/Magnum/Resource.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::ResourceKey, Magnum::Resource, enum Magnum::ResourceState + * @brief Class @ref Magnum::ResourceKey, @ref Magnum::Resource, enum @ref Magnum::ResourceState */ #include @@ -37,11 +37,11 @@ namespace Magnum { -/** @relates Resource - * @brief %Resource state - * - * @see Resource::state(), ResourceManager::state() - */ +/** +@brief %Resource state + +@see @ref Resource::state(), @ref ResourceManager::state() +*/ enum class ResourceState: UnsignedByte { /** The resource is not yet loaded (and no fallback is available). */ NotLoaded, @@ -74,9 +74,7 @@ Debug MAGNUM_EXPORT operator<<(Debug debug, ResourceState value); /** @brief Key for accessing resource -See ResourceManager for more information. -@see ResourceManager::referenceCount(), ResourceManager::state(), - ResourceManager::get(), ResourceManager::set(), Resource::key() +See @ref ResourceManager for more information. */ class ResourceKey: public Utility::MurmurHash2::Digest { public: @@ -110,7 +108,7 @@ namespace Implementation { /** @brief %Resource reference -See ResourceManager for more information. +See @ref ResourceManager for more information. */ #ifdef DOXYGEN_GENERATING_OUTPUT template @@ -125,7 +123,7 @@ class Resource { * @brief Default constructor * * Creates empty resource. Resources are acquired from the manager by - * calling ResourceManager::get(). + * calling @ref ResourceManager::get(). */ explicit Resource(): manager(nullptr), lastCheck(0), _state(ResourceState::Final), data(nullptr) {} @@ -157,7 +155,7 @@ class Resource { /** * @brief %Resource state * - * @see operator bool(), ResourceManager::state() + * @see @ref operator bool(), @ref ResourceManager::state() */ ResourceState state() { acquire(); diff --git a/src/Magnum/ResourceManager.h b/src/Magnum/ResourceManager.h index 1030abc0f..67d6dfcc8 100644 --- a/src/Magnum/ResourceManager.h +++ b/src/Magnum/ResourceManager.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::ResourceManager, enum Magnum::ResourceDataState, Magnum::ResourcePolicy + * @brief Class @ref Magnum::ResourceManager, @ref Magnum::ResourceDataState, @ref Magnum::ResourcePolicy */ #include @@ -35,44 +35,44 @@ namespace Magnum { -/** @relates ResourceManager - * @brief %Resource data state - * - * @see ResourceManager::set(), ResourceState - */ +/** +@brief %Resource data state + +@see @ref ResourceManager::set(), @ref ResourceState +*/ enum class ResourceDataState: UnsignedByte { /** - * The resource is currently loading. Parameter @p data in ResourceManager::set() - * should be set to `null`. + * The resource is currently loading. Parameter @p data in + * @ref ResourceManager::set() should be set to `nullptr`. */ Loading = UnsignedByte(ResourceState::Loading), /** - * The resource was not found. Parameter @p data in ResourceManager::set() - * should be set to `null`. + * The resource was not found. Parameter @p data in + * @ref ResourceManager::set() should be set to `nullptr`. */ NotFound = UnsignedByte(ResourceState::NotFound), /** * The resource can be changed by the manager in the future. This is - * slower, as Resource needs to ask the manager for new version every time - * the data are accessed, but allows changing the data for e.g. debugging - * purposes. + * slower, as @ref Resource needs to ask the manager for new version every + * time the data are accessed, but allows changing the data for e.g. + * debugging purposes. */ Mutable = UnsignedByte(ResourceState::Mutable), /** * The resource cannot be changed by the manager in the future. This is - * faster, as Resource instances will ask for the data only one time, thus - * suitable for production code. + * faster, as @ref Resource instances will ask for the data only one time, + * thus suitable for production code. */ Final = UnsignedByte(ResourceState::Final) }; -/** @relates ResourceManager +/** @brief %Resource policy -@see ResourceManager::set(), ResourceManager::free() +@see @ref ResourceManager::set(), @ref ResourceManager::free() */ enum class ResourcePolicy: UnsignedByte { /** The resource will stay resident for whole lifetime of resource manager. */ @@ -80,7 +80,7 @@ enum class ResourcePolicy: UnsignedByte { /** * The resource will be unloaded when manually calling - * ResourceManager::free() if nothing references it. + * @ref ResourceManager::free() if nothing references it. */ Manual, @@ -160,43 +160,43 @@ template class ResourceManagerData { @brief %Resource manager Provides storage for arbitrary set of types, accessible globally using -instance(). +@ref instance(). @section ResourceManager-usage Usage -Each resource is referenced from Resource class. For optimizing performance, -each resource can be set as mutable or final. Mutable resources can be -modified by the manager and thus each %Resource instance asks the manager for -modifications on each access. On the other hand, final resources cannot be -modified by the manager, so %Resource instances don't have to ask the manager -every time, which is faster. +Each resource is referenced from @ref Resource class. For optimizing +performance, each resource can be set as mutable or final. Mutable resources +can be modified by the manager and thus each @ref Resource instance asks the +manager for modifications on each access. On the other hand, final resources +cannot be modified by the manager, so @ref Resource instances don't have to ask +the manager every time, which is faster. It's possible to provide fallback for resources which are not available using -setFallback(). Accessing data of such resources will access the fallback +@ref setFallback(). Accessing data of such resources will access the fallback instead of failing on null pointer dereference. Availability and state of each -resource can be queried through function state() on the manager or -Resource::state() on each resource. +resource can be queried through function @ref state() on the manager or +@ref Resource::state() on each resource. The resources can be managed in three ways - resident resources, which stay in memory for whole lifetime of the manager, manually managed resources, which -can be deleted by calling free() if nothing references them anymore, and +can be deleted by calling @ref free() if nothing references them anymore, and reference counted resources, which are deleted as soon as the last reference to them is removed. %Resource state and policy is configured when setting the resource data in -set() and can be changed each time the data are updated, although already +@ref set() and can be changed each time the data are updated, although already final resources cannot obviously be set as mutable again. Basic usage is: -- Typedef'ing manager of desired types, creating its instance. +- Typedef'ing manager of desired types, creating its instance. @code typedef ResourceManager MyResourceManager; MyResourceManager manager; @endcode -- Filling the manager with resource data and acquiring the resources. Note - that a resource can be acquired with get() even before the manager contains - the data for it, as long as the resource data are not accessed (or fallback - is provided). +- Filling the manager with resource data and acquiring the resources. Note + that a resource can be acquired with @ref get() even before the manager + contains the data for it, as long as the resource data are not accessed (or + fallback is provided). @code MyResourceManager* manager = MyResourceManager::instance(); Resource texture(manager->get("texture")); @@ -210,13 +210,13 @@ if(!cube) { manager->set(cube.key(), mesh, ResourceDataState::Final, ResourcePolicy::Resident); } @endcode -- Using the resource data. +- Using the resource data. @code shader->setTexture(layer); cube->draw(*shader); @endcode -- Destroying resource references and deleting manager instance when nothing - references the resources anymore. +- Destroying resource references and deleting manager instance when nothing + references the resources anymore. @see AbstractResourceLoader */ @@ -238,7 +238,7 @@ template class ResourceManager: private Implementation::Resource * Sets global instance pointer to itself. * @attention Only one instance of given ResourceManager type can be * created. - * @see instance() + * @see @ref instance() */ explicit ResourceManager(); @@ -246,7 +246,7 @@ template class ResourceManager: private Implementation::Resource * @brief Destructor * * Sets global instance pointer to `nullptr`. - * @see instance() + * @see @ref instance() */ ~ResourceManager(); @@ -274,7 +274,7 @@ template class ResourceManager: private Implementation::Resource /** * @brief Reference count of given resource * - * @see set() + * @see @ref set() */ template std::size_t referenceCount(ResourceKey key) const { return this->Implementation::ResourceManagerData::referenceCount(key); @@ -283,7 +283,7 @@ template class ResourceManager: private Implementation::Resource /** * @brief %Resource state * - * @see set(), Resource::state() + * @see @ref set(), @ref Resource::state() */ template ResourceState state(ResourceKey key) const { return this->Implementation::ResourceManagerData::state(key); @@ -293,20 +293,20 @@ template class ResourceManager: private Implementation::Resource * @brief Set resource data * @return Reference to self (for method chaining) * - * If @p policy is set to `ResourcePolicy::ReferenceCounted`, there + * If @p policy is set to @ref ResourcePolicy::ReferenceCounted, there * must be already at least one reference to given resource, otherwise - * the data will be deleted immediately and no resource will be - * added. To avoid spending unnecessary loading time, add - * reference-counted resources only if they are already referenced: + * the data will be deleted immediately and no resource will be added. + * To avoid spending unnecessary loading time, add reference-counted + * resources only if they are already referenced: * @code * if(manager.referenceCount("myresource")) { * // load data... * manager.set("myresource", data, state, ResourcePolicy::ReferenceCounted); * } * @endcode - * @attention If resource state is already `ResourceState::Final`, - * subsequent updates are not possible. - * @see referenceCount(), state() + * @attention Subsequent updates are not possible if resource state is + * already @ref ResourceState::Final. + * @see @ref referenceCount(), @ref state() */ template ResourceManager& set(ResourceKey key, T* data, ResourceDataState state, ResourcePolicy policy) { this->Implementation::ResourceManagerData::set(key, data, state, policy); @@ -380,7 +380,8 @@ template class ResourceManager: private Implementation::Resource * @brief Clear all resources of given type * @return Reference to self (for method chaining) * - * Unlike free() this function assumes that no resource is referenced. + * Unlike @ref free() this function assumes that no resource is + * referenced. */ template ResourceManager& clear() { this->Implementation::ResourceManagerData::clear(); @@ -391,7 +392,8 @@ template class ResourceManager: private Implementation::Resource * @brief Clear all resources * @return Reference to self (for method chaining) * - * Unlike free() this function assumes that no resource is referenced. + * Unlike @ref free() this function assumes that no resource is + * referenced. */ ResourceManager& clear() { clearInternal(); @@ -413,7 +415,7 @@ template class ResourceManager: private Implementation::Resource * @param loader Loader or `nullptr` if unsetting previous loader. * @return Reference to self (for method chaining) * - * See AbstractResourceLoader documentation for more information. + * See @ref AbstractResourceLoader documentation for more information. * @attention The loader is deleted on destruction before unloading * all resources. */ From 6015896ceb16cb1374f81a7527e98179d5192d63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 10 Feb 2014 14:34:39 +0100 Subject: [PATCH 84/86] Doxygen I hate you. --- src/Magnum/SceneGraph/AbstractObject.h | 1 + src/Magnum/SceneGraph/Object.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/Magnum/SceneGraph/AbstractObject.h b/src/Magnum/SceneGraph/AbstractObject.h index d464e2702..e6a77c132 100644 --- a/src/Magnum/SceneGraph/AbstractObject.h +++ b/src/Magnum/SceneGraph/AbstractObject.h @@ -163,6 +163,7 @@ template class AbstractObject /** * @copybrief transformationMatrices(const std::vector>>&, const MatrixType&) * @deprecated Use @ref Magnum::SceneGraph::AbstractObject::transformationMatrices(const std::vector>>&, const MatrixType&) "transformationMatrices(const std::vector>>&, const MatrixType&)" instead. + * @todoc The `ref` works when `const` is added, but then the quoted thing is not taken as a part of the reference. The `copybrief` doesn't parse the `const` at all. Doxygen I hate you. */ CORRADE_DEPRECATED("use transformationMatrices(const std::vector>>&, const MatrixType&) instead") std::vector transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; diff --git a/src/Magnum/SceneGraph/Object.h b/src/Magnum/SceneGraph/Object.h index dfa95b132..d40f3d97b 100644 --- a/src/Magnum/SceneGraph/Object.h +++ b/src/Magnum/SceneGraph/Object.h @@ -255,6 +255,7 @@ template class Object: public AbstractObject>>&, const MatrixType&) * @deprecated Use @ref Magnum::SceneGraph::Object::transformationMatrices(const std::vector>>&, const MatrixType&) "transformationMatrices(const std::vector>>&, const MatrixType&)" instead. + * @todoc fix this when Doxygen is sane (see this function in AbstractObject) */ CORRADE_DEPRECATED("use transformationMatrices(const std::vector>>&, const MatrixType&) instead") std::vector transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; @@ -283,6 +284,7 @@ template class Object: public AbstractObject>>, const typename Transformation::DataType&) * @deprecated Use @ref Magnum::SceneGraph::Object::transformations(std::vector>>, const typename Transformation::DataType&) "transformations(std::vector>>, const typename Transformation::DataType&)" instead. + * @todoc fix this when Doxygen is sane (see related function in AbstractObject) */ CORRADE_DEPRECATED("use transformations(std::vector>>, const typename Transformation::DataType&) instead") std::vector transformations(const std::vector*>& objects, const typename Transformation::DataType& initialTransformation = typename Transformation::DataType()) const; From 8a9fa4d99954de2d441640364957e3963afa0e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 10 Feb 2014 14:49:15 +0100 Subject: [PATCH 85/86] Test also ResourceManager::set() with default values. --- src/Magnum/Test/ResourceManagerTest.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Magnum/Test/ResourceManagerTest.cpp b/src/Magnum/Test/ResourceManagerTest.cpp index f4326538b..dd79a926a 100644 --- a/src/Magnum/Test/ResourceManagerTest.cpp +++ b/src/Magnum/Test/ResourceManagerTest.cpp @@ -43,6 +43,7 @@ class ResourceManagerTest: public TestSuite::Tester { void residentPolicy(); void referenceCountedPolicy(); void manualPolicy(); + void defaults(); void clear(); void clearWhileReferenced(); void loader(); @@ -68,6 +69,7 @@ ResourceManagerTest::ResourceManagerTest() { &ResourceManagerTest::residentPolicy, &ResourceManagerTest::referenceCountedPolicy, &ResourceManagerTest::manualPolicy, + &ResourceManagerTest::defaults, &ResourceManagerTest::clear, &ResourceManagerTest::clearWhileReferenced, &ResourceManagerTest::loader}); @@ -229,6 +231,12 @@ void ResourceManagerTest::manualPolicy() { CORRADE_COMPARE(Data::count, 1); } +void ResourceManagerTest::defaults() { + ResourceManager rm; + rm.set("data", new Data); + CORRADE_COMPARE(rm.state("data"), ResourceState::Final); +} + void ResourceManagerTest::clear() { ResourceManager rm; From e1105300cba877253ad3471cea1275601b4af9f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 13 Feb 2014 13:39:47 +0100 Subject: [PATCH 86/86] Fix Context initialization in WebGL. Broken since 41235c20eb2ab65bc034eefd77cadee33210b730 which was three weeks ago. I am SO thoroughly testing all the stuff, right? --- src/Magnum/Context.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index c11a579b0..100d408b1 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -313,6 +313,8 @@ Context::Context() { const std::string version = versionString(); #ifndef MAGNUM_TARGET_GLES if(version.compare(0, 4, "2.1 ") == 0) + #elif defined(CORRADE_TARGET_EMSCRIPTEN) + if(version.find("WebGL 1") != std::string::npos) #else if(version.find("OpenGL ES 2.0") != std::string::npos) #endif