diff --git a/src/canvas.cpp b/src/canvas.cpp index 4c8ea8d..c600dc1 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -828,6 +828,54 @@ std::vector Canvas::stroke_draw_compute(Stroke& stroke) con }); } +void Canvas::stroke_draw_pad_pass( + const std::array& pad_faces, + bool copy_stroke_destination, + const std::array& pad_destination_texture_binding, + const pp::panopainter::LegacyCanvasStrokeTextureInputDispatch& pad_destination_texture_dispatch, + const pp::renderer::Extent2D& stroke_extent, + const glm::vec4& pad_color) +{ + pp::panopainter::setup_legacy_stroke_pad_shader( + pp::panopainter::LegacyStrokePadUniforms { + .color = pad_color, + .uses_destination_feedback = copy_stroke_destination, + }); + [[maybe_unused]] const auto pad_result = pp::panopainter::execute_legacy_canvas_stroke_pad_face_callbacks( + pad_faces, + stroke_extent, + copy_stroke_destination, + [&](std::span pad_quad) { + m_brush_shape.update_vertices( + const_cast(pad_quad.data()), + static_cast(pad_quad.size())); + }, + [&](int face_index) { + m_tmp[face_index].bindFramebuffer(); + }, + [&](int) { + pp::panopainter::bind_legacy_canvas_stroke_texture_inputs( + pad_destination_texture_binding, + pad_destination_texture_dispatch); + }, + [&](const pp::paint_renderer::CanvasStrokeCopyRegion& copy_region) { + pp::panopainter::execute_legacy_canvas_stroke_pad_copy_region( + copy_region, + copy_framebuffer_to_texture_2d); + }, + [&](int) { + pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs( + pad_destination_texture_binding, + pad_destination_texture_dispatch); + }, + [&] { + m_brush_shape.draw_fill(); + }, + [&](int face_index) { + m_tmp[face_index].unbindFramebuffer(); + }); +} + void Canvas::stroke_draw() { if (!(m_current_stroke && m_current_stroke->has_sample())) @@ -1064,39 +1112,13 @@ void Canvas::stroke_draw() m_tex[dst_face_index].unbind(); }, 0); - [[maybe_unused]] const auto pad_result = pp::panopainter::execute_legacy_canvas_stroke_pad_face_callbacks( + stroke_draw_pad_pass( pad_faces, - stroke_extent, copy_stroke_destination, - [&](std::span pad_quad) { - m_brush_shape.update_vertices( - const_cast(pad_quad.data()), - static_cast(pad_quad.size())); - }, - [&](int face_index) { - m_tmp[face_index].bindFramebuffer(); - }, - [&](int face_index) { - pp::panopainter::bind_legacy_canvas_stroke_texture_inputs( - pad_destination_texture_binding, - pad_destination_texture_dispatch); - }, - [&](const pp::paint_renderer::CanvasStrokeCopyRegion& copy_region) { - pp::panopainter::execute_legacy_canvas_stroke_pad_copy_region( - copy_region, - copy_framebuffer_to_texture_2d); - }, - [&](int face_index) { - pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs( - pad_destination_texture_binding, - pad_destination_texture_dispatch); - }, - [&] { - m_brush_shape.draw_fill(); - }, - [&](int face_index) { - m_tmp[face_index].unbindFramebuffer(); - }); + pad_destination_texture_binding, + pad_destination_texture_dispatch, + stroke_extent, + pad_color); // DRAW DUAL BRUSH diff --git a/src/canvas.h b/src/canvas.h index f6f683c..4d3c715 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -238,6 +238,15 @@ public: bool project_open_thread(std::string file_path); void inject_xmp(std::string jpg_path); Image thumbnail_generate(int w, int h); + +private: + void stroke_draw_pad_pass( + const std::array& pad_faces, + bool copy_stroke_destination, + const std::array& pad_destination_texture_binding, + const pp::panopainter::LegacyCanvasStrokeTextureInputDispatch& pad_destination_texture_dispatch, + const pp::renderer::Extent2D& stroke_extent, + const glm::vec4& pad_color); 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 63ab5d9..23e1289 100644 --- a/tests/paint_renderer/compositor_tests.cpp +++ b/tests/paint_renderer/compositor_tests.cpp @@ -2009,6 +2009,58 @@ void legacy_canvas_stroke_pad_destination_dispatch_preserves_order(pp::tests::Ha PP_EXPECT(h, steps == expected); } +void legacy_canvas_stroke_pad_face_callbacks_preserve_order(pp::tests::Harness& h) +{ + std::vector steps; + const auto padded_faces = pp::panopainter::execute_legacy_canvas_stroke_pad_face_callbacks( + std::array { + pp::panopainter::LegacyCanvasStrokePadFace { + .index = 2, + .dirty = true, + .pass_dirty_box = glm::vec4(1.f), + }, + }, + pp::renderer::Extent2D { 64U, 32U }, + true, + [&](std::span pad_quad) { + steps.emplace_back("upload:" + std::to_string(pad_quad.size())); + }, + [&](int face_index) { + steps.emplace_back("begin:" + std::to_string(face_index)); + }, + [&](int face_index) { + steps.emplace_back("bind:" + std::to_string(face_index)); + }, + [&](const pp::paint_renderer::CanvasStrokeCopyRegion& copy_region) { + steps.emplace_back( + "copy:" + std::to_string(copy_region.x) + "," + + std::to_string(copy_region.y) + "," + + std::to_string(copy_region.width) + "," + + std::to_string(copy_region.height)); + }, + [&](int face_index) { + steps.emplace_back("unbind:" + std::to_string(face_index)); + }, + [&] { + steps.emplace_back("draw"); + }, + [&](int face_index) { + steps.emplace_back("finish:" + std::to_string(face_index)); + }); + + const std::vector expected { + "upload:6", + "begin:2", + "bind:2", + "copy:0,0,64,32", + "draw", + "unbind:2", + "finish:2", + }; + PP_EXPECT(h, padded_faces == 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(