Plan stroke preview composite sequence

This commit is contained in:
2026-06-13 04:40:54 +02:00
parent 36861cbf97
commit c810cc178b
7 changed files with 348 additions and 64 deletions

View File

@@ -25,6 +25,9 @@ using pp::paint_renderer::CanvasStrokeTextureRole;
using pp::paint_renderer::DocumentFaceCompositeRequest;
using pp::paint_renderer::DocumentFrameCompositeRequest;
using pp::paint_renderer::LayerCompositeView;
using pp::paint_renderer::StrokePreviewCompositeRequest;
using pp::paint_renderer::StrokePreviewCompositeStep;
using pp::paint_renderer::StrokePreviewTextureRole;
using pp::paint_renderer::StrokeCompositePath;
using pp::paint_renderer::StrokeCompositeRequest;
using pp::paint_renderer::composite_layer;
@@ -39,6 +42,7 @@ using pp::paint_renderer::plan_canvas_stroke_pad_region;
using pp::paint_renderer::plan_canvas_stroke_rasterization;
using pp::paint_renderer::plan_canvas_stroke_sample_bounds;
using pp::paint_renderer::plan_document_depth_export_render;
using pp::paint_renderer::plan_stroke_preview_composite;
using pp::paint_renderer::plan_stroke_composite;
using pp::paint_renderer::stroke_composite_path_name;
using pp::paint_renderer::stroke_composite_requires_feedback;
@@ -74,6 +78,29 @@ bool has_texture_binding(
return false;
}
bool has_preview_texture_slot(
const pp::paint_renderer::StrokePreviewCompositePlan& plan,
StrokePreviewTextureRole role,
std::uint8_t slot)
{
for (std::size_t i = 0; i < plan.texture_slot_count; ++i) {
if (plan.texture_slots[i].role == role && plan.texture_slots[i].slot == slot) {
return true;
}
}
return false;
}
void expect_preview_sequence(pp::tests::Harness& h, const pp::paint_renderer::StrokePreviewCompositePlan& plan)
{
PP_EXPECT(h, plan.step_count == 5U);
PP_EXPECT(h, plan.steps[0] == StrokePreviewCompositeStep::checkerboard_background);
PP_EXPECT(h, plan.steps[1] == StrokePreviewCompositeStep::capture_background_texture);
PP_EXPECT(h, plan.steps[2] == StrokePreviewCompositeStep::bind_final_composite_inputs);
PP_EXPECT(h, plan.steps[3] == StrokePreviewCompositeStep::final_composite_draw);
PP_EXPECT(h, plan.steps[4] == StrokePreviewCompositeStep::copy_preview_texture);
}
std::vector<std::uint8_t> solid_rgba8(
std::uint32_t width,
std::uint32_t height,
@@ -1665,6 +1692,71 @@ void plans_canvas_stroke_dual_material_intent(pp::tests::Harness& h)
PP_EXPECT(h, has_texture_binding(dual_composite_pattern, CanvasStrokeTextureRole::pattern, 2));
}
void plans_stroke_preview_composite_for_simple_brush(pp::tests::Harness& h)
{
const auto plan = plan_stroke_preview_composite(StrokePreviewCompositeRequest {});
expect_preview_sequence(h, plan);
PP_EXPECT(h, !plan.uses_mixer);
PP_EXPECT(h, !plan.uses_dual);
PP_EXPECT(h, !plan.uses_pattern);
PP_EXPECT(h, plan.texture_slot_count == 2U);
PP_EXPECT(h, has_preview_texture_slot(plan, StrokePreviewTextureRole::background, 0));
PP_EXPECT(h, has_preview_texture_slot(plan, StrokePreviewTextureRole::stroke, 1));
PP_EXPECT(h, !has_preview_texture_slot(plan, StrokePreviewTextureRole::mask, 2));
}
void plans_stroke_preview_composite_with_mixer_input(pp::tests::Harness& h)
{
const auto plan = plan_stroke_preview_composite(
StrokePreviewCompositeRequest {
.uses_mixer = true,
});
expect_preview_sequence(h, plan);
PP_EXPECT(h, plan.uses_mixer);
PP_EXPECT(h, !plan.uses_dual);
PP_EXPECT(h, !plan.uses_pattern);
PP_EXPECT(h, plan.texture_slot_count == 3U);
PP_EXPECT(h, has_preview_texture_slot(plan, StrokePreviewTextureRole::background, 0));
PP_EXPECT(h, has_preview_texture_slot(plan, StrokePreviewTextureRole::stroke, 1));
PP_EXPECT(h, has_preview_texture_slot(plan, StrokePreviewTextureRole::mixer, 3));
}
void plans_stroke_preview_composite_with_dual_input(pp::tests::Harness& h)
{
const auto plan = plan_stroke_preview_composite(
StrokePreviewCompositeRequest {
.uses_dual = true,
});
expect_preview_sequence(h, plan);
PP_EXPECT(h, !plan.uses_mixer);
PP_EXPECT(h, plan.uses_dual);
PP_EXPECT(h, !plan.uses_pattern);
PP_EXPECT(h, plan.texture_slot_count == 3U);
PP_EXPECT(h, has_preview_texture_slot(plan, StrokePreviewTextureRole::background, 0));
PP_EXPECT(h, has_preview_texture_slot(plan, StrokePreviewTextureRole::stroke, 1));
PP_EXPECT(h, has_preview_texture_slot(plan, StrokePreviewTextureRole::dual, 3));
}
void plans_stroke_preview_composite_with_pattern_input(pp::tests::Harness& h)
{
const auto plan = plan_stroke_preview_composite(
StrokePreviewCompositeRequest {
.uses_pattern = true,
});
expect_preview_sequence(h, plan);
PP_EXPECT(h, !plan.uses_mixer);
PP_EXPECT(h, !plan.uses_dual);
PP_EXPECT(h, plan.uses_pattern);
PP_EXPECT(h, plan.texture_slot_count == 3U);
PP_EXPECT(h, has_preview_texture_slot(plan, StrokePreviewTextureRole::background, 0));
PP_EXPECT(h, has_preview_texture_slot(plan, StrokePreviewTextureRole::stroke, 1));
PP_EXPECT(h, has_preview_texture_slot(plan, StrokePreviewTextureRole::pattern, 4));
}
void plans_canvas_blend_gate_from_persisted_indices(pp::tests::Harness& h)
{
const std::vector<int> normal_layers { 0, 0, 0 };
@@ -2086,6 +2178,10 @@ int main()
harness.run("rejects_bad_stroke_composite_plans", rejects_bad_stroke_composite_plans);
harness.run("plans_canvas_stroke_material_passes", plans_canvas_stroke_material_passes);
harness.run("plans_canvas_stroke_dual_material_intent", plans_canvas_stroke_dual_material_intent);
harness.run("plans_stroke_preview_composite_for_simple_brush", plans_stroke_preview_composite_for_simple_brush);
harness.run("plans_stroke_preview_composite_with_mixer_input", plans_stroke_preview_composite_with_mixer_input);
harness.run("plans_stroke_preview_composite_with_dual_input", plans_stroke_preview_composite_with_dual_input);
harness.run("plans_stroke_preview_composite_with_pattern_input", plans_stroke_preview_composite_with_pattern_input);
harness.run("plans_canvas_blend_gate_from_persisted_indices", plans_canvas_blend_gate_from_persisted_indices);
harness.run("canvas_blend_gate_preserves_legacy_fallbacks", canvas_blend_gate_preserves_legacy_fallbacks);
harness.run("plans_canvas_stroke_feedback_paths", plans_canvas_stroke_feedback_paths);