diff --git a/src/canvas.cpp b/src/canvas.cpp index c600dc1..9830223 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -876,6 +876,58 @@ void Canvas::stroke_draw_pad_pass( }); } +void Canvas::stroke_draw_dual_pass( + const std::vector& frames_dual, + const std::array& dual_pass_texture_bindings, + const pp::panopainter::LegacyCanvasStrokeTextureInputDispatch& dual_pass_brush_tip_dispatch, + const pp::renderer::Extent2D& stroke_extent, + const std::array& include_dual_dirty, + bool uses_pattern, + bool copy_stroke_destination) +{ + [[maybe_unused]] const auto dual_result = + pp::panopainter::execute_legacy_canvas_stroke_dual_pass( + pp::panopainter::LegacyCanvasStrokeDualPassRequest { + .context = "Canvas::stroke_draw", + .bind_brush_tip = [&] { + pp::panopainter::bind_legacy_canvas_stroke_texture_inputs( + dual_pass_texture_bindings, + dual_pass_brush_tip_dispatch); + }, + .unbind_brush_tip = [&] { + pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs( + dual_pass_texture_bindings, + dual_pass_brush_tip_dispatch); + }, + .setup_dual_shader = [&] { + pp::panopainter::setup_legacy_canvas_stroke_dual_shader( + uses_pattern); + }, + .execute_frame_pass = [&] { + pp::panopainter::execute_legacy_canvas_stroke_dual_pass_frame_callbacks( + frames_dual, + stroke_extent, + std::span(m_dirty_box), + std::span(), + std::span(include_dual_dirty), + [&](auto& f) { + pp::panopainter::apply_legacy_stroke_sample_uniforms( + pp::panopainter::LegacyStrokeSampleUniforms { + .color = f.col, + .alpha = f.flow, + .opacity = f.opacity, + }); + }, + [](auto&, int, auto&) {}, + [&](auto&, int i, auto& P) { + return stroke_draw_samples(i, P, copy_stroke_destination); + }, + m_tmp_dual, + true); + }, + }); +} + void Canvas::stroke_draw() { if (!(m_current_stroke && m_current_stroke->has_sample())) @@ -1150,47 +1202,14 @@ void Canvas::stroke_draw() auto frames_dual = stroke_draw_compute(*m_dual_stroke); const std::array include_dual_dirty = SIXPLETTE(stroke_material.composite_pass.dual_blend_mode == 0); - [[maybe_unused]] const auto dual_result = - pp::panopainter::execute_legacy_canvas_stroke_dual_pass( - pp::panopainter::LegacyCanvasStrokeDualPassRequest { - .context = "Canvas::stroke_draw", - .bind_brush_tip = [&] { - pp::panopainter::bind_legacy_canvas_stroke_texture_inputs( - dual_pass_texture_bindings, - dual_pass_brush_tip_dispatch); - }, - .unbind_brush_tip = [&] { - pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs( - dual_pass_texture_bindings, - dual_pass_brush_tip_dispatch); - }, - .setup_dual_shader = [&] { - pp::panopainter::setup_legacy_canvas_stroke_dual_shader( - stroke_material.dual_pass.uses_pattern); - }, - .execute_frame_pass = [&] { - pp::panopainter::execute_legacy_canvas_stroke_dual_pass_frame_callbacks( - frames_dual, - stroke_extent, - std::span(m_dirty_box), - std::span(), - std::span(include_dual_dirty), - [&](auto& f) { - pp::panopainter::apply_legacy_stroke_sample_uniforms( - pp::panopainter::LegacyStrokeSampleUniforms { - .color = f.col, - .alpha = f.flow, - .opacity = f.opacity, - }); - }, - [](auto&, int, auto&) {}, - [&](auto&, int i, auto& P) { - return stroke_draw_samples(i, P, copy_stroke_destination); - }, - m_tmp_dual, - true); - }, - }); + stroke_draw_dual_pass( + frames_dual, + dual_pass_texture_bindings, + dual_pass_brush_tip_dispatch, + stroke_extent, + include_dual_dirty, + stroke_material.dual_pass.uses_pattern, + copy_stroke_destination); } pp::panopainter::unbind_legacy_canvas_stroke_sampler_inputs( diff --git a/src/canvas.h b/src/canvas.h index 4d3c715..1963cf9 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -247,6 +247,14 @@ private: const pp::panopainter::LegacyCanvasStrokeTextureInputDispatch& pad_destination_texture_dispatch, const pp::renderer::Extent2D& stroke_extent, const glm::vec4& pad_color); + void stroke_draw_dual_pass( + const std::vector& frames_dual, + const std::array& dual_pass_texture_bindings, + const pp::panopainter::LegacyCanvasStrokeTextureInputDispatch& dual_pass_brush_tip_dispatch, + const pp::renderer::Extent2D& stroke_extent, + const std::array& include_dual_dirty, + bool uses_pattern, + bool copy_stroke_destination); Image thumbnail_read(std::string file_path); void draw_objects(std::function, int frame, bool save_history); void draw_objects(std::function, Layer& layer, int frame, bool save_history); diff --git a/tests/paint_renderer/compositor_tests.cpp b/tests/paint_renderer/compositor_tests.cpp index 23e1289..7f2e84f 100644 --- a/tests/paint_renderer/compositor_tests.cpp +++ b/tests/paint_renderer/compositor_tests.cpp @@ -2061,6 +2061,37 @@ void legacy_canvas_stroke_pad_face_callbacks_preserve_order(pp::tests::Harness& PP_EXPECT(h, steps == expected); } +void legacy_canvas_stroke_dual_pass_request_preserves_order(pp::tests::Harness& h) +{ + std::vector steps; + const auto result = pp::panopainter::execute_legacy_canvas_stroke_dual_pass( + pp::panopainter::LegacyCanvasStrokeDualPassRequest { + .context = "compositor-test", + .bind_brush_tip = [&] { + steps.emplace_back("bind"); + }, + .unbind_brush_tip = [&] { + steps.emplace_back("unbind"); + }, + .setup_dual_shader = [&] { + steps.emplace_back("setup"); + }, + .execute_frame_pass = [&] { + steps.emplace_back("frame"); + }, + }); + + const std::vector expected { + "setup", + "bind", + "frame", + "unbind", + }; + PP_EXPECT(h, result.ok); + PP_EXPECT(h, result.composed_planes == 1U); + PP_EXPECT(h, steps == expected); +} + void plans_canvas_stroke_commit_erase_sequence(pp::tests::Harness& h) { const auto plan = plan_canvas_stroke_commit_sequence( @@ -3939,6 +3970,9 @@ int main() harness.run( "legacy_canvas_stroke_dual_pass_brush_tip_dispatch_preserves_order", legacy_canvas_stroke_dual_pass_brush_tip_dispatch_preserves_order); + harness.run( + "legacy_canvas_stroke_dual_pass_request_preserves_order", + legacy_canvas_stroke_dual_pass_request_preserves_order); harness.run( "legacy_canvas_stroke_pad_copy_region_preserves_coordinates", legacy_canvas_stroke_pad_copy_region_preserves_coordinates);