Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit f75ea56

Browse files
authored
[Impeller] Add ColorBurn, fix SourceOver alpha, make default pipeline initialization robust (#33289)
1 parent 20c8165 commit f75ea56

16 files changed

+285
-200
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,12 @@ FILE: ../../../flutter/impeller/entity/entity_pass_delegate.h
530530
FILE: ../../../flutter/impeller/entity/entity_playground.cc
531531
FILE: ../../../flutter/impeller/entity/entity_playground.h
532532
FILE: ../../../flutter/impeller/entity/entity_unittests.cc
533+
FILE: ../../../flutter/impeller/entity/shaders/advanced_blend.vert
534+
FILE: ../../../flutter/impeller/entity/shaders/advanced_blend_colorburn.frag
535+
FILE: ../../../flutter/impeller/entity/shaders/advanced_blend_screen.frag
536+
FILE: ../../../flutter/impeller/entity/shaders/blend.frag
537+
FILE: ../../../flutter/impeller/entity/shaders/blend.vert
538+
FILE: ../../../flutter/impeller/entity/shaders/blending.glsl
533539
FILE: ../../../flutter/impeller/entity/shaders/border_mask_blur.frag
534540
FILE: ../../../flutter/impeller/entity/shaders/border_mask_blur.vert
535541
FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur.frag
@@ -542,10 +548,6 @@ FILE: ../../../flutter/impeller/entity/shaders/solid_fill.frag
542548
FILE: ../../../flutter/impeller/entity/shaders/solid_fill.vert
543549
FILE: ../../../flutter/impeller/entity/shaders/solid_stroke.frag
544550
FILE: ../../../flutter/impeller/entity/shaders/solid_stroke.vert
545-
FILE: ../../../flutter/impeller/entity/shaders/texture_blend.frag
546-
FILE: ../../../flutter/impeller/entity/shaders/texture_blend.vert
547-
FILE: ../../../flutter/impeller/entity/shaders/texture_blend_screen.frag
548-
FILE: ../../../flutter/impeller/entity/shaders/texture_blend_screen.vert
549551
FILE: ../../../flutter/impeller/entity/shaders/texture_fill.frag
550552
FILE: ../../../flutter/impeller/entity/shaders/texture_fill.vert
551553
FILE: ../../../flutter/impeller/fixtures/airplane.jpg

impeller/aiks/aiks_unittests.cc

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ TEST_P(AiksTest, CanDrawWithAdvancedBlend) {
493493
{"Modulate", Entity::BlendMode::kModulate},
494494
// Advanced blends (non Porter-Duff/color blends)
495495
{"Screen", Entity::BlendMode::kScreen},
496+
{"ColorBurn", Entity::BlendMode::kColorBurn},
496497
};
497498
assert(blends.size() ==
498499
static_cast<size_t>(Entity::BlendMode::kLastAdvancedBlendMode) + 1);
@@ -520,6 +521,7 @@ TEST_P(AiksTest, CanDrawWithAdvancedBlend) {
520521
};
521522

522523
Paint paint;
524+
paint.blend_mode = Entity::BlendMode::kSourceOver;
523525

524526
// Draw a fancy color wheel for the backdrop.
525527
// https://www.desmos.com/calculator/xw7kafthwd
@@ -546,10 +548,16 @@ TEST_P(AiksTest, CanDrawWithAdvancedBlend) {
546548
ImGui::SetNextWindowPos({325, 550});
547549
}
548550

549-
ImGui::Begin("Controls");
551+
// UI state.
550552
static int current_blend_index = 3;
551-
ImGui::ListBox("Blending mode", &current_blend_index,
552-
blend_mode_names.data(), blend_mode_names.size());
553+
static float alpha = 1;
554+
555+
ImGui::Begin("Controls");
556+
{
557+
ImGui::ListBox("Blending mode", &current_blend_index,
558+
blend_mode_names.data(), blend_mode_names.size());
559+
ImGui::SliderFloat("Alpha", &alpha, 0, 1);
560+
}
553561
ImGui::End();
554562

555563
Canvas canvas;
@@ -569,11 +577,11 @@ TEST_P(AiksTest, CanDrawWithAdvancedBlend) {
569577
paint.blend_mode = Entity::BlendMode::kPlus;
570578
const Scalar x = std::sin(k2Pi / 3);
571579
const Scalar y = -std::cos(k2Pi / 3);
572-
paint.color = Color::Red();
580+
paint.color = Color::Red().WithAlpha(alpha);
573581
canvas.DrawCircle(Point(-x, y) * 45, 65, paint);
574-
paint.color = Color::Green();
582+
paint.color = Color::Green().WithAlpha(alpha);
575583
canvas.DrawCircle(Point(0, -1) * 45, 65, paint);
576-
paint.color = Color::Blue();
584+
paint.color = Color::Blue().WithAlpha(alpha);
577585
canvas.DrawCircle(Point(x, y) * 45, 65, paint);
578586
}
579587
canvas.Restore();

impeller/blobcat/blob.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct Blob {
2626
kFragment,
2727
};
2828

29-
static constexpr size_t kMaxNameLength = 24u;
29+
static constexpr size_t kMaxNameLength = 32u;
3030

3131
ShaderType type = ShaderType::kVertex;
3232
uint64_t offset = 0;

impeller/display_list/display_list_dispatcher.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,13 @@ static std::optional<Entity::BlendMode> ToBlendMode(flutter::DlBlendMode mode) {
214214
case flutter::DlBlendMode::kModulate:
215215
return Entity::BlendMode::kModulate;
216216
case flutter::DlBlendMode::kScreen:
217+
return Entity::BlendMode::kScreen;
218+
case flutter::DlBlendMode::kColorBurn:
219+
return Entity::BlendMode::kColorBurn;
217220
case flutter::DlBlendMode::kOverlay:
218221
case flutter::DlBlendMode::kDarken:
219222
case flutter::DlBlendMode::kLighten:
220223
case flutter::DlBlendMode::kColorDodge:
221-
case flutter::DlBlendMode::kColorBurn:
222224
case flutter::DlBlendMode::kHardLight:
223225
case flutter::DlBlendMode::kSoftLight:
224226
case flutter::DlBlendMode::kDifference:
@@ -240,6 +242,7 @@ void DisplayListDispatcher::setBlendMode(flutter::DlBlendMode dl_mode) {
240242
paint_.blend_mode = mode.value();
241243
} else {
242244
UNIMPLEMENTED;
245+
paint_.blend_mode = Entity::BlendMode::kSourceOver;
243246
}
244247
}
245248

impeller/entity/BUILD.gn

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,25 @@ impeller_shaders("entity_shaders") {
88
name = "entity"
99

1010
shaders = [
11+
"shaders/advanced_blend.vert",
12+
"shaders/advanced_blend_colorburn.frag",
13+
"shaders/advanced_blend_screen.frag",
14+
"shaders/blend.frag",
15+
"shaders/blend.vert",
16+
"shaders/border_mask_blur.frag",
17+
"shaders/border_mask_blur.vert",
18+
"shaders/gaussian_blur.frag",
19+
"shaders/gaussian_blur.vert",
20+
"shaders/glyph_atlas.frag",
21+
"shaders/glyph_atlas.vert",
1122
"shaders/gradient_fill.frag",
1223
"shaders/gradient_fill.vert",
1324
"shaders/solid_fill.frag",
1425
"shaders/solid_fill.vert",
1526
"shaders/solid_stroke.frag",
1627
"shaders/solid_stroke.vert",
17-
"shaders/texture_blend.frag",
18-
"shaders/texture_blend.vert",
19-
"shaders/texture_blend_screen.frag",
20-
"shaders/texture_blend_screen.vert",
21-
"shaders/gaussian_blur.frag",
22-
"shaders/gaussian_blur.vert",
23-
"shaders/border_mask_blur.frag",
24-
"shaders/border_mask_blur.vert",
2528
"shaders/texture_fill.frag",
2629
"shaders/texture_fill.vert",
27-
"shaders/glyph_atlas.frag",
28-
"shaders/glyph_atlas.vert",
2930
]
3031
}
3132

impeller/entity/contents/content_context.cc

Lines changed: 144 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,161 @@
1313

1414
namespace impeller {
1515

16+
void ContentContextOptions::ApplyToPipelineDescriptor(
17+
PipelineDescriptor& desc) const {
18+
auto pipeline_blend = blend_mode;
19+
if (blend_mode > Entity::BlendMode::kLastPipelineBlendMode) {
20+
VALIDATION_LOG << "Cannot use blend mode " << static_cast<int>(blend_mode)
21+
<< " as a pipeline blend.";
22+
pipeline_blend = Entity::BlendMode::kSourceOver;
23+
}
24+
25+
desc.SetSampleCount(sample_count);
26+
27+
ColorAttachmentDescriptor color0 = *desc.GetColorAttachmentDescriptor(0u);
28+
color0.alpha_blend_op = BlendOperation::kAdd;
29+
color0.color_blend_op = BlendOperation::kAdd;
30+
31+
static_assert(Entity::BlendMode::kLastPipelineBlendMode ==
32+
Entity::BlendMode::kModulate);
33+
34+
switch (pipeline_blend) {
35+
case Entity::BlendMode::kClear:
36+
color0.dst_alpha_blend_factor = BlendFactor::kZero;
37+
color0.dst_color_blend_factor = BlendFactor::kZero;
38+
color0.src_alpha_blend_factor = BlendFactor::kZero;
39+
color0.src_color_blend_factor = BlendFactor::kZero;
40+
break;
41+
case Entity::BlendMode::kSource:
42+
color0.dst_alpha_blend_factor = BlendFactor::kZero;
43+
color0.dst_color_blend_factor = BlendFactor::kZero;
44+
color0.src_alpha_blend_factor = BlendFactor::kSourceAlpha;
45+
color0.src_color_blend_factor = BlendFactor::kOne;
46+
break;
47+
case Entity::BlendMode::kDestination:
48+
color0.dst_alpha_blend_factor = BlendFactor::kDestinationAlpha;
49+
color0.dst_color_blend_factor = BlendFactor::kOne;
50+
color0.src_alpha_blend_factor = BlendFactor::kZero;
51+
color0.src_color_blend_factor = BlendFactor::kZero;
52+
break;
53+
case Entity::BlendMode::kSourceOver:
54+
color0.dst_alpha_blend_factor = BlendFactor::kOneMinusSourceAlpha;
55+
color0.dst_color_blend_factor = BlendFactor::kOneMinusSourceAlpha;
56+
color0.src_alpha_blend_factor = BlendFactor::kOne;
57+
color0.src_color_blend_factor = BlendFactor::kOne;
58+
break;
59+
case Entity::BlendMode::kDestinationOver:
60+
color0.dst_alpha_blend_factor = BlendFactor::kDestinationAlpha;
61+
color0.dst_color_blend_factor = BlendFactor::kOne;
62+
color0.src_alpha_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
63+
color0.src_color_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
64+
break;
65+
case Entity::BlendMode::kSourceIn:
66+
color0.dst_alpha_blend_factor = BlendFactor::kZero;
67+
color0.dst_color_blend_factor = BlendFactor::kZero;
68+
color0.src_alpha_blend_factor = BlendFactor::kDestinationAlpha;
69+
color0.src_color_blend_factor = BlendFactor::kDestinationAlpha;
70+
break;
71+
case Entity::BlendMode::kDestinationIn:
72+
color0.dst_alpha_blend_factor = BlendFactor::kSourceAlpha;
73+
color0.dst_color_blend_factor = BlendFactor::kSourceAlpha;
74+
color0.src_alpha_blend_factor = BlendFactor::kZero;
75+
color0.src_color_blend_factor = BlendFactor::kZero;
76+
break;
77+
case Entity::BlendMode::kSourceOut:
78+
color0.dst_alpha_blend_factor = BlendFactor::kZero;
79+
color0.dst_color_blend_factor = BlendFactor::kZero;
80+
color0.src_alpha_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
81+
color0.src_color_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
82+
break;
83+
case Entity::BlendMode::kDestinationOut:
84+
color0.dst_alpha_blend_factor = BlendFactor::kOneMinusSourceAlpha;
85+
color0.dst_color_blend_factor = BlendFactor::kOneMinusSourceAlpha;
86+
color0.src_alpha_blend_factor = BlendFactor::kZero;
87+
color0.src_color_blend_factor = BlendFactor::kZero;
88+
break;
89+
case Entity::BlendMode::kSourceATop:
90+
color0.dst_alpha_blend_factor = BlendFactor::kOneMinusSourceAlpha;
91+
color0.dst_color_blend_factor = BlendFactor::kOneMinusSourceAlpha;
92+
color0.src_alpha_blend_factor = BlendFactor::kDestinationAlpha;
93+
color0.src_color_blend_factor = BlendFactor::kDestinationAlpha;
94+
break;
95+
case Entity::BlendMode::kDestinationATop:
96+
color0.dst_alpha_blend_factor = BlendFactor::kSourceAlpha;
97+
color0.dst_color_blend_factor = BlendFactor::kSourceAlpha;
98+
color0.src_alpha_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
99+
color0.src_color_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
100+
break;
101+
case Entity::BlendMode::kXor:
102+
color0.dst_alpha_blend_factor = BlendFactor::kOneMinusSourceAlpha;
103+
color0.dst_color_blend_factor = BlendFactor::kOneMinusSourceAlpha;
104+
color0.src_alpha_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
105+
color0.src_color_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
106+
break;
107+
case Entity::BlendMode::kPlus:
108+
color0.dst_alpha_blend_factor = BlendFactor::kOne;
109+
color0.dst_color_blend_factor = BlendFactor::kOne;
110+
color0.src_alpha_blend_factor = BlendFactor::kOne;
111+
color0.src_color_blend_factor = BlendFactor::kOne;
112+
break;
113+
case Entity::BlendMode::kModulate:
114+
// kSourceColor and kDestinationColor override the alpha blend factor.
115+
color0.dst_alpha_blend_factor = BlendFactor::kZero;
116+
color0.dst_color_blend_factor = BlendFactor::kSourceColor;
117+
color0.src_alpha_blend_factor = BlendFactor::kZero;
118+
color0.src_color_blend_factor = BlendFactor::kZero;
119+
break;
120+
default:
121+
FML_UNREACHABLE();
122+
}
123+
desc.SetColorAttachmentDescriptor(0u, std::move(color0));
124+
125+
if (desc.GetFrontStencilAttachmentDescriptor().has_value()) {
126+
StencilAttachmentDescriptor stencil =
127+
desc.GetFrontStencilAttachmentDescriptor().value();
128+
stencil.stencil_compare = stencil_compare;
129+
stencil.depth_stencil_pass = stencil_operation;
130+
desc.SetStencilAttachmentDescriptors(stencil);
131+
}
132+
}
133+
134+
template <typename PipelineT>
135+
static std::unique_ptr<PipelineT> CreateDefaultPipeline(
136+
const Context& context) {
137+
auto desc = PipelineT::Builder::MakeDefaultPipelineDescriptor(context);
138+
if (!desc.has_value()) {
139+
return nullptr;
140+
}
141+
// Apply default ContentContextOptions to the descriptor.
142+
ContentContextOptions{}.ApplyToPipelineDescriptor(*desc);
143+
return std::make_unique<PipelineT>(context, desc);
144+
}
145+
16146
ContentContext::ContentContext(std::shared_ptr<Context> context)
17147
: context_(std::move(context)) {
18148
if (!context_ || !context_->IsValid()) {
19149
return;
20150
}
21151

22-
// Pipelines whose default descriptors work fine for the entity framework.
23152
gradient_fill_pipelines_[{}] =
24-
std::make_unique<GradientFillPipeline>(*context_);
25-
solid_fill_pipelines_[{}] = std::make_unique<SolidFillPipeline>(*context_);
153+
CreateDefaultPipeline<GradientFillPipeline>(*context_);
154+
solid_fill_pipelines_[{}] =
155+
CreateDefaultPipeline<SolidFillPipeline>(*context_);
26156
texture_blend_pipelines_[{}] =
27-
std::make_unique<TextureBlendPipeline>(*context_);
28-
texture_blend_screen_pipelines_[{}] =
29-
std::make_unique<TextureBlendScreenPipeline>(*context_);
30-
texture_pipelines_[{}] = std::make_unique<TexturePipeline>(*context_);
157+
CreateDefaultPipeline<BlendPipeline>(*context_);
158+
blend_screen_pipelines_[{}] =
159+
CreateDefaultPipeline<BlendScreenPipeline>(*context_);
160+
blend_colorburn_pipelines_[{}] =
161+
CreateDefaultPipeline<BlendColorburnPipeline>(*context_);
162+
texture_pipelines_[{}] = CreateDefaultPipeline<TexturePipeline>(*context_);
31163
gaussian_blur_pipelines_[{}] =
32-
std::make_unique<GaussianBlurPipeline>(*context_);
164+
CreateDefaultPipeline<GaussianBlurPipeline>(*context_);
33165
border_mask_blur_pipelines_[{}] =
34-
std::make_unique<BorderMaskBlurPipeline>(*context_);
166+
CreateDefaultPipeline<BorderMaskBlurPipeline>(*context_);
35167
solid_stroke_pipelines_[{}] =
36-
std::make_unique<SolidStrokePipeline>(*context_);
37-
glyph_atlas_pipelines_[{}] = std::make_unique<GlyphAtlasPipeline>(*context_);
168+
CreateDefaultPipeline<SolidStrokePipeline>(*context_);
169+
glyph_atlas_pipelines_[{}] =
170+
CreateDefaultPipeline<GlyphAtlasPipeline>(*context_);
38171

39172
// Pipelines that are variants of the base pipelines with custom descriptors.
40173
// TODO(98684): Rework this API to allow fetching the descriptor without

0 commit comments

Comments
 (0)