diff --git a/src/canvas.cpp b/src/canvas.cpp index c4cd356..ee0b4f3 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -571,6 +571,17 @@ glm::vec4 Canvas::stroke_draw_samples( .slot = 1, }, }; + const pp::panopainter::LegacyCanvasStrokeTextureInputDispatch destination_texture_dispatch { + .activate_texture_unit = [&](int texture_slot) { + set_active_texture_unit(texture_slot); + }, + .bind_stroke_destination = [&] { + m_tex[i].bind(); // bg, copy of framebuffer (copied before drawing) + }, + .unbind_stroke_destination = [&] { + m_tex[i].unbind(); + }, + }; const auto result = pp::panopainter::execute_legacy_canvas_stroke_face_sample_polygon( pp::panopainter::LegacyStrokeFaceSamplePolygonExecutionRequest { .context = "Canvas::stroke_draw_samples", @@ -578,18 +589,6 @@ glm::vec4 Canvas::stroke_draw_samples( .polygon_vertices = P, .face_index = i, .copy_stroke_destination = copy_stroke_destination, - .bind_destination_texture = [&](int face_index) { - pp::panopainter::bind_legacy_canvas_stroke_texture_inputs( - destination_texture_binding, - pp::panopainter::LegacyCanvasStrokeTextureInputDispatch { - .activate_texture_unit = [&](int texture_slot) { - set_active_texture_unit(texture_slot); - }, - .bind_stroke_destination = [&] { - m_tex[face_index].bind(); // bg, copy of framebuffer (copied before drawing) - }, - }); - }, .copy_framebuffer_to_destination_texture = []( int, int src_x, @@ -600,18 +599,6 @@ glm::vec4 Canvas::stroke_draw_samples( int height) { copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height); }, - .unbind_destination_texture = [&](int face_index) { - pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs( - destination_texture_binding, - pp::panopainter::LegacyCanvasStrokeTextureInputDispatch { - .activate_texture_unit = [&](int texture_slot) { - set_active_texture_unit(texture_slot); - }, - .unbind_stroke_destination = [&] { - m_tex[face_index].unbind(); - }, - }); - }, .upload_brush_vertices = [&](int, std::span vertices) { m_brush_shape.update_vertices( const_cast(vertices.data()), @@ -620,7 +607,9 @@ glm::vec4 Canvas::stroke_draw_samples( .draw_brush_shape = [&](int) { m_brush_shape.draw_fill(); }, - }); + }, + destination_texture_binding, + destination_texture_dispatch); return result.dirty_bounds; } diff --git a/src/legacy_canvas_stroke_execution_services.h b/src/legacy_canvas_stroke_execution_services.h index ba2ea4a..2dea4b1 100644 --- a/src/legacy_canvas_stroke_execution_services.h +++ b/src/legacy_canvas_stroke_execution_services.h @@ -1031,6 +1031,36 @@ template +[[nodiscard]] inline LegacyStrokeSampleExecutionResult execute_legacy_canvas_stroke_face_sample_polygon( + const LegacyStrokeFaceSamplePolygonExecutionRequest& request, + const std::array& destination_texture_bindings, + const LegacyCanvasStrokeTextureInputDispatch& destination_texture_dispatch) +{ + return execute_legacy_canvas_stroke_face_sample_polygon( + LegacyStrokeFaceSamplePolygonExecutionRequest { + .context = request.context, + .target_size = request.target_size, + .polygon_vertices = request.polygon_vertices, + .face_index = request.face_index, + .copy_stroke_destination = request.copy_stroke_destination, + .bind_destination_texture = [&](int) { + bind_legacy_canvas_stroke_texture_inputs( + destination_texture_bindings, + destination_texture_dispatch); + }, + .copy_framebuffer_to_destination_texture = + request.copy_framebuffer_to_destination_texture, + .unbind_destination_texture = [&](int) { + unbind_legacy_canvas_stroke_texture_inputs( + destination_texture_bindings, + destination_texture_dispatch); + }, + .upload_brush_vertices = request.upload_brush_vertices, + .draw_brush_shape = request.draw_brush_shape, + }); +} + [[nodiscard]] inline LegacyCanvasStrokeMixPassResult execute_legacy_canvas_stroke_mix_pass( const LegacyCanvasStrokeMixPassRequest& request) { diff --git a/tests/paint_renderer/stroke_execution_tests.cpp b/tests/paint_renderer/stroke_execution_tests.cpp index 76688ac..20e1344 100644 --- a/tests/paint_renderer/stroke_execution_tests.cpp +++ b/tests/paint_renderer/stroke_execution_tests.cpp @@ -408,6 +408,65 @@ void retained_stroke_face_sample_polygon_triangulates_and_forwards_face_callback } } +void retained_stroke_face_sample_polygon_skips_destination_callbacks_when_copy_is_disabled(pp::tests::Harness& h) +{ + const auto polygon_vertices = make_polygon_vertices({ + glm::vec2(8.0F, 9.0F), + glm::vec2(18.0F, 9.0F), + glm::vec2(13.0F, 21.0F), + }); + + int bind_face_index = -1; + int copy_face_index = -1; + int unbind_face_index = -1; + int upload_face_index = -1; + int draw_face_index = -1; + int bind_calls = 0; + int copy_calls = 0; + int unbind_calls = 0; + std::size_t uploaded_vertex_count = 0; + + const auto result = pp::panopainter::execute_legacy_canvas_stroke_face_sample_polygon( + pp::panopainter::LegacyStrokeFaceSamplePolygonExecutionRequest { + .context = "test", + .target_size = glm::vec2(64.0F, 64.0F), + .polygon_vertices = polygon_vertices, + .face_index = 3, + .copy_stroke_destination = false, + .bind_destination_texture = [&](int face_index) { + ++bind_calls; + bind_face_index = face_index; + }, + .copy_framebuffer_to_destination_texture = + [&](int face_index, int, int, int, int, int, int) { + ++copy_calls; + copy_face_index = face_index; + }, + .unbind_destination_texture = [&](int face_index) { + ++unbind_calls; + unbind_face_index = face_index; + }, + .upload_brush_vertices = [&](int face_index, std::span vertices) { + upload_face_index = face_index; + uploaded_vertex_count = vertices.size(); + }, + .draw_brush_shape = [&](int face_index) { + draw_face_index = face_index; + }, + }); + + PP_EXPECT(h, result.ok); + PP_EXPECT(h, bind_calls == 0); + PP_EXPECT(h, copy_calls == 0); + PP_EXPECT(h, unbind_calls == 0); + PP_EXPECT(h, upload_face_index == 3); + PP_EXPECT(h, draw_face_index == 3); + PP_EXPECT(h, uploaded_vertex_count == 3U); + PP_EXPECT(h, bind_face_index == -1); + PP_EXPECT(h, copy_face_index == -1); + PP_EXPECT(h, unbind_face_index == -1); +} + struct StrokeFrame { int id = -1; std::array, 6> shapes {}; @@ -1185,6 +1244,9 @@ int main() harness.run( "retained_stroke_face_sample_polygon_triangulates_and_forwards_face_callbacks", retained_stroke_face_sample_polygon_triangulates_and_forwards_face_callbacks); + harness.run( + "retained_stroke_face_sample_polygon_skips_destination_callbacks_when_copy_is_disabled", + retained_stroke_face_sample_polygon_skips_destination_callbacks_when_copy_is_disabled); harness.run( "retained_stroke_frame_samples_preserve_frame_face_callback_order", retained_stroke_frame_samples_preserve_frame_face_callback_order);