From b4a9061cc442b84a9122672e417e28277c523f5b Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 23 Apr 2019 12:17:46 +0200 Subject: [PATCH] lazy stroke preview rendering --- src/app.cpp | 16 ++++++++++++++-- src/node.cpp | 17 ++++++++++++++++- src/node.h | 3 +++ src/node_panel_brush.h | 20 -------------------- src/node_stroke_preview.cpp | 34 +++++++++++++++++++++++++++------- src/node_stroke_preview.h | 7 +++---- src/util.h | 8 ++++++++ 7 files changed, 71 insertions(+), 34 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index b75bdee..33902eb 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -590,8 +590,6 @@ void App::update(float dt) { auto box = n->m_clip_uncut; Node* p = n->m_parent; - if (dynamic_cast(n)) - p = p; while (p) { float pt = YGNodeLayoutGetPadding(p->y_node, YGEdgeTop); @@ -607,7 +605,21 @@ void App::update(float dt) //auto box = n->m_clip; //glm::ivec4 c = glm::vec4((int)box.x - 1, (int)(height / zoom - box.y - box.w) - 1, (int)box.z + 2, (int)box.w + 2) * zoom; if (box.z <= 0.f || box.w <= 0.f) + { + if (n->m_on_screen) + { + if (dynamic_cast(n)) + p = p; + n->handle_on_screen(true, false); + n->m_on_screen = false; + } return false; + } + if (!n->m_on_screen) + { + n->handle_on_screen(false, true); + n->m_on_screen = true; + } glm::ivec4 c = glm::vec4((int)box.x, (int)(height / zoom - box.y - box.w), (int)box.z, (int)box.w) * zoom; glScissor(c.x + off_x, c.y + off_y, c.z, c.w); n->draw(); diff --git a/src/node.cpp b/src/node.cpp index 5f190ce..cb0afad 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -63,7 +63,7 @@ void Node::watch(std::function observer) { for (auto& c : m_children) { - if (!glm::any(glm::lessThanEqual(zw(c->m_clip), { 0, 0 }))) + //if (!glm::any(glm::lessThanEqual(zw(c->m_clip), { 0, 0 }))) c->watch(observer); } } @@ -268,6 +268,21 @@ void Node::handle_resize(glm::vec2 old_size, glm::vec2 new_size) } +void Node::handle_on_screen(bool old_visibility, bool new_visibility) +{ + if (new_visibility == false) + { + for (auto& c : m_children) + { + if (c->m_on_screen) + { + c->handle_on_screen(true, false); + c->m_on_screen = false; + } + } + } +} + void Node::handle_parent_resize(glm::vec2 old_size, glm::vec2 new_size) { diff --git a/src/node.h b/src/node.h index 013cb5d..f3b94e5 100644 --- a/src/node.h +++ b/src/node.h @@ -132,6 +132,8 @@ public: glm::vec4 m_clip_uncut{ 0, 0, 0, 0 }; std::string m_name; bool m_display = true; + // it's actually rendering + bool m_on_screen = false; Node(const Node&) = delete; Node& operator=(const Node&) = delete; @@ -251,6 +253,7 @@ public: virtual kEventResult on_event(Event* e); virtual kEventResult handle_event(Event* e); virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size); + virtual void handle_on_screen(bool old_visibility, bool new_visibility); virtual void handle_parent_resize(glm::vec2 old_size, glm::vec2 new_size); virtual void create(); virtual void init(); diff --git a/src/node_panel_brush.h b/src/node_panel_brush.h index 8730476..e6f3891 100644 --- a/src/node_panel_brush.h +++ b/src/node_panel_brush.h @@ -37,20 +37,6 @@ class NodePanelBrush : public Node NodeButtonCustom* m_btn_down; NodeButtonCustom* m_btn_remove; bool m_interacted = false; - struct header_t { - char magic[5]{ 'P', 'P', 'B', 'R', 0 }; - uint16_t version = 0; - uint16_t build = g_version_build; - uint16_t brushes = 0; - uint16_t deleted = 0; - }; - struct item_t { - int m_name_len = 0; - int m_high_len = 0; - int m_thumb_len = 0; - bool m_deleted = false; - bool m_user_brush = false; - }; public: NodeScroll* m_container; std::string m_dir_name; @@ -94,12 +80,6 @@ class NodePanelBrushPreset : public Node NodeButtonCustom* m_btn_down; NodeButtonCustom* m_btn_delete; NodeButtonCustom* m_btn_save; - struct header_t { - char magic[5]{ 'P', 'P', 'P', 'R', 0 }; - uint16_t version = 0; - uint16_t count = 0; - }; - public: Node* m_container; std::function& brush)> on_brush_changed; diff --git a/src/node_stroke_preview.cpp b/src/node_stroke_preview.cpp index 75c4dd5..09d6eb8 100644 --- a/src/node_stroke_preview.cpp +++ b/src/node_stroke_preview.cpp @@ -38,6 +38,8 @@ void NodeStrokePreview::empty_queue() s_queue.q.clear(); } +int NodeStrokePreview::instances = 0; + Node* NodeStrokePreview::clone_instantiate() const { return new NodeStrokePreview(); @@ -271,7 +273,10 @@ void NodeStrokePreview::draw_stroke_immediate() m_sampler_linear.bind(4); const auto& b = m_brush; - + + Stroke m_stroke; + Stroke m_dual_stroke; + m_stroke.m_filter_points = false; m_stroke.m_max_size = m_max_size > 0 ? m_max_size : m_size.y * .75f; m_stroke.m_camera.fov = Canvas::I->m_cam_fov; @@ -518,10 +523,13 @@ void NodeStrokePreview::draw_stroke() node->m_brush->preload(); node->async_start(); + gl_state gl; gl.save(); - auto new_size = node->m_tex_preview.size(); + auto new_size = node->m_preview_size; + if (!node->m_tex_preview.ready() || node->m_tex_preview.size() != new_size) + node->m_tex_preview.create((int)new_size.x, (int)new_size.y); if (m_tex.size() != new_size) { m_rtt.create((int)new_size.x, (int)new_size.y); @@ -558,7 +566,6 @@ void NodeStrokePreview::draw_stroke() void NodeStrokePreview::draw() { - //glEnable(GL_BLEND); ShaderManager::use(kShader::Texture); ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp); ShaderManager::u_int(kShaderUniform::Tex, 0); @@ -574,11 +581,10 @@ void NodeStrokePreview::handle_resize(glm::vec2 old_size, glm::vec2 new_size) if (m_tex_preview.size() == new_size || !m_brush) return; - new_size *= root()->m_zoom; + m_preview_size = new_size * root()->m_zoom; - m_tex_preview.create((int)new_size.x, (int)new_size.y); - - draw_stroke(); + if (m_on_screen) + draw_stroke(); } void NodeStrokePreview::destroy_immediate() @@ -586,3 +592,17 @@ void NodeStrokePreview::destroy_immediate() Node::destroy_immediate(); m_tex_preview.destroy(); } + +void NodeStrokePreview::handle_on_screen(bool old_visibility, bool new_visibility) +{ + parent::handle_on_screen(old_visibility, new_visibility); + if (new_visibility) + { + draw_stroke(); + } + else + { + s_queue.Remove(std::static_pointer_cast(shared_from_this())); + m_tex_preview.destroy(); + } +} diff --git a/src/node_stroke_preview.h b/src/node_stroke_preview.h index 4e6e76e..87e72c7 100644 --- a/src/node_stroke_preview.h +++ b/src/node_stroke_preview.h @@ -26,6 +26,7 @@ class NodeStrokePreview : public NodeBorder static DynamicShape m_brush_shape; Texture2D m_tex_preview; public: + using parent = NodeBorder; static std::atomic_int s_instances; static std::atomic_bool s_running; static std::thread s_renderer; @@ -33,11 +34,8 @@ public: static void terminate_renderer(); static void empty_queue(); std::shared_ptr m_brush; - std::shared_ptr m_dual_brush; bool m_draw_first = false; - Stroke m_stroke; - Stroke m_dual_stroke; - std::vector m_bez_points; + glm::vec2 m_preview_size = { 0, 0 }; float m_min_flow = 0.f; float m_max_size = 0.f; float m_pad_override = NAN; @@ -57,4 +55,5 @@ public: virtual void draw() override; virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size) override; virtual void destroy_immediate() override; + virtual void handle_on_screen(bool old_visibility, bool new_visibility) override; }; diff --git a/src/util.h b/src/util.h index 50128bb..e2a2f1e 100644 --- a/src/util.h +++ b/src/util.h @@ -198,6 +198,14 @@ public: } get_cv.notify_one(); } + void Remove(T pkt) + { + std::unique_lock lock(mutex); + auto it = std::find_if(q.begin(), q.end(), [&pkt](auto const& x) { return x.first == pkt; }); + if (it != q.end()) + q.erase(it); + if (Max > 0) post_cv.notify_all(); + } T Get() { static T emptyT{};