Centralize canvas blend gate planning

This commit is contained in:
2026-06-03 18:20:01 +02:00
parent a89f5e6cf2
commit 1369a9048e
8 changed files with 327 additions and 86 deletions

View File

@@ -44,36 +44,6 @@ GLenum rgba_pixel_format()
return static_cast<GLenum>(pp::renderer::gl::rgba_pixel_format());
}
bool to_paint_blend_mode(int value, pp::paint::BlendMode& out) noexcept
{
switch (value) {
case 0: out = pp::paint::BlendMode::normal; return true;
case 1: out = pp::paint::BlendMode::multiply; return true;
case 2: out = pp::paint::BlendMode::screen; return true;
case 3: out = pp::paint::BlendMode::color_dodge; return true;
case 4: out = pp::paint::BlendMode::overlay; return true;
default: return false;
}
}
bool to_stroke_blend_mode(int value, pp::paint::StrokeBlendMode& out) noexcept
{
switch (value) {
case 0: out = pp::paint::StrokeBlendMode::normal; return true;
case 1: out = pp::paint::StrokeBlendMode::multiply; return true;
case 2: out = pp::paint::StrokeBlendMode::subtract; return true;
case 3: out = pp::paint::StrokeBlendMode::darken; return true;
case 4: out = pp::paint::StrokeBlendMode::overlay; return true;
case 5: out = pp::paint::StrokeBlendMode::color_dodge; return true;
case 6: out = pp::paint::StrokeBlendMode::color_burn; return true;
case 7: out = pp::paint::StrokeBlendMode::linear_burn; return true;
case 8: out = pp::paint::StrokeBlendMode::hard_mix; return true;
case 9: out = pp::paint::StrokeBlendMode::linear_height; return true;
case 10: out = pp::paint::StrokeBlendMode::height; return true;
default: return false;
}
}
pp::renderer::RenderDeviceFeatures canvas_stroke_composite_features() noexcept
{
return pp::renderer::RenderDeviceFeatures {
@@ -82,64 +52,33 @@ pp::renderer::RenderDeviceFeatures canvas_stroke_composite_features() noexcept
};
}
bool stroke_composite_plan_needs_shader_blend(
int width,
int height,
pp::paint::BlendMode layer_blend_mode,
pp::paint::StrokeBlendMode stroke_blend_mode) noexcept
{
const auto plan = pp::paint_renderer::plan_stroke_composite(
canvas_stroke_composite_features(),
pp::paint_renderer::StrokeCompositeRequest {
.extent = pp::renderer::Extent2D {
.width = static_cast<std::uint32_t>(std::max(width, 0)),
.height = static_cast<std::uint32_t>(std::max(height, 0)),
},
.layer_blend_mode = layer_blend_mode,
.stroke_blend_mode = stroke_blend_mode,
});
return plan ? plan.value().complex_blend : true;
}
bool draw_merge_needs_shader_blend(
int width,
int height,
const std::vector<std::shared_ptr<Layer>>& layers,
const Brush* brush) noexcept
{
std::vector<int> layer_blend_modes;
layer_blend_modes.reserve(layers.size());
for (const auto& layer : layers) {
if (!layer) {
continue;
}
pp::paint::BlendMode layer_blend = pp::paint::BlendMode::normal;
if (!to_paint_blend_mode(layer->m_blend_mode, layer_blend)) {
if (layer->m_blend_mode != 0) {
return true;
}
continue;
}
if (stroke_composite_plan_needs_shader_blend(
width,
height,
layer_blend,
pp::paint::StrokeBlendMode::normal)) {
return true;
}
layer_blend_modes.push_back(layer->m_blend_mode);
}
if (brush) {
pp::paint::StrokeBlendMode stroke_blend = pp::paint::StrokeBlendMode::normal;
if (!to_stroke_blend_mode(brush->m_blend_mode, stroke_blend)) {
return brush->m_blend_mode != 0;
}
return stroke_composite_plan_needs_shader_blend(
width,
height,
pp::paint::BlendMode::normal,
stroke_blend);
}
return false;
const auto plan = pp::paint_renderer::plan_canvas_blend_gate(
canvas_stroke_composite_features(),
pp::paint_renderer::CanvasBlendGateRequest {
.extent = pp::renderer::Extent2D {
.width = static_cast<std::uint32_t>(std::max(width, 0)),
.height = static_cast<std::uint32_t>(std::max(height, 0)),
},
.layer_blend_modes = layer_blend_modes,
.has_stroke_blend_mode = brush != nullptr,
.stroke_blend_mode = brush ? brush->m_blend_mode : 0,
});
return plan ? plan.value().shader_blend : true;
}
GLenum unsigned_byte_component_type()