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] 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;