Share document export readiness reporting

This commit is contained in:
2026-06-05 20:19:46 +02:00
parent 2d33f9d928
commit ebc84373e6
9 changed files with 181 additions and 87 deletions

View File

@@ -252,9 +252,10 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.p
rectangles into full renderer-sized RGBA buffers with layer visibility, rectangles into full renderer-sized RGBA buffers with layer visibility,
opacity, and blend mode applied in document order, then uploading those six opacity, and blend mode applied in document order, then uploading those six
faces through the renderer-neutral `IRenderDevice` texture API using the faces through the renderer-neutral `IRenderDevice` texture API using the
recording backend. It also covers the shared recorded-upload report helper recording backend. It also covers the shared
consumed by CLI and live export-readiness bridges, plus a pure six-face PNG `prepare_document_frame_export_readiness` report consumed by CLI and live
export helper that encodes composited document-frame faces through `pp_assets`. export-readiness bridges, including the recorded upload command summary and
pure six-face PNG export bytes encoded through `pp_assets`.
- `pano_cli simulate-document-export` exposes the same pure document-to-PPI - `pano_cli simulate-document-export` exposes the same pure document-to-PPI
export, asset-level decode, and document reimport path through JSON export, asset-level decode, and document reimport path through JSON
automation and is covered by `pano_cli_simulate_document_export_smoke`. automation and is covered by `pano_cli_simulate_document_export_smoke`.
@@ -271,17 +272,15 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.p
payload-complete or metadata-only snapshots, the same app-core boundary now payload-complete or metadata-only snapshots, the same app-core boundary now
exports through the pure `pp_document` PPI writer and reports generated byte exports through the pure `pp_document` PPI writer and reports generated byte
counts plus decoded dirty-face counts in `ppiExport` JSON. Payload-complete counts plus decoded dirty-face counts in `ppiExport` JSON. Payload-complete
snapshots also feed the active frame through the `pp_paint_renderer` snapshots also feed the active frame through the shared `pp_paint_renderer`
document-frame compositor and renderer-neutral recorded-upload report helper, export-readiness report, reporting texture, transition, command, byte, and
reporting texture, transition, command, byte, and active-frame payload counts active-frame payload counts in `rendererUpload` JSON plus `facePngExport`
in `rendererUpload` JSON. The same payload-complete path also reports readiness, face count, byte count, and payload count. It is covered by
`facePngExport` readiness, face count, byte count, and payload count from the
pure face-PNG export helper. It is covered by
`pano_cli_plan_canvas_document_snapshot_smoke` plus the payload-bearing `pano_cli_plan_canvas_document_snapshot_smoke` plus the payload-bearing
snapshot smoke. snapshot smoke.
- Live equirectangular, layer, animation-frame, and cube-face export adapters - Live equirectangular, layer, animation-frame, and cube-face export adapters
now prepare and log the same payload-bearing canvas document snapshot plus now prepare and log the same payload-bearing canvas document snapshot plus
shared renderer-neutral active-frame upload and face-PNG export reports. shared paint-renderer export-readiness report.
Cube-face export writes the pure document/renderer PNG bytes through the Cube-face export writes the pure document/renderer PNG bytes through the
app-core write/publish executor to the planned retained face filename set and app-core write/publish executor to the planned retained face filename set and
falls back to `Canvas::export_cube_faces` if snapshot capture, PNG generation, falls back to `Canvas::export_cube_faces` if snapshot capture, PNG generation,
@@ -1125,7 +1124,7 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.p
exports, Web prepared-file handoff, and legacy `Canvas` export execution while exports, Web prepared-file handoff, and legacy `Canvas` export execution while
retained renderer/document/platform ownership is tracked by `DEBT-0043`. retained renderer/document/platform ownership is tracked by `DEBT-0043`.
Equirectangular, layer, animation-frame, and cube-face execution now prepare Equirectangular, layer, animation-frame, and cube-face execution now prepare
the document snapshot plus renderer-upload readiness report before those the document snapshot plus shared paint-renderer export-readiness report before those
retained calls; cube-face export writes pure face-PNG bytes to the app-core retained calls; cube-face export writes pure face-PNG bytes to the app-core
planned legacy work-directory face paths through the app-core write/publish planned legacy work-directory face paths through the app-core write/publish
executor before falling back to the retained writer, and depth export remains executor before falling back to the retained writer, and depth export remains

