Plan stroke commit sequencing
This commit is contained in:
129
src/legacy_canvas_stroke_commit_services.h
Normal file
129
src/legacy_canvas_stroke_commit_services.h
Normal file
@@ -0,0 +1,129 @@
|
||||
#pragma once
|
||||
|
||||
#include "paint_renderer/compositor.h"
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <string_view>
|
||||
|
||||
namespace pp::panopainter {
|
||||
|
||||
struct LegacyCanvasStrokeCommitFace {
|
||||
int index = 0;
|
||||
bool dirty = false;
|
||||
};
|
||||
|
||||
struct LegacyCanvasStrokeCommitCallbacks {
|
||||
std::function<void()> mark_commit_started;
|
||||
std::function<void()> capture_render_state;
|
||||
std::function<void()> prepare_render_state;
|
||||
std::function<void()> restore_render_state;
|
||||
std::function<void()> publish_history;
|
||||
std::function<void()> capture_timelapse_frame;
|
||||
|
||||
std::function<void(int)> bind_layer_framebuffer;
|
||||
std::function<void(int)> capture_history_region;
|
||||
std::function<void(int)> apply_layer_dirty_region;
|
||||
std::function<void(int)> copy_layer_to_commit_destination;
|
||||
std::function<void(int)> bind_commit_inputs;
|
||||
std::function<void(int)> execute_erase_composite;
|
||||
std::function<void(int)> execute_paint_composite;
|
||||
std::function<void(int)> copy_committed_to_dilate_source;
|
||||
std::function<void(int)> execute_commit_dilate;
|
||||
std::function<void(int)> unbind_layer_framebuffer;
|
||||
};
|
||||
|
||||
struct LegacyCanvasStrokeCommitRequest {
|
||||
std::string_view context;
|
||||
std::array<LegacyCanvasStrokeCommitFace, 6> faces {};
|
||||
pp::paint_renderer::CanvasStrokeCommitSequencePlan sequence;
|
||||
LegacyCanvasStrokeCommitCallbacks callbacks;
|
||||
};
|
||||
|
||||
struct LegacyCanvasStrokeCommitResult {
|
||||
bool ok = false;
|
||||
int committed_faces = 0;
|
||||
};
|
||||
|
||||
[[nodiscard]] inline bool legacy_canvas_stroke_commit_callbacks_ready(
|
||||
const LegacyCanvasStrokeCommitCallbacks& callbacks) noexcept
|
||||
{
|
||||
return callbacks.mark_commit_started &&
|
||||
callbacks.capture_render_state &&
|
||||
callbacks.prepare_render_state &&
|
||||
callbacks.restore_render_state &&
|
||||
callbacks.publish_history &&
|
||||
callbacks.capture_timelapse_frame &&
|
||||
callbacks.bind_layer_framebuffer &&
|
||||
callbacks.capture_history_region &&
|
||||
callbacks.apply_layer_dirty_region &&
|
||||
callbacks.copy_layer_to_commit_destination &&
|
||||
callbacks.bind_commit_inputs &&
|
||||
callbacks.execute_erase_composite &&
|
||||
callbacks.execute_paint_composite &&
|
||||
callbacks.copy_committed_to_dilate_source &&
|
||||
callbacks.execute_commit_dilate &&
|
||||
callbacks.unbind_layer_framebuffer;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline LegacyCanvasStrokeCommitResult execute_legacy_canvas_stroke_commit_sequence(
|
||||
const LegacyCanvasStrokeCommitRequest& request)
|
||||
{
|
||||
LegacyCanvasStrokeCommitResult result;
|
||||
if (!legacy_canvas_stroke_commit_callbacks_ready(request.callbacks)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
request.callbacks.mark_commit_started();
|
||||
request.callbacks.capture_render_state();
|
||||
request.callbacks.prepare_render_state();
|
||||
|
||||
for (const auto& face : request.faces) {
|
||||
if (!face.dirty) {
|
||||
continue;
|
||||
}
|
||||
|
||||
request.callbacks.bind_layer_framebuffer(face.index);
|
||||
|
||||
for (std::size_t step_index = 0; step_index < request.sequence.step_count; ++step_index) {
|
||||
switch (request.sequence.steps[step_index]) {
|
||||
case pp::paint_renderer::CanvasStrokeCommitStep::readback_history_region:
|
||||
request.callbacks.capture_history_region(face.index);
|
||||
break;
|
||||
case pp::paint_renderer::CanvasStrokeCommitStep::update_layer_dirty_state:
|
||||
request.callbacks.apply_layer_dirty_region(face.index);
|
||||
break;
|
||||
case pp::paint_renderer::CanvasStrokeCommitStep::copy_layer_rtt_to_scratch:
|
||||
request.callbacks.copy_layer_to_commit_destination(face.index);
|
||||
break;
|
||||
case pp::paint_renderer::CanvasStrokeCommitStep::bind_commit_inputs:
|
||||
request.callbacks.bind_commit_inputs(face.index);
|
||||
break;
|
||||
case pp::paint_renderer::CanvasStrokeCommitStep::erase_draw:
|
||||
request.callbacks.execute_erase_composite(face.index);
|
||||
break;
|
||||
case pp::paint_renderer::CanvasStrokeCommitStep::composite_draw:
|
||||
request.callbacks.execute_paint_composite(face.index);
|
||||
break;
|
||||
case pp::paint_renderer::CanvasStrokeCommitStep::copy_committed_rtt_to_scratch:
|
||||
request.callbacks.copy_committed_to_dilate_source(face.index);
|
||||
break;
|
||||
case pp::paint_renderer::CanvasStrokeCommitStep::dilate_edges_draw:
|
||||
request.callbacks.execute_commit_dilate(face.index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
request.callbacks.unbind_layer_framebuffer(face.index);
|
||||
++result.committed_faces;
|
||||
}
|
||||
|
||||
request.callbacks.restore_render_state();
|
||||
request.callbacks.publish_history();
|
||||
request.callbacks.capture_timelapse_frame();
|
||||
|
||||
result.ok = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace pp::panopainter
|
||||
@@ -1445,6 +1445,55 @@ pp::foundation::Result<CanvasStrokeRasterizationPlan> plan_canvas_stroke_rasteri
|
||||
return pp::foundation::Result<CanvasStrokeRasterizationPlan>::success(plan);
|
||||
}
|
||||
|
||||
CanvasStrokeCommitSequencePlan plan_canvas_stroke_commit_sequence(CanvasStrokeCommitRequest request) noexcept
|
||||
{
|
||||
CanvasStrokeCommitSequencePlan plan;
|
||||
plan.erase_mode = request.erase_mode;
|
||||
plan.alpha_locked = request.alpha_locked;
|
||||
plan.selection_mask_active = request.selection_mask_active;
|
||||
plan.uses_dual_stroke = !request.erase_mode && request.dual_stroke_enabled;
|
||||
plan.uses_pattern = !request.erase_mode && request.pattern_enabled;
|
||||
plan.updates_layer_bounds = !request.alpha_locked;
|
||||
|
||||
auto append_step = [&plan](CanvasStrokeCommitStep step) noexcept {
|
||||
if (plan.step_count >= plan.steps.size()) {
|
||||
return;
|
||||
}
|
||||
plan.steps[plan.step_count] = step;
|
||||
++plan.step_count;
|
||||
};
|
||||
auto bind = [&plan](CanvasStrokeCommitTextureRole role, std::uint8_t slot) noexcept {
|
||||
if (plan.texture_binding_count >= plan.texture_bindings.size()) {
|
||||
return;
|
||||
}
|
||||
plan.texture_bindings[plan.texture_binding_count] = CanvasStrokeCommitTextureBindingPlan {
|
||||
.role = role,
|
||||
.slot = slot,
|
||||
};
|
||||
++plan.texture_binding_count;
|
||||
};
|
||||
|
||||
append_step(CanvasStrokeCommitStep::readback_history_region);
|
||||
append_step(CanvasStrokeCommitStep::update_layer_dirty_state);
|
||||
append_step(CanvasStrokeCommitStep::copy_layer_rtt_to_scratch);
|
||||
append_step(CanvasStrokeCommitStep::bind_commit_inputs);
|
||||
append_step(request.erase_mode ? CanvasStrokeCommitStep::erase_draw : CanvasStrokeCommitStep::composite_draw);
|
||||
append_step(CanvasStrokeCommitStep::copy_committed_rtt_to_scratch);
|
||||
append_step(CanvasStrokeCommitStep::dilate_edges_draw);
|
||||
|
||||
bind(CanvasStrokeCommitTextureRole::layer_scratch, 0);
|
||||
bind(CanvasStrokeCommitTextureRole::stroke, 1);
|
||||
bind(CanvasStrokeCommitTextureRole::selection_mask, 2);
|
||||
if (plan.uses_dual_stroke) {
|
||||
bind(CanvasStrokeCommitTextureRole::dual_stroke, 3);
|
||||
}
|
||||
if (plan.uses_pattern) {
|
||||
bind(CanvasStrokeCommitTextureRole::pattern, 4);
|
||||
}
|
||||
|
||||
return plan;
|
||||
}
|
||||
|
||||
CanvasStrokeSampleBoundsPlan plan_canvas_stroke_sample_bounds(
|
||||
CanvasStrokeSampleBoundsRequest request) noexcept
|
||||
{
|
||||
|
||||
@@ -187,6 +187,55 @@ struct CanvasStrokeRasterizationPlan {
|
||||
bool compatibility_fallback = false;
|
||||
};
|
||||
|
||||
enum class CanvasStrokeCommitStep : std::uint8_t {
|
||||
readback_history_region,
|
||||
update_layer_dirty_state,
|
||||
copy_layer_rtt_to_scratch,
|
||||
bind_commit_inputs,
|
||||
erase_draw,
|
||||
composite_draw,
|
||||
copy_committed_rtt_to_scratch,
|
||||
dilate_edges_draw,
|
||||
};
|
||||
|
||||
enum class CanvasStrokeCommitTextureRole : std::uint8_t {
|
||||
layer_scratch,
|
||||
stroke,
|
||||
selection_mask,
|
||||
dual_stroke,
|
||||
pattern,
|
||||
};
|
||||
|
||||
struct CanvasStrokeCommitTextureBindingPlan {
|
||||
CanvasStrokeCommitTextureRole role = CanvasStrokeCommitTextureRole::layer_scratch;
|
||||
std::uint8_t slot = 0;
|
||||
};
|
||||
|
||||
struct CanvasStrokeCommitRequest {
|
||||
bool erase_mode = false;
|
||||
bool alpha_locked = false;
|
||||
bool selection_mask_active = false;
|
||||
bool dual_stroke_enabled = false;
|
||||
bool pattern_enabled = false;
|
||||
};
|
||||
|
||||
struct CanvasStrokeCommitSequencePlan {
|
||||
std::array<CanvasStrokeCommitStep, 8> steps {};
|
||||
std::size_t step_count = 0;
|
||||
std::array<CanvasStrokeCommitTextureBindingPlan, 5> texture_bindings {};
|
||||
std::size_t texture_binding_count = 0;
|
||||
bool erase_mode = false;
|
||||
bool alpha_locked = false;
|
||||
bool selection_mask_active = false;
|
||||
bool uses_dual_stroke = false;
|
||||
bool uses_pattern = false;
|
||||
bool requires_history_readback = true;
|
||||
bool updates_layer_bounds = true;
|
||||
bool requires_layer_scratch_copy = true;
|
||||
bool requires_committed_scratch_copy = true;
|
||||
bool requires_dilate = true;
|
||||
};
|
||||
|
||||
struct CanvasStrokePoint {
|
||||
float x = 0.0F;
|
||||
float y = 0.0F;
|
||||
@@ -493,6 +542,9 @@ export_document_animation_frames_equirectangular_pngs(
|
||||
pp::renderer::RenderDeviceFeatures features,
|
||||
pp::renderer::Extent2D extent) noexcept;
|
||||
|
||||
[[nodiscard]] CanvasStrokeCommitSequencePlan plan_canvas_stroke_commit_sequence(
|
||||
CanvasStrokeCommitRequest request) noexcept;
|
||||
|
||||
[[nodiscard]] CanvasStrokeSampleBoundsPlan plan_canvas_stroke_sample_bounds(
|
||||
CanvasStrokeSampleBoundsRequest request) noexcept;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user