diff --git a/yg/blitter.cpp b/yg/blitter.cpp index 9e18955a05..65eea88d75 100644 --- a/yg/blitter.cpp +++ b/yg/blitter.cpp @@ -135,15 +135,15 @@ namespace yg immDrawTexturedPrimitives(rectPoints, texRectPoints, 4, texture, true, yg::Color(), false); } - void Blitter::setupAuxVertexLayout(bool hasColor, bool hasTexture) + void Blitter::setupAuxVertexLayout(bool hasColor, bool hasTexture, void * glPtr) { OGLCHECK(glEnableClientState(GL_VERTEX_ARRAY)); - OGLCHECK(glVertexPointer(2, GL_FLOAT, sizeof(AuxVertex), (void*)AuxVertex::vertexOffs)); + OGLCHECK(glVertexPointer(2, GL_FLOAT, sizeof(AuxVertex), (void*)((char*)glPtr + AuxVertex::vertexOffs))); if (hasColor) { OGLCHECK(glEnableClientState(GL_COLOR_ARRAY)); - OGLCHECK(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(AuxVertex), (void*)AuxVertex::colorOffs)); + OGLCHECK(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(AuxVertex), (void*)((char*)glPtr + AuxVertex::colorOffs))); } else OGLCHECK(glDisableClientState(GL_COLOR_ARRAY)); @@ -151,7 +151,7 @@ namespace yg if (hasTexture) { OGLCHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); - OGLCHECK(glTexCoordPointer(2, GL_FLOAT, sizeof(AuxVertex), (void*)AuxVertex::texCoordsOffs)); + OGLCHECK(glTexCoordPointer(2, GL_FLOAT, sizeof(AuxVertex), (void*)((char*)glPtr + AuxVertex::texCoordsOffs))); } else { @@ -184,7 +184,7 @@ namespace yg m_blitStorage.m_vertices->unlock(); m_blitStorage.m_vertices->makeCurrent(); - setupAuxVertexLayout(hasColor, hasTexture); + setupAuxVertexLayout(hasColor, hasTexture, m_blitStorage.m_vertices->glPtr()); if (texture) texture->makeCurrent(); @@ -194,17 +194,17 @@ namespace yg m_blitStorage.m_indices->unlock(); m_blitStorage.m_indices->makeCurrent(); - resourceManager()->freeBlitStorage(m_blitStorage); - m_blitStorage = yg::gl::Storage(); - OGLCHECK(glDisable(GL_BLEND)); OGLCHECK(glDisable(GL_DEPTH_TEST)); - OGLCHECK(glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, 0)); + OGLCHECK(glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, m_blitStorage.m_indices->glPtr())); OGLCHECK(glEnable(GL_DEPTH_TEST)); OGLCHECK(glEnable(GL_TEXTURE_2D)); OGLCHECK(glEnable(GL_BLEND)); /// This call is necessary to avoid parasite blitting in updateActualTarget() on IPhone. OGLCHECK(glFinish()); + + resourceManager()->freeBlitStorage(m_blitStorage); + m_blitStorage = yg::gl::Storage(); } } } diff --git a/yg/blitter.hpp b/yg/blitter.hpp index fd1782a8cf..f97b93fad0 100644 --- a/yg/blitter.hpp +++ b/yg/blitter.hpp @@ -27,7 +27,7 @@ namespace yg typedef Clipper base_t; - void setupAuxVertexLayout(bool hasColor, bool hasTexture); + void setupAuxVertexLayout(bool hasColor, bool hasTexture, void * glPtr); public: diff --git a/yg/geometry_renderer.cpp b/yg/geometry_renderer.cpp index 81526f7be4..81d7daacef 100644 --- a/yg/geometry_renderer.cpp +++ b/yg/geometry_renderer.cpp @@ -19,7 +19,8 @@ namespace yg size_t indicesCount) { vertices->makeCurrent(); - Vertex::setupLayout(); + /// it's important to setupLayout after vertices->makeCurrent + Vertex::setupLayout(vertices->glPtr()); indices->makeCurrent(); texture->makeCurrent(); @@ -28,7 +29,7 @@ namespace yg GL_TRIANGLES, indicesCount, GL_UNSIGNED_SHORT, - 0)); + indices->glPtr())); } } } diff --git a/yg/indexbuffer.cpp b/yg/indexbuffer.cpp index 256e5726f8..a547c81b97 100644 --- a/yg/indexbuffer.cpp +++ b/yg/indexbuffer.cpp @@ -32,14 +32,18 @@ namespace yg indexBufferStack.pop_back(); } - IndexBuffer::IndexBuffer() : m_size(0), m_gpuData(0) + IndexBuffer::IndexBuffer(bool useVA) + : m_size(0), m_gpuData(0), m_useVA(useVA) { - OGLCHECK(glGenBuffers(1, &m_id)); + if (!m_useVA) + OGLCHECK(glGenBuffers(1, &m_id)); } - IndexBuffer::IndexBuffer(size_t size) : m_size(0), m_gpuData(0) + IndexBuffer::IndexBuffer(size_t size, bool useVA) + : m_size(0), m_gpuData(0), m_useVA(useVA) { - OGLCHECK(glGenBuffers(1, &m_id)); + if (!m_useVA) + OGLCHECK(glGenBuffers(1, &m_id)); resize(size); } @@ -49,7 +53,13 @@ namespace yg { m_size = size; makeCurrent(); - OGLCHECK(glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_size, 0, GL_DYNAMIC_DRAW)); + if (m_useVA) + { + delete [] (unsigned char*) m_gpuData; + m_gpuData = new unsigned char[size]; + } + else + OGLCHECK(glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_size, 0, GL_DYNAMIC_DRAW)); } } @@ -60,11 +70,15 @@ namespace yg IndexBuffer::~IndexBuffer() { - OGLCHECK(glDeleteBuffers(1, &m_id)); + if (!m_useVA) + OGLCHECK(glDeleteBuffers(1, &m_id)); } void * IndexBuffer::lock() { + if (m_useVA) + return m_gpuData; + makeCurrent(); /// orphaning the old copy of the buffer data. @@ -82,6 +96,9 @@ namespace yg void IndexBuffer::unlock() { + if (m_useVA) + return; + ASSERT(m_gpuData != 0, ("IndexBuffer is not locked")); makeCurrent(); #ifdef OMIM_GL_ES @@ -94,9 +111,20 @@ namespace yg void IndexBuffer::makeCurrent() { + if (m_useVA) + return; + if (m_id != current()) OGLCHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_id)); } + + void * IndexBuffer::glPtr() + { + if (m_useVA) + return m_gpuData; + else + return 0; + } } } diff --git a/yg/indexbuffer.hpp b/yg/indexbuffer.hpp index adaddfb75c..a6c3dab7d2 100644 --- a/yg/indexbuffer.hpp +++ b/yg/indexbuffer.hpp @@ -11,11 +11,12 @@ namespace yg unsigned int m_id; unsigned int m_size; void * m_gpuData; + bool m_useVA; public: - IndexBuffer(); - IndexBuffer(size_t size); + IndexBuffer(bool useVA); + IndexBuffer(size_t size, bool useVA); ~IndexBuffer(); void resize(size_t size); @@ -25,9 +26,12 @@ namespace yg void * lock(); void unlock(); + void * glPtr(); + static void pushCurrent(); static void popCurrent(); static int current(); + }; } } diff --git a/yg/resource_manager.cpp b/yg/resource_manager.cpp index 25beb78eb8..585c878cff 100644 --- a/yg/resource_manager.cpp +++ b/yg/resource_manager.cpp @@ -22,26 +22,31 @@ namespace yg size_t blitVBSize, size_t blitIBSize, size_t blitStoragesCount, size_t texWidth, size_t texHeight, size_t texCount, char const * blocksFile, char const * whiteListFile, char const * blackListFile, size_t maxGlyphCacheSize, - RtFormat fmt) + RtFormat fmt, + bool useVA) : m_textureWidth(texWidth), m_textureHeight(texHeight), m_vbSize(vbSize), m_ibSize(ibSize), m_smallVBSize(smallVBSize), m_smallIBSize(smallIBSize), m_blitVBSize(blitVBSize), m_blitIBSize(blitIBSize), m_glyphCache(GlyphCache::Params(blocksFile, whiteListFile, blackListFile, maxGlyphCacheSize)), - m_format(fmt) + m_format(fmt), + m_useVA(useVA) { + if (useVA) + LOG(LINFO, ("buffer objects are unsupported. using client vertex array instead.")); + for (size_t i = 0; i < storagesCount; ++i) - m_storages.push_back(gl::Storage(vbSize, ibSize)); + m_storages.push_back(gl::Storage(vbSize, ibSize, m_useVA)); LOG(LINFO, ("allocating ", (vbSize + ibSize) * storagesCount, " bytes for main storage")); for (size_t i = 0; i < smallStoragesCount; ++i) - m_smallStorages.push_back(gl::Storage(smallVBSize, smallIBSize)); + m_smallStorages.push_back(gl::Storage(smallVBSize, smallIBSize, m_useVA)); LOG(LINFO, ("allocating ", (smallVBSize + smallIBSize) * smallStoragesCount, " bytes for small storage")); for (size_t i = 0; i < blitStoragesCount; ++i) - m_blitStorages.push_back(gl::Storage(blitVBSize, blitIBSize)); + m_blitStorages.push_back(gl::Storage(blitVBSize, blitIBSize, m_useVA)); LOG(LINFO, ("allocating ", (blitVBSize + blitIBSize) * blitStoragesCount, " bytes for blit storage")); @@ -227,11 +232,11 @@ namespace yg threads::MutexGuard guard(m_mutex); for (list::iterator it = m_storages.begin(); it != m_storages.end(); ++it) - *it = gl::Storage(m_vbSize, m_ibSize); + *it = gl::Storage(m_vbSize, m_ibSize, m_useVA); for (list::iterator it = m_smallStorages.begin(); it != m_smallStorages.end(); ++it) - *it = gl::Storage(m_smallVBSize, m_smallIBSize); + *it = gl::Storage(m_smallVBSize, m_smallIBSize, m_useVA); for (list::iterator it = m_blitStorages.begin(); it != m_blitStorages.end(); ++it) - *it = gl::Storage(m_blitVBSize, m_blitIBSize); + *it = gl::Storage(m_blitVBSize, m_blitIBSize, m_useVA); for (list >::iterator it = m_dynamicTextures.begin(); it != m_dynamicTextures.end(); ++it) *it = shared_ptr(new TDynamicTexture(m_textureWidth, m_textureHeight)); diff --git a/yg/resource_manager.hpp b/yg/resource_manager.hpp index 141bc77418..8fd3e4de98 100644 --- a/yg/resource_manager.hpp +++ b/yg/resource_manager.hpp @@ -63,6 +63,8 @@ namespace yg RtFormat m_format; + bool m_useVA; + public: ResourceManager(size_t vbSize, size_t ibSize, size_t storagesCount, @@ -70,7 +72,8 @@ namespace yg size_t blitVBSize, size_t blitIBSize, size_t blitStoragesCount, size_t texWidth, size_t texHeight, size_t texCount, char const * blocksFile, char const * whileListFile, char const * blackListFile, size_t maxGlyphCacheSize, - RtFormat fmt); + RtFormat fmt, + bool useVA); shared_ptr const & getTexture(string const & fileName); diff --git a/yg/storage.cpp b/yg/storage.cpp index e15a7f78e0..aec4005580 100644 --- a/yg/storage.cpp +++ b/yg/storage.cpp @@ -10,9 +10,9 @@ namespace yg Storage::Storage() {} - Storage::Storage(size_t vbSize, size_t ibSize) : - m_vertices(new VertexBuffer(vbSize)), - m_indices(new IndexBuffer(ibSize)) + Storage::Storage(size_t vbSize, size_t ibSize, bool useVA) : + m_vertices(new VertexBuffer(vbSize, useVA)), + m_indices(new IndexBuffer(ibSize, useVA)) {} } } diff --git a/yg/storage.hpp b/yg/storage.hpp index 1b9e1f8f3c..65723789bc 100644 --- a/yg/storage.hpp +++ b/yg/storage.hpp @@ -16,7 +16,7 @@ namespace yg shared_ptr m_indices; Storage(); - Storage(size_t vbSize, size_t ibSize); + Storage(size_t vbSize, size_t ibSize, bool useVA); }; } } diff --git a/yg/vertex.cpp b/yg/vertex.cpp index 134fbb9a36..424e0edea4 100644 --- a/yg/vertex.cpp +++ b/yg/vertex.cpp @@ -29,14 +29,14 @@ namespace yg return *this; } - void Vertex::setupLayout() + void Vertex::setupLayout(void * glPtr) { OGLCHECK(glDisableClientState(GL_COLOR_ARRAY)); OGLCHECK(glEnableClientState(GL_VERTEX_ARRAY)); - OGLCHECK(glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (void*)Vertex::vertexOffset)); + OGLCHECK(glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (void*)((char*)glPtr + Vertex::vertexOffset))); OGLCHECK(glEnable(GL_TEXTURE_2D)); OGLCHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); - OGLCHECK(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void*)Vertex::texCoordOffset)); + OGLCHECK(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void*)((char*)glPtr + Vertex::texCoordOffset))); } } } diff --git a/yg/vertex.hpp b/yg/vertex.hpp index c0cd0da582..6c2f9deec5 100644 --- a/yg/vertex.hpp +++ b/yg/vertex.hpp @@ -22,7 +22,7 @@ namespace yg Vertex(Vertex const & v); Vertex const & operator=(Vertex const & v); - static void setupLayout(); + static void setupLayout(void * glPtr); }; struct AuxVertex diff --git a/yg/vertexbuffer.cpp b/yg/vertexbuffer.cpp index f845d172fc..05e326362a 100644 --- a/yg/vertexbuffer.cpp +++ b/yg/vertexbuffer.cpp @@ -32,14 +32,18 @@ namespace yg vertexBufferStack.pop_back(); } - VertexBuffer::VertexBuffer() : m_size(0), m_gpuData(0) + VertexBuffer::VertexBuffer(bool useVA) + : m_size(0), m_gpuData(0), m_useVA(useVA) { - OGLCHECK(glGenBuffers(1, &m_id)); + if (!m_useVA) + OGLCHECK(glGenBuffers(1, &m_id)); } - VertexBuffer::VertexBuffer(size_t size) : m_size(0), m_gpuData(0) + VertexBuffer::VertexBuffer(size_t size, bool useVA) + : m_size(0), m_gpuData(0), m_useVA(useVA) { - OGLCHECK(glGenBuffers(1, &m_id)); + if (!m_useVA) + OGLCHECK(glGenBuffers(1, &m_id)); resize(size); } @@ -49,7 +53,13 @@ namespace yg { m_size = size; makeCurrent(); - OGLCHECK(glBufferData(GL_ARRAY_BUFFER, m_size, 0, GL_DYNAMIC_DRAW)); + if (m_useVA) + { + delete [] (unsigned char*)m_gpuData; + m_gpuData = new unsigned char [size]; + } + else + OGLCHECK(glBufferData(GL_ARRAY_BUFFER, m_size, 0, GL_DYNAMIC_DRAW)); } } @@ -60,11 +70,17 @@ namespace yg VertexBuffer::~VertexBuffer() { - OGLCHECK(glDeleteBuffers(1, &m_id)); + if (m_useVA) + delete [] (unsigned char*)m_gpuData; + else + OGLCHECK(glDeleteBuffers(1, &m_id)); } void * VertexBuffer::lock() { + if (m_useVA) + return m_gpuData; + makeCurrent(); /// orphaning the old copy of the buffer data. @@ -82,6 +98,9 @@ namespace yg void VertexBuffer::unlock() { + if (m_useVA) + return; + ASSERT(m_gpuData != 0, ("VertexBuffer is not locked")); makeCurrent(); #ifdef OMIM_GL_ES @@ -92,8 +111,18 @@ namespace yg m_gpuData = 0; } + void * VertexBuffer::glPtr() const + { + if (m_useVA) + return m_gpuData; + return 0; + } + void VertexBuffer::makeCurrent() { + if (m_useVA) + return; + if (m_id != current()) OGLCHECK(glBindBuffer(GL_ARRAY_BUFFER, m_id)); } diff --git a/yg/vertexbuffer.hpp b/yg/vertexbuffer.hpp index 0dc7e3ae95..819ec594c7 100644 --- a/yg/vertexbuffer.hpp +++ b/yg/vertexbuffer.hpp @@ -12,10 +12,13 @@ namespace yg unsigned int m_size; void * m_gpuData; + /// using VA instead of buffer objects on some old GPU's + bool m_useVA; + public: - VertexBuffer(); - VertexBuffer(size_t size); + VertexBuffer(bool useVA); + VertexBuffer(size_t size, bool useVA); ~VertexBuffer(); void resize(size_t size); @@ -24,6 +27,7 @@ namespace yg void makeCurrent(); void * lock(); void unlock(); + void * glPtr() const; static unsigned current(); static void pushCurrent();