View File

@@ -11,7 +11,7 @@ and validation command.
| Capability | Current Area | Target Owner | Required Tests | | Capability | Current Area | Target Owner | Required Tests |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| PPI open/save | `Canvas`, serializer, dialogs | `pp_document`, `pp_assets`, `pano_cli` | Round-trip tiny project, old-version fixture, corrupt/truncated fixture, live-canvas-to-`pp_document` snapshot projection with captured RGBA8 payloads, pending renderer-readback counts, save-readiness reporting before retained live saves, pure PPI export from payload-complete snapshots, and renderer-neutral active-frame upload from the same snapshot | | PPI open/save | `Canvas`, serializer, dialogs | `pp_document`, `pp_assets`, `pano_cli` | Round-trip tiny project, old-version fixture, corrupt/truncated fixture, live-canvas-to-`pp_document` snapshot projection with captured RGBA8 payloads, pending renderer-readback counts, save-readiness reporting before retained live saves, pure PPI export from payload-complete snapshots, and shared paint-renderer export-readiness reporting from the same snapshot |
| Open-document routing | `App::open_document` | `pp_app_core`, `pano_cli`, `pp_panopainter_ui`, `pp_document`, `pp_assets` | Project/ABR/PPBR route tests, malformed path tests, open-action plan tests, CLI route/action smoke, app open smoke | | Open-document routing | `App::open_document` | `pp_app_core`, `pano_cli`, `pp_panopainter_ui`, `pp_document`, `pp_assets` | Project/ABR/PPBR route tests, malformed path tests, open-action plan tests, CLI route/action smoke, app open smoke |
| Document session decisions | `App::open_document`, `App::request_close`, save hotkeys, file menu, dialogs | `pp_app_core`, `pano_cli`, `pp_panopainter_ui` | Clean/dirty/prompt-open/save/save-as/save-version/save-before-workflow/name/new-document resolution/overwrite/version-target decision tests, CLI session, new-document, document-file, and document-version smoke, app close/open/save/new/browse smoke | | Document session decisions | `App::open_document`, `App::request_close`, save hotkeys, file menu, dialogs | `pp_app_core`, `pano_cli`, `pp_panopainter_ui` | Clean/dirty/prompt-open/save/save-as/save-version/save-before-workflow/name/new-document resolution/overwrite/version-target decision tests, CLI session, new-document, document-file, and document-version smoke, app close/open/save/new/browse smoke |
| Version metadata | `scripts/pre-build.py`, `version.*` | build system, `pp_foundation` | Generated header smoke test, missing-tag behavior | | Version metadata | `scripts/pre-build.py`, `version.*` | build system, `pp_foundation` | Generated header smoke test, missing-tag behavior |
@@ -24,9 +24,9 @@ and validation command.
| Capability | Current Area | Target Owner | Required Tests | | Capability | Current Area | Target Owner | Required Tests |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| PNG/JPEG import | `Image`, `Canvas` import paths | `pp_assets`, `pp_document` | Fixture import, malformed file | | PNG/JPEG import | `Image`, `Canvas` import paths | `pp_assets`, `pp_document` | Fixture import, malformed file |
| PNG/JPEG export | `Canvas`, `Image`, export dialogs | `pp_assets`, `pp_paint_renderer`, `pp_app_core` | Golden output tolerance, export start/target planning tests, live export-adapter document snapshot readiness | | PNG/JPEG export | `Canvas`, `Image`, export dialogs | `pp_assets`, `pp_paint_renderer`, `pp_app_core` | Golden output tolerance, export start/target planning tests, live export-adapter document snapshot readiness through the shared paint-renderer export report |
| Equirectangular import/export | `Canvas`, shaders, RTT, export dialogs | `pp_paint_renderer`, `pp_app_core` | Tiny cube/equirect golden, app-core file target tests, live export-adapter renderer-upload readiness | | Equirectangular import/export | `Canvas`, shaders, RTT, export dialogs | `pp_paint_renderer`, `pp_app_core` | Tiny cube/equirect golden, app-core file target tests, live export-adapter renderer-upload/face-PNG readiness report |
| Cube face export | `Canvas` fallback | `pp_paint_renderer`, `pp_app_core` | Pure six-face document frame composite, renderer texture-upload bridge, pure face-PNG export helper, app-core face filename planning and write/publish service execution, payload-complete canvas-snapshot renderer-upload and face-PNG automation, live document/renderer face-PNG writer with retained Canvas fallback, OpenGL command-plan coverage, six-face golden set | | Cube face export | `Canvas` fallback | `pp_paint_renderer`, `pp_app_core` | Pure six-face document frame composite, renderer texture-upload bridge, shared export-readiness report, app-core face filename planning and write/publish service execution, payload-complete canvas-snapshot renderer-upload and face-PNG automation, live document/renderer face-PNG writer with retained Canvas fallback, OpenGL command-plan coverage, six-face golden set |
| Depth export | `Canvas`, grid tools | `pp_paint_renderer` | Float/readback validation | | Depth export | `Canvas`, grid tools | `pp_paint_renderer` | Float/readback validation |
## Brush And Painting ## Brush And Painting

