Plan stroke preview composite sequence
This commit is contained in:
@@ -18,6 +18,12 @@ agent or engineer to remove them without reconstructing context from chat.
|
|||||||
|
|
||||||
## Recent Reductions
|
## Recent Reductions
|
||||||
|
|
||||||
|
- 2026-06-13: DEBT-0036 was narrowed again. `NodeStrokePreview` final preview
|
||||||
|
background capture, composite input binding/draw, and preview texture copy now
|
||||||
|
route through `legacy_canvas_stroke_preview_services.h`, with semantic preview
|
||||||
|
composite ordering and texture-slot intent covered by `pp_paint_renderer`
|
||||||
|
tests. Static preview RTT/texture ownership, checkerboard shader setup,
|
||||||
|
framebuffer copies, and retained GL callbacks remain in legacy preview code.
|
||||||
- 2026-06-13: DEBT-0036 was narrowed again. Stroke sample copy bounds, live
|
- 2026-06-13: DEBT-0036 was narrowed again. Stroke sample copy bounds, live
|
||||||
face dirty-box accumulation, and preview padding region math now live as
|
face dirty-box accumulation, and preview padding region math now live as
|
||||||
tested `pp_paint_renderer` planners and are consumed by retained Canvas and
|
tested `pp_paint_renderer` planners and are consumed by retained Canvas and
|
||||||
|
|||||||
@@ -1359,6 +1359,10 @@ callback execution under `DEBT-0036`. Stroke sample copy bounds, live face
|
|||||||
dirty-box accumulation, and preview padding region math now live as tested
|
dirty-box accumulation, and preview padding region math now live as tested
|
||||||
`pp_paint_renderer` planners while retained Canvas/preview code still owns GL
|
`pp_paint_renderer` planners while retained Canvas/preview code still owns GL
|
||||||
ordering, RTT/texture binding, history mutation, and final dirty state storage.
|
ordering, RTT/texture binding, history mutation, and final dirty state storage.
|
||||||
|
`NodeStrokePreview` also now consumes a tested preview composite sequence plan
|
||||||
|
for mixer intent, and retained preview background capture, composite input
|
||||||
|
binding/draw, and preview texture copy are centralized behind
|
||||||
|
`legacy_canvas_stroke_preview_services.h`.
|
||||||
It also owns renderer API texture-format to
|
It also owns renderer API texture-format to
|
||||||
OpenGL internal/pixel/component token mapping, including depth-stencil formats,
|
OpenGL internal/pixel/component token mapping, including depth-stencil formats,
|
||||||
for future backend texture objects. `Texture2D` 2D texture binding, upload,
|
for future backend texture objects. `Texture2D` 2D texture binding, upload,
|
||||||
|
|||||||
55
src/legacy_canvas_stroke_preview_services.h
Normal file
55
src/legacy_canvas_stroke_preview_services.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
|
||||||
|
struct LegacyStrokePreviewCopySize {
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename SetupCheckerboard,
|
||||||
|
typename DrawPlane,
|
||||||
|
typename BindBackgroundTexture,
|
||||||
|
typename CopyFramebufferToTexture>
|
||||||
|
void execute_legacy_stroke_preview_background_capture(
|
||||||
|
SetupCheckerboard&& setup_checkerboard,
|
||||||
|
DrawPlane&& draw_plane,
|
||||||
|
BindBackgroundTexture&& bind_background_texture,
|
||||||
|
CopyFramebufferToTexture&& copy_framebuffer_to_texture,
|
||||||
|
LegacyStrokePreviewCopySize copy_size)
|
||||||
|
{
|
||||||
|
setup_checkerboard();
|
||||||
|
draw_plane();
|
||||||
|
bind_background_texture();
|
||||||
|
copy_framebuffer_to_texture(0, 0, 0, 0, copy_size.width, copy_size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename SetupCompositeShader,
|
||||||
|
typename BindCompositeSamplers,
|
||||||
|
typename BindCompositeInputs,
|
||||||
|
typename DrawPlane>
|
||||||
|
void execute_legacy_stroke_preview_final_composite(
|
||||||
|
SetupCompositeShader&& setup_composite_shader,
|
||||||
|
BindCompositeSamplers&& bind_composite_samplers,
|
||||||
|
BindCompositeInputs&& bind_composite_inputs,
|
||||||
|
DrawPlane&& draw_plane)
|
||||||
|
{
|
||||||
|
setup_composite_shader();
|
||||||
|
bind_composite_samplers();
|
||||||
|
bind_composite_inputs();
|
||||||
|
draw_plane();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename BindPreviewTexture, typename CopyFramebufferToTexture>
|
||||||
|
void copy_legacy_stroke_preview_texture(
|
||||||
|
BindPreviewTexture&& bind_preview_texture,
|
||||||
|
CopyFramebufferToTexture&& copy_framebuffer_to_texture,
|
||||||
|
LegacyStrokePreviewCopySize copy_size)
|
||||||
|
{
|
||||||
|
bind_preview_texture();
|
||||||
|
copy_framebuffer_to_texture(0, 0, 0, 0, copy_size.width, copy_size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "legacy_canvas_stroke_composite_services.h"
|
#include "legacy_canvas_stroke_composite_services.h"
|
||||||
#include "legacy_canvas_stroke_execution_services.h"
|
#include "legacy_canvas_stroke_execution_services.h"
|
||||||
|
#include "legacy_canvas_stroke_preview_services.h"
|
||||||
#include "legacy_canvas_stroke_shader_services.h"
|
#include "legacy_canvas_stroke_shader_services.h"
|
||||||
#include "legacy_canvas_stroke_services.h"
|
#include "legacy_canvas_stroke_services.h"
|
||||||
#include "legacy_ui_gl_dispatch.h"
|
#include "legacy_ui_gl_dispatch.h"
|
||||||
@@ -451,6 +452,12 @@ void NodeStrokePreview::draw_stroke_immediate()
|
|||||||
const auto stroke_feedback = stroke_preview_destination_feedback_plan(m_rtt.getWidth(), m_rtt.getHeight());
|
const auto stroke_feedback = stroke_preview_destination_feedback_plan(m_rtt.getWidth(), m_rtt.getHeight());
|
||||||
const bool copy_stroke_destination = !stroke_feedback.reads_destination_color;
|
const bool copy_stroke_destination = !stroke_feedback.reads_destination_color;
|
||||||
const auto material = stroke_preview_material_plan(*b, copy_stroke_destination);
|
const auto material = stroke_preview_material_plan(*b, copy_stroke_destination);
|
||||||
|
const auto preview_composite_plan = pp::paint_renderer::plan_stroke_preview_composite(
|
||||||
|
pp::paint_renderer::StrokePreviewCompositeRequest {
|
||||||
|
.uses_mixer = b->m_tip_mix > 0.0f,
|
||||||
|
.uses_dual = material.composite_pass.use_dual,
|
||||||
|
.uses_pattern = material.composite_pass.use_pattern,
|
||||||
|
});
|
||||||
pp::panopainter::setup_legacy_stroke_shader(
|
pp::panopainter::setup_legacy_stroke_shader(
|
||||||
pp::panopainter::LegacyStrokeShaderSetupUniforms {
|
pp::panopainter::LegacyStrokeShaderSetupUniforms {
|
||||||
.resolution = size,
|
.resolution = size,
|
||||||
@@ -508,21 +515,34 @@ void NodeStrokePreview::draw_stroke_immediate()
|
|||||||
|
|
||||||
// CHEKCERBOARD
|
// CHEKCERBOARD
|
||||||
|
|
||||||
|
pp::panopainter::execute_legacy_stroke_preview_background_capture(
|
||||||
|
[&] {
|
||||||
// copy background color to tex2
|
// copy background color to tex2
|
||||||
ShaderManager::use(kShader::Checkerboard);
|
ShaderManager::use(kShader::Checkerboard);
|
||||||
ShaderManager::u_int(kShaderUniform::Colorize, b->m_tip_mix > 0.f || b->m_blend_mode != 0);
|
ShaderManager::u_int(kShaderUniform::Colorize, b->m_tip_mix > 0.f || b->m_blend_mode != 0);
|
||||||
float aspect = size.x / size.y;
|
float aspect = size.x / size.y;
|
||||||
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f / aspect, .5f / aspect, -1.f, 1.f));
|
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f / aspect, .5f / aspect, -1.f, 1.f));
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
m_plane.draw_fill();
|
m_plane.draw_fill();
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
//m_rtt.clear({ .3f, .3f, .3f, 1.f });
|
//m_rtt.clear({ .3f, .3f, .3f, 1.f });
|
||||||
m_tex_background.bind();
|
m_tex_background.bind();
|
||||||
copy_framebuffer_to_texture_2d(
|
},
|
||||||
0,
|
[](
|
||||||
0,
|
int src_x,
|
||||||
0,
|
int src_y,
|
||||||
0,
|
int dst_x,
|
||||||
static_cast<int>(size.x),
|
int dst_y,
|
||||||
static_cast<int>(size.y));
|
int width,
|
||||||
|
int height) {
|
||||||
|
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
||||||
|
},
|
||||||
|
pp::panopainter::LegacyStrokePreviewCopySize {
|
||||||
|
.width = static_cast<int>(size.x),
|
||||||
|
.height = static_cast<int>(size.y),
|
||||||
|
});
|
||||||
|
|
||||||
// DRAW MAIN BRUSH
|
// DRAW MAIN BRUSH
|
||||||
|
|
||||||
@@ -545,7 +565,7 @@ void NodeStrokePreview::draw_stroke_immediate()
|
|||||||
b->m_pattern_texture->bind() :
|
b->m_pattern_texture->bind() :
|
||||||
unbind_texture_2d();
|
unbind_texture_2d();
|
||||||
set_active_texture_unit(3U);
|
set_active_texture_unit(3U);
|
||||||
b->m_tip_mix > 0.f ? m_rtt_mixer.bindTexture() : unbind_texture_2d();
|
preview_composite_plan.uses_mixer ? m_rtt_mixer.bindTexture() : unbind_texture_2d();
|
||||||
auto frames = stroke_draw_compute(m_stroke, zoom);
|
auto frames = stroke_draw_compute(m_stroke, zoom);
|
||||||
m_rtt.clear();
|
m_rtt.clear();
|
||||||
for (auto& f : frames)
|
for (auto& f : frames)
|
||||||
@@ -582,6 +602,8 @@ void NodeStrokePreview::draw_stroke_immediate()
|
|||||||
|
|
||||||
// COMPOSITE
|
// COMPOSITE
|
||||||
|
|
||||||
|
pp::panopainter::execute_legacy_stroke_preview_final_composite(
|
||||||
|
[&] {
|
||||||
pp::panopainter::setup_legacy_stroke_composite_shader(
|
pp::panopainter::setup_legacy_stroke_composite_shader(
|
||||||
pp::panopainter::LegacyStrokeCompositeUniforms {
|
pp::panopainter::LegacyStrokeCompositeUniforms {
|
||||||
.resolution = size,
|
.resolution = size,
|
||||||
@@ -605,13 +627,15 @@ void NodeStrokePreview::draw_stroke_immediate()
|
|||||||
.dual_alpha = material.composite_pass.dual_alpha,
|
.dual_alpha = material.composite_pass.dual_alpha,
|
||||||
.use_pattern = material.composite_pass.use_pattern,
|
.use_pattern = material.composite_pass.use_pattern,
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
m_sampler_linear.bind(0);
|
m_sampler_linear.bind(0);
|
||||||
m_sampler_linear.bind(1);
|
m_sampler_linear.bind(1);
|
||||||
m_sampler_linear.bind(2);
|
m_sampler_linear.bind(2);
|
||||||
m_sampler_linear.bind(3);
|
m_sampler_linear.bind(3);
|
||||||
m_sampler_linear_repeat.bind(4);
|
m_sampler_linear_repeat.bind(4);
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
set_active_texture_unit(0U);
|
set_active_texture_unit(0U);
|
||||||
m_tex_background.bind();
|
m_tex_background.bind();
|
||||||
set_active_texture_unit(1U);
|
set_active_texture_unit(1U);
|
||||||
@@ -622,17 +646,29 @@ void NodeStrokePreview::draw_stroke_immediate()
|
|||||||
b->m_pattern_texture ?
|
b->m_pattern_texture ?
|
||||||
b->m_pattern_texture->bind() :
|
b->m_pattern_texture->bind() :
|
||||||
unbind_texture_2d();
|
unbind_texture_2d();
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
m_plane.draw_fill();
|
m_plane.draw_fill();
|
||||||
|
});
|
||||||
|
|
||||||
// copy the result to the actual preview
|
// copy the result to the actual preview
|
||||||
|
pp::panopainter::copy_legacy_stroke_preview_texture(
|
||||||
|
[&] {
|
||||||
m_tex_preview.bind();
|
m_tex_preview.bind();
|
||||||
copy_framebuffer_to_texture_2d(
|
},
|
||||||
0,
|
[](
|
||||||
0,
|
int src_x,
|
||||||
0,
|
int src_y,
|
||||||
0,
|
int dst_x,
|
||||||
static_cast<int>(size.x),
|
int dst_y,
|
||||||
static_cast<int>(size.y));
|
int width,
|
||||||
|
int height) {
|
||||||
|
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
||||||
|
},
|
||||||
|
pp::panopainter::LegacyStrokePreviewCopySize {
|
||||||
|
.width = static_cast<int>(size.x),
|
||||||
|
.height = static_cast<int>(size.y),
|
||||||
|
});
|
||||||
|
|
||||||
m_rtt.unbindFramebuffer();
|
m_rtt.unbindFramebuffer();
|
||||||
|
|
||||||
|
|||||||
@@ -1264,6 +1264,52 @@ CanvasStrokeMaterialPlan plan_canvas_stroke_material(CanvasStrokeMaterialRequest
|
|||||||
return plan;
|
return plan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StrokePreviewCompositePlan plan_stroke_preview_composite(StrokePreviewCompositeRequest request) noexcept
|
||||||
|
{
|
||||||
|
StrokePreviewCompositePlan plan;
|
||||||
|
plan.uses_mixer = request.uses_mixer;
|
||||||
|
plan.uses_dual = request.uses_dual;
|
||||||
|
plan.uses_pattern = request.uses_pattern;
|
||||||
|
|
||||||
|
auto append_step = [&plan](StrokePreviewCompositeStep step) noexcept {
|
||||||
|
if (plan.step_count >= plan.steps.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
plan.steps[plan.step_count] = step;
|
||||||
|
++plan.step_count;
|
||||||
|
};
|
||||||
|
auto bind = [&plan](StrokePreviewTextureRole role, std::uint8_t slot) noexcept {
|
||||||
|
if (plan.texture_slot_count >= plan.texture_slots.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
plan.texture_slots[plan.texture_slot_count] = StrokePreviewTextureSlotPlan {
|
||||||
|
.role = role,
|
||||||
|
.slot = slot,
|
||||||
|
};
|
||||||
|
++plan.texture_slot_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
append_step(StrokePreviewCompositeStep::checkerboard_background);
|
||||||
|
append_step(StrokePreviewCompositeStep::capture_background_texture);
|
||||||
|
append_step(StrokePreviewCompositeStep::bind_final_composite_inputs);
|
||||||
|
append_step(StrokePreviewCompositeStep::final_composite_draw);
|
||||||
|
append_step(StrokePreviewCompositeStep::copy_preview_texture);
|
||||||
|
|
||||||
|
bind(StrokePreviewTextureRole::background, 0);
|
||||||
|
bind(StrokePreviewTextureRole::stroke, 1);
|
||||||
|
if (request.uses_dual) {
|
||||||
|
bind(StrokePreviewTextureRole::dual, 3);
|
||||||
|
}
|
||||||
|
if (request.uses_pattern) {
|
||||||
|
bind(StrokePreviewTextureRole::pattern, 4);
|
||||||
|
}
|
||||||
|
if (request.uses_mixer) {
|
||||||
|
bind(StrokePreviewTextureRole::mixer, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return plan;
|
||||||
|
}
|
||||||
|
|
||||||
pp::foundation::Result<CanvasBlendGatePlan> plan_canvas_blend_gate(
|
pp::foundation::Result<CanvasBlendGatePlan> plan_canvas_blend_gate(
|
||||||
pp::renderer::RenderDeviceFeatures features,
|
pp::renderer::RenderDeviceFeatures features,
|
||||||
CanvasBlendGateRequest request) noexcept
|
CanvasBlendGateRequest request) noexcept
|
||||||
|
|||||||
@@ -109,6 +109,44 @@ struct CanvasStrokeMaterialPlan {
|
|||||||
std::size_t texture_binding_count = 0;
|
std::size_t texture_binding_count = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class StrokePreviewCompositeStep : std::uint8_t {
|
||||||
|
checkerboard_background,
|
||||||
|
capture_background_texture,
|
||||||
|
bind_final_composite_inputs,
|
||||||
|
final_composite_draw,
|
||||||
|
copy_preview_texture,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class StrokePreviewTextureRole : std::uint8_t {
|
||||||
|
background,
|
||||||
|
stroke,
|
||||||
|
mask,
|
||||||
|
dual,
|
||||||
|
pattern,
|
||||||
|
mixer,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StrokePreviewTextureSlotPlan {
|
||||||
|
StrokePreviewTextureRole role = StrokePreviewTextureRole::background;
|
||||||
|
std::uint8_t slot = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StrokePreviewCompositeRequest {
|
||||||
|
bool uses_mixer = false;
|
||||||
|
bool uses_dual = false;
|
||||||
|
bool uses_pattern = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StrokePreviewCompositePlan {
|
||||||
|
std::array<StrokePreviewCompositeStep, 5> steps {};
|
||||||
|
std::size_t step_count = 0;
|
||||||
|
std::array<StrokePreviewTextureSlotPlan, 5> texture_slots {};
|
||||||
|
std::size_t texture_slot_count = 0;
|
||||||
|
bool uses_mixer = false;
|
||||||
|
bool uses_dual = false;
|
||||||
|
bool uses_pattern = false;
|
||||||
|
};
|
||||||
|
|
||||||
struct CanvasBlendGateRequest {
|
struct CanvasBlendGateRequest {
|
||||||
pp::renderer::Extent2D extent {};
|
pp::renderer::Extent2D extent {};
|
||||||
std::span<const int> layer_blend_modes;
|
std::span<const int> layer_blend_modes;
|
||||||
@@ -440,6 +478,9 @@ export_document_animation_frames_equirectangular_pngs(
|
|||||||
[[nodiscard]] CanvasStrokeMaterialPlan plan_canvas_stroke_material(
|
[[nodiscard]] CanvasStrokeMaterialPlan plan_canvas_stroke_material(
|
||||||
CanvasStrokeMaterialRequest request) noexcept;
|
CanvasStrokeMaterialRequest request) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] StrokePreviewCompositePlan plan_stroke_preview_composite(
|
||||||
|
StrokePreviewCompositeRequest request) noexcept;
|
||||||
|
|
||||||
[[nodiscard]] pp::foundation::Result<CanvasBlendGatePlan> plan_canvas_blend_gate(
|
[[nodiscard]] pp::foundation::Result<CanvasBlendGatePlan> plan_canvas_blend_gate(
|
||||||
pp::renderer::RenderDeviceFeatures features,
|
pp::renderer::RenderDeviceFeatures features,
|
||||||
CanvasBlendGateRequest request) noexcept;
|
CanvasBlendGateRequest request) noexcept;
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ using pp::paint_renderer::CanvasStrokeTextureRole;
|
|||||||
using pp::paint_renderer::DocumentFaceCompositeRequest;
|
using pp::paint_renderer::DocumentFaceCompositeRequest;
|
||||||
using pp::paint_renderer::DocumentFrameCompositeRequest;
|
using pp::paint_renderer::DocumentFrameCompositeRequest;
|
||||||
using pp::paint_renderer::LayerCompositeView;
|
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::StrokeCompositePath;
|
||||||
using pp::paint_renderer::StrokeCompositeRequest;
|
using pp::paint_renderer::StrokeCompositeRequest;
|
||||||
using pp::paint_renderer::composite_layer;
|
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_rasterization;
|
||||||
using pp::paint_renderer::plan_canvas_stroke_sample_bounds;
|
using pp::paint_renderer::plan_canvas_stroke_sample_bounds;
|
||||||
using pp::paint_renderer::plan_document_depth_export_render;
|
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::plan_stroke_composite;
|
||||||
using pp::paint_renderer::stroke_composite_path_name;
|
using pp::paint_renderer::stroke_composite_path_name;
|
||||||
using pp::paint_renderer::stroke_composite_requires_feedback;
|
using pp::paint_renderer::stroke_composite_requires_feedback;
|
||||||
@@ -74,6 +78,29 @@ bool has_texture_binding(
|
|||||||
return false;
|
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::vector<std::uint8_t> solid_rgba8(
|
||||||
std::uint32_t width,
|
std::uint32_t width,
|
||||||
std::uint32_t height,
|
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));
|
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)
|
void plans_canvas_blend_gate_from_persisted_indices(pp::tests::Harness& h)
|
||||||
{
|
{
|
||||||
const std::vector<int> normal_layers { 0, 0, 0 };
|
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("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_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_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("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("canvas_blend_gate_preserves_legacy_fallbacks", canvas_blend_gate_preserves_legacy_fallbacks);
|
||||||
harness.run("plans_canvas_stroke_feedback_paths", plans_canvas_stroke_feedback_paths);
|
harness.run("plans_canvas_stroke_feedback_paths", plans_canvas_stroke_feedback_paths);
|
||||||
|
|||||||
Reference in New Issue
Block a user