diff --git a/drape/drape_common.pri b/drape/drape_common.pri index 5a07533500..2389503146 100644 --- a/drape/drape_common.pri +++ b/drape/drape_common.pri @@ -18,6 +18,7 @@ SOURCES += \ $$DRAPE_DIR/glbuffer.cpp \ $$DRAPE_DIR/utils/list_generator.cpp \ $$DRAPE_DIR/shader_def.cpp \ + $$DRAPE_DIR/glextensions_list.cpp HEADERS += \ $$DRAPE_DIR/data_buffer.hpp \ @@ -39,3 +40,4 @@ HEADERS += \ $$DRAPE_DIR/glbuffer.hpp \ $$DRAPE_DIR/utils/list_generator.hpp \ $$DRAPE_DIR/shader_def.hpp \ + $$DRAPE_DIR/glextensions_list.hpp diff --git a/drape/glextensions_list.cpp b/drape/glextensions_list.cpp new file mode 100644 index 0000000000..b5836ebbe5 --- /dev/null +++ b/drape/glextensions_list.cpp @@ -0,0 +1,21 @@ +#include "glextensions_list.hpp" +#include "glfunctions.hpp" + +#include "../base/assert.hpp" + +GLExtensionsList::GLExtensionsList() +{ + m_supportMap[VertexArrayObject] = GLFunctions::glHasExtension("GL_OES_vertex_array_object"); +} + +GLExtensionsList & GLExtensionsList::Instance() +{ + static GLExtensionsList extList; + return extList; +} + +bool GLExtensionsList::IsSupported(const ExtensionName & extName) +{ + ASSERT(m_supportMap.find(extName) != m_supportMap.end(), ("Not all used extensions is checked")); + return m_supportMap[extName]; +} diff --git a/drape/glextensions_list.hpp b/drape/glextensions_list.hpp new file mode 100644 index 0000000000..acb36f4043 --- /dev/null +++ b/drape/glextensions_list.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "../std/noncopyable.hpp" +#include "../std/map.hpp" + +class GLExtensionsList : private noncopyable +{ +public: + enum ExtensionName + { + VertexArrayObject + }; + + static GLExtensionsList & Instance(); + bool IsSupported(const ExtensionName & extName); + +private: + GLExtensionsList(); + map m_supportMap; +}; diff --git a/drape/vertex_array_buffer.cpp b/drape/vertex_array_buffer.cpp index 4eedbc262f..23fba6c7e9 100644 --- a/drape/vertex_array_buffer.cpp +++ b/drape/vertex_array_buffer.cpp @@ -1,11 +1,13 @@ #include "vertex_array_buffer.hpp" #include "glfunctions.hpp" +#include "glextensions_list.hpp" #include "../base/assert.hpp" VertexArrayBuffer::VertexArrayBuffer(uint32_t indexBufferSize, uint32_t dataBufferSize) : m_VAO(0) , m_dataBufferSize(dataBufferSize) + , m_program(NULL) { m_indexBuffer.Reset(new IndexBuffer(indexBufferSize)); } @@ -23,6 +25,7 @@ VertexArrayBuffer::~VertexArrayBuffer() /// Build called only when VertexArrayBuffer fulled and transfer to FrontendRenderer /// but if user move screen before all geometry readed from MWM we delete VertexArrayBuffer on BackendRenderer /// in this case m_VAO will be equal a 0 + /// also m_VAO == 0 will be on device that not support OES_vertex_array_object extension GLFunctions::glDeleteVertexArray(m_VAO); } } @@ -31,43 +34,33 @@ void VertexArrayBuffer::Render() { if (!m_buffers.empty()) { - Bind(); + ASSERT(!m_program.IsNull(), ("Somebody not call Build. It's very bad. Very very bad")); + m_program->Bind(); + /// if OES_vertex_array_object is supported than all bindings already saved in VAO + /// and we need only bind VAO. In Bind method have ASSERT("bind already called") + if (GLExtensionsList::Instance().IsSupported(GLExtensionsList::VertexArrayObject)) + Bind(); + else + BindBuffers(); + GLFunctions::glDrawElements(m_indexBuffer->GetCurrentSize()); } } void VertexArrayBuffer::Build(ReferencePoiner program) { - ASSERT(m_VAO == 0, ("No-no-no! You can't rebuild VertexArrayBuffer")); + ASSERT(m_VAO == 0 && m_program.IsNull(), ("No-no-no! You can't rebuild VertexArrayBuffer")); + m_program = program; + /// if OES_vertex_array_object not supported, than buffers will be bind on each Render call + if (!GLExtensionsList::Instance().IsSupported(GLExtensionsList::VertexArrayObject)) + return; + if (m_buffers.empty()) return; m_VAO = GLFunctions::glGenVertexArray(); Bind(); - - buffers_map_t::iterator it = m_buffers.begin(); - for (; it != m_buffers.end(); ++it) - { - const BindingInfo & binding = it->first; - ReferencePoiner buffer = it->second.GetWeakPointer(); - buffer->Bind(); - - for (uint16_t i = 0; i < binding.GetCount(); ++i) - { - BindingDecl const & decl = binding.GetBindingDecl(i); - int8_t attributeLocation = program->GetAttributeLocation(decl.m_attributeName); - assert(attributeLocation != -1); - GLFunctions::glEnableVertexAttribute(attributeLocation); - GLFunctions::glVertexAttributePointer(attributeLocation, - decl.m_componentCount, - decl.m_componentType, - false, - decl.m_stride, - decl.m_offset); - } - } - - m_indexBuffer->Bind(); + BindBuffers(); } ReferencePoiner VertexArrayBuffer::GetBuffer(const BindingInfo & bindingInfo) @@ -129,3 +122,30 @@ void VertexArrayBuffer::Bind() ASSERT(m_VAO != 0, ("You need to call Build method before bind it and render")); GLFunctions::glBindVertexArray(m_VAO); } + +void VertexArrayBuffer::BindBuffers() +{ + buffers_map_t::iterator it = m_buffers.begin(); + for (; it != m_buffers.end(); ++it) + { + const BindingInfo & binding = it->first; + ReferencePoiner buffer = it->second.GetWeakPointer(); + buffer->Bind(); + + for (uint16_t i = 0; i < binding.GetCount(); ++i) + { + BindingDecl const & decl = binding.GetBindingDecl(i); + int8_t attributeLocation = m_program->GetAttributeLocation(decl.m_attributeName); + assert(attributeLocation != -1); + GLFunctions::glEnableVertexAttribute(attributeLocation); + GLFunctions::glVertexAttributePointer(attributeLocation, + decl.m_componentCount, + decl.m_componentType, + false, + decl.m_stride, + decl.m_offset); + } + } + + m_indexBuffer->Bind(); +} diff --git a/drape/vertex_array_buffer.hpp b/drape/vertex_array_buffer.hpp index 169088b52b..6acc46cc0b 100644 --- a/drape/vertex_array_buffer.hpp +++ b/drape/vertex_array_buffer.hpp @@ -31,6 +31,7 @@ public: private: void Bind(); + void BindBuffers(); private: int m_VAO; @@ -39,4 +40,6 @@ private: OwnedPointer m_indexBuffer; uint32_t m_dataBufferSize; + + ReferencePoiner m_program; };