File diff suppressed because one or more lines are too long

View File

@@ -676,19 +676,17 @@ delegating to retained `Canvas::project_save`; the app-core snapshot boundary
also has a tested pure PPI export helper, and also has a tested pure PPI export helper, and
`pano_cli plan-canvas-document-snapshot` runs that helper for payload-complete `pano_cli plan-canvas-document-snapshot` runs that helper for payload-complete
snapshots and reports generated byte/dirty-face summaries. The same automation snapshots and reports generated byte/dirty-face summaries. The same automation
now feeds payload-complete snapshots through the `pp_paint_renderer` now feeds payload-complete snapshots through the shared
document-frame compositor and renderer-neutral recording upload path, reporting `pp_paint_renderer::prepare_document_frame_export_readiness` report, which
texture, transition, byte, payload, and command counts through the shared records renderer-neutral six-face texture upload commands and encodes the
`record_document_frame_upload` report helper. Payload-complete snapshot active document frame's six composited faces to PNG bytes. This gives CLI
automation also encodes the active document frame's six composited faces to PNG automation and live export adapters the same document/canvas-to-renderer
bytes through `pp_paint_renderer::export_document_frame_face_pngs`, giving the readiness boundary before broader writer replacement. Live save writer
cube-face export path a pure renderer/document writer primitive before live replacement, export adoption, and renderer-owned readback remain under
writer replacement. Live save writer replacement, export adoption, and
renderer-owned readback remain under
`DEBT-0010`/`DEBT-0013`/`DEBT-0036`. `DEBT-0010`/`DEBT-0013`/`DEBT-0036`.
Live equirectangular, layer, animation-frame, and cube-face export adapters now Live equirectangular, layer, animation-frame, and cube-face export adapters now
prepare the same payload-bearing document snapshot and renderer-neutral upload prepare the same payload-bearing document snapshot and shared renderer export
report helper plus pure face-PNG export report. Cube-face export writes those readiness report. Cube-face export writes those
document/renderer-owned PNG bytes through a tested app-core write/publish document/renderer-owned PNG bytes through a tested app-core write/publish
executor using the app-core-planned legacy face filenames when available and executor using the app-core-planned legacy face filenames when available and
falls back to retained `Canvas::export_cube_faces` on snapshot/write failure; falls back to retained `Canvas::export_cube_faces` on snapshot/write failure;
@@ -2523,13 +2521,11 @@ Results:
`pano_cli plan-canvas-document-snapshot` reports `ppiExport` readiness, `pano_cli plan-canvas-document-snapshot` reports `ppiExport` readiness,
byte count, and dirty-face count for agent automation. byte count, and dirty-face count for agent automation.
- Payload-complete canvas snapshot automation also crosses the renderer - Payload-complete canvas snapshot automation also crosses the renderer
boundary now: `pano_cli plan-canvas-document-snapshot` records the same boundary now: `pano_cli plan-canvas-document-snapshot` feeds the same snapshot
snapshot through the pure document-frame compositor and renderer-neutral through `pp_paint_renderer::prepare_document_frame_export_readiness`, which
texture upload stream through `pp_paint_renderer::record_document_frame_upload`, records the renderer-neutral active-frame texture upload stream and encodes
and encodes the composited active-frame cube faces as PNG bytes through the composited active-frame cube faces as PNG bytes, so agents validate the
`pp_paint_renderer::export_document_frame_face_pngs`, so agents can validate same document/canvas-to-renderer readiness report consumed by live export.
document/canvas payloads moving into renderer commands and image bytes before
live canvas export/save writer replacement.
- Live image/collection/cube export adapters now prepare and log the same - Live image/collection/cube export adapters now prepare and log the same
document/canvas plus shared renderer-upload and face-PNG export readiness document/canvas plus shared renderer-upload and face-PNG export readiness
reports. Cube-face export now writes the pure document/renderer PNG bytes to reports. Cube-face export now writes the pure document/renderer PNG bytes to

