Plan live stroke rasterization boundaries
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include "canvas.h"
|
||||
#include "app.h"
|
||||
#include "legacy_gl_renderbuffer_dispatch.h"
|
||||
#include "legacy_canvas_stroke_services.h"
|
||||
#include "legacy_ui_gl_dispatch.h"
|
||||
#include "legacy_ui_overlay_services.h"
|
||||
#include "app_core/document_canvas.h"
|
||||
@@ -43,25 +44,21 @@ pp::renderer::RenderDeviceFeatures canvas_render_device_features() noexcept
|
||||
return ShaderManager::render_device_features();
|
||||
}
|
||||
|
||||
pp::paint_renderer::CanvasStrokeRasterizationPlan canvas_stroke_rasterization_plan(
|
||||
int width,
|
||||
int height) noexcept
|
||||
{
|
||||
return pp::panopainter::plan_legacy_canvas_stroke_rasterization(
|
||||
canvas_render_device_features(),
|
||||
width,
|
||||
height);
|
||||
}
|
||||
|
||||
pp::paint_renderer::CanvasStrokeFeedbackPlan canvas_destination_feedback_plan(
|
||||
int width,
|
||||
int height) noexcept
|
||||
{
|
||||
const auto plan = pp::paint_renderer::plan_canvas_stroke_feedback(
|
||||
canvas_render_device_features(),
|
||||
pp::renderer::Extent2D {
|
||||
.width = static_cast<std::uint32_t>(std::max(width, 0)),
|
||||
.height = static_cast<std::uint32_t>(std::max(height, 0)),
|
||||
});
|
||||
if (plan) {
|
||||
return plan.value();
|
||||
}
|
||||
|
||||
pp::paint_renderer::CanvasStrokeFeedbackPlan fallback;
|
||||
fallback.compatibility_fallback = true;
|
||||
fallback.path = pp::paint_renderer::StrokeCompositePath::ping_pong_textures;
|
||||
fallback.requires_auxiliary_texture = true;
|
||||
return fallback;
|
||||
return canvas_stroke_rasterization_plan(width, height).feedback;
|
||||
}
|
||||
|
||||
pp::paint_renderer::CanvasBlendGatePlan draw_merge_blend_gate_plan(
|
||||
@@ -667,8 +664,8 @@ void Canvas::stroke_draw()
|
||||
if (brush->m_pattern_flipx) patt_scale.x *= -1.f;
|
||||
if (brush->m_pattern_flipy) patt_scale.y *= -1.f;
|
||||
|
||||
const auto stroke_feedback = canvas_destination_feedback_plan(m_width, m_height);
|
||||
const bool copy_stroke_destination = !stroke_feedback.reads_destination_color;
|
||||
const auto stroke_rasterization = canvas_stroke_rasterization_plan(m_width, m_height);
|
||||
const bool copy_stroke_destination = stroke_rasterization.copy_stroke_destination;
|
||||
|
||||
apply_canvas_capability(blend_state(), false);
|
||||
ShaderManager::use(kShader::Stroke);
|
||||
|
||||
35
src/legacy_canvas_stroke_services.h
Normal file
35
src/legacy_canvas_stroke_services.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "paint_renderer/compositor.h"
|
||||
#include "renderer_api/renderer_api.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
|
||||
namespace pp::panopainter {
|
||||
|
||||
[[nodiscard]] inline pp::paint_renderer::CanvasStrokeRasterizationPlan plan_legacy_canvas_stroke_rasterization(
|
||||
pp::renderer::RenderDeviceFeatures features,
|
||||
int width,
|
||||
int height) noexcept
|
||||
{
|
||||
const auto plan = pp::paint_renderer::plan_canvas_stroke_rasterization(
|
||||
features,
|
||||
pp::renderer::Extent2D {
|
||||
.width = static_cast<std::uint32_t>(std::max(width, 0)),
|
||||
.height = static_cast<std::uint32_t>(std::max(height, 0)),
|
||||
});
|
||||
if (plan) {
|
||||
return plan.value();
|
||||
}
|
||||
|
||||
pp::paint_renderer::CanvasStrokeRasterizationPlan fallback;
|
||||
fallback.feedback.compatibility_fallback = true;
|
||||
fallback.feedback.path = pp::paint_renderer::StrokeCompositePath::ping_pong_textures;
|
||||
fallback.feedback.requires_auxiliary_texture = true;
|
||||
fallback.copy_stroke_destination = true;
|
||||
fallback.compatibility_fallback = true;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
} // namespace pp::panopainter
|
||||
@@ -1186,6 +1186,56 @@ pp::foundation::Result<StrokeCompositePlan> plan_stroke_composite(
|
||||
return pp::foundation::Result<StrokeCompositePlan>::success(plan);
|
||||
}
|
||||
|
||||
CanvasStrokeMaterialPlan plan_canvas_stroke_material(CanvasStrokeMaterialRequest request) noexcept
|
||||
{
|
||||
CanvasStrokeMaterialPlan plan;
|
||||
|
||||
auto bind = [&plan](CanvasStrokeTextureRole role, std::uint8_t slot) noexcept {
|
||||
if (plan.texture_binding_count >= plan.texture_bindings.size()) {
|
||||
return;
|
||||
}
|
||||
plan.texture_bindings[plan.texture_binding_count] = CanvasStrokeTextureBindingPlan {
|
||||
.role = role,
|
||||
.slot = slot,
|
||||
};
|
||||
++plan.texture_binding_count;
|
||||
};
|
||||
|
||||
bind(CanvasStrokeTextureRole::main_brush_tip, 0);
|
||||
|
||||
plan.stroke_pass.uses_destination_feedback = request.destination_feedback_needed;
|
||||
if (request.destination_feedback_needed) {
|
||||
bind(CanvasStrokeTextureRole::destination_feedback, 1);
|
||||
}
|
||||
|
||||
plan.stroke_pass.uses_pattern = request.pattern_enabled && request.pattern_eachsample;
|
||||
if (plan.stroke_pass.uses_pattern) {
|
||||
bind(CanvasStrokeTextureRole::pattern, 2);
|
||||
}
|
||||
|
||||
plan.stroke_pass.uses_mixer = request.wet_blend || request.mix_blend || request.noise_enabled;
|
||||
if (plan.stroke_pass.uses_mixer) {
|
||||
bind(CanvasStrokeTextureRole::mixer, 3);
|
||||
}
|
||||
|
||||
plan.dual_pass.enabled = request.dual_brush_enabled;
|
||||
plan.dual_pass.uses_pattern = false;
|
||||
if (request.dual_brush_enabled) {
|
||||
bind(CanvasStrokeTextureRole::dual_brush_tip, 4);
|
||||
}
|
||||
|
||||
plan.composite_pass.use_dual = request.dual_brush_enabled;
|
||||
plan.composite_pass.use_pattern = request.pattern_enabled && !request.pattern_eachsample;
|
||||
plan.composite_pass.dual_blend_mode = request.dual_blend_mode;
|
||||
plan.composite_pass.pattern_blend_mode = request.pattern_blend_mode;
|
||||
plan.composite_pass.dual_alpha = request.dual_alpha;
|
||||
if (plan.composite_pass.use_pattern && !plan.stroke_pass.uses_pattern) {
|
||||
bind(CanvasStrokeTextureRole::pattern, 2);
|
||||
}
|
||||
|
||||
return plan;
|
||||
}
|
||||
|
||||
pp::foundation::Result<CanvasBlendGatePlan> plan_canvas_blend_gate(
|
||||
pp::renderer::RenderDeviceFeatures features,
|
||||
CanvasBlendGateRequest request) noexcept
|
||||
@@ -1301,6 +1351,26 @@ pp::foundation::Result<CanvasStrokeFeedbackPlan> plan_canvas_stroke_feedback(
|
||||
return pp::foundation::Result<CanvasStrokeFeedbackPlan>::success(fallback);
|
||||
}
|
||||
|
||||
pp::foundation::Result<CanvasStrokeRasterizationPlan> plan_canvas_stroke_rasterization(
|
||||
pp::renderer::RenderDeviceFeatures features,
|
||||
pp::renderer::Extent2D extent) noexcept
|
||||
{
|
||||
const auto feedback = plan_canvas_stroke_feedback(features, extent);
|
||||
if (!feedback) {
|
||||
return pp::foundation::Result<CanvasStrokeRasterizationPlan>::failure(feedback.status());
|
||||
}
|
||||
|
||||
CanvasStrokeRasterizationPlan plan;
|
||||
plan.feedback = feedback.value();
|
||||
plan.copy_stroke_destination = !plan.feedback.reads_destination_color;
|
||||
plan.can_route_feedback_through_renderer =
|
||||
plan.feedback.reads_destination_color
|
||||
|| plan.feedback.requires_texture_copy
|
||||
|| plan.feedback.requires_render_target_blit;
|
||||
plan.compatibility_fallback = plan.feedback.compatibility_fallback;
|
||||
return pp::foundation::Result<CanvasStrokeRasterizationPlan>::success(plan);
|
||||
}
|
||||
|
||||
const char* stroke_composite_path_name(StrokeCompositePath path) noexcept
|
||||
{
|
||||
switch (path) {
|
||||
|
||||
@@ -56,6 +56,59 @@ struct StrokeCompositePlan {
|
||||
bool requires_explicit_transition = false;
|
||||
};
|
||||
|
||||
enum class CanvasStrokeTextureRole : std::uint8_t {
|
||||
main_brush_tip,
|
||||
destination_feedback,
|
||||
pattern,
|
||||
mixer,
|
||||
dual_brush_tip,
|
||||
};
|
||||
|
||||
struct CanvasStrokeTextureBindingPlan {
|
||||
CanvasStrokeTextureRole role = CanvasStrokeTextureRole::main_brush_tip;
|
||||
std::uint8_t slot = 0;
|
||||
};
|
||||
|
||||
struct CanvasStrokeMaterialRequest {
|
||||
bool destination_feedback_needed = false;
|
||||
bool pattern_enabled = false;
|
||||
bool pattern_eachsample = false;
|
||||
bool wet_blend = false;
|
||||
bool mix_blend = false;
|
||||
bool noise_enabled = false;
|
||||
bool dual_brush_enabled = false;
|
||||
int dual_blend_mode = 0;
|
||||
int pattern_blend_mode = 0;
|
||||
float dual_alpha = 1.0F;
|
||||
};
|
||||
|
||||
struct CanvasStrokeShaderPassPlan {
|
||||
bool uses_destination_feedback = false;
|
||||
bool uses_pattern = false;
|
||||
bool uses_mixer = false;
|
||||
};
|
||||
|
||||
struct CanvasStrokeDualPassPlan {
|
||||
bool enabled = false;
|
||||
bool uses_pattern = false;
|
||||
};
|
||||
|
||||
struct CanvasStrokeCompositePassPlan {
|
||||
bool use_dual = false;
|
||||
bool use_pattern = false;
|
||||
int dual_blend_mode = 0;
|
||||
int pattern_blend_mode = 0;
|
||||
float dual_alpha = 1.0F;
|
||||
};
|
||||
|
||||
struct CanvasStrokeMaterialPlan {
|
||||
CanvasStrokeShaderPassPlan stroke_pass {};
|
||||
CanvasStrokeDualPassPlan dual_pass {};
|
||||
CanvasStrokeCompositePassPlan composite_pass {};
|
||||
std::array<CanvasStrokeTextureBindingPlan, 5> texture_bindings {};
|
||||
std::size_t texture_binding_count = 0;
|
||||
};
|
||||
|
||||
struct CanvasBlendGateRequest {
|
||||
pp::renderer::Extent2D extent {};
|
||||
std::span<const int> layer_blend_modes;
|
||||
@@ -89,6 +142,13 @@ struct CanvasStrokeFeedbackPlan {
|
||||
bool compatibility_fallback = false;
|
||||
};
|
||||
|
||||
struct CanvasStrokeRasterizationPlan {
|
||||
CanvasStrokeFeedbackPlan feedback {};
|
||||
bool copy_stroke_destination = true;
|
||||
bool can_route_feedback_through_renderer = false;
|
||||
bool compatibility_fallback = false;
|
||||
};
|
||||
|
||||
struct DocumentFaceCompositeRequest {
|
||||
const pp::document::CanvasDocument* document = nullptr;
|
||||
std::size_t frame_index = 0;
|
||||
@@ -318,6 +378,9 @@ export_document_animation_frames_equirectangular_pngs(
|
||||
pp::renderer::RenderDeviceFeatures features,
|
||||
StrokeCompositeRequest request) noexcept;
|
||||
|
||||
[[nodiscard]] CanvasStrokeMaterialPlan plan_canvas_stroke_material(
|
||||
CanvasStrokeMaterialRequest request) noexcept;
|
||||
|
||||
[[nodiscard]] pp::foundation::Result<CanvasBlendGatePlan> plan_canvas_blend_gate(
|
||||
pp::renderer::RenderDeviceFeatures features,
|
||||
CanvasBlendGateRequest request) noexcept;
|
||||
@@ -326,6 +389,10 @@ export_document_animation_frames_equirectangular_pngs(
|
||||
pp::renderer::RenderDeviceFeatures features,
|
||||
pp::renderer::Extent2D extent) noexcept;
|
||||
|
||||
[[nodiscard]] pp::foundation::Result<CanvasStrokeRasterizationPlan> plan_canvas_stroke_rasterization(
|
||||
pp::renderer::RenderDeviceFeatures features,
|
||||
pp::renderer::Extent2D extent) noexcept;
|
||||
|
||||
[[nodiscard]] const char* stroke_composite_path_name(StrokeCompositePath path) noexcept;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user