diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 66a889286..43d2d3a86 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -781,7 +781,10 @@ std::vector Context::extensionStrings() const { #ifndef MAGNUM_TARGET_GLES bool Context::isCoreProfile() { - Implementation::ContextState& state = *_state->context; + return isCoreProfileInternal(*_state->context); +} + +bool Context::isCoreProfileInternal(Implementation::ContextState& state) { Implementation::ContextState::CoreProfile& value = state.coreProfile; if(value == Implementation::ContextState::CoreProfile::Initial) diff --git a/src/Magnum/Context.h b/src/Magnum/Context.h index cbf10f651..49275372e 100644 --- a/src/Magnum/Context.h +++ b/src/Magnum/Context.h @@ -523,6 +523,10 @@ class MAGNUM_EXPORT Context { bool isDriverWorkaroundDisabled(const std::string& workaround); Implementation::State& state() { return *_state; } + /* This function is called from MeshState constructor, which means the + state() pointer is not ready yet so we have to pass it directly */ + MAGNUM_LOCAL bool isCoreProfileInternal(Implementation::ContextState& state); + private: explicit Context(NoCreateT, Int argc, const char** argv, void functionLoader()); diff --git a/src/Magnum/Implementation/MeshState.cpp b/src/Magnum/Implementation/MeshState.cpp index 826f6c9b1..0c39666de 100644 --- a/src/Magnum/Implementation/MeshState.cpp +++ b/src/Magnum/Implementation/MeshState.cpp @@ -33,7 +33,7 @@ namespace Magnum { namespace Implementation { -MeshState::MeshState(Context& context, std::vector& extensions): currentVAO(0) +MeshState::MeshState(Context& context, ContextState& contextState, std::vector& extensions): currentVAO(0) #ifndef MAGNUM_TARGET_GLES2 , maxElementIndex{0}, maxElementsIndices{0}, maxElementsVertices{0} #endif @@ -159,6 +159,24 @@ MeshState::MeshState(Context& context, std::vector& extensions): cu #endif else vertexAttribDivisorImplementation = nullptr; #endif + + #ifndef MAGNUM_TARGET_GLES + /* If we are on core profile and ARB_VAO was explicitly disabled by the + user, we need to bind a default VAO so we are still able to draw things */ + if(context.isExtensionDisabled() && context.isCoreProfileInternal(contextState)) { + glGenVertexArrays(1, &defaultVAO); + glBindVertexArray(defaultVAO); + } + #else + static_cast(contextState); + #endif +} + +MeshState::~MeshState() { + #ifndef MAGNUM_TARGET_GLES + /* If the default VAO was created, we need to delete it to avoid leaks */ + if(defaultVAO) glDeleteVertexArrays(1, &defaultVAO); + #endif } void MeshState::reset() { diff --git a/src/Magnum/Implementation/MeshState.h b/src/Magnum/Implementation/MeshState.h index 36ab38d54..5b0b30c6f 100644 --- a/src/Magnum/Implementation/MeshState.h +++ b/src/Magnum/Implementation/MeshState.h @@ -32,8 +32,11 @@ namespace Magnum { namespace Implementation { +struct ContextState; + struct MeshState { - explicit MeshState(Context& context, std::vector& extensions); + explicit MeshState(Context& context, ContextState& contextState, std::vector& extensions); + ~MeshState(); void reset(); @@ -56,6 +59,10 @@ struct MeshState { void(*multiDrawImplementation)(std::initializer_list>); #endif + #ifndef MAGNUM_TARGET_GLES + GLuint defaultVAO{}; /* Used on core profile in case ARB_VAO is disabled */ + #endif + GLuint currentVAO; #ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_WEBGL diff --git a/src/Magnum/Implementation/State.cpp b/src/Magnum/Implementation/State.cpp index 71fd6c01f..8eda91424 100644 --- a/src/Magnum/Implementation/State.cpp +++ b/src/Magnum/Implementation/State.cpp @@ -66,7 +66,7 @@ State::State(Context& context, std::ostream* const out) { debug.reset(new DebugState{context, extensions}); #endif framebuffer.reset(new FramebufferState{context, extensions}); - mesh.reset(new MeshState{context, extensions}); + mesh.reset(new MeshState{context, *this->context, extensions}); #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) query.reset(new QueryState{context, extensions}); #endif