View File

@@ -104,18 +104,20 @@ pp::foundation::Result<LegacyDocumentExportSnapshotReports> prepare_legacy_docum
return pp::foundation::Result<LegacyDocumentExportSnapshotReports>::success(std::move(reports)); return pp::foundation::Result<LegacyDocumentExportSnapshotReports>::success(std::move(reports));
} }
const auto recorded_upload = pp::paint_renderer::record_document_frame_upload( auto readiness = pp::paint_renderer::prepare_document_frame_export_readiness(
pp::paint_renderer::DocumentFrameUploadRequest { pp::paint_renderer::DocumentFrameCompositeRequest {
.document = &reports.snapshot.document, .document = &reports.snapshot.document,
.frame_index = reports.snapshot.document.active_frame_index(), .frame_index = reports.snapshot.document.active_frame_index(),
.clear_color = {}, .clear_color = {},
}); });
if (!recorded_upload) { if (!readiness) {
LOG("%s document export renderer upload failed: %s", context, recorded_upload.status().message); LOG("%s document export renderer readiness failed: %s", context, readiness.status().message);
return pp::foundation::Result<LegacyDocumentExportSnapshotReports>::failure(recorded_upload.status()); return pp::foundation::Result<LegacyDocumentExportSnapshotReports>::failure(readiness.status());
} }
const auto& uploaded = recorded_upload.value().upload; auto readiness_value = std::move(readiness.value());
const auto& recorded_upload = readiness_value.recorded_upload;
const auto& uploaded = recorded_upload.upload;
LOG( LOG(
"%s document export renderer upload: textures=%zu bytes=%llu transitions=%zu facePayloads=%zu commands=%zu uploadCommands=%zu transitionCommands=%zu", "%s document export renderer upload: textures=%zu bytes=%llu transitions=%zu facePayloads=%zu commands=%zu uploadCommands=%zu transitionCommands=%zu",
context, context,
@@ -123,28 +125,18 @@ pp::foundation::Result<LegacyDocumentExportSnapshotReports> prepare_legacy_docum
static_cast<unsigned long long>(uploaded.uploaded_bytes), static_cast<unsigned long long>(uploaded.uploaded_bytes),
uploaded.transition_count, uploaded.transition_count,
uploaded.composite.face_payload_count, uploaded.composite.face_payload_count,
recorded_upload.value().command_count, recorded_upload.command_count,
recorded_upload.value().upload_command_count, recorded_upload.upload_command_count,
recorded_upload.value().transition_command_count); recorded_upload.transition_command_count);
const auto face_pngs = pp::paint_renderer::export_document_frame_face_pngs(
pp::paint_renderer::DocumentFrameCompositeRequest {
.document = &reports.snapshot.document,
.frame_index = reports.snapshot.document.active_frame_index(),
.clear_color = {},
});
if (!face_pngs) {
LOG("%s document export face PNG export failed: %s", context, face_pngs.status().message);
return pp::foundation::Result<LegacyDocumentExportSnapshotReports>::failure(face_pngs.status());
}
LOG( LOG(
"%s document export face PNG export: faces=%zu bytes=%llu facePayloads=%zu compositedLayerFaces=%zu", "%s document export face PNG export: faces=%zu bytes=%llu facePayloads=%zu compositedLayerFaces=%zu",
context, context,
face_pngs.value().face_count, readiness_value.face_pngs.face_count,
static_cast<unsigned long long>(face_pngs.value().encoded_bytes), static_cast<unsigned long long>(readiness_value.face_pngs.encoded_bytes),
face_pngs.value().composite.face_payload_count, readiness_value.face_pngs.composite.face_payload_count,
face_pngs.value().composite.composited_layer_face_count); readiness_value.face_pngs.composite.composited_layer_face_count);
reports.face_pngs = std::move(face_pngs.value()); reports.face_pngs = std::move(readiness_value.face_pngs);
return pp::foundation::Result<LegacyDocumentExportSnapshotReports>::success(std::move(reports)); return pp::foundation::Result<LegacyDocumentExportSnapshotReports>::success(std::move(reports));
} }

