Plan stroke commit sequencing

This commit is contained in:
2026-06-13 04:51:16 +02:00
parent cc67159784
commit b889f26443
7 changed files with 337 additions and 0 deletions

View File

@@ -16,6 +16,9 @@ using pp::paint::StrokeBlendMode;
using pp::assets::decode_png_rgba8;
using pp::paint_renderer::CanvasBlendGateRequest;
using pp::paint_renderer::CanvasStrokeBox;
using pp::paint_renderer::CanvasStrokeCommitRequest;
using pp::paint_renderer::CanvasStrokeCommitStep;
using pp::paint_renderer::CanvasStrokeCommitTextureRole;
using pp::paint_renderer::CanvasStrokeFaceDirtyUpdateRequest;
using pp::paint_renderer::CanvasStrokeMaterialRequest;
using pp::paint_renderer::CanvasStrokePadRegionRequest;
@@ -37,6 +40,7 @@ using pp::paint_renderer::export_document_depth_pngs;
using pp::paint_renderer::plan_canvas_blend_gate;
using pp::paint_renderer::plan_canvas_stroke_face_dirty_update;
using pp::paint_renderer::plan_canvas_stroke_feedback;
using pp::paint_renderer::plan_canvas_stroke_commit_sequence;
using pp::paint_renderer::plan_canvas_stroke_material;
using pp::paint_renderer::plan_canvas_stroke_pad_region;
using pp::paint_renderer::plan_canvas_stroke_rasterization;
@@ -91,6 +95,19 @@ bool has_preview_texture_slot(
return false;
}
bool has_commit_texture_binding(
const pp::paint_renderer::CanvasStrokeCommitSequencePlan& plan,
CanvasStrokeCommitTextureRole role,
std::uint8_t slot)
{
for (std::size_t i = 0; i < plan.texture_binding_count; ++i) {
if (plan.texture_bindings[i].role == role && plan.texture_bindings[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);
@@ -101,6 +118,17 @@ void expect_preview_sequence(pp::tests::Harness& h, const pp::paint_renderer::St
PP_EXPECT(h, plan.steps[4] == StrokePreviewCompositeStep::copy_preview_texture);
}
void expect_commit_prefix(pp::tests::Harness& h, const pp::paint_renderer::CanvasStrokeCommitSequencePlan& plan)
{
PP_EXPECT(h, plan.step_count == 7U);
PP_EXPECT(h, plan.steps[0] == CanvasStrokeCommitStep::readback_history_region);
PP_EXPECT(h, plan.steps[1] == CanvasStrokeCommitStep::update_layer_dirty_state);
PP_EXPECT(h, plan.steps[2] == CanvasStrokeCommitStep::copy_layer_rtt_to_scratch);
PP_EXPECT(h, plan.steps[3] == CanvasStrokeCommitStep::bind_commit_inputs);
PP_EXPECT(h, plan.steps[5] == CanvasStrokeCommitStep::copy_committed_rtt_to_scratch);
PP_EXPECT(h, plan.steps[6] == CanvasStrokeCommitStep::dilate_edges_draw);
}
std::vector<std::uint8_t> solid_rgba8(
std::uint32_t width,
std::uint32_t height,
@@ -1692,6 +1720,62 @@ 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_canvas_stroke_commit_erase_sequence(pp::tests::Harness& h)
{
const auto plan = plan_canvas_stroke_commit_sequence(
CanvasStrokeCommitRequest {
.erase_mode = true,
.alpha_locked = true,
.selection_mask_active = true,
.dual_stroke_enabled = true,
.pattern_enabled = true,
});
expect_commit_prefix(h, plan);
PP_EXPECT(h, plan.steps[4] == CanvasStrokeCommitStep::erase_draw);
PP_EXPECT(h, plan.erase_mode);
PP_EXPECT(h, plan.alpha_locked);
PP_EXPECT(h, plan.selection_mask_active);
PP_EXPECT(h, !plan.uses_dual_stroke);
PP_EXPECT(h, !plan.uses_pattern);
PP_EXPECT(h, plan.requires_history_readback);
PP_EXPECT(h, !plan.updates_layer_bounds);
PP_EXPECT(h, plan.requires_layer_scratch_copy);
PP_EXPECT(h, plan.requires_committed_scratch_copy);
PP_EXPECT(h, plan.requires_dilate);
PP_EXPECT(h, plan.texture_binding_count == 3U);
PP_EXPECT(h, has_commit_texture_binding(plan, CanvasStrokeCommitTextureRole::layer_scratch, 0));
PP_EXPECT(h, has_commit_texture_binding(plan, CanvasStrokeCommitTextureRole::stroke, 1));
PP_EXPECT(h, has_commit_texture_binding(plan, CanvasStrokeCommitTextureRole::selection_mask, 2));
}
void plans_canvas_stroke_commit_composite_sequence(pp::tests::Harness& h)
{
const auto plan = plan_canvas_stroke_commit_sequence(
CanvasStrokeCommitRequest {
.erase_mode = false,
.alpha_locked = false,
.selection_mask_active = true,
.dual_stroke_enabled = true,
.pattern_enabled = true,
});
expect_commit_prefix(h, plan);
PP_EXPECT(h, plan.steps[4] == CanvasStrokeCommitStep::composite_draw);
PP_EXPECT(h, !plan.erase_mode);
PP_EXPECT(h, !plan.alpha_locked);
PP_EXPECT(h, plan.selection_mask_active);
PP_EXPECT(h, plan.uses_dual_stroke);
PP_EXPECT(h, plan.uses_pattern);
PP_EXPECT(h, plan.updates_layer_bounds);
PP_EXPECT(h, plan.texture_binding_count == 5U);
PP_EXPECT(h, has_commit_texture_binding(plan, CanvasStrokeCommitTextureRole::layer_scratch, 0));
PP_EXPECT(h, has_commit_texture_binding(plan, CanvasStrokeCommitTextureRole::stroke, 1));
PP_EXPECT(h, has_commit_texture_binding(plan, CanvasStrokeCommitTextureRole::selection_mask, 2));
PP_EXPECT(h, has_commit_texture_binding(plan, CanvasStrokeCommitTextureRole::dual_stroke, 3));
PP_EXPECT(h, has_commit_texture_binding(plan, CanvasStrokeCommitTextureRole::pattern, 4));
}
void plans_stroke_preview_composite_for_simple_brush(pp::tests::Harness& h)
{
const auto plan = plan_stroke_preview_composite(StrokePreviewCompositeRequest {});
@@ -2178,6 +2262,8 @@ 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_canvas_stroke_commit_erase_sequence", plans_canvas_stroke_commit_erase_sequence);
harness.run("plans_canvas_stroke_commit_composite_sequence", plans_canvas_stroke_commit_composite_sequence);
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);