From dd638e5af42b9100da29b96b63e790b934554213 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Wed, 17 Jun 2026 18:33:36 +0200 Subject: [PATCH] Thin retained app and render runtime seams --- cmake/PanoPainterSources.cmake | 2 + docs/modernization/debt.md | 18 ++ docs/modernization/tasks.md | 5 +- src/font.cpp | 5 +- src/legacy_app_shell_services.cpp | 46 +-- src/legacy_document_image_import_services.cpp | 57 ++++ src/legacy_document_image_import_services.h | 20 ++ ...y_node_stroke_preview_runtime_services.cpp | 261 +++++++++++++----- ...acy_node_stroke_preview_runtime_services.h | 12 + src/node_stroke_preview.h | 10 +- src/shader.cpp | 15 +- src/shape.cpp | 25 +- 12 files changed, 344 insertions(+), 132 deletions(-) create mode 100644 src/legacy_document_image_import_services.cpp create mode 100644 src/legacy_document_image_import_services.h diff --git a/cmake/PanoPainterSources.cmake b/cmake/PanoPainterSources.cmake index 8dfccbfd..6f9decf2 100644 --- a/cmake/PanoPainterSources.cmake +++ b/cmake/PanoPainterSources.cmake @@ -88,6 +88,7 @@ set(PP_LEGACY_APP_SOURCES src/legacy_canvas_mode_fill.cpp src/legacy_canvas_mode_pen_line.cpp src/legacy_canvas_mode_helpers.cpp + src/legacy_document_image_import_services.cpp src/legacy_canvas_mode_helpers.h src/legacy_canvas_mode_mask.cpp src/legacy_canvas_mode_transform.cpp @@ -101,6 +102,7 @@ set(PP_LEGACY_APP_SOURCES src/legacy_preference_storage.h src/legacy_document_canvas_services.cpp src/legacy_document_canvas_services.h + src/legacy_document_image_import_services.h src/legacy_document_layer_services.cpp src/legacy_document_layer_services.h src/legacy_history_services.cpp diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index f097793c..74c135fd 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -18,6 +18,24 @@ agent or engineer to remove them without reconstructing context from chat. ## Reductions +- 2026-06-17: `DEBT-0036` was narrowed again. Retained `Shape`, + `src/shader.cpp`, and `src/font.cpp` now queue render-thread create/update/ + destroy work through `src/renderer_gl/render_runtime_dispatch.h` instead of + calling `App::I` directly, and `Shader` render-thread entry points now assert + that explicit runtime contract while shader-program and mesh ownership remain + retained. +- 2026-06-17: `DEBT-0036` was narrowed again. `NodeStrokePreview` no longer + owns static worker-thread, queue, or render-mutex state directly; + `src/legacy_node_stroke_preview_runtime_services.*` now owns the retained + preview worker lifecycle and queue helpers, leaving the node as a thinner + adapter while the retained preview runtime still reaches app/render helpers + internally. +- 2026-06-17: `DEBT-0029` was narrowed again. + `LegacyFileMenuServices::pick_image_for_import()` in + `src/legacy_app_shell_services.cpp` now delegates retained import execution + to `src/legacy_document_image_import_services.*`, so the File-menu adapter no + longer defines the live `DocumentImageImportServices` implementation inline; + legacy `Image` loading and retained canvas/import-mode execution still remain. - 2026-06-17: `DEBT-0003` was narrowed again. `src/app_runtime.cpp` and `src/app_runtime.h` now synchronize render/UI worker running state, reject cross-thread work once those workers stop, and drain queued work through diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index 9d8ed9e3..170b512f 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -53,8 +53,9 @@ Key facts: - `Canvas::I` still appears hundreds of times in retained canvas modes, panels, and workflow bridges. - Raw `Node*` and callback captures remain a dominant UI lifetime risk. -- `RTT`, `Texture2D`, `Shape`, `Shader`, `Font`, and `CanvasLayer` still route - render work through `App::I` queues. +- `CanvasLayer` and retained stroke-preview/runtime draw paths still depend on + legacy render/runtime helpers, but `RTT`, `Texture2D`, `Shape`, `Shader`, + and `TextMesh` no longer call `App::I` directly for queueing. - `AppRuntime` now owns synchronized running flags plus explicit post/reject, same-thread execution, and queue-drain behavior, but broader singleton reach and app-shell ownership remain. diff --git a/src/font.cpp b/src/font.cpp index 460bc245..407011e7 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -3,6 +3,7 @@ #include "font.h" #include "legacy_gl_mesh_dispatch.h" #include "legacy_ui_gl_dispatch.h" +#include "renderer_gl/render_runtime_dispatch.h" #include "shader.h" #include "asset.h" #include "util.h" @@ -202,7 +203,7 @@ std::vector TextMesh::tokenize(const std::string& s, const Font bool TextMesh::create() { - App::I->render_task([this] + pp::renderer::gl::render_runtime_dispatch().render_task([this] { const auto mesh = pp::legacy::gl_mesh::create_mesh_objects( pp::renderer::gl::OpenGlMeshUpload { @@ -305,7 +306,7 @@ void TextMesh::update(const std::string& text, const std::string& font, int size cur_box -= glm::vec4(xy(f.bounds), 0, 0); bb = bbmax - bbmin; font_array_count = (int)idx.size(); - App::I->render_task([&] + pp::renderer::gl::render_runtime_dispatch().render_task([&] { (void)pp::legacy::gl_mesh::upload_buffer_data( pp::renderer::gl::OpenGlBufferUpload { diff --git a/src/legacy_app_shell_services.cpp b/src/legacy_app_shell_services.cpp index 838750b6..30242cdf 100644 --- a/src/legacy_app_shell_services.cpp +++ b/src/legacy_app_shell_services.cpp @@ -6,6 +6,7 @@ #include "app_core/document_import.h" #include "legacy_app_dialog_services.h" #include "legacy_canvas_view_services.h" +#include "legacy_document_image_import_services.h" #include "legacy_document_canvas_services.h" #include "legacy_history_services.h" #include "legacy_ui_overlay_services.h" @@ -51,50 +52,23 @@ public: void pick_image_for_import() override { - auto* app_ptr = &app_; - app_.pick_image([app_ptr](std::string path) { + app_.pick_image([this](std::string path) { Image img; img.load_file(path); const auto import_plan = pp::app::plan_document_image_import(img.width, img.height); if (!import_plan) return; - class LegacyDocumentImageImportServices final : public pp::app::DocumentImageImportServices { - public: - LegacyDocumentImageImportServices(App& app, Image& image) noexcept - : app_(app) - , image_(image) - { - } - - void import_equirectangular(std::string_view import_path) override - { - if (Canvas::I) - Canvas::I->import_equirectangular(std::string(import_path)); - } - - void enter_transform_import(std::string_view) override - { - if (!app_.canvas || !app_.canvas->m_canvas) - return; - - auto* mode = static_cast( - app_.canvas->m_canvas->modes[(int)kCanvasMode::Import][0]); - mode->m_action = CanvasModeTransform::ActionType::Import; - mode->m_source_image = std::move(image_); - Canvas::set_mode(kCanvasMode::Import); - } - - private: - App& app_; - Image& image_; - }; - - LegacyDocumentImageImportServices services(*app_ptr, img); - const auto status = pp::app::execute_document_image_import_plan( + auto* canvas = app_.canvas ? app_.canvas->m_canvas.get() : nullptr; + auto* import_mode = canvas + ? static_cast(canvas->modes[(int)kCanvasMode::Import][0]) + : nullptr; + const auto status = execute_legacy_document_image_import_plan( import_plan.value(), path, - services); + canvas, + import_mode, + std::move(img)); if (!status.ok()) LOG("Image import failed: %s", status.message); }); diff --git a/src/legacy_document_image_import_services.cpp b/src/legacy_document_image_import_services.cpp new file mode 100644 index 00000000..7d88d07d --- /dev/null +++ b/src/legacy_document_image_import_services.cpp @@ -0,0 +1,57 @@ +#include "pch.h" + +#include "legacy_document_image_import_services.h" + +#include "canvas.h" +#include "canvas_modes.h" + +#include + +namespace pp::panopainter { +namespace { + +class LegacyDocumentImageImportServices final : public pp::app::DocumentImageImportServices { +public: + LegacyDocumentImageImportServices(Canvas* canvas, CanvasModeTransform* import_mode, Image image) noexcept + : canvas_(canvas) + , import_mode_(import_mode) + , image_(std::move(image)) + { + } + + void import_equirectangular(std::string_view import_path) override + { + if (canvas_) + canvas_->import_equirectangular(std::string(import_path)); + } + + void enter_transform_import(std::string_view) override + { + if (!canvas_ || !import_mode_) + return; + + import_mode_->m_action = CanvasModeTransform::ActionType::Import; + import_mode_->m_source_image = std::move(image_); + Canvas::set_mode(kCanvasMode::Import); + } + +private: + Canvas* canvas_ = nullptr; + CanvasModeTransform* import_mode_ = nullptr; + Image image_; +}; + +} // namespace + +pp::foundation::Status execute_legacy_document_image_import_plan( + const pp::app::DocumentImageImportPlan& plan, + std::string_view path, + Canvas* canvas, + CanvasModeTransform* import_mode, + Image image) +{ + LegacyDocumentImageImportServices services(canvas, import_mode, std::move(image)); + return pp::app::execute_document_image_import_plan(plan, path, services); +} + +} // namespace pp::panopainter diff --git a/src/legacy_document_image_import_services.h b/src/legacy_document_image_import_services.h new file mode 100644 index 00000000..cc06c75a --- /dev/null +++ b/src/legacy_document_image_import_services.h @@ -0,0 +1,20 @@ +#pragma once + +#include "app_core/document_import.h" +#include "image.h" + +#include + +class Canvas; +class CanvasModeTransform; + +namespace pp::panopainter { + +[[nodiscard]] pp::foundation::Status execute_legacy_document_image_import_plan( + const pp::app::DocumentImageImportPlan& plan, + std::string_view path, + Canvas* canvas, + CanvasModeTransform* import_mode, + Image image); + +} // namespace pp::panopainter diff --git a/src/legacy_node_stroke_preview_runtime_services.cpp b/src/legacy_node_stroke_preview_runtime_services.cpp index 44fb93ca..cf7e1a9d 100644 --- a/src/legacy_node_stroke_preview_runtime_services.cpp +++ b/src/legacy_node_stroke_preview_runtime_services.cpp @@ -19,6 +19,7 @@ #include "paint_renderer/compositor.h" #include "renderer_gl/opengl_capabilities.h" #include "util.h" +#include #include #include #include @@ -477,11 +478,141 @@ bool execute_legacy_node_stroke_preview_immediate_draw(NodeStrokePreview& previe } // namespace pp::panopainter -std::atomic_int NodeStrokePreview::s_instances{ 0 }; -std::atomic_bool NodeStrokePreview::s_running{ false }; -std::mutex NodeStrokePreview::s_render_mutex; -BlockingQueue> NodeStrokePreview::s_queue; +namespace pp::panopainter { +class NodeStrokePreviewRuntime +{ +public: + std::mutex& render_mutex() noexcept + { + return render_mutex_; + } + + void start() + { + std::lock_guard lock(lifecycle_mutex_); + if (worker_.joinable()) + return; + + worker_ = std::jthread([this](std::stop_token stop_token) { + run(stop_token); + }); + } + + void stop() + { + std::jthread worker; + { + std::lock_guard lock(lifecycle_mutex_); + if (!worker_.joinable()) + return; + + worker = std::move(worker_); + } + + worker.request_stop(); + queue_.UnlockGetters(); + if (worker.joinable()) + worker.join(); + } + + void clear_queue() + { + std::lock_guard lock(queue_.mutex); + queue_.q.clear(); + } + + void enqueue(const std::shared_ptr& preview, bool draw_first) + { + if (!preview) + return; + + start(); + queue_.PostUnique(preview, draw_first); + } + + void remove(const std::shared_ptr& preview) + { + if (!preview) + return; + + std::lock_guard lock(queue_.mutex); + auto it = std::find_if(queue_.q.begin(), queue_.q.end(), [&preview](const auto& queued) { + return queued.first == preview; + }); + if (it != queue_.q.end()) + queue_.q.erase(it); + } + +private: + void run(std::stop_token stop_token) + { + BT_SetTerminate(); + + NodeStrokePreview::m_sampler_linear.create(); + NodeStrokePreview::m_sampler_linear_repeat.create( + pp::renderer::gl::linear_texture_filter(), + pp::renderer::gl::repeat_texture_wrap()); + NodeStrokePreview::m_sampler_mipmap.create(); + NodeStrokePreview::m_sampler_mipmap.set_filter( + pp::renderer::gl::linear_mipmap_linear_texture_filter(), + pp::renderer::gl::linear_texture_filter()); + NodeStrokePreview::m_brush_shape.create(); + + while (!stop_token.stop_requested()) + { + auto node = queue_.Get(); + if (!node) { + if (stop_token.stop_requested()) + break; + continue; + } + + std::lock_guard render_lock(render_mutex_); + + // if the brush is not already loaded, load it and then destroy it + const bool to_unload = (node->m_brush->m_tip_texture == nullptr); + node->m_brush->preload(); + + pp::panopainter::execute_legacy_node_stroke_preview_render_task([node, to_unload] { + gl_state gl; + gl.save(); + + node->m_brush->load(); + node->draw_stroke_immediate(); + if (to_unload) + node->m_brush->unload(); + + gl.restore(); + }); + + node->app_redraw(); + std::this_thread::yield(); + } + + NodeStrokePreview::m_rtt.destroy(); + NodeStrokePreview::m_rtt_mixer.destroy(); + NodeStrokePreview::m_tex.destroy(); + NodeStrokePreview::m_tex_dual.destroy(); + NodeStrokePreview::m_tex_background.destroy(); + NodeStrokePreview::m_brush_shape.destroy(); + } + + std::mutex lifecycle_mutex_; + std::mutex render_mutex_; + BlockingQueue> queue_; + std::jthread worker_; +}; + +NodeStrokePreviewRuntime& legacy_node_stroke_preview_runtime() +{ + static NodeStrokePreviewRuntime runtime; + return runtime; +} + +} // namespace pp::panopainter + +std::atomic_int NodeStrokePreview::s_instances{ 0 }; RTT NodeStrokePreview::m_rtt; RTT NodeStrokePreview::m_rtt_mixer; Texture2D NodeStrokePreview::m_tex; // blending tmp texture @@ -491,22 +622,60 @@ Sampler NodeStrokePreview::m_sampler_linear; Sampler NodeStrokePreview::m_sampler_linear_repeat; Sampler NodeStrokePreview::m_sampler_mipmap; DynamicShape NodeStrokePreview::m_brush_shape; -std::jthread NodeStrokePreview::s_renderer; + +namespace pp::panopainter { + +std::mutex& legacy_node_stroke_preview_render_mutex() +{ + return legacy_node_stroke_preview_runtime().render_mutex(); +} + +void execute_legacy_node_stroke_preview_render_task(std::function task) +{ + if (!task) + return; + + App::I->render_task(std::move(task)); +} + +void start_legacy_node_stroke_preview_worker() +{ + legacy_node_stroke_preview_runtime().start(); +} + +void stop_legacy_node_stroke_preview_worker() +{ + legacy_node_stroke_preview_runtime().stop(); +} + +void clear_legacy_node_stroke_preview_worker_queue() +{ + legacy_node_stroke_preview_runtime().clear_queue(); +} + +void enqueue_legacy_node_stroke_preview_worker( + const std::shared_ptr& preview, + bool draw_first) +{ + legacy_node_stroke_preview_runtime().enqueue(preview, draw_first); +} + +void remove_legacy_node_stroke_preview_worker( + const std::shared_ptr& preview) +{ + legacy_node_stroke_preview_runtime().remove(preview); +} + +} // namespace pp::panopainter void NodeStrokePreview::terminate_renderer() { - if (!s_renderer.joinable()) - return; - - s_running = false; - s_renderer.request_stop(); - s_queue.UnlockGetters(); - s_renderer.join(); + pp::panopainter::stop_legacy_node_stroke_preview_worker(); } void NodeStrokePreview::empty_queue() { - s_queue.q.clear(); + pp::panopainter::clear_legacy_node_stroke_preview_worker_queue(); } void NodeStrokePreview::restore_context() @@ -526,9 +695,9 @@ void NodeStrokePreview::clear_context() Image NodeStrokePreview::render_to_image() { - std::lock_guard _lock(s_render_mutex); + std::lock_guard _lock(pp::panopainter::legacy_node_stroke_preview_render_mutex()); - App::I->render_task([this] { + pp::panopainter::execute_legacy_node_stroke_preview_render_task([this] { draw_stroke_immediate(); }); return m_tex_preview.get_image(); @@ -538,63 +707,9 @@ void NodeStrokePreview::draw_stroke() { if (m_size.x == 0 || m_size.y == 0) return; - std::unique_lock queue_lock(s_queue.mutex); - if (!s_renderer.joinable()) - { - s_running = true; - s_renderer = std::jthread([](std::stop_token stop_token) { - BT_SetTerminate(); - - m_sampler_linear.create(); - m_sampler_linear_repeat.create( - pp::renderer::gl::linear_texture_filter(), - pp::renderer::gl::repeat_texture_wrap()); - m_sampler_mipmap.create(); - m_sampler_mipmap.set_filter( - pp::renderer::gl::linear_mipmap_linear_texture_filter(), - pp::renderer::gl::linear_texture_filter()); - m_brush_shape.create(); - while (s_running && !stop_token.stop_requested()) - { - auto node = s_queue.Get(); - if (node) - { - std::lock_guard _lock(s_render_mutex); - - // if the brush is not already loaded, load it and then destroy it - bool to_unload = (node->m_brush->m_tip_texture == nullptr); - node->m_brush->preload(); - - App::I->render_task([node, to_unload] - { - gl_state gl; - gl.save(); - - node->m_brush->load(); - node->draw_stroke_immediate(); - if (to_unload) - node->m_brush->unload(); - - gl.restore(); - }); - - node->app_redraw(); - - //std::this_thread::sleep_for(std::chrono::milliseconds(30)); - std::this_thread::yield(); - } - } - m_rtt.destroy(); - m_rtt_mixer.destroy(); - m_tex.destroy(); - m_tex_dual.destroy(); - m_tex_background.destroy(); - m_brush_shape.destroy(); - s_running = false; - }); - } - queue_lock.unlock(); - s_queue.PostUnique(std::static_pointer_cast(shared_from_this()), m_draw_first); + pp::panopainter::enqueue_legacy_node_stroke_preview_worker( + std::static_pointer_cast(shared_from_this()), + m_draw_first); } void NodeStrokePreview::draw() @@ -637,7 +752,7 @@ void NodeStrokePreview::handle_on_screen(bool old_visibility, bool new_visibilit } else { - s_queue.Remove(std::static_pointer_cast(shared_from_this())); + pp::panopainter::remove_legacy_node_stroke_preview_worker(std::static_pointer_cast(shared_from_this())); m_tex_preview.destroy(); } } diff --git a/src/legacy_node_stroke_preview_runtime_services.h b/src/legacy_node_stroke_preview_runtime_services.h index c7304590..3ddb52a2 100644 --- a/src/legacy_node_stroke_preview_runtime_services.h +++ b/src/legacy_node_stroke_preview_runtime_services.h @@ -14,6 +14,7 @@ #include #include #include +#include #include class Node; @@ -136,6 +137,17 @@ struct LegacyNodeStrokePreviewImmediateDrawRequest { [[nodiscard]] bool execute_legacy_node_stroke_preview_immediate_runtime( const LegacyNodeStrokePreviewImmediateRuntimeRequest& request); +[[nodiscard]] std::mutex& legacy_node_stroke_preview_render_mutex(); +void execute_legacy_node_stroke_preview_render_task(std::function task); +void start_legacy_node_stroke_preview_worker(); +void stop_legacy_node_stroke_preview_worker(); +void clear_legacy_node_stroke_preview_worker_queue(); +void enqueue_legacy_node_stroke_preview_worker( + const std::shared_ptr& preview, + bool draw_first); +void remove_legacy_node_stroke_preview_worker( + const std::shared_ptr& preview); + void initialize_legacy_node_stroke_preview_clone(Node* dest); [[nodiscard]] bool execute_legacy_node_stroke_preview_immediate_draw(NodeStrokePreview& preview); diff --git a/src/node_stroke_preview.h b/src/node_stroke_preview.h index 1977693f..02c60427 100644 --- a/src/node_stroke_preview.h +++ b/src/node_stroke_preview.h @@ -1,6 +1,5 @@ #pragma once #include -#include #include "node_border.h" #include "rtt.h" #include "brush.h" @@ -9,10 +8,15 @@ #include "legacy_node_stroke_preview_execution_services.h" #include "legacy_node_stroke_preview_runtime_services.h" +namespace pp::panopainter { +class NodeStrokePreviewRuntime; +} + class NodeStrokePreview : public NodeBorder { using StrokeFrame = pp::panopainter::LegacyNodeStrokePreviewFrame; + friend class pp::panopainter::NodeStrokePreviewRuntime; friend bool pp::panopainter::execute_legacy_node_stroke_preview_immediate_draw(NodeStrokePreview& preview); static RTT m_rtt; @@ -28,10 +32,6 @@ class NodeStrokePreview : public NodeBorder public: using parent = NodeBorder; static std::atomic_int s_instances; - static std::atomic_bool s_running; - static std::mutex s_render_mutex; - static std::jthread s_renderer; - static BlockingQueue> s_queue; static void terminate_renderer(); static void empty_queue(); std::shared_ptr m_brush; diff --git a/src/shader.cpp b/src/shader.cpp index 585144ef..4bfdb999 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -2,9 +2,9 @@ #include "log.h" #include "shader.h" #include "asset.h" -#include "app.h" #include "legacy_gl_shader_dispatch.h" #include "renderer_gl/opengl_capabilities.h" +#include "renderer_gl/render_runtime_dispatch.h" #include "renderer_gl/shader_bindings.h" #include @@ -165,7 +165,7 @@ bool Shader::reload() bool Shader::create(const std::string& vertex, const std::string& fragment) { bool ret = true; - App::I->render_task([this, &ret, vertex, fragment] + pp::renderer::gl::render_runtime_dispatch().render_task([this, &ret, vertex, fragment] { static char infolog[4096]; const auto vertex_shader = pp::renderer::gl::compile_opengl_shader_source( @@ -337,7 +337,7 @@ void Shader::destroy() { if (prog) { - App::I->render_task_async([prog=prog] + pp::renderer::gl::render_runtime_dispatch().render_task_async([prog=prog] { const auto status = pp::renderer::gl::delete_opengl_program( static_cast(prog), @@ -352,6 +352,7 @@ void Shader::destroy() void Shader::use() { + assert(pp::renderer::gl::render_runtime_dispatch().is_render_thread()); const auto status = pp::renderer::gl::use_opengl_program( static_cast(prog), pp::legacy::gl_shader::program_use_dispatch()); @@ -360,6 +361,7 @@ void Shader::use() } void Shader::u_vec4(kShaderUniform id, const glm::vec4& v) { + assert(pp::renderer::gl::render_runtime_dispatch().is_render_thread()); if (m_umap.count(id) == 0) LOG("UNIFORM vec4 %d NOT FOUND in shader %d", (int)id, (int)name) else @@ -374,6 +376,7 @@ void Shader::u_vec4(kShaderUniform id, const glm::vec4& v) } void Shader::u_vec3(kShaderUniform id, const glm::vec3& v) { + assert(pp::renderer::gl::render_runtime_dispatch().is_render_thread()); if (m_umap.count(id) == 0) LOG("UNIFORM vec3 %d NOT FOUND in shader %d", (int)id, (int)name) else @@ -389,6 +392,7 @@ void Shader::u_vec3(kShaderUniform id, const glm::vec3& v) void Shader::u_vec2(kShaderUniform id, const glm::vec2& v) { + assert(pp::renderer::gl::render_runtime_dispatch().is_render_thread()); if (m_umap.count(id) == 0) LOG("UNIFORM vec2 %d NOT FOUND in shader %d", (int)id, (int)name) else @@ -404,6 +408,7 @@ void Shader::u_vec2(kShaderUniform id, const glm::vec2& v) void Shader::u_mat4(kShaderUniform id, const glm::mat4& m) { + assert(pp::renderer::gl::render_runtime_dispatch().is_render_thread()); if (m_umap.count(id) == 0) LOG("UNIFORM mat4 %d NOT FOUND in shader %d", (int)id, (int)name) else @@ -418,6 +423,7 @@ void Shader::u_mat4(kShaderUniform id, const glm::mat4& m) } void Shader::u_int(kShaderUniform id, int i) { + assert(pp::renderer::gl::render_runtime_dispatch().is_render_thread()); if (m_umap.count(id) == 0) LOG("UNIFORM int %d NOT FOUND in shader %d", (int)id, (int)name) else @@ -432,6 +438,7 @@ void Shader::u_int(kShaderUniform id, int i) } void Shader::u_int(const char* uniform_name, int i) { + assert(pp::renderer::gl::render_runtime_dispatch().is_render_thread()); const auto location = pp::renderer::gl::get_opengl_attribute_location( static_cast(prog), uniform_name, @@ -450,6 +457,7 @@ void Shader::u_int(const char* uniform_name, int i) } void Shader::u_float(kShaderUniform id, float f) { + assert(pp::renderer::gl::render_runtime_dispatch().is_render_thread()); if (m_umap.count(id) == 0) LOG("UNIFORM float %d NOT FOUND in shader %d", (int)id, (int)name) else @@ -464,6 +472,7 @@ void Shader::u_float(kShaderUniform id, float f) } GLint Shader::GetAttribLocation(const char* attribute_name) { + assert(pp::renderer::gl::render_runtime_dispatch().is_render_thread()); const auto location = pp::renderer::gl::get_opengl_attribute_location( static_cast(prog), attribute_name, diff --git a/src/shape.cpp b/src/shape.cpp index 8c4eebff..d6514aca 100644 --- a/src/shape.cpp +++ b/src/shape.cpp @@ -2,8 +2,8 @@ #include "log.h" #include "legacy_gl_mesh_dispatch.h" #include "shape.h" -#include "app.h" #include "renderer_gl/opengl_capabilities.h" +#include "renderer_gl/render_runtime_dispatch.h" #include #include @@ -71,7 +71,7 @@ bool Shape::create_buffers_imp(GLvoid* idx, GLvoid* vertices, int isize, int vsi use_idx = true; bool ret = false; - App::I->render_task([&] + pp::renderer::gl::render_runtime_dispatch().render_task([&] { destroy(); @@ -101,7 +101,7 @@ bool Shape::create_buffers(GLvoid* vertices, int vsize) use_idx = false; bool ret = false; - App::I->render_task([&] + pp::renderer::gl::render_runtime_dispatch().render_task([&] { destroy(); @@ -129,7 +129,7 @@ void Shape::draw_fill() const if (count[0] == 0) return; const auto type = static_cast(pp::renderer::gl::primitive_mode_for_fill_count(count[0])); - App::I->render_task([=] + pp::renderer::gl::render_runtime_dispatch().render_task([=] { (void)pp::legacy::gl_mesh::draw_mesh( pp::renderer::gl::OpenGlMeshDraw { @@ -148,7 +148,7 @@ void Shape::draw_stroke() const if (count[0] == 0) return; const auto type = static_cast(pp::renderer::gl::primitive_mode_for_stroke_count(count[1])); - App::I->render_task([=] + pp::renderer::gl::render_runtime_dispatch().render_task([=] { (void)pp::legacy::gl_mesh::draw_mesh( pp::renderer::gl::OpenGlMeshDraw { @@ -165,10 +165,13 @@ void Shape::draw_stroke() const void Shape::destroy() { - if (App::I) App::I->render_task_async([b1=buffers[0],b2=buffers[1],a1=arrays[0],a2=arrays[1]] + if (buffers[0] || buffers[1] || arrays[0] || arrays[1]) { - (void)pp::legacy::gl_mesh::delete_mesh_objects({ b1, b2 }, { a1, a2 }, "Shape::destroy"); - }); + pp::renderer::gl::render_runtime_dispatch().render_task_async([b1=buffers[0],b2=buffers[1],a1=arrays[0],a2=arrays[1]] + { + (void)pp::legacy::gl_mesh::delete_mesh_objects({ b1, b2 }, { a1, a2 }, "Shape::destroy"); + }); + } buffers[0] = buffers[1] = 0; arrays[0] = arrays[1] = 0; } @@ -451,7 +454,7 @@ void Plane::update_vertices(const glm::vec4* data, const glm::vec2* uvs, const g vertices[i].pos.z = q; } - App::I->render_task([this] + pp::renderer::gl::render_runtime_dispatch().render_task([this] { (void)pp::legacy::gl_mesh::upload_buffer_data( pp::renderer::gl::OpenGlBufferUpload { @@ -732,7 +735,7 @@ void Sphere::create_impl(int rings, int sectors, float radius, } void LineSegment::update_vertices(const glm::vec4 data[2]) { - App::I->render_task([&] + pp::renderer::gl::render_runtime_dispatch().render_task([&] { static vertex_t vertices[2]; vertices[0] = { data[0], { 0, 0 } }; // A @@ -750,7 +753,7 @@ void LineSegment::update_vertices(const glm::vec4 data[2]) } void DynamicShape::update_vertices(vertex_t* vertices, int vcount) { - App::I->render_task([&] + pp::renderer::gl::render_runtime_dispatch().render_task([&] { count[0] = vcount; count[1] = vcount;