View File

@@ -481,6 +481,29 @@ pp::foundation::Result<DocumentFrameFacePngExportResult> export_document_frame_f
return pp::foundation::Result<DocumentFrameFacePngExportResult>::success(std::move(result)); return pp::foundation::Result<DocumentFrameFacePngExportResult>::success(std::move(result));
} }
pp::foundation::Result<DocumentFrameExportReadinessResult> prepare_document_frame_export_readiness(
DocumentFrameCompositeRequest request)
{
auto recorded_upload = record_document_frame_upload(DocumentFrameUploadRequest {
.document = request.document,
.frame_index = request.frame_index,
.clear_color = request.clear_color,
});
if (!recorded_upload) {
return pp::foundation::Result<DocumentFrameExportReadinessResult>::failure(recorded_upload.status());
}
auto face_pngs = export_document_frame_face_pngs(request);
if (!face_pngs) {
return pp::foundation::Result<DocumentFrameExportReadinessResult>::failure(face_pngs.status());
}
DocumentFrameExportReadinessResult result;
result.recorded_upload = std::move(recorded_upload.value());
result.face_pngs = std::move(face_pngs.value());
return pp::foundation::Result<DocumentFrameExportReadinessResult>::success(std::move(result));
}
bool stroke_composite_requires_feedback( bool stroke_composite_requires_feedback(
pp::paint::BlendMode layer_blend_mode, pp::paint::BlendMode layer_blend_mode,
pp::paint::StrokeBlendMode stroke_blend_mode, pp::paint::StrokeBlendMode stroke_blend_mode,

View File

@@ -146,6 +146,11 @@ struct DocumentFrameFacePngExportResult {
std::uint64_t encoded_bytes = 0; std::uint64_t encoded_bytes = 0;
}; };
struct DocumentFrameExportReadinessResult {
RecordedDocumentFrameUploadResult recorded_upload {};
DocumentFrameFacePngExportResult face_pngs {};
};
[[nodiscard]] pp::foundation::Status composite_layer( [[nodiscard]] pp::foundation::Status composite_layer(
std::span<pp::paint::Rgba> destination, std::span<pp::paint::Rgba> destination,
pp::renderer::Extent2D extent, pp::renderer::Extent2D extent,
@@ -167,6 +172,9 @@ struct DocumentFrameFacePngExportResult {
[[nodiscard]] pp::foundation::Result<DocumentFrameFacePngExportResult> export_document_frame_face_pngs( [[nodiscard]] pp::foundation::Result<DocumentFrameFacePngExportResult> export_document_frame_face_pngs(
DocumentFrameCompositeRequest request); DocumentFrameCompositeRequest request);
[[nodiscard]] pp::foundation::Result<DocumentFrameExportReadinessResult> prepare_document_frame_export_readiness(
DocumentFrameCompositeRequest request);
[[nodiscard]] bool stroke_composite_requires_feedback( [[nodiscard]] bool stroke_composite_requires_feedback(
pp::paint::BlendMode layer_blend_mode, pp::paint::BlendMode layer_blend_mode,
pp::paint::StrokeBlendMode stroke_blend_mode, pp::paint::StrokeBlendMode stroke_blend_mode,

View File

@@ -665,12 +665,83 @@ void exports_document_frame_faces_as_pngs(pp::tests::Harness& h)
} }
} }
void prepares_document_frame_export_readiness_report(pp::tests::Harness& h)
{
const AnimationFrame root_frames[] {
{ .duration_ms = 100, .face_pixels = {} },
};
const AnimationFrame layer_frames[] {
{
.duration_ms = 100,
.face_pixels = {
LayerFacePixels {
.face_index = 2,
.x = 0,
.y = 0,
.width = 1,
.height = 1,
.rgba8 = { 255, 128, 0, 255 },
},
},
},
};
const DocumentLayerConfig layers[] {
{
.name = "Paint",
.frames = std::span<const AnimationFrame>(layer_frames, 1),
},
};
const auto document = CanvasDocument::create_from_snapshot(DocumentSnapshotConfig {
.width = 1,
.height = 1,
.layers = std::span<const DocumentLayerConfig>(layers, 1),
.frames = std::span<const AnimationFrame>(root_frames, 1),
.selection_masks = {},
});
PP_EXPECT(h, document);
if (!document) {
return;
}
const auto readiness = pp::paint_renderer::prepare_document_frame_export_readiness(
DocumentFrameCompositeRequest {
.document = &document.value(),
.frame_index = 0,
.clear_color = {},
});
PP_EXPECT(h, readiness);
if (!readiness) {
return;
}
PP_EXPECT(h, readiness.value().recorded_upload.upload.texture_count == pp::document::cube_face_count);
PP_EXPECT(h, readiness.value().recorded_upload.upload.uploaded_bytes == 24U);
PP_EXPECT(h, readiness.value().recorded_upload.command_count == 12U);
PP_EXPECT(h, readiness.value().recorded_upload.upload_command_count == pp::document::cube_face_count);
PP_EXPECT(h, readiness.value().recorded_upload.transition_command_count == pp::document::cube_face_count);
PP_EXPECT(h, readiness.value().face_pngs.face_count == pp::document::cube_face_count);
PP_EXPECT(h, readiness.value().face_pngs.encoded_bytes > 0U);
PP_EXPECT(h, readiness.value().face_pngs.composite.face_payload_count == 1U);
const auto decoded = pp::assets::decode_png_rgba8(readiness.value().face_pngs.face_pngs[2]);
PP_EXPECT(h, decoded);
if (decoded) {
PP_EXPECT(h, decoded.value().pixels[0] == 255U);
PP_EXPECT(h, decoded.value().pixels[1] == 128U);
PP_EXPECT(h, decoded.value().pixels[2] == 0U);
PP_EXPECT(h, decoded.value().pixels[3] == 255U);
}
}
void document_frame_upload_rejects_invalid_requests(pp::tests::Harness& h) void document_frame_upload_rejects_invalid_requests(pp::tests::Harness& h)
{ {
RecordingRenderDevice device; RecordingRenderDevice device;
const auto no_document = pp::paint_renderer::upload_document_frame_faces( const auto no_document = pp::paint_renderer::upload_document_frame_faces(
device, device,
pp::paint_renderer::DocumentFrameUploadRequest {}); pp::paint_renderer::DocumentFrameUploadRequest {});
const auto no_document_readiness = pp::paint_renderer::prepare_document_frame_export_readiness(
DocumentFrameCompositeRequest {});
const AnimationFrame root_frames[] { const AnimationFrame root_frames[] {
{ .duration_ms = 100, .face_pixels = {} }, { .duration_ms = 100, .face_pixels = {} },
@@ -693,11 +764,20 @@ void document_frame_upload_rejects_invalid_requests(pp::tests::Harness& h)
.document = &document.value(), .document = &document.value(),
.frame_index = 1, .frame_index = 1,
}); });
const auto bad_frame_readiness = pp::paint_renderer::prepare_document_frame_export_readiness(
DocumentFrameCompositeRequest {
.document = &document.value(),
.frame_index = 1,
});
PP_EXPECT(h, !no_document.ok()); PP_EXPECT(h, !no_document.ok());
PP_EXPECT(h, no_document.status().code == StatusCode::invalid_argument); PP_EXPECT(h, no_document.status().code == StatusCode::invalid_argument);
PP_EXPECT(h, !no_document_readiness.ok());
PP_EXPECT(h, no_document_readiness.status().code == StatusCode::invalid_argument);
PP_EXPECT(h, !bad_frame.ok()); PP_EXPECT(h, !bad_frame.ok());
PP_EXPECT(h, bad_frame.status().code == StatusCode::out_of_range); PP_EXPECT(h, bad_frame.status().code == StatusCode::out_of_range);
PP_EXPECT(h, !bad_frame_readiness.ok());
PP_EXPECT(h, bad_frame_readiness.status().code == StatusCode::out_of_range);
PP_EXPECT(h, device.commands().empty()); PP_EXPECT(h, device.commands().empty());
} }
@@ -1048,6 +1128,7 @@ int main()
harness.run("uploads_document_frame_faces_to_renderer_api", uploads_document_frame_faces_to_renderer_api); harness.run("uploads_document_frame_faces_to_renderer_api", uploads_document_frame_faces_to_renderer_api);
harness.run("records_document_frame_upload_report", records_document_frame_upload_report); harness.run("records_document_frame_upload_report", records_document_frame_upload_report);
harness.run("exports_document_frame_faces_as_pngs", exports_document_frame_faces_as_pngs); harness.run("exports_document_frame_faces_as_pngs", exports_document_frame_faces_as_pngs);
harness.run("prepares_document_frame_export_readiness_report", prepares_document_frame_export_readiness_report);
harness.run("document_frame_upload_rejects_invalid_requests", document_frame_upload_rejects_invalid_requests); harness.run("document_frame_upload_rejects_invalid_requests", document_frame_upload_rejects_invalid_requests);
harness.run("detects_feedback_requirements", detects_feedback_requirements); harness.run("detects_feedback_requirements", detects_feedback_requirements);
harness.run("plans_stroke_composite_paths", plans_stroke_composite_paths); harness.run("plans_stroke_composite_paths", plans_stroke_composite_paths);

