diff options
Diffstat (limited to 'drape')
30 files changed, 945 insertions, 917 deletions
diff --git a/drape/CMakeLists.txt b/drape/CMakeLists.txt index bfff605500..4355682b36 100644 --- a/drape/CMakeLists.txt +++ b/drape/CMakeLists.txt @@ -42,6 +42,8 @@ set( ${DRAPE_ROOT}/dynamic_texture.hpp ${DRAPE_ROOT}/font_texture.cpp ${DRAPE_ROOT}/font_texture.hpp + ${DRAPE_ROOT}/framebuffer.cpp + ${DRAPE_ROOT}/framebuffer.hpp ${DRAPE_ROOT}/glconstants.cpp ${DRAPE_ROOT}/glconstants.hpp ${DRAPE_ROOT}/glextensions_list.cpp @@ -111,6 +113,8 @@ set( ${DRAPE_ROOT}/utils/vertex_decl.hpp ${DRAPE_ROOT}/vertex_array_buffer.cpp ${DRAPE_ROOT}/vertex_array_buffer.hpp + ${DRAPE_ROOT}/viewport.cpp + ${DRAPE_ROOT}/viewport.hpp ${DRAPE_ROOT}/visual_scale.hpp ) diff --git a/drape/data_buffer.cpp b/drape/data_buffer.cpp index fccc4fa7f9..672741fa9d 100644 --- a/drape/data_buffer.cpp +++ b/drape/data_buffer.cpp @@ -3,7 +3,6 @@ namespace dp { - DataBuffer::DataBuffer(uint8_t elementSize, uint32_t capacity) : m_impl(make_unique_dp<CpuBufferImpl>(elementSize, capacity)) { @@ -17,30 +16,31 @@ ref_ptr<DataBufferBase> DataBuffer::GetBuffer() const void DataBuffer::MoveToGPU(GPUBuffer::Target target) { - // if currentSize is 0 buffer hasn't been filled on preparation stage, let it be filled further + // If currentSize is 0 buffer hasn't been filled on preparation stage, let it be filled further. uint32_t const currentSize = m_impl->GetCurrentSize(); if (currentSize != 0) - m_impl = make_unique_dp<GpuBufferImpl>(target, m_impl->Data(),m_impl->GetElementSize(), currentSize); + { + m_impl = make_unique_dp<GpuBufferImpl>(target, m_impl->Data(), m_impl->GetElementSize(), + currentSize); + } else - m_impl = make_unique_dp<GpuBufferImpl>(target, nullptr, m_impl->GetElementSize(), m_impl->GetAvailableSize()); + { + m_impl = make_unique_dp<GpuBufferImpl>(target, nullptr, m_impl->GetElementSize(), + m_impl->GetAvailableSize()); + } } - -DataBufferMapper::DataBufferMapper(ref_ptr<DataBuffer> buffer) +DataBufferMapper::DataBufferMapper(ref_ptr<DataBuffer> buffer, uint32_t elementOffset, + uint32_t elementCount) : m_buffer(buffer) { m_buffer->GetBuffer()->Bind(); - m_ptr = m_buffer->GetBuffer()->Map(); -} - -DataBufferMapper::~DataBufferMapper() -{ - m_buffer->GetBuffer()->Unmap(); + m_ptr = m_buffer->GetBuffer()->Map(elementOffset, elementCount); } +DataBufferMapper::~DataBufferMapper() { m_buffer->GetBuffer()->Unmap(); } void DataBufferMapper::UpdateData(void const * data, uint32_t elementOffset, uint32_t elementCount) { m_buffer->GetBuffer()->UpdateData(m_ptr, data, elementOffset, elementCount); } - -} +} // namespace dp diff --git a/drape/data_buffer.hpp b/drape/data_buffer.hpp index 0c82228449..15871a0326 100644 --- a/drape/data_buffer.hpp +++ b/drape/data_buffer.hpp @@ -1,16 +1,14 @@ #pragma once -#include "drape/pointers.hpp" #include "drape/gpu_buffer.hpp" +#include "drape/pointers.hpp" namespace dp { - class DataBufferBase { public: virtual ~DataBufferBase() {} - virtual uint32_t GetCapacity() const = 0; virtual uint32_t GetCurrentSize() const = 0; virtual uint32_t GetAvailableSize() const = 0; @@ -19,14 +17,14 @@ public: virtual void const * Data() const = 0; virtual void UploadData(void const * data, uint32_t elementCount) = 0; - virtual void UpdateData(void * destPtr, void const * srcPtr, uint32_t elementOffset, uint32_t elementCount) = 0; + virtual void UpdateData(void * destPtr, void const * srcPtr, uint32_t elementOffset, + uint32_t elementCount) = 0; virtual void Bind() = 0; - virtual void * Map() = 0; + virtual void * Map(uint32_t elementOffset, uint32_t elementCount) = 0; virtual void Unmap() = 0; }; - class DataBuffer { public: @@ -39,11 +37,10 @@ private: drape_ptr<DataBufferBase> m_impl; }; - class DataBufferMapper { public: - DataBufferMapper(ref_ptr<DataBuffer> buffer); + DataBufferMapper(ref_ptr<DataBuffer> buffer, uint32_t elementOffset, uint32_t elementCount); ~DataBufferMapper(); void UpdateData(void const * data, uint32_t elementOffset, uint32_t elementCount); @@ -52,6 +49,4 @@ private: ref_ptr<DataBuffer> m_buffer; void * m_ptr; }; - -} // namespace dp - +} // namespace dp diff --git a/drape/data_buffer_impl.hpp b/drape/data_buffer_impl.hpp index 562e9a0913..1d46204a55 100644 --- a/drape/data_buffer_impl.hpp +++ b/drape/data_buffer_impl.hpp @@ -1,65 +1,40 @@ #pragma once -#include "data_buffer.hpp" -#include "cpu_buffer.hpp" -#include "gpu_buffer.hpp" +#include "drape/cpu_buffer.hpp" +#include "drape/data_buffer.hpp" +#include "drape/gpu_buffer.hpp" + #include "std/utility.hpp" namespace dp { - -/// generic implementation of data buffer +// Generic implementation of data buffer. template <typename TBuffer> class DataBufferImpl : public DataBufferBase { public: - template<typename... Args> DataBufferImpl(Args&&... params) - : m_buffer(make_unique_dp<TBuffer>(forward<Args>(params)...)) - { - } - - uint32_t GetCapacity() const override - { - return m_buffer->GetCapacity(); - } - - uint32_t GetCurrentSize() const override - { - return m_buffer->GetCurrentSize(); - } - - uint32_t GetAvailableSize() const override - { - return m_buffer->GetAvailableSize(); - } - - uint8_t GetElementSize() const override - { - return m_buffer->GetElementSize(); - } - - void Seek(uint32_t elementNumber) override - { - m_buffer->Seek(elementNumber); - } + template <typename... Args> + DataBufferImpl(Args &&... params) : m_buffer(make_unique_dp<TBuffer>(forward<Args>(params)...)) + {} + uint32_t GetCapacity() const override { return m_buffer->GetCapacity(); } + uint32_t GetCurrentSize() const override { return m_buffer->GetCurrentSize(); } + uint32_t GetAvailableSize() const override { return m_buffer->GetAvailableSize(); } + uint8_t GetElementSize() const override { return m_buffer->GetElementSize(); } + void Seek(uint32_t elementNumber) override { m_buffer->Seek(elementNumber); } protected: drape_ptr<TBuffer> m_buffer; }; -/// CPU implementation of data buffer +// CPU implementation of data buffer. class CpuBufferImpl : public DataBufferImpl<CPUBuffer> { public: - template<typename... Args> CpuBufferImpl(Args&&... params) - : DataBufferImpl(forward<Args>(params)...) + template <typename... Args> + CpuBufferImpl(Args &&... params) : DataBufferImpl(forward<Args>(params)...) {} - void const * Data() const override - { - return m_buffer->Data(); - } - + void const * Data() const override { return m_buffer->Data(); } void UploadData(void const * data, uint32_t elementCount) override { m_buffer->UploadData(data, elementCount); @@ -67,34 +42,28 @@ public: m_buffer->Seek(newOffset); } - void UpdateData(void * destPtr, void const * srcPtr, uint32_t elementOffset, uint32_t elementCount) override + void UpdateData(void * destPtr, void const * srcPtr, uint32_t elementOffset, + uint32_t elementCount) override { ASSERT(false, ("Data updating is unavailable for CPU buffer")); } - void Bind() override - { - ASSERT(false, ("Binding is unavailable for CPU buffer")); - } - - void * Map() override + void Bind() override { ASSERT(false, ("Binding is unavailable for CPU buffer")); } + void * Map(uint32_t elementOffset, uint32_t elementCount) override { ASSERT(false, ("Mapping is unavailable for CPU buffer")); return nullptr; } - void Unmap() override - { - ASSERT(false, ("Unmapping is unavailable for CPU buffer")); - } + void Unmap() override { ASSERT(false, ("Unmapping is unavailable for CPU buffer")); } }; -/// GPU implementation of data buffer +// GPU implementation of data buffer. class GpuBufferImpl : public DataBufferImpl<GPUBuffer> { public: - template<typename... Args> GpuBufferImpl(Args&&... params) - : DataBufferImpl(forward<Args>(params)...) + template <typename... Args> + GpuBufferImpl(Args &&... params) : DataBufferImpl(forward<Args>(params)...) {} void const * Data() const override @@ -108,25 +77,17 @@ public: m_buffer->UploadData(data, elementCount); } - void UpdateData(void * destPtr, void const * srcPtr, uint32_t elementOffset, uint32_t elementCount) override + void UpdateData(void * destPtr, void const * srcPtr, uint32_t elementOffset, + uint32_t elementCount) override { m_buffer->UpdateData(destPtr, srcPtr, elementOffset, elementCount); } - void Bind() override - { - m_buffer->Bind(); - } - - void * Map() override + void Bind() override { m_buffer->Bind(); } + void * Map(uint32_t elementOffset, uint32_t elementCount) override { - return m_buffer->Map(); - } - - void Unmap() override - { - return m_buffer->Unmap(); + return m_buffer->Map(elementOffset, elementCount); } + void Unmap() override { return m_buffer->Unmap(); } }; - -} // namespace dp +} // namespace dp diff --git a/drape/drape_common.pri b/drape/drape_common.pri index fa68b27b05..2511103f47 100644 --- a/drape/drape_common.pri +++ b/drape/drape_common.pri @@ -13,6 +13,7 @@ SOURCES += \ $$DRAPE_DIR/data_buffer.cpp \ $$DRAPE_DIR/debug_rect_renderer.cpp \ $$DRAPE_DIR/font_texture.cpp \ + $$DRAPE_DIR/framebuffer.cpp \ $$DRAPE_DIR/glconstants.cpp \ $$DRAPE_DIR/glextensions_list.cpp \ $$DRAPE_DIR/glstate.cpp \ @@ -44,6 +45,7 @@ SOURCES += \ $$DRAPE_DIR/utils/projection.cpp \ $$DRAPE_DIR/utils/vertex_decl.cpp \ $$DRAPE_DIR/vertex_array_buffer.cpp \ + $$DRAPE_DIR/viewport.cpp \ HEADERS += \ $$DRAPE_DIR/attribute_buffer_mutator.hpp \ @@ -63,6 +65,7 @@ HEADERS += \ $$DRAPE_DIR/drape_global.hpp \ $$DRAPE_DIR/dynamic_texture.hpp \ $$DRAPE_DIR/font_texture.hpp \ + $$DRAPE_DIR/framebuffer.hpp \ $$DRAPE_DIR/glconstants.hpp \ $$DRAPE_DIR/glextensions_list.hpp \ $$DRAPE_DIR/glfunctions.hpp \ @@ -101,6 +104,7 @@ HEADERS += \ $$DRAPE_DIR/utils/projection.hpp \ $$DRAPE_DIR/utils/vertex_decl.hpp \ $$DRAPE_DIR/vertex_array_buffer.hpp \ + $$DRAPE_DIR/viewport.hpp \ $$DRAPE_DIR/visual_scale.hpp \ iphone*{ diff --git a/drape/drape_global.hpp b/drape/drape_global.hpp index d445f72633..d3933057d0 100644 --- a/drape/drape_global.hpp +++ b/drape/drape_global.hpp @@ -72,4 +72,13 @@ struct FontDecl float m_size = 0; bool m_isSdf = true; }; + +inline std::string DebugPrint(dp::ApiVersion apiVersion) +{ + if (apiVersion == dp::OpenGLES2) + return "OpenGLES2"; + else if (apiVersion == dp::OpenGLES3) + return "OpenGLES3"; + return "Unknown"; +} } // namespace dp diff --git a/drape/drape_tests/font_texture_tests.cpp b/drape/drape_tests/font_texture_tests.cpp index b6b7882fd2..f4eab31fd1 100644 --- a/drape/drape_tests/font_texture_tests.cpp +++ b/drape/drape_tests/font_texture_tests.cpp @@ -1,6 +1,6 @@ -#include "testing/testing.hpp" -#include "drape/drape_tests/img.hpp" #include "drape/drape_tests/dummy_texture.hpp" +#include "drape/drape_tests/img.hpp" +#include "testing/testing.hpp" #include "drape/font_texture.hpp" #include "drape/glyph_manager.hpp" @@ -10,8 +10,8 @@ #include "std/bind.hpp" -#include <QtGui/QPainter> #include <QtCore/QPoint> +#include <QtGui/QPainter> #include "drape/drape_tests/glmock_functions.hpp" @@ -26,59 +26,52 @@ using namespace dp; namespace { - class UploadedRender +class UploadedRender +{ +public: + UploadedRender(QPoint const & pen) : m_pen(pen) {} + void glMemoryToQImage(int x, int y, int w, int h, glConst f, glConst t, void const * memory) + { + TEST(f == gl_const::GLAlpha || f == gl_const::GLAlpha8 || f == gl_const::GLRed, ()); + TEST(t == gl_const::GLUnsignedByteType, ()); + + uint8_t const * image = reinterpret_cast<uint8_t const *>(memory); + + QPoint p(m_pen); + p.rx() += x; + m_images.push_back(qMakePair(p, CreateImage(w, h, image))); + m_pen.ry() += h; + } + + void Render(QPaintDevice * device) { - public: - UploadedRender(QPoint const & pen) - : m_pen(pen) - { - } - - void glMemoryToQImage(int x, int y, int w, int h, glConst f, glConst t, void const * memory) - { - TEST(f == gl_const::GLAlpha || f == gl_const::GLAlpha8, ()); - TEST(t == gl_const::GLUnsignedByteType, ()); - - uint8_t const * image = reinterpret_cast<uint8_t const *>(memory); - - QPoint p(m_pen); - p.rx() += x; - m_images.push_back(qMakePair(p, CreateImage(w, h, image))); - m_pen.ry() += h; - } - - void Render(QPaintDevice * device) - { - QPainter p(device); - for (auto d : m_images) - p.drawImage(d.first, d.second); - } - - private: - QPoint m_pen; - QVector<QPair<QPoint, QImage> > m_images; - }; - - class DummyGlyphIndex : public GlyphIndex + QPainter p(device); + for (auto d : m_images) + p.drawImage(d.first, d.second); + } + +private: + QPoint m_pen; + QVector<QPair<QPoint, QImage>> m_images; +}; + +class DummyGlyphIndex : public GlyphIndex +{ + typedef GlyphIndex TBase; + +public: + DummyGlyphIndex(m2::PointU size, ref_ptr<GlyphManager> mng) : TBase(size, mng) {} + ref_ptr<Texture::ResourceInfo> MapResource(GlyphKey const & key) { - typedef GlyphIndex TBase; - public: - DummyGlyphIndex(m2::PointU size, ref_ptr<GlyphManager> mng) - : TBase(size, mng) - { - } - - ref_ptr<Texture::ResourceInfo> MapResource(GlyphKey const & key) - { - bool dummy = false; - return TBase::MapResource(key, dummy); - } - }; -} + bool dummy = false; + return TBase::MapResource(key, dummy); + } +}; +} // namespace UNIT_TEST(UploadingGlyphs) { - // This unit test creates window so can't be run in GUI-less Linux machine. +// This unit test creates window so can't be run in GUI-less Linux machine. #ifndef OMIM_OS_LINUX EXPECTGL(glHasExtension(_)).Times(AnyNumber()); EXPECTGL(glBindTexture(_)).Times(AnyNumber()); @@ -96,11 +89,12 @@ UNIT_TEST(UploadingGlyphs) GlyphManager mng(args); DummyGlyphIndex index(m2::PointU(128, 128), make_ref(&mng)); - size_t count = 1; // invalid symbol glyph has mapped internally. + size_t count = 1; // invalid symbol glyph has mapped internally. count += (index.MapResource(GlyphKey(0x58, GlyphManager::kDynamicGlyphSize)) != nullptr) ? 1 : 0; count += (index.MapResource(GlyphKey(0x59, GlyphManager::kDynamicGlyphSize)) != nullptr) ? 1 : 0; count += (index.MapResource(GlyphKey(0x61, GlyphManager::kDynamicGlyphSize)) != nullptr) ? 1 : 0; - while (index.GetPendingNodesCount() < count); + while (index.GetPendingNodesCount() < count) + ; Texture::Params p; p.m_allocator = GetDefaultAllocator(); @@ -109,7 +103,8 @@ UNIT_TEST(UploadingGlyphs) DummyTexture tex; tex.Create(p); - EXPECTGL(glTexSubImage2D(_, _, _, _, _, _, _)).WillRepeatedly(Invoke(&r, &UploadedRender::glMemoryToQImage)); + EXPECTGL(glTexSubImage2D(_, _, _, _, _, _, _)) + .WillRepeatedly(Invoke(&r, &UploadedRender::glMemoryToQImage)); index.UploadResources(make_ref(&tex)); count = 0; @@ -119,9 +114,11 @@ UNIT_TEST(UploadingGlyphs) count += (index.MapResource(GlyphKey(0x65, GlyphManager::kDynamicGlyphSize)) != nullptr) ? 1 : 0; count += (index.MapResource(GlyphKey(0x400, GlyphManager::kDynamicGlyphSize)) != nullptr) ? 1 : 0; count += (index.MapResource(GlyphKey(0x401, GlyphManager::kDynamicGlyphSize)) != nullptr) ? 1 : 0; - while (index.GetPendingNodesCount() < count); + while (index.GetPendingNodesCount() < count) + ; - EXPECTGL(glTexSubImage2D(_, _, _, _, _, _, _)).WillRepeatedly(Invoke(&r, &UploadedRender::glMemoryToQImage)); + EXPECTGL(glTexSubImage2D(_, _, _, _, _, _, _)) + .WillRepeatedly(Invoke(&r, &UploadedRender::glMemoryToQImage)); index.UploadResources(make_ref(&tex)); RunTestLoop("UploadingGlyphs", bind(&UploadedRender::Render, &r, _1)); diff --git a/drape/drape_tests/glfunctions.cpp b/drape/drape_tests/glfunctions.cpp index ad78bd869b..7cc5909d3b 100644 --- a/drape/drape_tests/glfunctions.cpp +++ b/drape/drape_tests/glfunctions.cpp @@ -7,6 +7,8 @@ using namespace emul; +dp::ApiVersion GLFunctions::CurrentApiVersion = dp::ApiVersion::OpenGLES2; + #define MOCK_CALL(f) GLMockFunctions::Instance().f; void GLFunctions::glFlush() @@ -270,6 +272,8 @@ void GLFunctions::glUniformValueiv(int8_t location, int32_t * v, uint32_t size) void * GLFunctions::glMapBuffer(glConst, glConst) { return 0; } +void * GLFunctions::glMapBufferRange(glConst, uint32_t, uint32_t, glConst) { return 0; } + void GLFunctions::glUnmapBuffer(glConst target) {} void GLFunctions::glDrawElements(glConst primitive, uint32_t sizeOfIndex, diff --git a/drape/drape_tests/memory_comparer.hpp b/drape/drape_tests/memory_comparer.hpp index d7cdd0e003..eb6a3fbdeb 100644 --- a/drape/drape_tests/memory_comparer.hpp +++ b/drape/drape_tests/memory_comparer.hpp @@ -1,46 +1,36 @@ #pragma once -#include "testing/testing.hpp" -#include "drape/glconstants.hpp" #include "base/logging.hpp" +#include "drape/glconstants.hpp" +#include "testing/testing.hpp" -#include "std/cstring.hpp" +#include <cstring> namespace dp { - struct MemoryComparer { void * m_mem; int m_size; - MemoryComparer(void * memory, int size) - : m_mem(memory) - , m_size(size) - { - } - + MemoryComparer(void * memory, int size) : m_mem(memory), m_size(size) {} void cmpSubBuffer(glConst /*type*/, uint32_t size, void const * data, uint32_t /*offset*/) const { TEST_EQUAL(size, m_size, ()); TEST_EQUAL(memcmp(m_mem, data, size), 0, ()); } - void cmpSubImage(uint32_t /*x*/, uint32_t /*y*/, uint32_t width, uint32_t height, - glConst layout, glConst pixelFormat, void const * data) const + void cmpSubImage(uint32_t /*x*/, uint32_t /*y*/, uint32_t width, uint32_t height, glConst layout, + glConst pixelFormat, void const * data) const { uint32_t channelCount = 0; - if (layout == gl_const::GLRGBA || - layout == gl_const::GLRGBA8 || - layout == gl_const::GLRGBA4) + if (layout == gl_const::GLRGBA || layout == gl_const::GLRGBA8 || layout == gl_const::GLRGBA4) channelCount = 4; else if (layout == gl_const::GLRGB) channelCount = 3; - else if (layout == gl_const::GLAlpha || - layout == gl_const::GLAlpha8 || - layout == gl_const::GLLuminance || - layout == gl_const::GLLuminance8 || - layout == gl_const::GLAlphaLuminance) + else if (layout == gl_const::GLAlpha || layout == gl_const::GLAlpha8 || + layout == gl_const::GLLuminance || layout == gl_const::GLLuminance8 || + layout == gl_const::GLAlphaLuminance || layout == gl_const::GLRed) { channelCount = 1; } @@ -55,9 +45,6 @@ struct MemoryComparer for (int i = 0; i < m_size; ++i) TEST_EQUAL(member[i], input[i], (i)); - - //TEST_EQUAL(memcmp(m_mem, data, m_size), 0, ()); } }; - -} +} // namespace dp diff --git a/drape/framebuffer.cpp b/drape/framebuffer.cpp new file mode 100644 index 0000000000..73d79173f5 --- /dev/null +++ b/drape/framebuffer.cpp @@ -0,0 +1,105 @@ +#include "drape/framebuffer.hpp" + +#include "drape/glfunctions.hpp" +#include "drape/oglcontext.hpp" + +#include "base/assert.hpp" +#include "base/logging.hpp" +#include "base/string_utils.hpp" + +namespace dp +{ +Framebuffer::~Framebuffer() { Destroy(); } +void Framebuffer::Destroy() +{ + if (m_colorTextureId != 0) + { + GLFunctions::glDeleteTexture(m_colorTextureId); + m_colorTextureId = 0; + } + + if (m_depthTextureId != 0) + { + GLFunctions::glDeleteTexture(m_depthTextureId); + m_depthTextureId = 0; + } + + if (m_framebufferId != 0) + { + GLFunctions::glDeleteFramebuffer(&m_framebufferId); + m_framebufferId = 0; + } +} + +void Framebuffer::SetDefaultContext(dp::OGLContext * context) { m_defaultContext = context; } +void Framebuffer::SetSize(uint32_t width, uint32_t height) +{ + ASSERT(m_defaultContext, ()); + + if (!m_isSupported) + return; + + if (m_width == width && m_height == height) + return; + + m_height = height; + m_width = width; + + Destroy(); + + m_colorTextureId = GLFunctions::glGenTexture(); + GLFunctions::glBindTexture(m_colorTextureId); + GLFunctions::glTexImage2D(m_width, m_height, gl_const::GLRGBA, gl_const::GLUnsignedByteType, + nullptr); + GLFunctions::glTexParameter(gl_const::GLMagFilter, gl_const::GLLinear); + GLFunctions::glTexParameter(gl_const::GLMinFilter, gl_const::GLLinear); + GLFunctions::glTexParameter(gl_const::GLWrapT, gl_const::GLClampToEdge); + GLFunctions::glTexParameter(gl_const::GLWrapS, gl_const::GLClampToEdge); + + m_depthTextureId = GLFunctions::glGenTexture(); + GLFunctions::glBindTexture(m_depthTextureId); + GLFunctions::glTexImage2D(m_width, m_height, gl_const::GLDepthComponent, + gl_const::GLUnsignedIntType, nullptr); + if (GLFunctions::CurrentApiVersion == dp::ApiVersion::OpenGLES3) + { + GLFunctions::glTexParameter(gl_const::GLMagFilter, gl_const::GLNearest); + GLFunctions::glTexParameter(gl_const::GLMinFilter, gl_const::GLNearest); + GLFunctions::glTexParameter(gl_const::GLWrapT, gl_const::GLClampToEdge); + GLFunctions::glTexParameter(gl_const::GLWrapS, gl_const::GLClampToEdge); + } + + GLFunctions::glBindTexture(0); + + GLFunctions::glGenFramebuffer(&m_framebufferId); + GLFunctions::glBindFramebuffer(m_framebufferId); + + GLFunctions::glFramebufferTexture2D(gl_const::GLColorAttachment, m_colorTextureId); + GLFunctions::glFramebufferTexture2D(gl_const::GLDepthAttachment, m_depthTextureId); + GLFunctions::glFramebufferTexture2D(gl_const::GLStencilAttachment, 0); + + uint32_t const status = GLFunctions::glCheckFramebufferStatus(); + if (status != gl_const::GLFramebufferComplete) + { + m_isSupported = false; + Destroy(); + LOG(LWARNING, ("Framebuffer is unsupported. Framebuffer status =", status)); + } + + m_defaultContext->setDefaultFramebuffer(); +} + +void Framebuffer::Enable() +{ + ASSERT(m_isSupported, ()); + GLFunctions::glBindFramebuffer(m_framebufferId); +} + +void Framebuffer::Disable() +{ + ASSERT(m_defaultContext, ()); + ASSERT(m_isSupported, ()); + m_defaultContext->setDefaultFramebuffer(); +} + +uint32_t Framebuffer::GetTextureId() const { return m_colorTextureId; } +} // namespace dp diff --git a/drape/framebuffer.hpp b/drape/framebuffer.hpp new file mode 100644 index 0000000000..39de064799 --- /dev/null +++ b/drape/framebuffer.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include <cstdint> + +namespace dp +{ +class OGLContext; + +class Framebuffer +{ +public: + Framebuffer() = default; + ~Framebuffer(); + + void SetDefaultContext(dp::OGLContext * context); + void SetSize(uint32_t width, uint32_t height); + + void Enable(); + void Disable(); + + uint32_t GetTextureId() const; + bool IsSupported() const { return m_isSupported; } +private: + void Destroy(); + + uint32_t m_width = 0; + uint32_t m_height = 0; + + uint32_t m_colorTextureId = 0; + uint32_t m_depthTextureId = 0; + uint32_t m_framebufferId = 0; + + dp::OGLContext * m_defaultContext = 0; + + bool m_isSupported = true; +}; +} // namespace dp diff --git a/drape/glIncludes.hpp b/drape/glIncludes.hpp index 5f87f1670e..b47df3e85a 100644 --- a/drape/glIncludes.hpp +++ b/drape/glIncludes.hpp @@ -3,9 +3,8 @@ #include "std/target_os.hpp" #if defined(OMIM_OS_IPHONE) - #define USE_OPENGLES20_IF_AVAILABLE 1 - #include <OpenGLES/ES2/gl.h> #include <OpenGLES/ES2/glext.h> + #include <OpenGLES/ES3/gl.h> #elif defined(OMIM_OS_MAC) #include <OpenGL/gl.h> #include <OpenGL/glext.h> @@ -15,10 +14,10 @@ #include <GL/gl.h> #include "3party/GL/glext.h" #elif defined(OMIM_OS_ANDROID) - #include <EGL/egl.h> - #include <GLES2/gl2.h> #define GL_GLEXT_PROTOTYPES #include <GLES2/gl2ext.h> + #include "android/jni/com/mapswithme/opengl/gl3stub.h" + #include <EGL/egl.h> #else #define GL_GLEXT_PROTOTYPES #include <GL/gl.h> diff --git a/drape/glconstants.cpp b/drape/glconstants.cpp index e934c7be71..0c3c0f5724 100644 --- a/drape/glconstants.cpp +++ b/drape/glconstants.cpp @@ -25,6 +25,14 @@ #define GL_LUMINANCE8_ALPHA4_OES 0x8043 #endif +#if !defined(GL_LUMINANCE) + #define GL_LUMINANCE 0x1909 +#endif + +#if !defined(GL_LUMINANCE_ALPHA) + #define GL_LUMINANCE_ALPHA 0x190A +#endif + #if defined(GL_WRITE_ONLY) #define WRITE_ONLY_DEF GL_WRITE_ONLY #elif defined(GL_WRITE_ONLY_OES) @@ -125,6 +133,7 @@ const glConst GLAlpha8 = GL_ALPHA8_OES; const glConst GLLuminance8 = GL_LUMINANCE8_OES; const glConst GLAlphaLuminance8 = GL_LUMINANCE8_ALPHA8_OES; const glConst GLAlphaLuminance4 = GL_LUMINANCE8_ALPHA4_OES; +const glConst GLRed = GL_RED; const glConst GL8BitOnChannel = GL_UNSIGNED_BYTE; const glConst GL4BitOnChannel = GL_UNSIGNED_SHORT_4_4_4_4; diff --git a/drape/glconstants.hpp b/drape/glconstants.hpp index 1dccc60bb8..c67c181fa9 100644 --- a/drape/glconstants.hpp +++ b/drape/glconstants.hpp @@ -62,6 +62,7 @@ extern const glConst GLAlpha8; extern const glConst GLLuminance8; extern const glConst GLAlphaLuminance8; extern const glConst GLAlphaLuminance4; +extern const glConst GLRed; /// Pixel type for texture upload extern const glConst GL8BitOnChannel; diff --git a/drape/glextensions_list.cpp b/drape/glextensions_list.cpp index b9647ebefd..69647f4fa5 100644 --- a/drape/glextensions_list.cpp +++ b/drape/glextensions_list.cpp @@ -3,121 +3,87 @@ #include "base/assert.hpp" -#include "std/string.hpp" +#include "std/target_os.hpp" namespace dp { - -#ifdef DEBUG - #include "std/map.hpp" - - class GLExtensionsList::Impl +GLExtensionsList::GLExtensionsList(dp::ApiVersion apiVersion) +{ +#if defined(OMIM_OS_MOBILE) + CheckExtension(TextureNPOT, "GL_OES_texture_npot"); + if (apiVersion == dp::ApiVersion::OpenGLES2) { - public: - void CheckExtension(GLExtensionsList::ExtensionName const & enumName, const string & extName) - { #ifdef OMIM_OS_ANDROID - if (enumName == GLExtensionsList::VertexArrayObject) - m_supportedMap[enumName] = false; - else -#endif - m_supportedMap[enumName] = GLFunctions::glHasExtension(extName); - } - - void SetExtension(GLExtensionsList::ExtensionName const & enumName, bool isSupported) - { - m_supportedMap[enumName] = isSupported; - } - - bool IsSupported(GLExtensionsList::ExtensionName const & enumName) const - { - map<GLExtensionsList::ExtensionName, bool>::const_iterator it = m_supportedMap.find(enumName); - if (it != m_supportedMap.end()) - return it->second; - - ASSERT(false, ("Not all used extensions is checked")); - return false; - } - - private: - map<GLExtensionsList::ExtensionName, bool> m_supportedMap; - }; + SetExtension(VertexArrayObject, false); #else - #include "std/set.hpp" - - class GLExtensionsList::Impl - { - public: - void CheckExtension(GLExtensionsList::ExtensionName const & enumName, const string & extName) - { -#ifdef OMIM_OS_ANDROID - if (enumName == GLExtensionsList::VertexArrayObject) - return; -#endif - if (GLFunctions::glHasExtension(extName)) - m_supported.insert(enumName); - } - - void SetExtension(GLExtensionsList::ExtensionName const & enumName, bool isSupported) - { - if (isSupported) - m_supported.insert(enumName); - } - - bool IsSupported(GLExtensionsList::ExtensionName const & enumName) const - { - if (m_supported.find(enumName) != m_supported.end()) - return true; - - return false; - } - - private: - set<GLExtensionsList::ExtensionName> m_supported; - }; + CheckExtension(VertexArrayObject, "GL_OES_vertex_array_object"); #endif - -GLExtensionsList::GLExtensionsList() - : m_impl(new Impl()) -{ -#if defined(OMIM_OS_MOBILE) - m_impl->CheckExtension(VertexArrayObject, "GL_OES_vertex_array_object"); - m_impl->CheckExtension(RequiredInternalFormat, "GL_OES_required_internalformat"); - m_impl->CheckExtension(TextureNPOT, "GL_OES_texture_npot"); - m_impl->CheckExtension(MapBuffer, "GL_OES_mapbuffer"); - m_impl->CheckExtension(UintIndices, "GL_OES_element_index_uint"); - m_impl->CheckExtension(MapBufferRange, "GL_EXT_map_buffer_range"); + CheckExtension(MapBuffer, "GL_OES_mapbuffer"); + CheckExtension(UintIndices, "GL_OES_element_index_uint"); + CheckExtension(MapBufferRange, "GL_EXT_map_buffer_range"); + } + else + { + SetExtension(VertexArrayObject, true); + SetExtension(MapBuffer, true); + SetExtension(MapBufferRange, true); + SetExtension(UintIndices, true); + } #elif defined(OMIM_OS_WINDOWS) m_impl->CheckExtension(TextureNPOT, "GL_ARB_texture_non_power_of_two"); - m_impl->SetExtension(VertexArrayObject, false); - m_impl->SetExtension(RequiredInternalFormat, false); - m_impl->SetExtension(MapBuffer, true); - m_impl->SetExtension(MapBufferRange, false); - m_impl->SetExtension(UintIndices, true); + SetExtension(MapBuffer, true); + SetExtension(UintIndices, true); + if (apiVersion == dp::ApiVersion::OpenGLES2) + { + SetExtension(VertexArrayObject, false); + SetExtension(MapBufferRange, false); + } + else + { + SetExtension(VertexArrayObject, true); + SetExtension(MapBufferRange, true); + } #else - m_impl->CheckExtension(VertexArrayObject, "GL_APPLE_vertex_array_object"); - m_impl->CheckExtension(TextureNPOT, "GL_ARB_texture_non_power_of_two"); - m_impl->SetExtension(RequiredInternalFormat, false); - m_impl->SetExtension(MapBuffer, true); - m_impl->SetExtension(MapBufferRange, false); - m_impl->SetExtension(UintIndices, true); + CheckExtension(TextureNPOT, "GL_ARB_texture_non_power_of_two"); + SetExtension(MapBuffer, true); + SetExtension(UintIndices, true); + if (apiVersion == dp::ApiVersion::OpenGLES2) + { + CheckExtension(VertexArrayObject, "GL_APPLE_vertex_array_object"); + SetExtension(MapBufferRange, false); + } + else + { + SetExtension(VertexArrayObject, true); + SetExtension(MapBufferRange, true); + } #endif } -GLExtensionsList::~GLExtensionsList() +// static +GLExtensionsList & GLExtensionsList::Instance() { - delete m_impl; + static GLExtensionsList extList(GLFunctions::CurrentApiVersion); + return extList; } -GLExtensionsList & GLExtensionsList::Instance() +bool GLExtensionsList::IsSupported(ExtensionName extName) const { - static GLExtensionsList extList; - return extList; + auto const it = m_supportedMap.find(extName); + if (it != m_supportedMap.end()) + return it->second; + + ASSERT(false, ("Not all used extensions are checked")); + return false; } -bool GLExtensionsList::IsSupported(ExtensionName const & extName) const +void GLExtensionsList::CheckExtension(ExtensionName enumName, std::string const & extName) { - return m_impl->IsSupported(extName); + m_supportedMap[enumName] = GLFunctions::glHasExtension(extName); } -} // namespace dp +void GLExtensionsList::SetExtension(ExtensionName enumName, bool isSupported) +{ + m_supportedMap[enumName] = isSupported; +} +} // namespace dp diff --git a/drape/glextensions_list.hpp b/drape/glextensions_list.hpp index d5ffc143ed..507c10ec52 100644 --- a/drape/glextensions_list.hpp +++ b/drape/glextensions_list.hpp @@ -1,33 +1,37 @@ #pragma once -#include "std/noncopyable.hpp" +#include "drape/drape_global.hpp" + +#include "base/macros.hpp" + +#include <map> +#include <string> namespace dp { - -class GLExtensionsList : private noncopyable +class GLExtensionsList { public: enum ExtensionName { VertexArrayObject, TextureNPOT, - RequiredInternalFormat, MapBuffer, UintIndices, MapBufferRange }; static GLExtensionsList & Instance(); - bool IsSupported(ExtensionName const & extName) const; -private: - GLExtensionsList(); - ~GLExtensionsList(); + bool IsSupported(ExtensionName extName) const; private: - class Impl; - Impl * m_impl; -}; + GLExtensionsList(dp::ApiVersion apiVersion); + void CheckExtension(ExtensionName enumName, std::string const & extName); + void SetExtension(ExtensionName enumName, bool isSupported); + + std::map<ExtensionName, bool> m_supportedMap; -} // namespace dp + DISALLOW_COPY_AND_MOVE(GLExtensionsList); +}; +} // namespace dp diff --git a/drape/glfunctions.cpp b/drape/glfunctions.cpp index 15887ac76b..0a272d6056 100644 --- a/drape/glfunctions.cpp +++ b/drape/glfunctions.cpp @@ -8,13 +8,10 @@ #include "base/mutex.hpp" #include "base/string_utils.hpp" -#ifdef DEBUG -#include "base/thread.hpp" -#endif - -#include "std/algorithm.hpp" -#include "std/map.hpp" -#include "std/utility.hpp" +#include <algorithm> +#include <map> +#include <mutex> +#include <utility> #if defined(OMIM_OS_WINDOWS) #define DP_APIENTRY __stdcall @@ -22,87 +19,103 @@ #define DP_APIENTRY #endif +// static +dp::ApiVersion GLFunctions::CurrentApiVersion = dp::ApiVersion::OpenGLES2; + namespace { #ifdef DEBUG - typedef pair<threads::ThreadID, glConst> TKey; - typedef pair<TKey, uint32_t> TNode; - typedef map<TKey, uint32_t> TBoundMap; - TBoundMap g_boundBuffers; - threads::Mutex g_mutex; +using NodeKey = std::pair<std::thread::id, glConst>; +using Node = std::pair<NodeKey, uint32_t>; +using BoundMap = std::map<NodeKey, uint32_t>; +BoundMap g_boundBuffers; +std::mutex g_boundBuffersMutex; #endif -inline GLboolean convert(bool v) -{ - return (v == true) ? GL_TRUE : GL_FALSE; -} - -typedef void (DP_APIENTRY *TglClearColorFn)(GLfloat r, GLfloat g, GLfloat b, GLfloat a); -typedef void (DP_APIENTRY *TglClearFn)(GLbitfield mask); -typedef void (DP_APIENTRY *TglViewportFn)(GLint x, GLint y, GLsizei w, GLsizei h); -typedef void (DP_APIENTRY *TglScissorFn)(GLint x, GLint y, GLsizei w, GLsizei h); -typedef void (DP_APIENTRY *TglFlushFn)(); - -typedef void (DP_APIENTRY *TglActiveTextureFn)(GLenum texture); -typedef void (DP_APIENTRY *TglBlendEquationFn)(GLenum mode); - -typedef void (DP_APIENTRY *TglGenVertexArraysFn)(GLsizei n, GLuint * ids); -typedef void (DP_APIENTRY *TglBindVertexArrayFn)(GLuint id); -typedef void (DP_APIENTRY *TglDeleteVertexArrayFn)(GLsizei n, GLuint const * ids); - -typedef void (DP_APIENTRY *TglGetBufferParameterFn)(GLenum target, GLenum value, GLint * data); -typedef void (DP_APIENTRY *TglGenBuffersFn)(GLsizei n, GLuint * buffers); -typedef void (DP_APIENTRY *TglBindBufferFn)(GLenum target, GLuint buffer); -typedef void (DP_APIENTRY *TglDeleteBuffersFn)(GLsizei n, GLuint const * buffers); -typedef void (DP_APIENTRY *TglBufferDataFn)(GLenum target, GLsizeiptr size, GLvoid const * data, GLenum usage); -typedef void (DP_APIENTRY *TglBufferSubDataFn)(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid const * data); -typedef void * (DP_APIENTRY *TglMapBufferFn)(GLenum target, GLenum access); -typedef GLboolean(DP_APIENTRY *TglUnmapBufferFn)(GLenum target); -typedef void * (DP_APIENTRY *TglMapBufferRangeFn)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); -typedef void (DP_APIENTRY *TglFlushMappedBufferRangeFn)(GLenum target, GLintptr offset, GLsizeiptr length); - -typedef GLuint(DP_APIENTRY *TglCreateShaderFn)(GLenum type); -typedef void (DP_APIENTRY *TglShaderSourceFn)(GLuint shaderID, GLsizei count, GLchar const ** string, GLint const * length); -typedef void (DP_APIENTRY *TglCompileShaderFn)(GLuint shaderID); -typedef void (DP_APIENTRY *TglDeleteShaderFn)(GLuint shaderID); -typedef void (DP_APIENTRY *TglGetShaderivFn)(GLuint shaderID, GLenum name, GLint * p); -typedef void (DP_APIENTRY *TglGetShaderInfoLogFn)(GLuint shaderID, GLsizei maxLength, GLsizei * length, GLchar * infoLog); - -typedef GLuint(DP_APIENTRY *TglCreateProgramFn)(); -typedef void (DP_APIENTRY *TglAttachShaderFn)(GLuint programID, GLuint shaderID); -typedef void (DP_APIENTRY *TglDetachShaderFn)(GLuint programID, GLuint shaderID); -typedef void (DP_APIENTRY *TglLinkProgramFn)(GLuint programID); -typedef void (DP_APIENTRY *TglDeleteProgramFn)(GLuint programID); -typedef void (DP_APIENTRY *TglGetProgramivFn)(GLuint programID, GLenum name, GLint * p); -typedef void (DP_APIENTRY *TglGetProgramInfoLogFn)(GLuint programID, GLsizei maxLength, GLsizei * length, GLchar * infoLog); - -typedef void (DP_APIENTRY *TglUseProgramFn)(GLuint programID); -typedef GLint (DP_APIENTRY *TglGetAttribLocationFn)(GLuint program, GLchar const * name); -typedef void (DP_APIENTRY *TglBindAttribLocationFn)(GLuint program, GLuint index, GLchar const * name); - -typedef void (DP_APIENTRY *TglEnableVertexAttributeFn)(GLuint location); -typedef void (DP_APIENTRY *TglVertexAttributePointerFn)(GLuint index, GLint count, GLenum type, GLboolean normalize, - GLsizei stride, GLvoid const * p); -typedef GLint(DP_APIENTRY *TglGetUniformLocationFn)(GLuint programID, GLchar const * name); -typedef void (DP_APIENTRY *TglGetActiveUniformFn)(GLuint programID, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, - GLint * size, GLenum * type, GLchar * name); -typedef void (DP_APIENTRY *TglUniform1iFn)(GLint location, GLint value); -typedef void (DP_APIENTRY *TglUniform2iFn)(GLint location, GLint v1, GLint v2); -typedef void (DP_APIENTRY *TglUniform3iFn)(GLint location, GLint v1, GLint v2, GLint v3); -typedef void (DP_APIENTRY *TglUniform4iFn)(GLint location, GLint v1, GLint v2, GLint v3, GLint v4); -typedef void (DP_APIENTRY *TglUniform1ivFn)(GLint location, GLsizei count, GLint const * value); -typedef void (DP_APIENTRY *TglUniform1fFn)(GLint location, GLfloat value); -typedef void (DP_APIENTRY *TglUniform2fFn)(GLint location, GLfloat v1, GLfloat v2); -typedef void (DP_APIENTRY *TglUniform3fFn)(GLint location, GLfloat v1, GLfloat v2, GLfloat v3); -typedef void (DP_APIENTRY *TglUniform4fFn)(GLint location, GLfloat v1, GLfloat v2, GLfloat v3, GLfloat v4); -typedef void (DP_APIENTRY *TglUniform1fvFn)(GLint location, GLsizei count, GLfloat const * value); -typedef void (DP_APIENTRY *TglUniformMatrix4fvFn)(GLint location, GLsizei count, GLboolean transpose, GLfloat const * value); - -typedef void (DP_APIENTRY *TglGenFramebuffersFn)(GLsizei n, GLuint * framebuffers); -typedef void (DP_APIENTRY *TglDeleteFramebuffersFn)(GLsizei n, GLuint const * framebuffers); -typedef void (DP_APIENTRY *TglBindFramebufferFn)(GLenum target, GLuint id); -typedef void (DP_APIENTRY *TglFramebufferTexture2DFn)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -typedef GLenum(DP_APIENTRY *TglCheckFramebufferStatusFn)(GLenum target); +inline GLboolean convert(bool v) { return static_cast<GLboolean>(v ? GL_TRUE : GL_FALSE); } + +typedef void(DP_APIENTRY * TglClearColorFn)(GLfloat r, GLfloat g, GLfloat b, GLfloat a); +typedef void(DP_APIENTRY * TglClearFn)(GLbitfield mask); +typedef void(DP_APIENTRY * TglViewportFn)(GLint x, GLint y, GLsizei w, GLsizei h); +typedef void(DP_APIENTRY * TglScissorFn)(GLint x, GLint y, GLsizei w, GLsizei h); +typedef void(DP_APIENTRY * TglFlushFn)(); + +typedef void(DP_APIENTRY * TglActiveTextureFn)(GLenum texture); +typedef void(DP_APIENTRY * TglBlendEquationFn)(GLenum mode); + +typedef void(DP_APIENTRY * TglGenVertexArraysFn)(GLsizei n, GLuint * ids); +typedef void(DP_APIENTRY * TglBindVertexArrayFn)(GLuint id); +typedef void(DP_APIENTRY * TglDeleteVertexArrayFn)(GLsizei n, GLuint const * ids); + +typedef void(DP_APIENTRY * TglGetBufferParameterFn)(GLenum target, GLenum value, GLint * data); +typedef void(DP_APIENTRY * TglGenBuffersFn)(GLsizei n, GLuint * buffers); +typedef void(DP_APIENTRY * TglBindBufferFn)(GLenum target, GLuint buffer); +typedef void(DP_APIENTRY * TglDeleteBuffersFn)(GLsizei n, GLuint const * buffers); +typedef void(DP_APIENTRY * TglBufferDataFn)(GLenum target, GLsizeiptr size, GLvoid const * data, + GLenum usage); +typedef void(DP_APIENTRY * TglBufferSubDataFn)(GLenum target, GLintptr offset, GLsizeiptr size, + GLvoid const * data); +typedef void *(DP_APIENTRY * TglMapBufferFn)(GLenum target, GLenum access); +typedef GLboolean(DP_APIENTRY * TglUnmapBufferFn)(GLenum target); +typedef void *(DP_APIENTRY * TglMapBufferRangeFn)(GLenum target, GLintptr offset, GLsizeiptr length, + GLbitfield access); +typedef void(DP_APIENTRY * TglFlushMappedBufferRangeFn)(GLenum target, GLintptr offset, + GLsizeiptr length); + +typedef GLuint(DP_APIENTRY * TglCreateShaderFn)(GLenum type); +typedef void(DP_APIENTRY * TglShaderSourceFn)(GLuint shaderID, GLsizei count, + GLchar const ** string, GLint const * length); +typedef void(DP_APIENTRY * TglCompileShaderFn)(GLuint shaderID); +typedef void(DP_APIENTRY * TglDeleteShaderFn)(GLuint shaderID); +typedef void(DP_APIENTRY * TglGetShaderivFn)(GLuint shaderID, GLenum name, GLint * p); +typedef void(DP_APIENTRY * TglGetShaderInfoLogFn)(GLuint shaderID, GLsizei maxLength, + GLsizei * length, GLchar * infoLog); + +typedef GLuint(DP_APIENTRY * TglCreateProgramFn)(); +typedef void(DP_APIENTRY * TglAttachShaderFn)(GLuint programID, GLuint shaderID); +typedef void(DP_APIENTRY * TglDetachShaderFn)(GLuint programID, GLuint shaderID); +typedef void(DP_APIENTRY * TglLinkProgramFn)(GLuint programID); +typedef void(DP_APIENTRY * TglDeleteProgramFn)(GLuint programID); +typedef void(DP_APIENTRY * TglGetProgramivFn)(GLuint programID, GLenum name, GLint * p); +typedef void(DP_APIENTRY * TglGetProgramInfoLogFn)(GLuint programID, GLsizei maxLength, + GLsizei * length, GLchar * infoLog); + +typedef void(DP_APIENTRY * TglUseProgramFn)(GLuint programID); +typedef GLint(DP_APIENTRY * TglGetAttribLocationFn)(GLuint program, GLchar const * name); +typedef void(DP_APIENTRY * TglBindAttribLocationFn)(GLuint program, GLuint index, + GLchar const * name); + +typedef void(DP_APIENTRY * TglEnableVertexAttributeFn)(GLuint location); +typedef void(DP_APIENTRY * TglVertexAttributePointerFn)(GLuint index, GLint count, GLenum type, + GLboolean normalize, GLsizei stride, + GLvoid const * p); +typedef GLint(DP_APIENTRY * TglGetUniformLocationFn)(GLuint programID, GLchar const * name); +typedef void(DP_APIENTRY * TglGetActiveUniformFn)(GLuint programID, GLuint uniformIndex, + GLsizei bufSize, GLsizei * length, GLint * size, + GLenum * type, GLchar * name); +typedef void(DP_APIENTRY * TglUniform1iFn)(GLint location, GLint value); +typedef void(DP_APIENTRY * TglUniform2iFn)(GLint location, GLint v1, GLint v2); +typedef void(DP_APIENTRY * TglUniform3iFn)(GLint location, GLint v1, GLint v2, GLint v3); +typedef void(DP_APIENTRY * TglUniform4iFn)(GLint location, GLint v1, GLint v2, GLint v3, GLint v4); +typedef void(DP_APIENTRY * TglUniform1ivFn)(GLint location, GLsizei count, GLint const * value); +typedef void(DP_APIENTRY * TglUniform1fFn)(GLint location, GLfloat value); +typedef void(DP_APIENTRY * TglUniform2fFn)(GLint location, GLfloat v1, GLfloat v2); +typedef void(DP_APIENTRY * TglUniform3fFn)(GLint location, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void(DP_APIENTRY * TglUniform4fFn)(GLint location, GLfloat v1, GLfloat v2, GLfloat v3, + GLfloat v4); +typedef void(DP_APIENTRY * TglUniform1fvFn)(GLint location, GLsizei count, GLfloat const * value); +typedef void(DP_APIENTRY * TglUniformMatrix4fvFn)(GLint location, GLsizei count, + GLboolean transpose, GLfloat const * value); + +typedef void(DP_APIENTRY * TglGenFramebuffersFn)(GLsizei n, GLuint * framebuffers); +typedef void(DP_APIENTRY * TglDeleteFramebuffersFn)(GLsizei n, GLuint const * framebuffers); +typedef void(DP_APIENTRY * TglBindFramebufferFn)(GLenum target, GLuint id); +typedef void(DP_APIENTRY * TglFramebufferTexture2DFn)(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, + GLint level); +typedef GLenum(DP_APIENTRY * TglCheckFramebufferStatusFn)(GLenum target); + +typedef GLubyte const * (DP_APIENTRY * TglGetStringiFn) (GLenum name, GLuint index); TglClearColorFn glClearColorFn = nullptr; TglClearFn glClearFn = nullptr; @@ -173,184 +186,19 @@ TglBindFramebufferFn glBindFramebufferFn = nullptr; TglFramebufferTexture2DFn glFramebufferTexture2DFn = nullptr; TglCheckFramebufferStatusFn glCheckFramebufferStatusFn = nullptr; -int const GLCompileStatus = GL_COMPILE_STATUS; -int const GLLinkStatus = GL_LINK_STATUS; - -threads::Mutex s_mutex; -bool s_inited = false; - -class GLFunctionsCache -{ -public: - GLFunctionsCache() = default; - - void SetThread(thread::id const & threadId) - { - m_threadId = threadId; - - m_glBindTextureCache = CachedParam<uint32_t>(); - m_glActiveTextureCache = CachedParam<glConst>(); - m_glUseProgramCache = CachedParam<uint32_t>(); - m_glLineWidthCache = CachedParam<uint32_t>(); - m_glStateCache.clear(); - m_uniformsCache.clear(); - } - - void glBindTexture(uint32_t textureID) - { - if (!IsCachedThread() || m_glBindTextureCache.Assign(textureID)) - GLCHECK(::glBindTexture(GL_TEXTURE_2D, textureID)); - } - - void glActiveTexture(glConst texBlock) - { - if (!IsCachedThread() || m_glActiveTextureCache.Assign(texBlock)) - { - ASSERT(glActiveTextureFn != nullptr, ()); - GLCHECK(glActiveTextureFn(texBlock)); - } - } +TglGetStringiFn glGetStringiFn = nullptr; - void glUseProgram(uint32_t programID) - { - if (!IsCachedThread() || m_glUseProgramCache.Assign(programID)) - { - ASSERT(glUseProgramFn != nullptr, ()); - GLCHECK(glUseProgramFn(programID)); - } - } - - void glEnable(glConst mode) - { - if (!IsCachedThread() || m_glStateCache[mode].Assign(true)) - GLCHECK(::glEnable(mode)); - } - - void glDisable(glConst mode) - { - if (!IsCachedThread() || m_glStateCache[mode].Assign(false)) - GLCHECK(::glDisable(mode)); - } - - void glUniformValuei(int8_t location, int32_t v) - { - if (!IsCachedThread() || GetCacheForCurrentProgram().Assign(location, v)) - { - ASSERT(glUniform1iFn != nullptr, ()); - ASSERT(location != -1, ()); - GLCHECK(glUniform1iFn(location, v)); - } - } - - void glUniformValuef(int8_t location, float v) - { - if (!IsCachedThread() || GetCacheForCurrentProgram().Assign(location, v)) - { - ASSERT(glUniform1fFn != nullptr, ()); - ASSERT(location != -1, ()); - GLCHECK(glUniform1fFn(location, v)); - } - } - - void glLineWidth(uint32_t value) - { - if (!IsCachedThread() || m_glLineWidthCache.Assign(value)) - { - GLCHECK(::glLineWidth(static_cast<float>(value))); - } - } - -private: - - template<typename TValue> - struct CachedParam - { - TValue m_value; - bool m_inited; - - CachedParam() - : m_value(TValue()) - , m_inited(false) - { - } - - explicit CachedParam(TValue const & value) - : m_value(value) - , m_inited(true) - { - } - - bool Assign(TValue const & newValue) - { - if (m_inited && newValue == m_value) - return false; - - m_value = newValue; - m_inited = true; - return true; - } - - bool operator!=(TValue const & value) const - { - return m_value != value; - } - - CachedParam & operator=(TValue const & param) - { - m_value = param; - m_inited = true; - return *this; - } - }; - - template<typename TValue> using UniformCache = map<int8_t, CachedParam<TValue>>; - using StateParams = map<glConst, CachedParam<bool>>; - - struct UniformsCache - { - UniformCache<int32_t> m_glUniform1iCache; - UniformCache<float> m_glUniform1fCache; - - bool Assign(int8_t location, int32_t value) { return Assign(location, value, m_glUniform1iCache); } - bool Assign(int8_t location, float value) { return Assign(location, value, m_glUniform1fCache); } - - template<typename TValue> - bool Assign(int8_t location, TValue const & value, UniformCache<TValue> & cache) - { - return cache[location].Assign(value); - } - }; - - GLFunctionsCache::UniformsCache & GetCacheForCurrentProgram() - { - ASSERT(m_glUseProgramCache.m_inited, ()); - return m_uniformsCache[m_glUseProgramCache.m_value]; - } - - bool IsCachedThread() const - { - return this_thread::get_id() == m_threadId; - } - - CachedParam<uint32_t> m_glBindTextureCache; - CachedParam<glConst> m_glActiveTextureCache; - CachedParam<uint32_t> m_glUseProgramCache; - StateParams m_glStateCache; - CachedParam<uint32_t> m_glLineWidthCache; - - map<uint32_t, UniformsCache> m_uniformsCache; - - thread::id m_threadId; -}; - -GLFunctionsCache s_cache; +#if !defined(GL_NUM_EXTENSIONS) + #define GL_NUM_EXTENSIONS 0x821D +#endif -} // namespace +std::mutex s_mutex; +bool s_inited = false; +} // namespace #ifdef OMIM_OS_WINDOWS - template <typename TFunc> -TFunc LoadExtension(string const & ext) +TFunc LoadExtension(std::string const & ext) { TFunc func = reinterpret_cast<TFunc>(wglGetProcAddress(ext.c_str())); if (func == nullptr) @@ -361,21 +209,21 @@ TFunc LoadExtension(string const & ext) return func; } - - #define LOAD_GL_FUNC(type, func) LoadExtension<type>(#func); +#define LOAD_GL_FUNC(type, func) LoadExtension<type>(#func); #else - #define LOAD_GL_FUNC(type, func) &::func +#define LOAD_GL_FUNC(type, func) static_cast<type>(&::func) #endif - -void GLFunctions::Init() +void GLFunctions::Init(dp::ApiVersion apiVersion) { - threads::MutexGuard g(s_mutex); + std::lock_guard<std::mutex> lock(s_mutex); if (s_inited) return; + CurrentApiVersion = apiVersion; s_inited = true; - /// VAO + +/// VAO #if defined(OMIM_OS_MAC) glGenVertexArraysFn = &glGenVertexArraysAPPLE; glBindVertexArrayFn = &glBindVertexArrayAPPLE; @@ -386,24 +234,59 @@ void GLFunctions::Init() glGenVertexArraysFn = &::glGenVertexArrays; glBindVertexArrayFn = &::glBindVertexArray; glDeleteVertexArrayFn = &::glDeleteVertexArrays; - glMapBufferFn = &::glMapBuffer; // I don't know correct name for linux! - glUnmapBufferFn = &::glUnmapBuffer; // I don't know correct name for linux! + glMapBufferFn = &::glMapBuffer; + glUnmapBufferFn = &::glUnmapBuffer; #elif defined(OMIM_OS_ANDROID) - glGenVertexArraysFn = (TglGenVertexArraysFn)eglGetProcAddress("glGenVertexArraysOES"); - glBindVertexArrayFn = (TglBindVertexArrayFn)eglGetProcAddress("glBindVertexArrayOES"); - glDeleteVertexArrayFn = (TglDeleteVertexArrayFn)eglGetProcAddress("glDeleteVertexArraysOES"); - glMapBufferFn = &::glMapBufferOES; - glUnmapBufferFn = &::glUnmapBufferOES; - glMapBufferRangeFn = (TglMapBufferRangeFn)eglGetProcAddress("glMapBufferRangeEXT"); - glFlushMappedBufferRangeFn = (TglFlushMappedBufferRangeFn)eglGetProcAddress("glFlushMappedBufferRangeEXT"); + if (CurrentApiVersion == dp::ApiVersion::OpenGLES2) + { + glGenVertexArraysFn = (TglGenVertexArraysFn)eglGetProcAddress("glGenVertexArraysOES"); + glBindVertexArrayFn = (TglBindVertexArrayFn)eglGetProcAddress("glBindVertexArrayOES"); + glDeleteVertexArrayFn = (TglDeleteVertexArrayFn)eglGetProcAddress("glDeleteVertexArraysOES"); + glMapBufferFn = &::glMapBufferOES; + glUnmapBufferFn = &::glUnmapBufferOES; + glMapBufferRangeFn = (TglMapBufferRangeFn)eglGetProcAddress("glMapBufferRangeEXT"); + glFlushMappedBufferRangeFn = + (TglFlushMappedBufferRangeFn)eglGetProcAddress("glFlushMappedBufferRangeEXT"); + } + else if (CurrentApiVersion == dp::ApiVersion::OpenGLES3) + { + glGenVertexArraysFn = ::glGenVertexArrays; + glBindVertexArrayFn = ::glBindVertexArray; + glDeleteVertexArrayFn = ::glDeleteVertexArrays; + glUnmapBufferFn = ::glUnmapBuffer; + glMapBufferRangeFn = ::glMapBufferRange; + glFlushMappedBufferRangeFn = ::glFlushMappedBufferRange; + glGetStringiFn = ::glGetStringi; + } + else + { + ASSERT(false, ("Unknown Graphics API")); + } #elif defined(OMIM_OS_MOBILE) - glGenVertexArraysFn = &glGenVertexArraysOES; - glBindVertexArrayFn = &glBindVertexArrayOES; - glDeleteVertexArrayFn = &glDeleteVertexArraysOES; - glMapBufferFn = &::glMapBufferOES; - glUnmapBufferFn = &::glUnmapBufferOES; - glMapBufferRangeFn = &::glMapBufferRangeEXT; - glFlushMappedBufferRangeFn = &::glFlushMappedBufferRangeEXT; + if (CurrentApiVersion == dp::ApiVersion::OpenGLES2) + { + glGenVertexArraysFn = &glGenVertexArraysOES; + glBindVertexArrayFn = &glBindVertexArrayOES; + glDeleteVertexArrayFn = &glDeleteVertexArraysOES; + glMapBufferFn = &::glMapBufferOES; + glUnmapBufferFn = &::glUnmapBufferOES; + glMapBufferRangeFn = &::glMapBufferRangeEXT; + glFlushMappedBufferRangeFn = &::glFlushMappedBufferRangeEXT; + } + else if (CurrentApiVersion == dp::ApiVersion::OpenGLES3) + { + glGenVertexArraysFn = &::glGenVertexArrays; + glBindVertexArrayFn = &::glBindVertexArray; + glDeleteVertexArrayFn = &::glDeleteVertexArrays; + glUnmapBufferFn = &::glUnmapBuffer; + glMapBufferRangeFn = &::glMapBufferRange; + glFlushMappedBufferRangeFn = &::glFlushMappedBufferRange; + glGetStringiFn = &::glGetStringi; + } + else + { + ASSERT(false, ("Unknown Graphics API")); + } #elif defined(OMIM_OS_WINDOWS) if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject)) { @@ -411,16 +294,15 @@ void GLFunctions::Init() glBindVertexArrayFn = LOAD_GL_FUNC(TglBindVertexArrayFn, glBindVertexArray); glDeleteVertexArrayFn = LOAD_GL_FUNC(TglDeleteVertexArrayFn, glDeleteVertexArrays); } - glMapBufferFn = LOAD_GL_FUNC(TglMapBufferFn, glMapBuffer); glUnmapBufferFn = LOAD_GL_FUNC(TglUnmapBufferFn, glUnmapBuffer); #endif - glClearColorFn = &::glClearColor; - glClearFn = &::glClear; - glViewportFn = &::glViewport; - glScissorFn = &::glScissor; - glFlushFn = &::glFlush; + glClearColorFn = LOAD_GL_FUNC(TglClearColorFn, glClearColor); + glClearFn = LOAD_GL_FUNC(TglClearFn, glClear); + glViewportFn = LOAD_GL_FUNC(TglViewportFn, glViewport); + glScissorFn = LOAD_GL_FUNC(TglScissorFn, glScissor); + glFlushFn = LOAD_GL_FUNC(TglFlushFn, glFlush); glActiveTextureFn = LOAD_GL_FUNC(TglActiveTextureFn, glActiveTexture); glBlendEquationFn = LOAD_GL_FUNC(TglBlendEquationFn, glBlendEquation); @@ -438,7 +320,8 @@ void GLFunctions::Init() #ifdef OMIM_OS_WINDOWS glShaderSourceFn = LOAD_GL_FUNC(TglShaderSourceFn, glShaderSource); #else - typedef void (DP_APIENTRY *glShaderSource_Type)(GLuint shaderID, GLsizei count, GLchar const ** string, GLint const * length); + typedef void(DP_APIENTRY * glShaderSource_Type)(GLuint shaderID, GLsizei count, + GLchar const ** string, GLint const * length); glShaderSourceFn = reinterpret_cast<glShaderSource_Type>(&::glShaderSource); #endif glCompileShaderFn = LOAD_GL_FUNC(TglCompileShaderFn, glCompileShader); @@ -485,29 +368,39 @@ void GLFunctions::Init() glCheckFramebufferStatusFn = LOAD_GL_FUNC(TglCheckFramebufferStatusFn, glCheckFramebufferStatus); } -void GLFunctions::AttachCache(thread::id const & threadId) -{ - s_cache.SetThread(threadId); -} - -bool GLFunctions::glHasExtension(string const & name) +bool GLFunctions::glHasExtension(std::string const & name) { - char const * extensions = reinterpret_cast<char const * >(::glGetString(GL_EXTENSIONS)); - GLCHECKCALL(); - if (extensions == nullptr) - return false; - - char const * extName = name.c_str(); - char const * ptr = nullptr; - while ((ptr = strstr(extensions, extName)) != nullptr) + if (CurrentApiVersion == dp::ApiVersion::OpenGLES2) { - char const * end = ptr + strlen(extName); - if (isspace(*end) || *end == '\0') + char const * extensions = reinterpret_cast<char const *>(::glGetString(GL_EXTENSIONS)); + GLCHECKCALL(); + if (extensions == nullptr) + return false; + + char const * extName = name.c_str(); + char const * ptr = nullptr; + while ((ptr = strstr(extensions, extName)) != nullptr) + { + char const * end = ptr + strlen(extName); + if (isspace(*end) || *end == '\0') return true; - extensions = end; + extensions = end; + } + } + else if (CurrentApiVersion == dp::ApiVersion::OpenGLES3) + { + ASSERT(glGetStringiFn != nullptr, ()); + GLint n = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &n); + for (GLint i = 0; i < n; i++) + { + std::string const extension = + std::string(reinterpret_cast<char const *>(glGetStringiFn(GL_EXTENSIONS, i))); + if (extension == name) + return true; + } } - return false; } @@ -547,21 +440,9 @@ void GLFunctions::glFlush() GLCHECK(glFlushFn()); } -void GLFunctions::glFinish() -{ - GLCHECK(::glFinish()); -} - -void GLFunctions::glFrontFace(glConst mode) -{ - GLCHECK(::glFrontFace(mode)); -} - -void GLFunctions::glCullFace(glConst face) -{ - GLCHECK(::glCullFace(face)); -} - +void GLFunctions::glFinish() { GLCHECK(::glFinish()); } +void GLFunctions::glFrontFace(glConst mode) { GLCHECK(::glFrontFace(mode)); } +void GLFunctions::glCullFace(glConst face) { GLCHECK(::glCullFace(face)); } void GLFunctions::glPixelStore(glConst name, uint32_t value) { GLCHECK(::glPixelStorei(name, value)); @@ -574,21 +455,21 @@ int32_t GLFunctions::glGetInteger(glConst pname) return (int32_t)value; } -string GLFunctions::glGetString(glConst pname) +std::string GLFunctions::glGetString(glConst pname) { - char const * str = reinterpret_cast<char const * >(::glGetString(pname)); + char const * str = reinterpret_cast<char const *>(::glGetString(pname)); GLCHECKCALL(); if (str == nullptr) return ""; - return string(str); + return std::string(str); } int32_t GLFunctions::glGetMaxLineWidth() { GLint range[2]; GLCHECK(::glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, range)); - return max(range[0], range[1]); + return std::max(range[0], range[1]); } int32_t GLFunctions::glGetBufferParameter(glConst target, glConst name) @@ -601,12 +482,12 @@ int32_t GLFunctions::glGetBufferParameter(glConst target, glConst name) void GLFunctions::glEnable(glConst mode) { - s_cache.glEnable(mode); + GLCHECK(::glEnable(mode)); } void GLFunctions::glDisable(glConst mode) { - s_cache.glDisable(mode); + GLCHECK(::glDisable(mode)); } void GLFunctions::glClearDepthValue(double depth) @@ -623,11 +504,7 @@ void GLFunctions::glDepthMask(bool needWriteToDepthBuffer) GLCHECK(::glDepthMask(convert(needWriteToDepthBuffer))); } -void GLFunctions::glDepthFunc(glConst depthFunc) -{ - GLCHECK(::glDepthFunc(depthFunc)); -} - +void GLFunctions::glDepthFunc(glConst depthFunc) { GLCHECK(::glDepthFunc(depthFunc)); } void GLFunctions::glBlendEquation(glConst function) { ASSERT(glBlendEquationFn != nullptr, ()); @@ -671,8 +548,8 @@ void GLFunctions::glBindBuffer(uint32_t vbo, uint32_t target) { ASSERT(glBindBufferFn != nullptr, ()); #ifdef DEBUG - threads::MutexGuard guard(g_mutex); - g_boundBuffers[make_pair(threads::GetCurrentThreadID(), target)] = vbo; + std::lock_guard<std::mutex> guard(g_boundBuffersMutex); + g_boundBuffers[std::make_pair(std::this_thread::get_id(), target)] = vbo; #endif GLCHECK(glBindBufferFn(target, vbo)); } @@ -681,11 +558,9 @@ void GLFunctions::glDeleteBuffer(uint32_t vbo) { ASSERT(glDeleteBuffersFn != nullptr, ()); #ifdef DEBUG - threads::MutexGuard guard(g_mutex); - for (TNode const & n : g_boundBuffers) - { + std::lock_guard<std::mutex> guard(g_boundBuffersMutex); + for (auto const & n : g_boundBuffers) ASSERT(n.second != vbo, ()); - } #endif GLCHECK(glDeleteBuffersFn(1, &vbo)); } @@ -717,7 +592,8 @@ void GLFunctions::glUnmapBuffer(glConst target) GLCHECKCALL(); } -void * GLFunctions::glMapBufferRange(glConst target, uint32_t offset, uint32_t length, glConst access) +void * GLFunctions::glMapBufferRange(glConst target, uint32_t offset, uint32_t length, + glConst access) { ASSERT(glMapBufferRangeFn != nullptr, ()); void * result = glMapBufferRangeFn(target, offset, length, access); @@ -739,24 +615,29 @@ uint32_t GLFunctions::glCreateShader(glConst type) return result; } -void GLFunctions::glShaderSource(uint32_t shaderID, string const & src, string const & defines) +void GLFunctions::glShaderSource(uint32_t shaderID, std::string const & src, std::string const & defines) { ASSERT(glShaderSourceFn != nullptr, ()); - GLchar const * source[2] = + + std::string fullSrc; + if (src.find("#version") != std::string::npos) { - defines.c_str(), - src.c_str() - }; - - GLint lengths[2] = + auto pos = src.find('\n'); + ASSERT_NOT_EQUAL(pos, std::string::npos, ()); + fullSrc = src; + fullSrc.insert(pos + 1, defines); + } + else { - static_cast<GLint>(defines.size()), - static_cast<GLint>(src.size()) - }; - GLCHECK(glShaderSourceFn(shaderID, 2, source, lengths)); + fullSrc = defines + src; + } + + GLchar const * source[1] = {fullSrc.c_str()}; + GLint lengths[1] = {static_cast<GLint>(fullSrc.size())}; + GLCHECK(glShaderSourceFn(shaderID, 1, source, lengths)); } -bool GLFunctions::glCompileShader(uint32_t shaderID, string &errorLog) +bool GLFunctions::glCompileShader(uint32_t shaderID, std::string & errorLog) { ASSERT(glCompileShaderFn != nullptr, ()); ASSERT(glGetShaderivFn != nullptr, ()); @@ -764,14 +645,14 @@ bool GLFunctions::glCompileShader(uint32_t shaderID, string &errorLog) GLCHECK(glCompileShaderFn(shaderID)); GLint result = GL_FALSE; - GLCHECK(glGetShaderivFn(shaderID, GLCompileStatus, &result)); + GLCHECK(glGetShaderivFn(shaderID, GL_COMPILE_STATUS, &result)); if (result == GL_TRUE) return true; GLchar buf[1024]; GLint length = 0; GLCHECK(glGetShaderInfoLogFn(shaderID, 1024, &length, buf)); - errorLog = string(buf, length); + errorLog = std::string(buf, static_cast<size_t>(length)); return false; } @@ -801,7 +682,7 @@ void GLFunctions::glDetachShader(uint32_t programID, uint32_t shaderID) GLCHECK(glDetachShaderFn(programID, shaderID)); } -bool GLFunctions::glLinkProgram(uint32_t programID, string & errorLog) +bool GLFunctions::glLinkProgram(uint32_t programID, std::string & errorLog) { ASSERT(glLinkProgramFn != nullptr, ()); ASSERT(glGetProgramivFn != nullptr, ()); @@ -809,7 +690,7 @@ bool GLFunctions::glLinkProgram(uint32_t programID, string & errorLog) GLCHECK(glLinkProgramFn(programID)); GLint result = GL_FALSE; - GLCHECK(glGetProgramivFn(programID, GLLinkStatus, &result)); + GLCHECK(glGetProgramivFn(programID, GL_LINK_STATUS, &result)); if (result == GL_TRUE) return true; @@ -817,7 +698,7 @@ bool GLFunctions::glLinkProgram(uint32_t programID, string & errorLog) GLchar buf[1024]; GLint length = 0; GLCHECK(glGetProgramInfoLogFn(programID, 1024, &length, buf)); - errorLog = string(buf, length); + errorLog = std::string(buf, static_cast<size_t>(length)); return false; } @@ -829,19 +710,20 @@ void GLFunctions::glDeleteProgram(uint32_t programID) void GLFunctions::glUseProgram(uint32_t programID) { - s_cache.glUseProgram(programID); + ASSERT(glUseProgramFn != nullptr, ()); + GLCHECK(glUseProgramFn(programID)); } -int8_t GLFunctions::glGetAttribLocation(uint32_t programID, string const & name) +int8_t GLFunctions::glGetAttribLocation(uint32_t programID, std::string const & name) { ASSERT(glGetAttribLocationFn != nullptr, ()); int result = glGetAttribLocationFn(programID, name.c_str()); GLCHECKCALL(); ASSERT(result != -1, ()); - return result; + return static_cast<int8_t>(result); } -void GLFunctions::glBindAttribLocation(uint32_t programID, uint8_t index, string const & name) +void GLFunctions::glBindAttribLocation(uint32_t programID, uint8_t index, std::string const & name) { ASSERT(glBindAttribLocationFn != nullptr, ()); GLCHECK(glBindAttribLocationFn(programID, index, name.c_str())); @@ -853,43 +735,38 @@ void GLFunctions::glEnableVertexAttribute(int attributeLocation) GLCHECK(glEnableVertexAttributeFn(attributeLocation)); } -void GLFunctions::glVertexAttributePointer(int attrLocation, - uint32_t count, - glConst type, - bool needNormalize, - uint32_t stride, - uint32_t offset) +void GLFunctions::glVertexAttributePointer(int attrLocation, uint32_t count, glConst type, + bool needNormalize, uint32_t stride, uint32_t offset) { ASSERT(glVertexAttributePointerFn != nullptr, ()); - GLCHECK(glVertexAttributePointerFn(attrLocation, - count, - type, - convert(needNormalize), - stride, + GLCHECK(glVertexAttributePointerFn(attrLocation, count, type, convert(needNormalize), stride, reinterpret_cast<void *>(offset))); } void GLFunctions::glGetActiveUniform(uint32_t programID, uint32_t uniformIndex, - int32_t * uniformSize, glConst * type, string & name) + int32_t * uniformSize, glConst * type, std::string & name) { ASSERT(glGetActiveUniformFn != nullptr, ()); GLchar buff[256]; - GLCHECK(glGetActiveUniformFn(programID, uniformIndex, ARRAY_SIZE(buff), nullptr, uniformSize, type, buff)); + GLCHECK(glGetActiveUniformFn(programID, uniformIndex, ARRAY_SIZE(buff), nullptr, uniformSize, + type, buff)); name = buff; } -int8_t GLFunctions::glGetUniformLocation(uint32_t programID, string const & name) +int8_t GLFunctions::glGetUniformLocation(uint32_t programID, std::string const & name) { ASSERT(glGetUniformLocationFn != nullptr, ()); int result = glGetUniformLocationFn(programID, name.c_str()); GLCHECKCALL(); ASSERT(result != -1, ()); - return result; + return static_cast<int8_t>(result); } void GLFunctions::glUniformValuei(int8_t location, int32_t v) { - s_cache.glUniformValuei(location, v); + ASSERT(glUniform1iFn != nullptr, ()); + ASSERT(location != -1, ()); + GLCHECK(glUniform1iFn(location, v)); } void GLFunctions::glUniformValuei(int8_t location, int32_t v1, int32_t v2) @@ -922,7 +799,9 @@ void GLFunctions::glUniformValueiv(int8_t location, int32_t * v, uint32_t size) void GLFunctions::glUniformValuef(int8_t location, float v) { - s_cache.glUniformValuef(location, v); + ASSERT(glUniform1fFn != nullptr, ()); + ASSERT(location != -1, ()); + GLCHECK(glUniform1fFn(location, v)); } void GLFunctions::glUniformValuef(int8_t location, float v1, float v2) @@ -953,7 +832,7 @@ void GLFunctions::glUniformValuefv(int8_t location, float * v, uint32_t size) GLCHECK(glUniform1fvFn(location, size, v)); } -void GLFunctions::glUniformMatrix4x4Value(int8_t location, float const * values) +void GLFunctions::glUniformMatrix4x4Value(int8_t location, float const * values) { ASSERT(glUniformMatrix4fvFn != nullptr, ()); ASSERT(location != -1, ()); @@ -964,7 +843,8 @@ uint32_t GLFunctions::glGetCurrentProgram() { GLint programIndex = 0; GLCHECK(glGetIntegerv(GL_CURRENT_PROGRAM, &programIndex)); - return programIndex; + ASSERT_GREATER_OR_EQUAL(programIndex, 0, ()); + return static_cast<uint32_t>(programIndex); } int32_t GLFunctions::glGetProgramiv(uint32_t program, glConst paramName) @@ -977,7 +857,8 @@ int32_t GLFunctions::glGetProgramiv(uint32_t program, glConst paramName) void GLFunctions::glActiveTexture(glConst texBlock) { - s_cache.glActiveTexture(texBlock); + ASSERT(glActiveTextureFn != nullptr, ()); + GLCHECK(glActiveTextureFn(texBlock)); } uint32_t GLFunctions::glGenTexture() @@ -994,15 +875,39 @@ void GLFunctions::glDeleteTexture(uint32_t id) void GLFunctions::glBindTexture(uint32_t textureID) { - s_cache.glBindTexture(textureID); + GLCHECK(::glBindTexture(GL_TEXTURE_2D, textureID)); } -void GLFunctions::glTexImage2D(int width, int height, glConst layout, glConst pixelType, void const * data) +void GLFunctions::glTexImage2D(int width, int height, glConst layout, glConst pixelType, + void const * data) { - GLCHECK(::glTexImage2D(GL_TEXTURE_2D, 0, layout, width, height, 0, layout, pixelType, data)); + // In OpenGL ES3: + // - we can't create unsized GL_RED texture, so we use GL_R8; + // - we can't create unsized GL_DEPTH_COMPONENT texture, so we use GL_DEPTH_COMPONENT16 + // or GL_DEPTH_COMPONENT24 or GL_DEPTH_COMPONENT32F. + glConst internalFormat = layout; + if (CurrentApiVersion == dp::ApiVersion::OpenGLES3) + { + if (layout == gl_const::GLRed) + { + internalFormat = GL_R8; + } + else if (layout == gl_const::GLDepthComponent) + { + internalFormat = GL_DEPTH_COMPONENT16; + if (pixelType == gl_const::GLUnsignedIntType) + internalFormat = GL_DEPTH_COMPONENT24; + else if (pixelType == gl_const::GLFloatType) + internalFormat = GL_DEPTH_COMPONENT32F; + } + } + + GLCHECK( + ::glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, layout, pixelType, data)); } -void GLFunctions::glTexSubImage2D(int x, int y, int width, int height, glConst layout, glConst pixelType, void const * data) +void GLFunctions::glTexSubImage2D(int x, int y, int width, int height, glConst layout, + glConst pixelType, void const * data) { GLCHECK(::glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, layout, pixelType, data)); } @@ -1012,9 +917,11 @@ void GLFunctions::glTexParameter(glConst param, glConst value) GLCHECK(::glTexParameteri(GL_TEXTURE_2D, param, value)); } -void GLFunctions::glDrawElements(glConst primitive, uint32_t sizeOfIndex, uint32_t indexCount, uint32_t startIndex) +void GLFunctions::glDrawElements(glConst primitive, uint32_t sizeOfIndex, uint32_t indexCount, + uint32_t startIndex) { - GLCHECK(::glDrawElements(primitive, indexCount, sizeOfIndex == sizeof(uint32_t) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, + GLCHECK(::glDrawElements(primitive, indexCount, + sizeOfIndex == sizeof(uint32_t) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, reinterpret_cast<GLvoid *>(startIndex * sizeOfIndex))); } @@ -1057,25 +964,23 @@ uint32_t GLFunctions::glCheckFramebufferStatus() void GLFunctions::glLineWidth(uint32_t value) { - s_cache.glLineWidth(value); + GLCHECK(::glLineWidth(static_cast<float>(value))); } namespace { - -string GetGLError(GLenum error) +std::string GetGLError(GLenum error) { switch (error) { - case GL_INVALID_ENUM: return "GL_INVALID_ENUM"; - case GL_INVALID_VALUE: return "GL_INVALID_VALUE"; - case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION"; - case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY"; - default: return strings::to_string(error); + case GL_INVALID_ENUM: return "GL_INVALID_ENUM"; + case GL_INVALID_VALUE: return "GL_INVALID_VALUE"; + case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION"; + case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY"; + default: return strings::to_string(error); } } - -} // namespace +} // namespace void CheckGLError(my::SrcPoint const & srcPoint) { diff --git a/drape/glfunctions.hpp b/drape/glfunctions.hpp index dab34efe89..4c3e87c4d5 100644 --- a/drape/glfunctions.hpp +++ b/drape/glfunctions.hpp @@ -1,25 +1,23 @@ #pragma once +#include "drape/drape_global.hpp" #include "drape/glconstants.hpp" #include "base/src_point.hpp" -#include "std/string.hpp" -#include "std/thread.hpp" +#include <string> +#include <thread> class GLFunctions { friend class GLFunctionsCache; public: - static void Init(); + static dp::ApiVersion CurrentApiVersion; - /// Attaches cache of gl-functions to specified thread. The only cache - /// is available, so invoking of this method on other thread leads to - /// disabling of current cache and enabling another - static void AttachCache(thread::id const & threadId); + static void Init(dp::ApiVersion apiVersion); - static bool glHasExtension(string const & name); + static bool glHasExtension(std::string const & name); static void glClearColor(float r, float g, float b, float a); static void glClear(); static void glClearDepth(); @@ -38,7 +36,7 @@ public: /// name = { gl_const::GLBufferSize, gl_const::GLBufferUsage } static int32_t glGetBufferParameter(glConst target, glConst name); - static string glGetString(glConst pname); + static std::string glGetString(glConst pname); static int32_t glGetMaxLineWidth(); @@ -74,41 +72,40 @@ public: /// Shaders support static uint32_t glCreateShader(glConst type); - static void glShaderSource(uint32_t shaderID, string const & src, string const & defines); - static bool glCompileShader(uint32_t shaderID, string & errorLog); + static void glShaderSource(uint32_t shaderID, std::string const & src, + std::string const & defines); + static bool glCompileShader(uint32_t shaderID, std::string & errorLog); static void glDeleteShader(uint32_t shaderID); static uint32_t glCreateProgram(); static void glAttachShader(uint32_t programID, uint32_t shaderID); static void glDetachShader(uint32_t programID, uint32_t shaderID); - static bool glLinkProgram(uint32_t programID, string & errorLog); + static bool glLinkProgram(uint32_t programID, std::string & errorLog); static void glDeleteProgram(uint32_t programID); static void glUseProgram(uint32_t programID); - static int8_t glGetAttribLocation(uint32_t programID, string const & name); - static void glBindAttribLocation(uint32_t programID, uint8_t index, string const & name); + static int8_t glGetAttribLocation(uint32_t programID, std::string const & name); + static void glBindAttribLocation(uint32_t programID, uint8_t index, std::string const & name); /// enable vertex attribute binding. To get attributeLocation need to call glGetAttributeLocation static void glEnableVertexAttribute(int32_t attributeLocation); /// Configure vertex attribute binding. /// attrLocation - attribute location in shader program /// count - specify number of components with "type" for generic attribute - /// needNormalize - if "true" then OGL will map integer value on [-1 : 1] for signed of on [0 : 1] for unsigned + /// needNormalize - if "true" then OGL will map integer value on [-1 : 1] for signed of on [0 : 1] + /// for unsigned /// if "false" it will direct convert to float type /// if "type" == GLFloat this parameter have no sense /// stride - how much bytes need to seek from current attribute value to get the second value - /// offset - how much bytes need to seek from begin of currenct buffer to get first attribute value - static void glVertexAttributePointer(int32_t attrLocation, - uint32_t count, - glConst type, - bool needNormalize, - uint32_t stride, - uint32_t offset); - - static void glGetActiveUniform(uint32_t programID, uint32_t uniformIndex, - int32_t * uniformSize, glConst * type, string & name); - - static int8_t glGetUniformLocation(uint32_t programID, string const & name); + /// offset - how much bytes need to seek from begin of currenct buffer to get first attribute + /// value + static void glVertexAttributePointer(int32_t attrLocation, uint32_t count, glConst type, + bool needNormalize, uint32_t stride, uint32_t offset); + + static void glGetActiveUniform(uint32_t programID, uint32_t uniformIndex, int32_t * uniformSize, + glConst * type, std::string & name); + + static int8_t glGetUniformLocation(uint32_t programID, std::string const & name); static void glUniformValuei(int8_t location, int32_t v); static void glUniformValuei(int8_t location, int32_t v1, int32_t v2); static void glUniformValuei(int8_t location, int32_t v1, int32_t v2, int32_t v3); @@ -121,7 +118,7 @@ public: static void glUniformValuef(int8_t location, float v1, float v2, float v3, float v4); static void glUniformValuefv(int8_t location, float * v, uint32_t size); - static void glUniformMatrix4x4Value(int8_t location, float const *values); + static void glUniformMatrix4x4Value(int8_t location, float const * values); static uint32_t glGetCurrentProgram(); @@ -132,12 +129,15 @@ public: static uint32_t glGenTexture(); static void glDeleteTexture(uint32_t id); static void glBindTexture(uint32_t textureID); - static void glTexImage2D(int width, int height, glConst layout, glConst pixelType, void const * data); - static void glTexSubImage2D(int x, int y, int width, int height, glConst layout, glConst pixelType, void const * data); + static void glTexImage2D(int width, int height, glConst layout, glConst pixelType, + void const * data); + static void glTexSubImage2D(int x, int y, int width, int height, glConst layout, + glConst pixelType, void const * data); static void glTexParameter(glConst param, glConst value); // Draw support - static void glDrawElements(glConst primitive, uint32_t sizeOfIndex, uint32_t indexCount, uint32_t startIndex = 0); + static void glDrawElements(glConst primitive, uint32_t sizeOfIndex, uint32_t indexCount, + uint32_t startIndex = 0); static void glDrawArrays(glConst mode, int32_t first, uint32_t count); // FBO support @@ -148,12 +148,12 @@ public: static uint32_t glCheckFramebufferStatus(); }; -void CheckGLError(my::SrcPoint const &src); +void CheckGLError(my::SrcPoint const & src); #ifdef DEBUG - #define GLCHECK(x) do { (x); CheckGLError(SRC()); } while (false) - #define GLCHECKCALL() do { CheckGLError(SRC()); } while (false) +#define GLCHECK(x) do { (x); CheckGLError(SRC()); } while (false) +#define GLCHECKCALL() do { CheckGLError(SRC()); } while (false) #else - #define GLCHECK(x) (x) - #define GLCHECKCALL() +#define GLCHECK(x) (x) +#define GLCHECKCALL() #endif diff --git a/drape/gpu_buffer.cpp b/drape/gpu_buffer.cpp index 5d91dc06f2..12afc9109c 100644 --- a/drape/gpu_buffer.cpp +++ b/drape/gpu_buffer.cpp @@ -1,24 +1,23 @@ #include "drape/gpu_buffer.hpp" -#include "drape/glfunctions.hpp" #include "drape/glextensions_list.hpp" +#include "drape/glfunctions.hpp" #include "drape/utils/gpu_mem_tracker.hpp" #include "base/assert.hpp" -#include "std/cstring.hpp" +#include <cstring> //#define CHECK_VBO_BOUNDS namespace dp { - namespace { - bool IsMapBufferSupported() - { - static bool const isSupported = GLExtensionsList::Instance().IsSupported(GLExtensionsList::MapBuffer); - return isSupported; - } +bool IsMapBufferSupported() +{ + static bool const isSupported = + GLExtensionsList::Instance().IsSupported(GLExtensionsList::MapBuffer); + return isSupported; } glConst glTarget(GPUBuffer::Target t) @@ -28,10 +27,12 @@ glConst glTarget(GPUBuffer::Target t) return gl_const::GLElementArrayBuffer; } +} // namespace GPUBuffer::GPUBuffer(Target t, void const * data, uint8_t elementSize, uint32_t capacity) : TBase(elementSize, capacity) , m_t(t) + , m_mappingOffset(0) #ifdef DEBUG , m_isMapped(false) #endif @@ -51,20 +52,22 @@ GPUBuffer::~GPUBuffer() void GPUBuffer::UploadData(void const * data, uint32_t elementCount) { - ASSERT(m_isMapped == false, ()); + ASSERT(!m_isMapped, ()); uint32_t currentSize = GetCurrentSize(); uint8_t elementSize = GetElementSize(); - ASSERT(GetCapacity() >= elementCount + currentSize, ("Not enough memory to upload ", elementCount, " elements")); + ASSERT(GetCapacity() >= elementCount + currentSize, + ("Not enough memory to upload ", elementCount, " elements")); Bind(); #if defined(CHECK_VBO_BOUNDS) int32_t size = GLFunctions::glGetBufferParameter(glTarget(m_t), gl_const::GLBufferSize); ASSERT_EQUAL(GetCapacity() * elementSize, size, ()); - ASSERT_LESS_OR_EQUAL((elementCount + currentSize) * elementSize, size,()); + ASSERT_LESS_OR_EQUAL((elementCount + currentSize) * elementSize, size, ()); #endif - GLFunctions::glBufferSubData(glTarget(m_t), elementCount * elementSize, data, currentSize * elementSize); + GLFunctions::glBufferSubData(glTarget(m_t), elementCount * elementSize, data, + currentSize * elementSize); TBase::UploadData(elementCount); #if defined(TRACK_GPU_MEM) @@ -72,46 +75,55 @@ void GPUBuffer::UploadData(void const * data, uint32_t elementCount) #endif } -void GPUBuffer::Bind() -{ - GLFunctions::glBindBuffer(m_bufferID, glTarget(m_t)); -} - -void * GPUBuffer::Map() +void GPUBuffer::Bind() { GLFunctions::glBindBuffer(m_bufferID, glTarget(m_t)); } +void * GPUBuffer::Map(uint32_t elementOffset, uint32_t elementCount) { #ifdef DEBUG - ASSERT(m_isMapped == false, ()); + ASSERT(!m_isMapped, ()); m_isMapped = true; #endif - if (IsMapBufferSupported()) - return GLFunctions::glMapBuffer(glTarget(m_t)); - - return NULL; + if (GLFunctions::CurrentApiVersion == dp::ApiVersion::OpenGLES2) + { + m_mappingOffset = elementOffset; + return IsMapBufferSupported() ? GLFunctions::glMapBuffer(glTarget(m_t)) : nullptr; + } + else if (GLFunctions::CurrentApiVersion == dp::ApiVersion::OpenGLES3) + { + ASSERT(IsMapBufferSupported(), ()); + m_mappingOffset = 0; + uint32_t const elementSize = GetElementSize(); + uint32_t const byteOffset = elementOffset * elementSize; + uint32_t const byteCount = elementCount * elementSize; + return GLFunctions::glMapBufferRange(glTarget(m_t), byteOffset, byteCount, + gl_const::GLWriteBufferBit); + } + return nullptr; } -void GPUBuffer::UpdateData(void * gpuPtr, void const * data, uint32_t elementOffset, uint32_t elementCount) +void GPUBuffer::UpdateData(void * gpuPtr, void const * data, uint32_t elementOffset, + uint32_t elementCount) { uint32_t const elementSize = GetElementSize(); - uint32_t const byteOffset = elementOffset * elementSize; + uint32_t const byteOffset = (elementOffset + m_mappingOffset) * elementSize; uint32_t const byteCount = elementCount * elementSize; uint32_t const byteCapacity = GetCapacity() * elementSize; - ASSERT(m_isMapped == true, ()); + ASSERT(m_isMapped, ()); #if defined(CHECK_VBO_BOUNDS) int32_t size = GLFunctions::glGetBufferParameter(glTarget(m_t), gl_const::GLBufferSize); ASSERT_EQUAL(size, byteCapacity, ()); - ASSERT_LESS(byteOffset + byteCount, size, ()); + ASSERT_LESS_OR_EQUAL(byteOffset + byteCount, size, ()); #endif if (IsMapBufferSupported()) { - ASSERT(gpuPtr != NULL, ()); + ASSERT(gpuPtr != nullptr, ()); memcpy((uint8_t *)gpuPtr + byteOffset, data, byteCount); } else { - ASSERT(gpuPtr == NULL, ()); + ASSERT(gpuPtr == nullptr, ()); if (byteOffset == 0 && byteCount == byteCapacity) GLFunctions::glBufferData(glTarget(m_t), byteCount, data, gl_const::GLStaticDraw); else @@ -122,9 +134,10 @@ void GPUBuffer::UpdateData(void * gpuPtr, void const * data, uint32_t elementOff void GPUBuffer::Unmap() { #ifdef DEBUG - ASSERT(m_isMapped == true, ()); + ASSERT(m_isMapped, ()); m_isMapped = false; #endif + m_mappingOffset = 0; if (IsMapBufferSupported()) GLFunctions::glUnmapBuffer(glTarget(m_t)); } @@ -133,9 +146,10 @@ void GPUBuffer::Resize(void const * data, uint32_t elementCount) { TBase::Resize(elementCount); Bind(); - GLFunctions::glBufferData(glTarget(m_t), GetCapacity() * GetElementSize(), data, gl_const::GLDynamicDraw); + GLFunctions::glBufferData(glTarget(m_t), GetCapacity() * GetElementSize(), data, + gl_const::GLDynamicDraw); - // if we have set up data already (in glBufferData), we have to call SetDataSize + // If we have set up data already (in glBufferData), we have to call SetDataSize. if (data != nullptr) SetDataSize(elementCount); @@ -147,5 +161,4 @@ void GPUBuffer::Resize(void const * data, uint32_t elementCount) dp::GPUMemTracker::Inst().SetUsed("VBO", m_bufferID, GetCurrentSize() * GetElementSize()); #endif } - -} // namespace dp +} // namespace dp diff --git a/drape/gpu_buffer.hpp b/drape/gpu_buffer.hpp index ec65cd47d7..b04ef21ff8 100644 --- a/drape/gpu_buffer.hpp +++ b/drape/gpu_buffer.hpp @@ -1,14 +1,14 @@ #pragma once -#include "drape/pointers.hpp" #include "drape/buffer_base.hpp" +#include "drape/pointers.hpp" namespace dp { - class GPUBuffer : public BufferBase { - typedef BufferBase TBase; + using TBase = BufferBase; + public: enum Target { @@ -23,22 +23,22 @@ public: void UploadData(void const * data, uint32_t elementCount); void Bind(); - void * Map(); + void * Map(uint32_t elementOffset, uint32_t elementCount); void UpdateData(void * gpuPtr, void const * data, uint32_t elementOffset, uint32_t elementCount); void Unmap(); protected: - /// discard old data + // Discard old data. void Resize(void const * data, uint32_t elementCount); private: friend class GPUBufferMapper; Target m_t; uint32_t m_bufferID; + uint32_t m_mappingOffset; #ifdef DEBUG bool m_isMapped; #endif }; - -} // namespace dp +} // namespace dp diff --git a/drape/gpu_program_manager.cpp b/drape/gpu_program_manager.cpp index 5b9df04b81..6ddb7e193c 100644 --- a/drape/gpu_program_manager.cpp +++ b/drape/gpu_program_manager.cpp @@ -30,6 +30,9 @@ void GpuProgramManager::Init(drape_ptr<gpu::GpuProgramGetter> && programGetter) if (SupportManager::Instance().IsSamsungGoogleNexus()) m_globalDefines.append("#define SAMSUNG_GOOGLE_NEXUS\n"); + + if (GLFunctions::CurrentApiVersion == dp::ApiVersion::OpenGLES3) + m_globalDefines.append("#define GLES3\n"); } ref_ptr<GpuProgram> GpuProgramManager::GetProgram(int index) diff --git a/drape/hw_texture.cpp b/drape/hw_texture.cpp index 547a82c6c0..06a6c580b7 100644 --- a/drape/hw_texture.cpp +++ b/drape/hw_texture.cpp @@ -1,7 +1,7 @@ #include "hw_texture.hpp" -#include "glfunctions.hpp" #include "glextensions_list.hpp" +#include "glfunctions.hpp" #include "platform/platform.hpp" @@ -15,21 +15,12 @@ namespace dp { - HWTexture::HWTexture() - : m_width(0) - , m_height(0) - , m_format(UNSPECIFIED) - , m_textureID(-1) - , m_filter(gl_const::GLLinear) -{ -} - -void HWTexture::Create(Params const & params) + : m_width(0), m_height(0), m_format(UNSPECIFIED), m_textureID(-1), m_filter(gl_const::GLLinear) { - Create(params, nullptr); } +void HWTexture::Create(Params const & params) { Create(params, nullptr); } void HWTexture::Create(Params const & params, ref_ptr<void> /*data*/) { m_width = params.m_width; @@ -47,7 +38,7 @@ void HWTexture::Create(Params const & params, ref_ptr<void> /*data*/) if (pixelType == gl_const::GL4BitOnChannel) channelBitSize = 4; - if (layout == gl_const::GLAlpha) + if (layout == gl_const::GLAlpha || layout == gl_const::GLRed) channelCount = 1; uint32_t bitCount = channelBitSize * channelCount * m_width * m_height; @@ -57,11 +48,7 @@ void HWTexture::Create(Params const & params, ref_ptr<void> /*data*/) #endif } -TextureFormat HWTexture::GetFormat() const -{ - return m_format; -} - +TextureFormat HWTexture::GetFormat() const { return m_format; } uint32_t HWTexture::GetWidth() const { ASSERT_ID; @@ -95,19 +82,20 @@ void HWTexture::UnpackFormat(TextureFormat format, glConst & layout, glConst & p pixelType = gl_const::GL8BitOnChannel; break; case ALPHA: - layout = gl_const::GLAlpha; + // On OpenGL ES3 GLAlpha is not supported, we use GLRed instead. + layout = GLFunctions::CurrentApiVersion == dp::ApiVersion::OpenGLES2 ? gl_const::GLAlpha + : gl_const::GLRed; pixelType = gl_const::GL8BitOnChannel; break; - default: - ASSERT(false, ()); - break; + default: ASSERT(false, ()); break; } } void HWTexture::Bind() const { ASSERT_ID; - GLFunctions::glBindTexture(GetID()); + if (m_textureID != -1) + GLFunctions::glBindTexture(static_cast<uint32_t>(GetID())); } void HWTexture::SetFilter(glConst filter) @@ -120,15 +108,11 @@ void HWTexture::SetFilter(glConst filter) } } -int32_t HWTexture::GetID() const -{ - return m_textureID; -} - +int32_t HWTexture::GetID() const { return m_textureID; } OpenGLHWTexture::~OpenGLHWTexture() { if (m_textureID != -1) - GLFunctions::glDeleteTexture(m_textureID); + GLFunctions::glDeleteTexture(static_cast<uint32_t>(m_textureID)); } void OpenGLHWTexture::Create(Params const & params, ref_ptr<void> data) @@ -158,7 +142,8 @@ void OpenGLHWTexture::Create(Params const & params, ref_ptr<void> data) GLFunctions::glBindTexture(0); } -void OpenGLHWTexture::UploadData(uint32_t x, uint32_t y, uint32_t width, uint32_t height, ref_ptr<void> data) +void OpenGLHWTexture::UploadData(uint32_t x, uint32_t y, uint32_t width, uint32_t height, + ref_ptr<void> data) { ASSERT_ID; glConst layout; @@ -175,9 +160,11 @@ drape_ptr<HWTexture> OpenGLHWTextureAllocator::CreateTexture() drape_ptr<HWTextureAllocator> CreateAllocator() { - if (!Platform::IsCustomTextureAllocatorSupported()) - return make_unique_dp<OpenGLHWTextureAllocator>();; - + if (GLFunctions::CurrentApiVersion == dp::ApiVersion::OpenGLES3 || + !Platform::IsCustomTextureAllocatorSupported()) + { + return make_unique_dp<OpenGLHWTextureAllocator>(); + } #if defined(OMIM_OS_IPHONE) && !defined(OMIM_OS_IPHONE_SIMULATOR) return make_unique_dp<HWTextureAllocatorApple>(); #else @@ -190,5 +177,4 @@ ref_ptr<HWTextureAllocator> GetDefaultAllocator() static OpenGLHWTextureAllocator s_allocator; return make_ref<HWTextureAllocator>(&s_allocator); } - -} +} // namespace dp diff --git a/drape/hw_texture_ios.mm b/drape/hw_texture_ios.mm index 538d24af05..87951b8a7a 100644 --- a/drape/hw_texture_ios.mm +++ b/drape/hw_texture_ios.mm @@ -3,6 +3,7 @@ #include "base/logging.hpp" #include "drape/glfunctions.hpp" +#include "drape/glIncludes.hpp" #import <QuartzCore/CAEAGLLayer.h> diff --git a/drape/support_manager.cpp b/drape/support_manager.cpp index 10a0ecccc8..6a68449086 100644 --- a/drape/support_manager.cpp +++ b/drape/support_manager.cpp @@ -15,7 +15,7 @@ void SupportManager::Init() { string const renderer = GLFunctions::glGetString(gl_const::GLRenderer); string const version = GLFunctions::glGetString(gl_const::GLVersion); - LOG(LINFO, ("Renderer =", renderer, "Version =", version)); + LOG(LINFO, ("Renderer =", renderer, "Api =", GLFunctions::CurrentApiVersion, "Driver version =", version)); // On Android the engine may be recreated. Here we guarantee that GPU info is sent once per session. static bool gpuInfoSent = false; diff --git a/drape/texture.cpp b/drape/texture.cpp index c198dc2722..e764f5e17b 100644 --- a/drape/texture.cpp +++ b/drape/texture.cpp @@ -1,7 +1,7 @@ #include "drape/texture.hpp" -#include "drape/glfunctions.hpp" #include "drape/glextensions_list.hpp" +#include "drape/glfunctions.hpp" #include "drape/utils/gpu_mem_tracker.hpp" #include "base/math.hpp" @@ -10,25 +10,13 @@ namespace dp { +Texture::ResourceInfo::ResourceInfo(m2::RectF const & texRect) : m_texRect(texRect) {} -Texture::ResourceInfo::ResourceInfo(m2::RectF const & texRect) - : m_texRect(texRect) {} +m2::RectF const & Texture::ResourceInfo::GetTexRect() const { return m_texRect; } -m2::RectF const & Texture::ResourceInfo::GetTexRect() const -{ - return m_texRect; -} +Texture::Texture() {} -////////////////////////////////////////////////////////////////// - -Texture::Texture() -{ -} - -Texture::~Texture() -{ - Destroy(); -} +Texture::~Texture() { Destroy(); } void Texture::Create(Params const & params) { @@ -42,7 +30,8 @@ void Texture::Create(Params const & params, ref_ptr<void> data) m_hwTexture->Create(params, data); } -void Texture::UploadData(uint32_t x, uint32_t y, uint32_t width, uint32_t height, ref_ptr<void> data) +void Texture::UploadData(uint32_t x, uint32_t y, uint32_t width, uint32_t height, + ref_ptr<void> data) { ASSERT(m_hwTexture != nullptr, ()); m_hwTexture->UploadData(x, y, width, height, data); @@ -98,13 +87,10 @@ void Texture::SetFilter(glConst filter) uint32_t Texture::GetMaxTextureSize() { - return GLFunctions::glGetInteger(gl_const::GLMaxTextureSize); + return static_cast<uint32_t>(GLFunctions::glGetInteger(gl_const::GLMaxTextureSize)); } -void Texture::Destroy() -{ - m_hwTexture.reset(); -} +void Texture::Destroy() { m_hwTexture.reset(); } bool Texture::AllocateTexture(ref_ptr<HWTextureAllocator> allocator) { @@ -116,5 +102,4 @@ bool Texture::AllocateTexture(ref_ptr<HWTextureAllocator> allocator) return false; } - -} // namespace dp +} // namespace dp diff --git a/drape/texture.hpp b/drape/texture.hpp index 12237e9622..b795855793 100644 --- a/drape/texture.hpp +++ b/drape/texture.hpp @@ -1,9 +1,9 @@ #pragma once -#include "drape/pointers.hpp" -#include "drape/glconstants.hpp" #include "drape/drape_global.hpp" +#include "drape/glconstants.hpp" #include "drape/hw_texture.hpp" +#include "drape/pointers.hpp" #include "geometry/rect2d.hpp" @@ -12,7 +12,6 @@ namespace dp { - class Texture { public: @@ -37,7 +36,6 @@ public: public: ResourceInfo(m2::RectF const & texRect); virtual ~ResourceInfo() {} - virtual ResourceType GetType() const = 0; m2::RectF const & GetTexRect() const; @@ -52,7 +50,6 @@ public: virtual void UpdateState() {} virtual bool HasAsyncRoutines() const { return false; } virtual bool HasEnoughSpace(uint32_t /*newKeysCount*/) const { return true; } - using Params = HWTexture::Params; void Create(Params const & params); @@ -81,5 +78,4 @@ protected: private: drape_ptr<HWTexture> m_hwTexture; }; - -} // namespace dp +} // namespace dp diff --git a/drape/vertex_array_buffer.cpp b/drape/vertex_array_buffer.cpp index b812881732..9da306ec15 100644 --- a/drape/vertex_array_buffer.cpp +++ b/drape/vertex_array_buffer.cpp @@ -1,14 +1,35 @@ #include "drape/vertex_array_buffer.hpp" -#include "drape/glfunctions.hpp" + #include "drape/glextensions_list.hpp" +#include "drape/glfunctions.hpp" #include "drape/index_storage.hpp" #include "drape/support_manager.hpp" -#include "base/stl_add.hpp" #include "base/assert.hpp" +#include "base/logging.hpp" namespace dp { +namespace +{ +std::pair<uint32_t, uint32_t> CalculateMappingPart(std::vector<dp::MutateNode> const & nodes) +{ + uint32_t minOffset = std::numeric_limits<uint32_t>::max(); + uint32_t maxOffset = std::numeric_limits<uint32_t>::min(); + for (size_t i = 0; i < nodes.size(); ++i) + { + MutateNode const & node = nodes[i]; + ASSERT_GREATER(node.m_region.m_count, 0, ()); + if (node.m_region.m_offset < minOffset) + minOffset = node.m_region.m_offset; + uint32_t const endOffset = node.m_region.m_offset + node.m_region.m_count; + if (endOffset > maxOffset) + maxOffset = endOffset; + } + ASSERT_LESS(minOffset, maxOffset, ()); + return std::make_pair(minOffset, maxOffset - minOffset); +}; +} // namespace VertexArrayBuffer::VertexArrayBuffer(uint32_t indexBufferSize, uint32_t dataBufferSize) : m_VAO(0) @@ -33,10 +54,10 @@ VertexArrayBuffer::~VertexArrayBuffer() if (m_VAO != 0) { - /// 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 + // Build is called only when VertexArrayBuffer is full and transferred to FrontendRenderer. + // If user move screen before all geometry read from MWM we delete VertexArrayBuffer on + // BackendRenderer. In this case m_VAO will be equal 0 also m_VAO == 0 is on devices + // that do not support OES_vertex_array_object extension. GLFunctions::glDeleteVertexArray(m_VAO); } } @@ -52,10 +73,10 @@ void VertexArrayBuffer::PreflushImpl() ASSERT(!m_isPreflushed, ()); // Buffers are ready, so moving them from CPU to GPU. - for(auto & buffer : m_staticBuffers) + for (auto & buffer : m_staticBuffers) buffer.second->MoveToGPU(GPUBuffer::ElementBuffer); - for(auto & buffer : m_dynamicBuffers) + for (auto & buffer : m_dynamicBuffers) buffer.second->MoveToGPU(GPUBuffer::ElementBuffer); ASSERT(m_indexBuffer != nullptr, ()); @@ -77,16 +98,16 @@ void VertexArrayBuffer::RenderRange(bool drawAsLine, IndicesRange const & range) if (!(m_staticBuffers.empty() && m_dynamicBuffers.empty()) && GetIndexCount() > 0) { ASSERT(m_program != nullptr, ("Somebody not call Build. It's very bad. Very very bad")); - /// if OES_vertex_array_object is supported than all bindings already saved in VAO - /// and we need only bind VAO. + // If OES_vertex_array_object is supported than all bindings have already saved in VAO + // and we need only bind VAO. if (!Bind()) BindStaticBuffers(); BindDynamicBuffers(); GetIndexBuffer()->Bind(); GLFunctions::glDrawElements(drawAsLine ? gl_const::GLLines : gl_const::GLTriangles, - dp::IndexStorage::SizeOfIndex(), - range.m_idxCount, range.m_idxStart); + dp::IndexStorage::SizeOfIndex(), range.m_idxCount, + range.m_idxStart); Unbind(); } @@ -98,10 +119,10 @@ void VertexArrayBuffer::Build(ref_ptr<GpuProgram> program) PreflushImpl(); if (m_VAO != 0 && m_program == program) - return; + return; m_program = program; - /// if OES_vertex_array_object not supported, than buffers will be bind on each Render call + // If OES_vertex_array_object not supported, than buffers will be bound on each render call. if (!GLExtensionsList::Instance().IsSupported(GLExtensionsList::VertexArrayObject)) return; @@ -116,7 +137,8 @@ void VertexArrayBuffer::Build(ref_ptr<GpuProgram> program) Unbind(); } -void VertexArrayBuffer::UploadData(BindingInfo const & bindingInfo, void const * data, uint32_t count) +void VertexArrayBuffer::UploadData(BindingInfo const & bindingInfo, void const * data, + uint32_t count) { ref_ptr<DataBuffer> buffer; if (!bindingInfo.IsDynamic()) @@ -144,35 +166,38 @@ ref_ptr<DataBuffer> VertexArrayBuffer::GetOrCreateStaticBuffer(BindingInfo const return GetOrCreateBuffer(bindingInfo, false); } -ref_ptr<DataBuffer> VertexArrayBuffer::GetBuffer(BindingInfo const & bindingInfo, bool isDynamic) const +ref_ptr<DataBuffer> VertexArrayBuffer::GetBuffer(BindingInfo const & bindingInfo, + bool isDynamic) const { - TBuffersMap const * buffers = nullptr; + BuffersMap const * buffers = nullptr; if (isDynamic) buffers = &m_dynamicBuffers; else buffers = &m_staticBuffers; - TBuffersMap::const_iterator it = buffers->find(bindingInfo); + auto it = buffers->find(bindingInfo); if (it == buffers->end()) return nullptr; return make_ref(it->second); } -ref_ptr<DataBuffer> VertexArrayBuffer::GetOrCreateBuffer(BindingInfo const & bindingInfo, bool isDynamic) +ref_ptr<DataBuffer> VertexArrayBuffer::GetOrCreateBuffer(BindingInfo const & bindingInfo, + bool isDynamic) { - TBuffersMap * buffers = nullptr; + BuffersMap * buffers = nullptr; if (isDynamic) buffers = &m_dynamicBuffers; else buffers = &m_staticBuffers; - TBuffersMap::iterator it = buffers->find(bindingInfo); + auto it = buffers->find(bindingInfo); if (it == buffers->end()) { - drape_ptr<DataBuffer> dataBuffer = make_unique_dp<DataBuffer>(bindingInfo.GetElementSize(), m_dataBufferSize); + drape_ptr<DataBuffer> dataBuffer = + make_unique_dp<DataBuffer>(bindingInfo.GetElementSize(), m_dataBufferSize); ref_ptr<DataBuffer> result = make_ref(dataBuffer); - (*buffers).insert(make_pair(bindingInfo, move(dataBuffer))); + (*buffers).insert(std::make_pair(bindingInfo, move(dataBuffer))); return result; } @@ -190,8 +215,8 @@ uint32_t VertexArrayBuffer::GetAvailableVertexCount() const return m_dataBufferSize; #ifdef DEBUG - TBuffersMap::const_iterator it = m_staticBuffers.begin(); - uint32_t prev = it->second->GetBuffer()->GetAvailableSize(); + auto it = m_staticBuffers.begin(); + uint32_t const prev = it->second->GetBuffer()->GetAvailableSize(); for (; it != m_staticBuffers.end(); ++it) ASSERT_EQUAL(prev, it->second->GetBuffer()->GetAvailableSize(), ()); #endif @@ -205,8 +230,8 @@ uint32_t VertexArrayBuffer::GetStartIndexValue() const return 0; #ifdef DEBUG - TBuffersMap::const_iterator it = m_staticBuffers.begin(); - uint32_t prev = it->second->GetBuffer()->GetCurrentSize(); + auto it = m_staticBuffers.begin(); + uint32_t const prev = it->second->GetBuffer()->GetCurrentSize(); for (; it != m_staticBuffers.end(); ++it) ASSERT(prev == it->second->GetBuffer()->GetCurrentSize(), ()); #endif @@ -219,11 +244,7 @@ uint32_t VertexArrayBuffer::GetDynamicBufferOffset(BindingInfo const & bindingIn return GetOrCreateDynamicBuffer(bindingInfo)->GetBuffer()->GetCurrentSize(); } -uint32_t VertexArrayBuffer::GetIndexCount() const -{ - return GetIndexBuffer()->GetCurrentSize(); -} - +uint32_t VertexArrayBuffer::GetIndexCount() const { return GetIndexBuffer()->GetCurrentSize(); } void VertexArrayBuffer::UploadIndexes(void const * data, uint32_t count) { ASSERT_LESS_OR_EQUAL(count, GetIndexBuffer()->GetAvailableSize(), ()); @@ -233,8 +254,8 @@ void VertexArrayBuffer::UploadIndexes(void const * data, uint32_t count) void VertexArrayBuffer::ApplyMutation(ref_ptr<IndexBufferMutator> indexMutator, ref_ptr<AttributeBufferMutator> attrMutator) { - /// We need to bind current VAO before calling glBindBuffer if OES_vertex_array_object is supported. - /// Otherwise we risk affecting a previously binded VAO. + // We need to bind current VAO before calling glBindBuffer if OES_vertex_array_object is + // supported. Otherwise we risk affecting a previously bound VAO. Bind(); if (indexMutator != nullptr) @@ -254,21 +275,24 @@ void VertexArrayBuffer::ApplyMutation(ref_ptr<IndexBufferMutator> indexMutator, return; } - typedef AttributeBufferMutator::TMutateData TMutateData; - typedef AttributeBufferMutator::TMutateNodes TMutateNodes; - TMutateData const & data = attrMutator->GetMutateData(); - for (TMutateData::const_iterator it = data.begin(); it != data.end(); ++it) + auto const & data = attrMutator->GetMutateData(); + for (auto it = data.begin(); it != data.end(); ++it) { + auto const & nodes = it->second; + if (nodes.empty()) + continue; + + auto const offsets = CalculateMappingPart(nodes); + ref_ptr<DataBuffer> buffer = GetDynamicBuffer(it->first); ASSERT(buffer != nullptr, ()); - DataBufferMapper mapper(buffer); - TMutateNodes const & nodes = it->second; - + DataBufferMapper mapper(buffer, offsets.first, offsets.second); for (size_t i = 0; i < nodes.size(); ++i) { MutateNode const & node = nodes[i]; ASSERT_GREATER(node.m_region.m_count, 0, ()); - mapper.UpdateData(node.m_data.get(), node.m_region.m_offset, node.m_region.m_count); + mapper.UpdateData(node.m_data.get(), node.m_region.m_offset - offsets.first, + node.m_region.m_count); } } @@ -292,20 +316,11 @@ void VertexArrayBuffer::Unbind() const GLFunctions::glBindVertexArray(0); } -void VertexArrayBuffer::BindStaticBuffers() const -{ - BindBuffers(m_staticBuffers); -} - -void VertexArrayBuffer::BindDynamicBuffers() const +void VertexArrayBuffer::BindStaticBuffers() const { BindBuffers(m_staticBuffers); } +void VertexArrayBuffer::BindDynamicBuffers() const { BindBuffers(m_dynamicBuffers); } +void VertexArrayBuffer::BindBuffers(BuffersMap const & buffers) const { - BindBuffers(m_dynamicBuffers); -} - -void VertexArrayBuffer::BindBuffers(TBuffersMap const & buffers) const -{ - TBuffersMap::const_iterator it = buffers.begin(); - for (; it != buffers.end(); ++it) + for (auto it = buffers.begin(); it != buffers.end(); ++it) { BindingInfo const & binding = it->first; ref_ptr<DataBuffer> buffer = make_ref(it->second); @@ -317,11 +332,8 @@ void VertexArrayBuffer::BindBuffers(TBuffersMap const & buffers) const 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, + GLFunctions::glVertexAttributePointer(attributeLocation, decl.m_componentCount, + decl.m_componentType, false, decl.m_stride, decl.m_offset); } } @@ -332,5 +344,4 @@ ref_ptr<DataBufferBase> VertexArrayBuffer::GetIndexBuffer() const ASSERT(m_indexBuffer != nullptr, ()); return m_indexBuffer->GetBuffer(); } - -} // namespace dp +} // namespace dp diff --git a/drape/vertex_array_buffer.hpp b/drape/vertex_array_buffer.hpp index baab293954..49fc1c67e2 100644 --- a/drape/vertex_array_buffer.hpp +++ b/drape/vertex_array_buffer.hpp @@ -1,14 +1,14 @@ #pragma once -#include "drape/index_buffer_mutator.hpp" #include "drape/attribute_buffer_mutator.hpp" -#include "drape/pointers.hpp" -#include "drape/index_buffer.hpp" -#include "drape/data_buffer.hpp" #include "drape/binding_info.hpp" +#include "drape/data_buffer.hpp" #include "drape/gpu_program.hpp" +#include "drape/index_buffer.hpp" +#include "drape/index_buffer_mutator.hpp" +#include "drape/pointers.hpp" -#include "std/map.hpp" +#include <map> namespace df { @@ -17,42 +17,34 @@ class BatchMergeHelper; namespace dp { - struct IndicesRange { uint32_t m_idxStart; uint32_t m_idxCount; - IndicesRange() - : m_idxStart(0), m_idxCount(0) - {} - - IndicesRange(uint32_t idxStart, uint32_t idxCount) - : m_idxStart(idxStart), m_idxCount(idxCount) - {} - + IndicesRange() : m_idxStart(0), m_idxCount(0) {} + IndicesRange(uint32_t idxStart, uint32_t idxCount) : m_idxStart(idxStart), m_idxCount(idxCount) {} bool IsValid() const { return m_idxCount != 0; } }; class VertexArrayBuffer { - typedef map<BindingInfo, drape_ptr<DataBuffer> > TBuffersMap; + using BuffersMap = std::map<BindingInfo, drape_ptr<DataBuffer>>; friend class df::BatchMergeHelper; + public: VertexArrayBuffer(uint32_t indexBufferSize, uint32_t dataBufferSize); ~VertexArrayBuffer(); - /// This method must be call on reading thread, before VAO will be transfer on render thread + // This method must be call on reading thread, before VAO will be transfered on render thread. void Preflush(); - ///{@ - /// On devices where implemented OES_vertex_array_object extensions we use it for build VertexArrayBuffer - /// OES_vertex_array_object create OpenGL resource that belong only one GL context (which was created by) - /// by this reason Build/Bind and Render must be called only on Frontendrendere thread + // OES_vertex_array_object create OpenGL resource that belong only one GL context (which was + // created by). By this reason Build/Bind and Render must be called only on FrontendRenderer + // thread. void Render(bool drawAsLine); void RenderRange(bool drawAsLine, IndicesRange const & range); void Build(ref_ptr<GpuProgram> program); - ///@} uint32_t GetAvailableVertexCount() const; uint32_t GetAvailableIndexCount() const; @@ -68,7 +60,6 @@ public: void ResetChangingTracking() { m_isChanged = false; } bool IsChanged() const { return m_isChanged; } - private: ref_ptr<DataBuffer> GetOrCreateStaticBuffer(BindingInfo const & bindingInfo); ref_ptr<DataBuffer> GetOrCreateDynamicBuffer(BindingInfo const & bindingInfo); @@ -80,17 +71,17 @@ private: void Unbind() const; void BindStaticBuffers() const; void BindDynamicBuffers() const; - void BindBuffers(TBuffersMap const & buffers) const; + void BindBuffers(BuffersMap const & buffers) const; ref_ptr<DataBufferBase> GetIndexBuffer() const; void PreflushImpl(); private: - /// m_VAO - VertexArrayObject name/identificator + // m_VAO - VertexArrayObject name/identifier. int m_VAO; - TBuffersMap m_staticBuffers; - TBuffersMap m_dynamicBuffers; + BuffersMap m_staticBuffers; + BuffersMap m_dynamicBuffers; drape_ptr<IndexBuffer> m_indexBuffer; uint32_t m_dataBufferSize; @@ -101,5 +92,4 @@ private: bool m_moveToGpuOnBuild; bool m_isChanged; }; - -} // namespace dp +} // namespace dp diff --git a/drape/viewport.cpp b/drape/viewport.cpp new file mode 100644 index 0000000000..f36b1b6cc1 --- /dev/null +++ b/drape/viewport.cpp @@ -0,0 +1,25 @@ +#include "drape/viewport.hpp" +#include "drape/glfunctions.hpp" + +namespace dp +{ +Viewport::Viewport(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h) : m_zero(x0, y0), m_size(w, h) +{ +} + +void Viewport::SetViewport(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h) +{ + m_zero = m2::PointU(x0, y0); + m_size = m2::PointU(w, h); +} + +uint32_t Viewport::GetX0() const { return m_zero.x; } +uint32_t Viewport::GetY0() const { return m_zero.y; } +uint32_t Viewport::GetWidth() const { return m_size.x; } +uint32_t Viewport::GetHeight() const { return m_size.y; } +void Viewport::Apply() const +{ + GLCHECK(GLFunctions::glViewport(GetX0(), GetY0(), GetWidth(), GetHeight())); + GLCHECK(GLFunctions::glScissor(GetX0(), GetY0(), GetWidth(), GetHeight())); +} +} // namespace dp diff --git a/drape/viewport.hpp b/drape/viewport.hpp new file mode 100644 index 0000000000..65dcffffa3 --- /dev/null +++ b/drape/viewport.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "geometry/point2d.hpp" + +namespace dp +{ +// Pixel ratio independent viewport implementation. +// pixelRatio is ratio between physical pixels and device-independent pixels for the window. +class Viewport +{ +public: + // x0, y0, w, h is device-independent pixels + Viewport(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h); + + // On iOS we must multiply this on scaleFactor. + // On Android we get true size from surface. + void SetViewport(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h); + + uint32_t GetX0() const; + uint32_t GetY0() const; + uint32_t GetWidth() const; + uint32_t GetHeight() const; + + // Apply viewport to graphics pipeline with convert start point and size to physical pixels. + void Apply() const; + +private: + m2::PointU m_zero; + m2::PointU m_size; +}; +} // namespace dp |