diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index c087233..3990337 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -18,6 +18,12 @@ agent or engineer to remove them without reconstructing context from chat. ## Recent Reductions +- 2026-06-12: DEBT-0036 was narrowed again. Canvas live draw-merge and + `NodeStrokePreview` final stroke composite `kShader::CompDraw` setup now + share `legacy_canvas_stroke_composite_services.h` for retained shader binding + and composite/pattern/dual uniform writes. Texture/RTT binding, samplers, + draw calls, commit-time compositing, and non-stroke `CompDraw` callers remain + retained legacy execution. - 2026-06-12: DEBT-0036 was narrowed again. Canvas and `NodeStrokePreview` live stroke passes now route retained `kShader::Stroke` binding plus setup, blend, pattern, and per-sample uniform writes through diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 6a8e0e3..087483c 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -1348,9 +1348,11 @@ destination copy, brush vertex upload, brush-shape draw, and destination unbind through `execute_legacy_canvas_stroke_sample`, creating the first retained OpenGL stroke execution service seam. Live stroke `kShader::Stroke` binding, setup, blend, pattern, and per-sample uniform writes now pass through -`legacy_canvas_stroke_shader_services.h`, leaving RTT/texture ownership, -dirty-box policy, composite/pad/checkerboard shaders, and retained callback -execution under `DEBT-0036`. +`legacy_canvas_stroke_shader_services.h`. Live draw-merge and preview final +stroke composite `kShader::CompDraw` setup now pass through +`legacy_canvas_stroke_composite_services.h`, leaving RTT/texture ownership, +dirty-box policy, pad/checkerboard/commit composite shaders, and retained +callback execution under `DEBT-0036`. It also owns renderer API texture-format to OpenGL internal/pixel/component token mapping, including depth-stencil formats, for future backend texture objects. `Texture2D` 2D texture binding, upload, diff --git a/src/canvas.cpp b/src/canvas.cpp index c09391c..5d92918 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -3,6 +3,7 @@ #include "canvas.h" #include "app.h" #include "legacy_gl_renderbuffer_dispatch.h" +#include "legacy_canvas_stroke_composite_services.h" #include "legacy_canvas_stroke_execution_services.h" #include "legacy_canvas_stroke_shader_services.h" #include "legacy_canvas_stroke_services.h" @@ -1264,30 +1265,29 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array faces /*= SI if (b->m_pattern_flipx) patt_scale.x *= -1.f; if (b->m_pattern_flipy) patt_scale.y *= -1.f; - ShaderManager::use(kShader::CompDraw); - ShaderManager::u_int(kShaderUniform::Tex, 0); - ShaderManager::u_int(kShaderUniform::TexStroke, 1); - ShaderManager::u_int(kShaderUniform::TexMask, 2); - ShaderManager::u_int(kShaderUniform::TexDual, 3); - ShaderManager::u_vec2(kShaderUniform::Resolution, Canvas::I->m_size); - ShaderManager::u_int(kShaderUniform::TexPattern, 4); - ShaderManager::u_float(kShaderUniform::Alpha, m_layers[layer_index]->m_opacity); - ShaderManager::u_int(kShaderUniform::Lock, m_layers[layer_index]->m_alpha_locked); - ShaderManager::u_int(kShaderUniform::Mask, m_smask_active); - ShaderManager::u_int(kShaderUniform::UseFragcoord, false); - ShaderManager::u_int(kShaderUniform::BlendMode, b->m_blend_mode); - ShaderManager::u_mat4(kShaderUniform::MVP, ortho); - ShaderManager::u_int(kShaderUniform::UseDual, stroke_material.composite_pass.use_dual); - ShaderManager::u_int(kShaderUniform::DualBlendMode, stroke_material.composite_pass.dual_blend_mode); - ShaderManager::u_int(kShaderUniform::UsePattern, stroke_material.composite_pass.use_pattern); - ShaderManager::u_vec2(kShaderUniform::PatternScale, patt_scale); - ShaderManager::u_float(kShaderUniform::PatternInvert, b->m_pattern_invert); - ShaderManager::u_float(kShaderUniform::PatternBright, b->m_pattern_brightness); - ShaderManager::u_float(kShaderUniform::PatternContrast, b->m_pattern_contrast); - ShaderManager::u_float(kShaderUniform::PatternDepth, b->m_pattern_depth); - ShaderManager::u_int(kShaderUniform::PatternBlendMode, b->m_pattern_blend_mode); - ShaderManager::u_vec2(kShaderUniform::PatternOffset, Canvas::I->m_pattern_offset); - ShaderManager::u_float(kShaderUniform::DualAlpha, stroke_material.composite_pass.dual_alpha); + pp::panopainter::setup_legacy_stroke_composite_shader( + pp::panopainter::LegacyStrokeCompositeUniforms { + .resolution = Canvas::I->m_size, + .pattern = { + .scale = patt_scale, + .invert = static_cast(b->m_pattern_invert), + .brightness = b->m_pattern_brightness, + .contrast = b->m_pattern_contrast, + .depth = b->m_pattern_depth, + .blend_mode = b->m_pattern_blend_mode, + .offset = Canvas::I->m_pattern_offset, + }, + .mvp = ortho, + .layer_alpha = m_layers[layer_index]->m_opacity, + .alpha_lock = m_layers[layer_index]->m_alpha_locked, + .mask_enabled = m_smask_active, + .use_fragcoord = false, + .blend_mode = b->m_blend_mode, + .use_dual = stroke_material.composite_pass.use_dual, + .dual_blend_mode = stroke_material.composite_pass.dual_blend_mode, + .dual_alpha = stroke_material.composite_pass.dual_alpha, + .use_pattern = stroke_material.composite_pass.use_pattern, + }); set_active_texture_unit(0); m_layers[layer_index]->rtt(plane_index).bindTexture(); diff --git a/src/legacy_canvas_stroke_composite_services.h b/src/legacy_canvas_stroke_composite_services.h new file mode 100644 index 0000000..262768f --- /dev/null +++ b/src/legacy_canvas_stroke_composite_services.h @@ -0,0 +1,96 @@ +#pragma once + +#include "shader.h" +#include "util.h" + +#include + +namespace pp::panopainter { + +struct LegacyStrokeCompositePatternUniforms { + glm::vec2 scale {}; + float invert = 0.0f; + float brightness = 0.0f; + float contrast = 0.0f; + float depth = 0.0f; + int blend_mode = 0; + glm::vec2 offset {}; +}; + +struct LegacyStrokeCompositeUniforms { + glm::vec2 resolution {}; + LegacyStrokeCompositePatternUniforms pattern; + glm::mat4 mvp { 1.0f }; + float layer_alpha = 1.0f; + bool alpha_lock = false; + bool mask_enabled = false; + bool use_fragcoord = false; + int blend_mode = 0; + bool use_dual = false; + int dual_blend_mode = 0; + float dual_alpha = 0.0f; + bool use_pattern = false; +}; + +struct LegacyStrokeCompositeShaderExecution { + std::function use_shader; + std::function set_int; + std::function set_float; + std::function set_vec2; + std::function set_mat4; +}; + +[[nodiscard]] inline LegacyStrokeCompositeShaderExecution legacy_shader_manager_stroke_composite_execution() noexcept +{ + return { + .use_shader = [](kShader shader) { ShaderManager::use(shader); }, + .set_int = [](kShaderUniform uniform, int value) { ShaderManager::u_int(uniform, value); }, + .set_float = [](kShaderUniform uniform, float value) { ShaderManager::u_float(uniform, value); }, + .set_vec2 = [](kShaderUniform uniform, const glm::vec2& value) { ShaderManager::u_vec2(uniform, value); }, + .set_mat4 = [](kShaderUniform uniform, const glm::mat4& value) { ShaderManager::u_mat4(uniform, value); }, + }; +} + +inline void apply_legacy_stroke_composite_pattern_uniforms( + const LegacyStrokeCompositePatternUniforms& uniforms, + const LegacyStrokeCompositeShaderExecution& execution) noexcept +{ + execution.set_vec2(kShaderUniform::PatternScale, uniforms.scale); + execution.set_float(kShaderUniform::PatternInvert, uniforms.invert); + execution.set_float(kShaderUniform::PatternBright, uniforms.brightness); + execution.set_float(kShaderUniform::PatternContrast, uniforms.contrast); + execution.set_float(kShaderUniform::PatternDepth, uniforms.depth); + execution.set_int(kShaderUniform::PatternBlendMode, uniforms.blend_mode); + execution.set_vec2(kShaderUniform::PatternOffset, uniforms.offset); +} + +inline void setup_legacy_stroke_composite_shader( + const LegacyStrokeCompositeUniforms& uniforms, + const LegacyStrokeCompositeShaderExecution& execution) noexcept +{ + execution.use_shader(kShader::CompDraw); + execution.set_int(kShaderUniform::Tex, 0); + execution.set_int(kShaderUniform::TexStroke, 1); + execution.set_int(kShaderUniform::TexMask, 2); + execution.set_int(kShaderUniform::TexDual, 3); + execution.set_int(kShaderUniform::TexPattern, 4); + execution.set_vec2(kShaderUniform::Resolution, uniforms.resolution); + execution.set_float(kShaderUniform::Alpha, uniforms.layer_alpha); + execution.set_int(kShaderUniform::Lock, uniforms.alpha_lock); + execution.set_int(kShaderUniform::Mask, uniforms.mask_enabled); + execution.set_int(kShaderUniform::UseFragcoord, uniforms.use_fragcoord); + execution.set_int(kShaderUniform::BlendMode, uniforms.blend_mode); + execution.set_mat4(kShaderUniform::MVP, uniforms.mvp); + execution.set_int(kShaderUniform::UseDual, uniforms.use_dual); + execution.set_int(kShaderUniform::UsePattern, uniforms.use_pattern); + execution.set_int(kShaderUniform::DualBlendMode, uniforms.dual_blend_mode); + apply_legacy_stroke_composite_pattern_uniforms(uniforms.pattern, execution); + execution.set_float(kShaderUniform::DualAlpha, uniforms.dual_alpha); +} + +inline void setup_legacy_stroke_composite_shader(const LegacyStrokeCompositeUniforms& uniforms) +{ + setup_legacy_stroke_composite_shader(uniforms, legacy_shader_manager_stroke_composite_execution()); +} + +} // namespace pp::panopainter diff --git a/src/node_stroke_preview.cpp b/src/node_stroke_preview.cpp index b8bdbee..835e5a8 100644 --- a/src/node_stroke_preview.cpp +++ b/src/node_stroke_preview.cpp @@ -6,6 +6,7 @@ #include "bezier.h" #include "canvas.h" #include "app.h" +#include "legacy_canvas_stroke_composite_services.h" #include "legacy_canvas_stroke_execution_services.h" #include "legacy_canvas_stroke_shader_services.h" #include "legacy_canvas_stroke_services.h" @@ -574,29 +575,29 @@ void NodeStrokePreview::draw_stroke_immediate() // COMPOSITE - ShaderManager::use(kShader::CompDraw); - ShaderManager::u_int(kShaderUniform::Tex, 0); - ShaderManager::u_int(kShaderUniform::TexStroke, 1); - ShaderManager::u_int(kShaderUniform::TexMask, 2); - ShaderManager::u_int(kShaderUniform::TexDual, 3); - ShaderManager::u_int(kShaderUniform::TexPattern, 4); - ShaderManager::u_vec2(kShaderUniform::Resolution, size); - ShaderManager::u_float(kShaderUniform::Alpha, 1); - ShaderManager::u_int(kShaderUniform::UseFragcoord, false); - ShaderManager::u_int(kShaderUniform::Mask, false); - ShaderManager::u_int(kShaderUniform::BlendMode, b->m_blend_mode); - ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); - ShaderManager::u_int(kShaderUniform::UseDual, material.composite_pass.use_dual); - ShaderManager::u_int(kShaderUniform::UsePattern, material.composite_pass.use_pattern); - ShaderManager::u_int(kShaderUniform::DualBlendMode, material.composite_pass.dual_blend_mode); - ShaderManager::u_vec2(kShaderUniform::PatternScale, patt_scale); - ShaderManager::u_float(kShaderUniform::PatternInvert, b->m_pattern_invert); - ShaderManager::u_float(kShaderUniform::PatternBright, b->m_pattern_brightness); - ShaderManager::u_float(kShaderUniform::PatternContrast, b->m_pattern_contrast); - ShaderManager::u_float(kShaderUniform::PatternDepth, b->m_pattern_depth); - ShaderManager::u_int(kShaderUniform::PatternBlendMode, material.composite_pass.pattern_blend_mode); - ShaderManager::u_vec2(kShaderUniform::PatternOffset, glm::vec2(b->m_pattern_rand_offset ? 0.5f : 0.0f)); - ShaderManager::u_float(kShaderUniform::DualAlpha, material.composite_pass.dual_alpha); + pp::panopainter::setup_legacy_stroke_composite_shader( + pp::panopainter::LegacyStrokeCompositeUniforms { + .resolution = size, + .pattern = { + .scale = patt_scale, + .invert = static_cast(b->m_pattern_invert), + .brightness = b->m_pattern_brightness, + .contrast = b->m_pattern_contrast, + .depth = b->m_pattern_depth, + .blend_mode = material.composite_pass.pattern_blend_mode, + .offset = glm::vec2(b->m_pattern_rand_offset ? 0.5f : 0.0f), + }, + .mvp = glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f), + .layer_alpha = 1.0f, + .alpha_lock = false, + .mask_enabled = false, + .use_fragcoord = false, + .blend_mode = b->m_blend_mode, + .use_dual = material.composite_pass.use_dual, + .dual_blend_mode = material.composite_pass.dual_blend_mode, + .dual_alpha = material.composite_pass.dual_alpha, + .use_pattern = material.composite_pass.use_pattern, + }); m_sampler_linear.bind(0); m_sampler_linear.bind(1);