View File

@@ -6028,42 +6028,32 @@ int plan_canvas_document_snapshot(int argc, char** argv)
ppi_export_bytes = exported.value().bytes.size(); ppi_export_bytes = exported.value().bytes.size();
ppi_export_dirty_faces = decoded.value().project.body.summary.dirty_face_count; ppi_export_dirty_faces = decoded.value().project.body.summary.dirty_face_count;
const auto recorded_upload = pp::paint_renderer::record_document_frame_upload( const auto readiness = pp::paint_renderer::prepare_document_frame_export_readiness(
pp::paint_renderer::DocumentFrameUploadRequest {
.document = &document,
.frame_index = document.active_frame_index(),
.clear_color = {},
});
if (!recorded_upload) {
print_error("plan-canvas-document-snapshot", recorded_upload.status().message);
return 2;
}
renderer_upload_ready = true;
renderer_texture_count = recorded_upload.value().upload.texture_count;
renderer_transition_count = recorded_upload.value().upload.transition_count;
renderer_uploaded_bytes = recorded_upload.value().upload.uploaded_bytes;
renderer_face_payloads = recorded_upload.value().upload.composite.face_payload_count;
renderer_composited_layer_faces = recorded_upload.value().upload.composite.composited_layer_face_count;
renderer_command_count = recorded_upload.value().command_count;
renderer_upload_command_count = recorded_upload.value().upload_command_count;
renderer_transition_command_count = recorded_upload.value().transition_command_count;
const auto face_pngs = pp::paint_renderer::export_document_frame_face_pngs(
pp::paint_renderer::DocumentFrameCompositeRequest { pp::paint_renderer::DocumentFrameCompositeRequest {
.document = &document, .document = &document,
.frame_index = document.active_frame_index(), .frame_index = document.active_frame_index(),
.clear_color = {}, .clear_color = {},
}); });
if (!face_pngs) { if (!readiness) {
print_error("plan-canvas-document-snapshot", face_pngs.status().message); print_error("plan-canvas-document-snapshot", readiness.status().message);
return 2; return 2;
} }
renderer_upload_ready = true;
renderer_texture_count = readiness.value().recorded_upload.upload.texture_count;
renderer_transition_count = readiness.value().recorded_upload.upload.transition_count;
renderer_uploaded_bytes = readiness.value().recorded_upload.upload.uploaded_bytes;
renderer_face_payloads = readiness.value().recorded_upload.upload.composite.face_payload_count;
renderer_composited_layer_faces =
readiness.value().recorded_upload.upload.composite.composited_layer_face_count;
renderer_command_count = readiness.value().recorded_upload.command_count;
renderer_upload_command_count = readiness.value().recorded_upload.upload_command_count;
renderer_transition_command_count = readiness.value().recorded_upload.transition_command_count;
face_png_export_ready = true; face_png_export_ready = true;
face_png_export_faces = face_pngs.value().face_count; face_png_export_faces = readiness.value().face_pngs.face_count;
face_png_export_bytes = face_pngs.value().encoded_bytes; face_png_export_bytes = readiness.value().face_pngs.encoded_bytes;
face_png_export_payloads = face_pngs.value().composite.face_payload_count; face_png_export_payloads = readiness.value().face_pngs.composite.face_payload_count;
} }
std::cout << "{\"ok\":true,\"command\":\"plan-canvas-document-snapshot\"" std::cout << "{\"ok\":true,\"command\":\"plan-canvas-document-snapshot\""