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

Commit bd44442

Browse files
author
Jonah Williams
authored
Merge branch 'main' into border_mask
2 parents 05bfb42 + 8850178 commit bd44442

File tree

7 files changed

+342
-347
lines changed

7 files changed

+342
-347
lines changed

impeller/entity/contents/filters/blend_filter_contents.cc

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <optional>
1010

1111
#include "impeller/core/formats.h"
12+
#include "impeller/entity/contents/anonymous_contents.h"
1213
#include "impeller/entity/contents/content_context.h"
1314
#include "impeller/entity/contents/contents.h"
1415
#include "impeller/entity/contents/filters/inputs/filter_input.h"
@@ -178,6 +179,168 @@ static std::optional<Entity> AdvancedBlend(
178179
entity.GetBlendMode(), entity.GetStencilDepth());
179180
}
180181

182+
std::optional<Entity> BlendFilterContents::CreateForegroundBlend(
183+
const std::shared_ptr<FilterInput>& input,
184+
const ContentContext& renderer,
185+
const Entity& entity,
186+
const Rect& coverage,
187+
Color foreground_color,
188+
BlendMode blend_mode,
189+
std::optional<Scalar> alpha,
190+
bool absorb_opacity) const {
191+
auto dst_snapshot = input->GetSnapshot(renderer, entity);
192+
if (!dst_snapshot.has_value()) {
193+
return std::nullopt;
194+
}
195+
196+
RenderProc render_proc = [foreground_color, coverage, dst_snapshot,
197+
blend_mode, alpha, absorb_opacity](
198+
const ContentContext& renderer,
199+
const Entity& entity, RenderPass& pass) -> bool {
200+
using VS = BlendScreenPipeline::VertexShader;
201+
using FS = BlendScreenPipeline::FragmentShader;
202+
203+
auto& host_buffer = pass.GetTransientsBuffer();
204+
205+
auto maybe_dst_uvs = dst_snapshot->GetCoverageUVs(coverage);
206+
if (!maybe_dst_uvs.has_value()) {
207+
return false;
208+
}
209+
auto dst_uvs = maybe_dst_uvs.value();
210+
211+
auto size = coverage.size;
212+
auto origin = coverage.origin;
213+
VertexBufferBuilder<VS::PerVertexData> vtx_builder;
214+
vtx_builder.AddVertices({
215+
{origin, dst_uvs[0], dst_uvs[0]},
216+
{Point(origin.x + size.width, origin.y), dst_uvs[1], dst_uvs[1]},
217+
{Point(origin.x + size.width, origin.y + size.height), dst_uvs[3],
218+
dst_uvs[3]},
219+
{origin, dst_uvs[0], dst_uvs[0]},
220+
{Point(origin.x + size.width, origin.y + size.height), dst_uvs[3],
221+
dst_uvs[3]},
222+
{Point(origin.x, origin.y + size.height), dst_uvs[2], dst_uvs[2]},
223+
});
224+
auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);
225+
226+
Command cmd;
227+
cmd.label = "Foreground Advanced Blend Filter";
228+
cmd.BindVertices(vtx_buffer);
229+
cmd.stencil_reference = entity.GetStencilDepth();
230+
auto options = OptionsFromPass(pass);
231+
232+
switch (blend_mode) {
233+
case BlendMode::kScreen:
234+
cmd.pipeline = renderer.GetBlendScreenPipeline(options);
235+
break;
236+
case BlendMode::kOverlay:
237+
cmd.pipeline = renderer.GetBlendOverlayPipeline(options);
238+
break;
239+
case BlendMode::kDarken:
240+
cmd.pipeline = renderer.GetBlendDarkenPipeline(options);
241+
break;
242+
case BlendMode::kLighten:
243+
cmd.pipeline = renderer.GetBlendLightenPipeline(options);
244+
break;
245+
case BlendMode::kColorDodge:
246+
cmd.pipeline = renderer.GetBlendColorDodgePipeline(options);
247+
break;
248+
case BlendMode::kColorBurn:
249+
cmd.pipeline = renderer.GetBlendColorBurnPipeline(options);
250+
break;
251+
case BlendMode::kHardLight:
252+
cmd.pipeline = renderer.GetBlendHardLightPipeline(options);
253+
break;
254+
case BlendMode::kSoftLight:
255+
cmd.pipeline = renderer.GetBlendSoftLightPipeline(options);
256+
break;
257+
case BlendMode::kDifference:
258+
cmd.pipeline = renderer.GetBlendDifferencePipeline(options);
259+
break;
260+
case BlendMode::kExclusion:
261+
cmd.pipeline = renderer.GetBlendExclusionPipeline(options);
262+
break;
263+
case BlendMode::kMultiply:
264+
cmd.pipeline = renderer.GetBlendMultiplyPipeline(options);
265+
break;
266+
case BlendMode::kHue:
267+
cmd.pipeline = renderer.GetBlendHuePipeline(options);
268+
break;
269+
case BlendMode::kSaturation:
270+
cmd.pipeline = renderer.GetBlendSaturationPipeline(options);
271+
break;
272+
case BlendMode::kColor:
273+
cmd.pipeline = renderer.GetBlendColorPipeline(options);
274+
break;
275+
case BlendMode::kLuminosity:
276+
cmd.pipeline = renderer.GetBlendLuminosityPipeline(options);
277+
break;
278+
default:
279+
return false;
280+
}
281+
282+
FS::BlendInfo blend_info;
283+
VS::FrameInfo frame_info;
284+
285+
auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor;
286+
if (renderer.GetDeviceCapabilities().SupportsDecalTileMode()) {
287+
dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
288+
dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
289+
}
290+
auto dst_sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler(
291+
dst_sampler_descriptor);
292+
FS::BindTextureSamplerDst(cmd, dst_snapshot->texture, dst_sampler);
293+
frame_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale();
294+
blend_info.dst_input_alpha =
295+
absorb_opacity ? dst_snapshot->opacity * alpha.value_or(1.0) : 1.0;
296+
297+
blend_info.color_factor = 1;
298+
blend_info.color = foreground_color;
299+
// This texture will not be sampled from due to the color factor. But
300+
// this is present so that validation doesn't trip on a missing
301+
// binding.
302+
FS::BindTextureSamplerSrc(cmd, dst_snapshot->texture, dst_sampler);
303+
304+
auto blend_uniform = host_buffer.EmplaceUniform(blend_info);
305+
FS::BindBlendInfo(cmd, blend_uniform);
306+
307+
frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize());
308+
309+
auto uniform_view = host_buffer.EmplaceUniform(frame_info);
310+
VS::BindFrameInfo(cmd, uniform_view);
311+
312+
return pass.AddCommand(cmd);
313+
};
314+
CoverageProc coverage_proc =
315+
[coverage](const Entity& entity) -> std::optional<Rect> {
316+
return coverage;
317+
};
318+
319+
auto contents = AnonymousContents::Make(render_proc, coverage_proc);
320+
321+
// If there is pending opacity but it was not absorbed by this entity, we have
322+
// to convert this back to a snapshot so it can be passed on. This generally
323+
// implies that there is another filter about to run, so we'd perform this
324+
// operation anyway.
325+
auto potential_opacity = alpha.value_or(1.0) * dst_snapshot->opacity;
326+
if (!absorb_opacity && potential_opacity < 1.0) {
327+
auto result_snapshot = contents->RenderToSnapshot(renderer, entity);
328+
if (!result_snapshot.has_value()) {
329+
return std::nullopt;
330+
}
331+
result_snapshot->opacity = potential_opacity;
332+
return Entity::FromSnapshot(result_snapshot.value(), entity.GetBlendMode(),
333+
entity.GetStencilDepth());
334+
}
335+
336+
Entity sub_entity;
337+
sub_entity.SetContents(std::move(contents));
338+
sub_entity.SetStencilDepth(entity.GetStencilDepth());
339+
sub_entity.SetTransformation(entity.GetTransformation());
340+
341+
return sub_entity;
342+
}
343+
181344
static std::optional<Entity> PipelineBlend(
182345
const FilterInput::Vector& inputs,
183346
const ContentContext& renderer,
@@ -373,6 +536,12 @@ std::optional<Entity> BlendFilterContents::RenderFilter(
373536
}
374537

375538
if (blend_mode_ <= Entity::kLastAdvancedBlendMode) {
539+
if (inputs.size() == 1 && foreground_color_.has_value()) {
540+
return CreateForegroundBlend(inputs[0], renderer, entity, coverage,
541+
foreground_color_.value(), blend_mode_,
542+
GetAlpha(), GetAbsorbOpacity());
543+
}
544+
376545
return advanced_blend_proc_(inputs, renderer, entity, coverage,
377546
foreground_color_, GetAbsorbOpacity(),
378547
GetAlpha());

impeller/entity/contents/filters/blend_filter_contents.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,20 @@ class BlendFilterContents : public ColorFilterContents {
3838
const Matrix& effect_transform,
3939
const Rect& coverage) const override;
4040

41+
/// @brief Optimized advanced blend that avoids a second subpass when there is
42+
/// only a single input and a foreground color.
43+
///
44+
/// These contents cannot absorb opacity.
45+
std::optional<Entity> CreateForegroundBlend(
46+
const std::shared_ptr<FilterInput>& input,
47+
const ContentContext& renderer,
48+
const Entity& entity,
49+
const Rect& coverage,
50+
Color foreground_color,
51+
BlendMode blend_mode,
52+
std::optional<Scalar> alpha,
53+
bool absorb_opacity) const;
54+
4155
BlendMode blend_mode_ = BlendMode::kSourceOver;
4256
AdvancedBlendProc advanced_blend_proc_;
4357
std::optional<Color> foreground_color_;

lib/ui/platform_dispatcher.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1155,7 +1155,7 @@ class PlatformDispatcher {
11551155
onSemanticsAction,
11561156
_onSemanticsActionZone,
11571157
nodeId,
1158-
SemanticsAction.values[action]!,
1158+
SemanticsAction.fromIndex(action)!,
11591159
args,
11601160
);
11611161
}

0 commit comments

Comments
 (0)