diff --git a/drape/debug_rect_renderer.cpp b/drape/debug_rect_renderer.cpp new file mode 100644 index 0000000000..9b52182d49 --- /dev/null +++ b/drape/debug_rect_renderer.cpp @@ -0,0 +1,118 @@ +#include "drape/debug_rect_renderer.hpp" + +#include "drape/gpu_program_manager.hpp" +#include "drape/glfunctions.hpp" +#include "drape/shader_def.hpp" + +namespace dp +{ + +namespace +{ + +m2::PointF PixelPointToScreenSpace(ScreenBase const & screen, m2::PointF const & pt) +{ + float const szX = static_cast(screen.PixelRect().SizeX()); + float const szY = static_cast(screen.PixelRect().SizeY()); + return m2::PointF(pt.x / szX - 0.5f, -pt.y / szY + 0.5f) * 2.0f; +} + +} + +DebugRectRenderer & DebugRectRenderer::Instance() +{ + static DebugRectRenderer renderer; + return renderer; +} + +DebugRectRenderer::DebugRectRenderer() + : m_VAO(0) + , m_vertexBuffer(0) + , m_isEnabled(true) +{ +} + +DebugRectRenderer::~DebugRectRenderer() +{ + ASSERT_EQUAL(m_VAO, 0, ()); + ASSERT_EQUAL(m_vertexBuffer, 0, ()); +} + +void DebugRectRenderer::Init(ref_ptr mng) +{ + m_vertexBuffer = GLFunctions::glGenBuffer(); + GLFunctions::glBindBuffer(m_vertexBuffer, gl_const::GLArrayBuffer); + + m_VAO = GLFunctions::glGenVertexArray(); + GLFunctions::glBindVertexArray(m_VAO); + + m_program = mng->GetProgram(gpu::DEBUG_RECT_PROGRAM); + int8_t attributeLocation = m_program->GetAttributeLocation("a_position"); + ASSERT_NOT_EQUAL(attributeLocation, -1, ()); + GLFunctions::glEnableVertexAttribute(attributeLocation); + GLFunctions::glVertexAttributePointer(attributeLocation, 2, gl_const::GLFloatType, false, sizeof(float) * 2, 0); + + GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); + GLFunctions::glBindVertexArray(0); +} + +void DebugRectRenderer::Destroy() +{ + if (m_vertexBuffer != 0) + { + GLFunctions::glDeleteBuffer(m_vertexBuffer); + m_vertexBuffer = 0; + } + + if (m_VAO != 0) + { + GLFunctions::glDeleteVertexArray(m_VAO); + m_VAO = 0; + } + + m_program = nullptr; +} + +bool DebugRectRenderer::IsEnabled() const +{ + return m_isEnabled; +} + +void DebugRectRenderer::SetEnabled(bool enabled) +{ + m_isEnabled = enabled; +} + +void DebugRectRenderer::DrawRect(ScreenBase const & screen, m2::RectF const & rect) +{ + if (!m_isEnabled) + return; + + ASSERT(m_program != nullptr, ()); + m_program->Bind(); + + GLFunctions::glBindBuffer(m_vertexBuffer, gl_const::GLArrayBuffer); + GLFunctions::glBindVertexArray(m_VAO); + + GLFunctions::glDisable(gl_const::GLDepthTest); + + array vertices; + vertices[0] = PixelPointToScreenSpace(screen, rect.LeftBottom()); + vertices[1] = PixelPointToScreenSpace(screen, rect.LeftTop()); + vertices[2] = PixelPointToScreenSpace(screen, rect.RightTop()); + vertices[3] = PixelPointToScreenSpace(screen, rect.RightBottom()); + vertices[4] = vertices[0]; + + GLFunctions::glBufferData(gl_const::GLArrayBuffer, vertices.size() * sizeof(vertices[0]), + vertices.data(), gl_const::GLStaticDraw); + + GLFunctions::glDrawArrays(gl_const::GLLineStrip, 0, vertices.size()); + + GLFunctions::glEnable(gl_const::GLDepthTest); + + GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); + GLFunctions::glBindVertexArray(0); +} + +} // namespace dp + diff --git a/drape/debug_rect_renderer.hpp b/drape/debug_rect_renderer.hpp new file mode 100644 index 0000000000..2232995831 --- /dev/null +++ b/drape/debug_rect_renderer.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include "drape/gpu_program_manager.hpp" +#include "drape/pointers.hpp" + +#include "geometry/rect2d.hpp" +#include "geometry/screenbase.hpp" + +//#define RENDER_DEBUG_RECTS + +namespace dp +{ + +class DebugRectRenderer +{ +public: + static DebugRectRenderer & Instance(); + void Init(ref_ptr mng); + void Destroy(); + + bool IsEnabled() const; + void SetEnabled(bool enabled); + + void DrawRect(ScreenBase const & screen, m2::RectF const & rect); + +private: + DebugRectRenderer(); + ~DebugRectRenderer(); + + int m_VAO; + int m_vertexBuffer; + ref_ptr m_program; + bool m_isEnabled; +}; + +} // namespace dp diff --git a/drape/drape_common.pri b/drape/drape_common.pri index f646c6064f..9d2ef86767 100644 --- a/drape/drape_common.pri +++ b/drape/drape_common.pri @@ -15,6 +15,7 @@ SOURCES += \ $$DRAPE_DIR/color.cpp \ $$DRAPE_DIR/cpu_buffer.cpp \ $$DRAPE_DIR/data_buffer.cpp \ + $$DRAPE_DIR/debug_rect_renderer.cpp \ $$DRAPE_DIR/font_texture.cpp \ $$DRAPE_DIR/fribidi.cpp \ $$DRAPE_DIR/glconstants.cpp \ @@ -61,6 +62,7 @@ HEADERS += \ $$DRAPE_DIR/cpu_buffer.hpp \ $$DRAPE_DIR/data_buffer.hpp \ $$DRAPE_DIR/data_buffer_impl.hpp \ + $$DRAPE_DIR/debug_rect_renderer.hpp \ $$DRAPE_DIR/depth_constants.hpp \ $$DRAPE_DIR/drape_global.hpp \ $$DRAPE_DIR/dynamic_texture.hpp \ diff --git a/drape/drape_tests/glfunctions.cpp b/drape/drape_tests/glfunctions.cpp index f2bf7aeec2..ed968b2ecb 100644 --- a/drape/drape_tests/glfunctions.cpp +++ b/drape/drape_tests/glfunctions.cpp @@ -257,6 +257,8 @@ void GLFunctions::glUnmapBuffer(glConst target) {} void GLFunctions::glDrawElements(uint32_t sizeOfIndex, uint32_t indexCount, uint32_t startIndex) {} +void GLFunctions::glDrawArrays(glConst mode, int32_t first, uint32_t count) {} + void GLFunctions::glPixelStore(glConst name, uint32_t value) {} int32_t GLFunctions::glGetBufferParameter(glConst target, glConst name) diff --git a/drape/glconstants.cpp b/drape/glconstants.cpp index 337514c47b..b7518e19de 100644 --- a/drape/glconstants.cpp +++ b/drape/glconstants.cpp @@ -145,4 +145,6 @@ const glConst GLAlways = GL_ALWAYS; const glConst GLActiveUniforms = GL_ACTIVE_UNIFORMS; +const glConst GLLineStrip = GL_LINE_STRIP; + } // namespace GLConst diff --git a/drape/glconstants.hpp b/drape/glconstants.hpp index df2d3902dc..ca75e3ec14 100644 --- a/drape/glconstants.hpp +++ b/drape/glconstants.hpp @@ -137,4 +137,7 @@ extern const glConst GLAlways; /// Program object parameter names extern const glConst GLActiveUniforms; +/// Draw primitives +extern const glConst GLLineStrip; + } // namespace GLConst diff --git a/drape/glfunctions.cpp b/drape/glfunctions.cpp index edca2002b4..abc2d0b702 100644 --- a/drape/glfunctions.cpp +++ b/drape/glfunctions.cpp @@ -939,6 +939,11 @@ void GLFunctions::glDrawElements(uint32_t sizeOfIndex, uint32_t indexCount, uint reinterpret_cast(startIndex * sizeOfIndex))); } +void GLFunctions::glDrawArrays(glConst mode, int32_t first, uint32_t count) +{ + GLCHECK(::glDrawArrays(mode, first, count)); +} + namespace { diff --git a/drape/glfunctions.hpp b/drape/glfunctions.hpp index b0a15f10d7..d2b479bf5a 100644 --- a/drape/glfunctions.hpp +++ b/drape/glfunctions.hpp @@ -130,6 +130,7 @@ public: // Draw support static void glDrawElements(uint32_t sizeOfIndex, uint32_t indexCount, uint32_t startIndex = 0); + static void glDrawArrays(glConst mode, int32_t first, uint32_t count); }; void CheckGLError(my::SrcPoint const &src); diff --git a/drape/overlay_tree.cpp b/drape/overlay_tree.cpp index 3c8044961b..9e5fa737dc 100644 --- a/drape/overlay_tree.cpp +++ b/drape/overlay_tree.cpp @@ -1,16 +1,46 @@ #include "drape/overlay_tree.hpp" +#include "std/algorithm.hpp" #include "std/bind.hpp" namespace dp { -int const FRAME_UPDATE_PERIOD = 10; +int const kFrameUpdarePeriod = 10; +int const kAverageHandlesCount = 500; + +namespace +{ + +class HandleComparator +{ +public: + bool operator()(OverlayTree::THandle const & l, OverlayTree::THandle const & r) + { + int const priorityLeft = l.first->GetPriority(); + int const priorityRight = r.first->GetPriority(); + if (priorityLeft > priorityRight) + return true; + + if (priorityLeft == priorityRight) + return l.first.get() > r.first.get(); + + return false; + } +}; + +} + +OverlayTree::OverlayTree() + : m_frameCounter(-1) +{ + m_handles.reserve(kAverageHandlesCount); +} void OverlayTree::Frame() { m_frameCounter++; - if (m_frameCounter >= FRAME_UPDATE_PERIOD) + if (m_frameCounter >= kFrameUpdarePeriod) m_frameCounter = -1; } @@ -48,6 +78,14 @@ void OverlayTree::Add(ref_ptr handle, bool isTransparent) return; } + m_handles.push_back(make_pair(handle, isTransparent)); +} + +void OverlayTree::InsertHandle(ref_ptr handle, bool isTransparent) +{ + ScreenBase const & modelView = GetModelView(); + m2::RectD const pixelRect = handle->GetPixelRect(modelView); + typedef buffer_vector OverlayContainerT; OverlayContainerT elements; /* @@ -79,6 +117,12 @@ void OverlayTree::Add(ref_ptr handle, bool isTransparent) void OverlayTree::EndOverlayPlacing() { + HandleComparator comparator; + sort(m_handles.begin(), m_handles.end(), bind(&HandleComparator::operator(), &comparator, _1, _2)); + for (auto const & handle : m_handles) + InsertHandle(handle.first, handle.second); + m_handles.clear(); + ForEach([] (detail::OverlayInfo const & info) { info.m_handle->SetIsVisible(true); diff --git a/drape/overlay_tree.hpp b/drape/overlay_tree.hpp index 3c35908d0e..ada959607c 100644 --- a/drape/overlay_tree.hpp +++ b/drape/overlay_tree.hpp @@ -7,6 +7,8 @@ #include "base/buffer_vector.hpp" +#include "std/vector.hpp" + namespace dp { @@ -44,9 +46,11 @@ struct OverlayTraits class OverlayTree : public m4::Tree { - typedef m4::Tree BaseT; + using BaseT = m4::Tree; public: + OverlayTree(); + void Frame(); bool IsNeedUpdate() const; void ForceUpdate(); @@ -58,11 +62,15 @@ public: using TSelectResult = buffer_vector, 8>; void Select(m2::RectD const & rect, TSelectResult & result) const; -private: - ScreenBase const & GetModelView() const { return m_traits.m_modelView; } + using THandle = pair, bool>; + using THandles = vector; private: - int m_frameCounter = -1; + ScreenBase const & GetModelView() const { return m_traits.m_modelView; } + void InsertHandle(ref_ptr handle, bool isTransparent); + + int m_frameCounter; + THandles m_handles; }; } // namespace dp diff --git a/drape/render_bucket.cpp b/drape/render_bucket.cpp index 5837094270..d9f5c77fa3 100644 --- a/drape/render_bucket.cpp +++ b/drape/render_bucket.cpp @@ -1,9 +1,10 @@ #include "drape/render_bucket.hpp" -#include "drape/overlay_handle.hpp" #include "drape/attribute_buffer_mutator.hpp" -#include "drape/vertex_array_buffer.hpp" +#include "drape/debug_rect_renderer.hpp" +#include "drape/overlay_handle.hpp" #include "drape/overlay_tree.hpp" +#include "drape/vertex_array_buffer.hpp" #include "base/stl_add.hpp" #include "std/bind.hpp" @@ -99,6 +100,19 @@ void RenderBucket::Render(ScreenBase const & screen) m_buffer->ApplyMutation(hasIndexMutation ? rfpIndex : nullptr, rfpAttrib); } m_buffer->Render(); + +#ifdef RENDER_DEBUG_RECTS + if (!m_overlay.empty()) + { + for (auto const & handle : m_overlay) + { + OverlayHandle::Rects rects; + handle->GetPixelShape(screen, rects); + for (auto const & rect : rects) + DebugRectRenderer::Instance().DrawRect(screen, rect); + } + } +#endif } } // namespace dp diff --git a/drape/shaders/debug_rect_fragment_shader.fsh b/drape/shaders/debug_rect_fragment_shader.fsh new file mode 100644 index 0000000000..688fe5fdba --- /dev/null +++ b/drape/shaders/debug_rect_fragment_shader.fsh @@ -0,0 +1,4 @@ +void main(void) +{ + gl_FragColor = vec4(1, 0, 0, 1); +} diff --git a/drape/shaders/debug_rect_vertex_shader.vsh b/drape/shaders/debug_rect_vertex_shader.vsh new file mode 100644 index 0000000000..c23b6da42d --- /dev/null +++ b/drape/shaders/debug_rect_vertex_shader.vsh @@ -0,0 +1,6 @@ +attribute vec2 a_position; + +void main(void) +{ + gl_Position = vec4(a_position, 0, 1); +} diff --git a/drape/shaders/shader_index.txt b/drape/shaders/shader_index.txt index 3337d69fed..86bc27a0d5 100644 --- a/drape/shaders/shader_index.txt +++ b/drape/shaders/shader_index.txt @@ -13,3 +13,4 @@ BUTTON_PROGRAM button_vertex_shader.vsh button_fragment_shader.fsh BOOKMARK_PROGRAM user_mark.vsh texturing_fragment_shader.fsh ROUTE_PROGRAM route_vertex_shader.vsh route_fragment_shader.fsh ROUTE_ARROW_PROGRAM route_vertex_shader.vsh route_arrow_fragment_shader.fsh +DEBUG_RECT_PROGRAM debug_rect_vertex_shader.vsh debug_rect_fragment_shader.fsh diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 978182da6d..ce8227435b 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -5,6 +5,8 @@ #include "drape_frontend/visual_params.hpp" #include "drape_frontend/user_mark_shapes.hpp" +#include "drape/debug_rect_renderer.hpp" + #include "drape/utils/glyph_usage_tracker.hpp" #include "drape/utils/gpu_mem_tracker.hpp" #include "drape/utils/projection.hpp" @@ -840,6 +842,10 @@ void FrontendRenderer::Routine::Do() dp::BlendingParams blendingParams; blendingParams.Apply(); +#ifdef RENDER_DEBUG_RECTS + dp::DebugRectRenderer::Instance().Init(make_ref(m_renderer.m_gpuProgramManager)); +#endif + double const kMaxInactiveSeconds = 2.0; my::Timer timer; @@ -906,6 +912,10 @@ void FrontendRenderer::Routine::Do() m_renderer.CheckRenderingEnabled(); } +#ifdef RENDER_DEBUG_RECTS + dp::DebugRectRenderer::Instance().Destroy(); +#endif + m_renderer.ReleaseResources(); } diff --git a/drape_frontend/path_text_shape.cpp b/drape_frontend/path_text_shape.cpp index e5ce930ae3..9238c21b71 100644 --- a/drape_frontend/path_text_shape.cpp +++ b/drape_frontend/path_text_shape.cpp @@ -21,6 +21,8 @@ #include "std/algorithm.hpp" #include "std/vector.hpp" +#include "drape/glfunctions.hpp" + using m2::Spline; namespace @@ -70,7 +72,8 @@ public: r.Add(pixelPivot + glsl::ToPoint(m_normals[quadIndex + 1].m_normal)); r.Add(pixelPivot + glsl::ToPoint(m_normals[quadIndex + 2].m_normal)); r.Add(pixelPivot + glsl::ToPoint(m_normals[quadIndex + 3].m_normal)); - rects.push_back(r); + if (screen.PixelRect().IsIntersect(m2::RectD(r))) + rects.push_back(r); } }