| Flutter Impeller |

blend_filter_contents.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/entity/contents/filters/blend_filter_contents.h"
6
7 #include <array>
8 #include <memory>
9 #include <optional>
10
11 #include "flutter/fml/logging.h"
12 #include "impeller/base/strings.h"
13 #include "impeller/core/formats.h"
14 #include "impeller/core/sampler_descriptor.h"
15 #include "impeller/core/texture_descriptor.h"
16 #include "impeller/core/vertex_buffer.h"
17 #include "impeller/entity/contents/anonymous_contents.h"
18 #include "impeller/entity/contents/content_context.h"
19 #include "impeller/entity/contents/contents.h"
20 #include "impeller/entity/contents/filters/color_filter_contents.h"
21 #include "impeller/entity/contents/filters/inputs/filter_input.h"
22 #include "impeller/entity/contents/solid_color_contents.h"
23 #include "impeller/entity/entity.h"
24 #include "impeller/entity/geometry/rect_geometry.h"
25 #include "impeller/entity/texture_fill.frag.h"
26 #include "impeller/entity/texture_fill.vert.h"
27 #include "impeller/geometry/color.h"
28 #include "impeller/renderer/render_pass.h"
29 #include "impeller/renderer/snapshot.h"
30
31 namespace impeller {
32
33 namespace {
34
35 #ifdef IMPELLER_DEBUG
36
37 #define _IMPELLER_BLEND_MODE_FILTER_NAME_LIST(blend_mode) \
38 "Blend Filter " #blend_mode,
39
40 static constexpr const char* kBlendModeFilterNames[] = {
41 IMPELLER_FOR_EACH_BLEND_MODE(_IMPELLER_BLEND_MODE_FILTER_NAME_LIST)};
42
43 const std::string_view BlendModeToFilterString(BlendMode blend_mode) {
44 return kBlendModeFilterNames[static_cast<std::underlying_type_t<BlendMode>>(
45 blend_mode)];
46 }
47 #endif // IMPELLER_DEBUG
48
49 } // namespace
50
51 std::optional<BlendMode> InvertPorterDuffBlend(BlendMode blend_mode) {
52 switch (blend_mode) {
53 case BlendMode::kClear:
54 return BlendMode::kClear;
55 case BlendMode::kSource:
56 return BlendMode::kDestination;
57 case BlendMode::kDestination:
58 return BlendMode::kSource;
59 case BlendMode::kSourceOver:
60 return BlendMode::kDestinationOver;
61 case BlendMode::kDestinationOver:
62 return BlendMode::kSourceOver;
63 case BlendMode::kSourceIn:
64 return BlendMode::kDestinationIn;
65 case BlendMode::kDestinationIn:
66 return BlendMode::kSourceIn;
67 case BlendMode::kSourceOut:
68 return BlendMode::kDestinationOut;
69 case BlendMode::kDestinationOut:
70 return BlendMode::kSourceOut;
71 case BlendMode::kSourceATop:
72 return BlendMode::kDestinationATop;
73 case BlendMode::kDestinationATop:
74 return BlendMode::kSourceATop;
75 case BlendMode::kXor:
76 return BlendMode::kXor;
77 case BlendMode::kPlus:
78 return BlendMode::kPlus;
79 case BlendMode::kModulate:
80 return BlendMode::kModulate;
81 default:
82 return std::nullopt;
83 }
84 }
85
86 BlendFilterContents::BlendFilterContents() {
87 SetBlendMode(BlendMode::kSourceOver);
88 }
89
90 BlendFilterContents::~BlendFilterContents() = default;
91
92 using PipelineProc =
93 PipelineRef (ContentContext::*)(ContentContextOptions) const;
94
95 template <typename TPipeline>
96 static std::optional<Entity> AdvancedBlend(
97 const FilterInput::Vector& inputs,
98 const ContentContext& renderer,
99 const Entity& entity,
100 const Rect& coverage,
101 BlendMode blend_mode,
102 std::optional<Color> foreground_color,
103 ColorFilterContents::AbsorbOpacity absorb_opacity,
104 PipelineProc pipeline_proc,
105 std::optional<Scalar> alpha) {
106 using VS = typename TPipeline::VertexShader;
107 using FS = typename TPipeline::FragmentShader;
108
109 //----------------------------------------------------------------------------
110 /// Handle inputs.
111 ///
112
113 const size_t total_inputs =
114 inputs.size() + (foreground_color.has_value() ? 1 : 0);
115 if (total_inputs < 2) {
116 return std::nullopt;
117 }
118
119 auto dst_snapshot =
120 inputs[0]->GetSnapshot("AdvancedBlend(Dst)", renderer, entity);
121 if (!dst_snapshot.has_value()) {
122 return std::nullopt;
123 }
124 auto maybe_dst_uvs = dst_snapshot->GetCoverageUVs(coverage);
125 if (!maybe_dst_uvs.has_value()) {
126 return std::nullopt;
127 }
128 auto dst_uvs = maybe_dst_uvs.value();
129
130 std::optional<Snapshot> src_snapshot;
131 std::array<Point, 4> src_uvs;
132 if (!foreground_color.has_value()) {
133 src_snapshot =
134 inputs[1]->GetSnapshot("AdvancedBlend(Src)", renderer, entity);
135 if (!src_snapshot.has_value()) {
136 if (!dst_snapshot.has_value()) {
137 return std::nullopt;
138 }
139 return Entity::FromSnapshot(dst_snapshot.value(), entity.GetBlendMode());
140 }
141 auto maybe_src_uvs = src_snapshot->GetCoverageUVs(coverage);
142 if (!maybe_src_uvs.has_value()) {
143 if (!dst_snapshot.has_value()) {
144 return std::nullopt;
145 }
146 return Entity::FromSnapshot(dst_snapshot.value(), entity.GetBlendMode());
147 }
148 src_uvs = maybe_src_uvs.value();
149 }
150
151 Rect subpass_coverage = coverage;
152 if (entity.GetContents()) {
153 auto coverage_hint = entity.GetContents()->GetCoverageHint();
154
155 if (coverage_hint.has_value()) {
156 auto maybe_subpass_coverage =
157 subpass_coverage.Intersection(*coverage_hint);
158 if (!maybe_subpass_coverage.has_value()) {
159 return std::nullopt; // Nothing to render.
160 }
161
162 subpass_coverage = *maybe_subpass_coverage;
163 }
164 }
165
166 //----------------------------------------------------------------------------
167 /// Render to texture.
168 ///
169
170 ContentContext::SubpassCallback callback = [&](const ContentContext& renderer,
171 RenderPass& pass) {
172 auto& host_buffer = renderer.GetTransientsBuffer();
173
174 auto size = pass.GetRenderTargetSize();
175
176 std::array<typename VS::PerVertexData, 4> vertices = {
177 typename VS::PerVertexData{Point(0, 0), dst_uvs[0], src_uvs[0]},
178 typename VS::PerVertexData{Point(size.width, 0), dst_uvs[1],
179 src_uvs[1]},
180 typename VS::PerVertexData{Point(0, size.height), dst_uvs[2],
181 src_uvs[2]},
182 typename VS::PerVertexData{Point(size.width, size.height), dst_uvs[3],
183 src_uvs[3]},
184 };
185 auto vtx_buffer =
186 CreateVertexBuffer(vertices, renderer.GetTransientsBuffer());
187
188 auto options = OptionsFromPass(pass);
189 options.primitive_type = PrimitiveType::kTriangleStrip;
190 options.blend_mode = BlendMode::kSource;
191 PipelineRef pipeline = std::invoke(pipeline_proc, renderer, options);
192
193 #ifdef IMPELLER_DEBUG
194 pass.SetCommandLabel(BlendModeToFilterString(blend_mode));
195 #endif // IMPELLER_DEBUG
196 pass.SetVertexBuffer(std::move(vtx_buffer));
197 pass.SetPipeline(pipeline);
198
199 typename FS::BlendInfo blend_info;
200 typename VS::FrameInfo frame_info;
201
202 auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor;
203 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
204 dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
205 dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
206 }
207 raw_ptr<const Sampler> dst_sampler =
208 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
209 dst_sampler_descriptor);
210 FS::BindTextureSamplerDst(pass, dst_snapshot->texture, dst_sampler);
211 frame_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale();
212 blend_info.dst_input_alpha =
213 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
214 ? dst_snapshot->opacity
215 : 1.0;
216
217 if (foreground_color.has_value()) {
218 blend_info.color_factor = 1;
219 blend_info.color = foreground_color.value();
220 // This texture will not be sampled from due to the color factor. But
221 // this is present so that validation doesn't trip on a missing
222 // binding.
223 FS::BindTextureSamplerSrc(pass, dst_snapshot->texture, dst_sampler);
224 } else {
225 auto src_sampler_descriptor = src_snapshot->sampler_descriptor;
226 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
227 src_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
228 src_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
229 }
230 raw_ptr<const Sampler> src_sampler =
231 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
232 src_sampler_descriptor);
233 blend_info.color_factor = 0;
234 blend_info.src_input_alpha = src_snapshot->opacity;
235 FS::BindTextureSamplerSrc(pass, src_snapshot->texture, src_sampler);
236 frame_info.src_y_coord_scale = src_snapshot->texture->GetYCoordScale();
237 }
238 auto blend_uniform = host_buffer.EmplaceUniform(blend_info);
239 FS::BindBlendInfo(pass, blend_uniform);
240
241 frame_info.mvp = pass.GetOrthographicTransform() *
242 Matrix::MakeTranslation(coverage.GetOrigin() -
243 subpass_coverage.GetOrigin());
244
245 auto uniform_view = host_buffer.EmplaceUniform(frame_info);
246 VS::BindFrameInfo(pass, uniform_view);
247
248 return pass.Draw().ok();
249 };
250
251 std::shared_ptr<CommandBuffer> command_buffer =
252 renderer.GetContext()->CreateCommandBuffer();
253 if (!command_buffer) {
254 return std::nullopt;
255 }
256 fml::StatusOr<RenderTarget> render_target = renderer.MakeSubpass(
257 "Advanced Blend Filter", ISize(subpass_coverage.GetSize()),
258 command_buffer, callback);
259 if (!render_target.ok()) {
260 return std::nullopt;
261 }
262 if (!renderer.GetContext()->EnqueueCommandBuffer(std::move(command_buffer))) {
263 return std::nullopt;
264 }
265
266 return Entity::FromSnapshot(
267 Snapshot{
268 .texture = render_target.value().GetRenderTargetTexture(),
269 .transform = Matrix::MakeTranslation(subpass_coverage.GetOrigin()),
270 // Since we absorbed the transform of the inputs and used the
271 // respective snapshot sampling modes when blending, pass on
272 // the default NN clamp sampler.
273 .sampler_descriptor = {},
274 .opacity = (absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
275 ? 1.0f
276 : dst_snapshot->opacity) *
277 alpha.value_or(1.0)},
278 entity.GetBlendMode());
279 }
280
281 std::optional<Entity> BlendFilterContents::CreateForegroundAdvancedBlend(
282 const std::shared_ptr<FilterInput>& input,
283 const ContentContext& renderer,
284 const Entity& entity,
285 const Rect& coverage,
286 Color foreground_color,
287 BlendMode blend_mode,
288 std::optional<Scalar> alpha,
289 ColorFilterContents::AbsorbOpacity absorb_opacity) const {
290 auto dst_snapshot =
291 input->GetSnapshot("ForegroundAdvancedBlend", renderer, entity);
292 if (!dst_snapshot.has_value()) {
293 return std::nullopt;
294 }
295
296 RenderProc render_proc = [foreground_color, dst_snapshot, blend_mode, alpha,
297 absorb_opacity](const ContentContext& renderer,
298 const Entity& entity,
299 RenderPass& pass) -> bool {
300 using VS = BlendScreenPipeline::VertexShader;
301 using FS = BlendScreenPipeline::FragmentShader;
302
303 auto& host_buffer = renderer.GetTransientsBuffer();
304 auto size = dst_snapshot->texture->GetSize();
305
306 std::array<VS::PerVertexData, 4> vertices = {
307 VS::PerVertexData{{0, 0}, {0, 0}, {0, 0}},
308 VS::PerVertexData{Point(size.width, 0), {1, 0}, {1, 0}},
309 VS::PerVertexData{Point(0, size.height), {0, 1}, {0, 1}},
310 VS::PerVertexData{Point(size.width, size.height), {1, 1}, {1, 1}},
311 };
312 auto vtx_buffer =
313 CreateVertexBuffer(vertices, renderer.GetTransientsBuffer());
314
315 #ifdef IMPELLER_DEBUG
316 pass.SetCommandLabel(BlendModeToFilterString(blend_mode));
317 #endif // IMPELLER_DEBUG
318 pass.SetVertexBuffer(std::move(vtx_buffer));
319 auto options = OptionsFromPassAndEntity(pass, entity);
320 options.primitive_type = PrimitiveType::kTriangleStrip;
321
322 switch (blend_mode) {
323 case BlendMode::kScreen:
324 pass.SetPipeline(renderer.GetBlendScreenPipeline(options));
325 break;
326 case BlendMode::kOverlay:
327 pass.SetPipeline(renderer.GetBlendOverlayPipeline(options));
328 break;
329 case BlendMode::kDarken:
330 pass.SetPipeline(renderer.GetBlendDarkenPipeline(options));
331 break;
332 case BlendMode::kLighten:
333 pass.SetPipeline(renderer.GetBlendLightenPipeline(options));
334 break;
335 case BlendMode::kColorDodge:
336 pass.SetPipeline(renderer.GetBlendColorDodgePipeline(options));
337 break;
338 case BlendMode::kColorBurn:
339 pass.SetPipeline(renderer.GetBlendColorBurnPipeline(options));
340 break;
341 case BlendMode::kHardLight:
342 pass.SetPipeline(renderer.GetBlendHardLightPipeline(options));
343 break;
344 case BlendMode::kSoftLight:
345 pass.SetPipeline(renderer.GetBlendSoftLightPipeline(options));
346 break;
347 case BlendMode::kDifference:
348 pass.SetPipeline(renderer.GetBlendDifferencePipeline(options));
349 break;
350 case BlendMode::kExclusion:
351 pass.SetPipeline(renderer.GetBlendExclusionPipeline(options));
352 break;
353 case BlendMode::kMultiply:
354 pass.SetPipeline(renderer.GetBlendMultiplyPipeline(options));
355 break;
356 case BlendMode::kHue:
357 pass.SetPipeline(renderer.GetBlendHuePipeline(options));
358 break;
359 case BlendMode::kSaturation:
360 pass.SetPipeline(renderer.GetBlendSaturationPipeline(options));
361 break;
362 case BlendMode::kColor:
363 pass.SetPipeline(renderer.GetBlendColorPipeline(options));
364 break;
365 case BlendMode::kLuminosity:
366 pass.SetPipeline(renderer.GetBlendLuminosityPipeline(options));
367 break;
368 default:
369 return false;
370 }
371
372 FS::BlendInfo blend_info;
373 VS::FrameInfo frame_info;
374
375 auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor;
376 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
377 dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
378 dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
379 }
380 raw_ptr<const Sampler> dst_sampler =
381 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
382 dst_sampler_descriptor);
383 FS::BindTextureSamplerDst(pass, dst_snapshot->texture, dst_sampler);
384 frame_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale();
385
386 frame_info.mvp = Entity::GetShaderTransform(
387 entity.GetShaderClipDepth(), pass,
388 entity.GetTransform() * dst_snapshot->transform);
389
390 blend_info.dst_input_alpha =
391 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
392 ? dst_snapshot->opacity * alpha.value_or(1.0)
393 : 1.0;
394
395 blend_info.color_factor = 1;
396 blend_info.color = foreground_color;
397 // This texture will not be sampled from due to the color factor. But
398 // this is present so that validation doesn't trip on a missing
399 // binding.
400 FS::BindTextureSamplerSrc(pass, dst_snapshot->texture, dst_sampler);
401
402 auto blend_uniform = host_buffer.EmplaceUniform(blend_info);
403 FS::BindBlendInfo(pass, blend_uniform);
404
405 auto uniform_view = host_buffer.EmplaceUniform(frame_info);
406 VS::BindFrameInfo(pass, uniform_view);
407
408 return pass.Draw().ok();
409 };
410 CoverageProc coverage_proc =
411 [coverage](const Entity& entity) -> std::optional<Rect> {
412 return coverage.TransformBounds(entity.GetTransform());
413 };
414
415 auto contents = AnonymousContents::Make(render_proc, coverage_proc);
416
417 Entity sub_entity;
418 sub_entity.SetContents(std::move(contents));
419 sub_entity.SetBlendMode(entity.GetBlendMode());
420
421 return sub_entity;
422 }
423
424 std::optional<Entity> BlendFilterContents::CreateForegroundPorterDuffBlend(
425 const std::shared_ptr<FilterInput>& input,
426 const ContentContext& renderer,
427 const Entity& entity,
428 const Rect& coverage,
429 Color foreground_color,
430 BlendMode blend_mode,
431 std::optional<Scalar> alpha,
432 ColorFilterContents::AbsorbOpacity absorb_opacity) const {
433 if (blend_mode == BlendMode::kClear) {
434 return std::nullopt;
435 }
436
437 auto dst_snapshot =
438 input->GetSnapshot("ForegroundPorterDuffBlend", renderer, entity);
439 if (!dst_snapshot.has_value()) {
440 return std::nullopt;
441 }
442
443 if (blend_mode == BlendMode::kDestination) {
444 return Entity::FromSnapshot(dst_snapshot.value(), entity.GetBlendMode());
445 }
446
447 RenderProc render_proc = [foreground_color, dst_snapshot, blend_mode,
448 absorb_opacity, alpha](
449 const ContentContext& renderer,
450 const Entity& entity, RenderPass& pass) -> bool {
451 using VS = PorterDuffBlendPipeline::VertexShader;
452 using FS = PorterDuffBlendPipeline::FragmentShader;
453
454 auto& host_buffer = renderer.GetTransientsBuffer();
455 auto size = dst_snapshot->texture->GetSize();
456 auto color = foreground_color.Premultiply();
457
458 std::array<VS::PerVertexData, 4> vertices = {
459 VS::PerVertexData{{0, 0}, {0, 0}, color},
460 VS::PerVertexData{Point(size.width, 0), {1, 0}, color},
461 VS::PerVertexData{Point(0, size.height), {0, 1}, color},
462 VS::PerVertexData{Point(size.width, size.height), {1, 1}, color},
463 };
464 auto vtx_buffer =
465 CreateVertexBuffer(vertices, renderer.GetTransientsBuffer());
466
467 #ifdef IMPELLER_DEBUG
468 pass.SetCommandLabel(BlendModeToFilterString(blend_mode));
469 #endif // IMPELLER_DEBUG
470 pass.SetVertexBuffer(std::move(vtx_buffer));
471 auto options = OptionsFromPassAndEntity(pass, entity);
472 options.primitive_type = PrimitiveType::kTriangleStrip;
473 pass.SetPipeline(renderer.GetPorterDuffPipeline(blend_mode, options));
474
475 FS::FragInfo frag_info;
476 VS::FrameInfo frame_info;
477
478 frame_info.mvp = Entity::GetShaderTransform(
479 entity.GetShaderClipDepth(), pass,
480 entity.GetTransform() * dst_snapshot->transform);
481
482 auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor;
483 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
484 dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
485 dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
486 }
487 raw_ptr<const Sampler> dst_sampler =
488 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
489 dst_sampler_descriptor);
490 FS::BindTextureSamplerDst(pass, dst_snapshot->texture, dst_sampler);
491 frame_info.texture_sampler_y_coord_scale =
492 dst_snapshot->texture->GetYCoordScale();
493
494 frag_info.input_alpha =
495 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
496 ? dst_snapshot->opacity * alpha.value_or(1.0)
497 : 1.0;
498 frag_info.output_alpha = 1.0;
499
500 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
501 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
502
503 return pass.Draw().ok();
504 };
505
506 CoverageProc coverage_proc =
507 [coverage](const Entity& entity) -> std::optional<Rect> {
508 return coverage.TransformBounds(entity.GetTransform());
509 };
510
511 auto contents = AnonymousContents::Make(render_proc, coverage_proc);
512
513 Entity sub_entity;
514 sub_entity.SetContents(std::move(contents));
515 sub_entity.SetBlendMode(entity.GetBlendMode());
516
517 return sub_entity;
518 }
519
520 static std::optional<Entity> PipelineBlend(
521 const FilterInput::Vector& inputs,
522 const ContentContext& renderer,
523 const Entity& entity,
524 const Rect& coverage,
525 BlendMode blend_mode,
526 std::optional<Color> foreground_color,
527 ColorFilterContents::AbsorbOpacity absorb_opacity,
528 std::optional<Scalar> alpha) {
529 using VS = TexturePipeline::VertexShader;
530 using FS = TexturePipeline::FragmentShader;
531
532 auto dst_snapshot =
533 inputs[0]->GetSnapshot("PipelineBlend(Dst)", renderer, entity);
534 if (!dst_snapshot.has_value()) {
535 return std::nullopt; // Nothing to render.
536 }
537
538 Rect subpass_coverage = coverage;
539 if (entity.GetContents()) {
540 auto coverage_hint = entity.GetContents()->GetCoverageHint();
541
542 if (coverage_hint.has_value()) {
543 auto maybe_subpass_coverage =
544 subpass_coverage.Intersection(*coverage_hint);
545 if (!maybe_subpass_coverage.has_value()) {
546 return std::nullopt; // Nothing to render.
547 }
548
549 subpass_coverage = *maybe_subpass_coverage;
550 }
551 }
552
553 ContentContext::SubpassCallback callback = [&](const ContentContext& renderer,
554 RenderPass& pass) {
555 auto& host_buffer = renderer.GetTransientsBuffer();
556
557 #ifdef IMPELLER_DEBUG
558 pass.SetCommandLabel(BlendModeToFilterString(blend_mode));
559 #endif // IMPELLER_DEBUG
560 auto options = OptionsFromPass(pass);
561 options.primitive_type = PrimitiveType::kTriangleStrip;
562
563 auto add_blend_command = [&](std::optional<Snapshot> input) {
564 if (!input.has_value()) {
565 return false;
566 }
567 auto input_coverage = input->GetCoverage();
568 if (!input_coverage.has_value()) {
569 return false;
570 }
571
572 raw_ptr<const Sampler> sampler =
573 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
574 input->sampler_descriptor);
575 FS::BindTextureSampler(pass, input->texture, sampler);
576
577 auto size = input->texture->GetSize();
578 std::array<VS::PerVertexData, 4> vertices = {
579 VS::PerVertexData{Point(0, 0), Point(0, 0)},
580 VS::PerVertexData{Point(size.width, 0), Point(1, 0)},
581 VS::PerVertexData{Point(0, size.height), Point(0, 1)},
582 VS::PerVertexData{Point(size.width, size.height), Point(1, 1)},
583 };
584 pass.SetVertexBuffer(
585 CreateVertexBuffer(vertices, renderer.GetTransientsBuffer()));
586
587 VS::FrameInfo frame_info;
588 frame_info.mvp = pass.GetOrthographicTransform() *
589 Matrix::MakeTranslation(-subpass_coverage.GetOrigin()) *
590 input->transform;
591 frame_info.texture_sampler_y_coord_scale =
592 input->texture->GetYCoordScale();
593
594 FS::FragInfo frag_info;
595 frag_info.alpha =
596 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
597 ? input->opacity
598 : 1.0;
599 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
600 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
601
602 return pass.Draw().ok();
603 };
604
605 // Draw the first texture using kSource.
606 options.blend_mode = BlendMode::kSource;
607 pass.SetPipeline(renderer.GetTexturePipeline(options));
608 if (!add_blend_command(dst_snapshot)) {
609 return true;
610 }
611
612 // Write subsequent textures using the selected blend mode.
613
614 if (inputs.size() >= 2) {
615 options.blend_mode = blend_mode;
616 pass.SetPipeline(renderer.GetTexturePipeline(options));
617
618 for (auto texture_i = inputs.begin() + 1; texture_i < inputs.end();
619 texture_i++) {
620 auto src_input = texture_i->get()->GetSnapshot("PipelineBlend(Src)",
621 renderer, entity);
622 if (!add_blend_command(src_input)) {
623 return true;
624 }
625 }
626 }
627
628 // If a foreground color is set, blend it in.
629
630 if (foreground_color.has_value()) {
631 auto contents = std::make_shared<SolidColorContents>();
632 RectGeometry geom(Rect::MakeSize(pass.GetRenderTargetSize()));
633 contents->SetGeometry(&geom);
634 contents->SetColor(foreground_color.value());
635
636 Entity foreground_entity;
637 foreground_entity.SetBlendMode(blend_mode);
638 foreground_entity.SetContents(contents);
639 if (!foreground_entity.Render(renderer, pass)) {
640 return false;
641 }
642 }
643
644 return true;
645 };
646
647 std::shared_ptr<CommandBuffer> command_buffer =
648 renderer.GetContext()->CreateCommandBuffer();
649 if (!command_buffer) {
650 return std::nullopt;
651 }
652
653 fml::StatusOr<RenderTarget> render_target = renderer.MakeSubpass(
654 "Pipeline Blend Filter", ISize(subpass_coverage.GetSize()),
655 command_buffer, callback);
656
657 if (!render_target.ok()) {
658 return std::nullopt;
659 }
660 if (!renderer.GetContext()->EnqueueCommandBuffer(std::move(command_buffer))) {
661 return std::nullopt;
662 }
663
664 return Entity::FromSnapshot(
665 Snapshot{
666 .texture = render_target.value().GetRenderTargetTexture(),
667 .transform = Matrix::MakeTranslation(subpass_coverage.GetOrigin()),
668 // Since we absorbed the transform of the inputs and used the
669 // respective snapshot sampling modes when blending, pass on
670 // the default NN clamp sampler.
671 .sampler_descriptor = {},
672 .opacity = (absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
673 ? 1.0f
674 : dst_snapshot->opacity) *
675 alpha.value_or(1.0)},
676 entity.GetBlendMode());
677 }
678
679 std::optional<Entity> BlendFilterContents::CreateFramebufferAdvancedBlend(
680 const FilterInput::Vector& inputs,
681 const ContentContext& renderer,
682 const Entity& entity,
683 const Rect& coverage,
684 std::optional<Color> foreground_color,
685 BlendMode blend_mode,
686 std::optional<Scalar> alpha,
687 ColorFilterContents::AbsorbOpacity absorb_opacity) const {
688 // This works with either 2 contents or 1 contents and a foreground color.
689 FML_DCHECK(inputs.size() == 2u ||
690 (inputs.size() == 1u && foreground_color.has_value()));
691
692 auto dst_snapshot =
693 inputs[0]->GetSnapshot("ForegroundAdvancedBlend", renderer, entity);
694 if (!dst_snapshot.has_value()) {
695 return std::nullopt;
696 }
697
698 std::shared_ptr<Texture> foreground_texture;
699
700 ContentContext::SubpassCallback subpass_callback = [&](const ContentContext&
701 renderer,
702 RenderPass& pass) {
703 // First, we create a new render pass and populate it with the contents
704 // of the first (dst) input.
705 HostBuffer& host_buffer = renderer.GetTransientsBuffer();
706
707 {
708 using FS = TextureFillFragmentShader;
709 using VS = TextureFillVertexShader;
710
711 pass.SetCommandLabel("Framebuffer Advanced Blend");
712 auto pipeline_options = OptionsFromPass(pass);
713 pipeline_options.primitive_type = PrimitiveType::kTriangleStrip;
714 pass.SetPipeline(renderer.GetTexturePipeline(pipeline_options));
715
716 VS::FrameInfo frame_info;
717 frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1));
718 frame_info.texture_sampler_y_coord_scale = 1.0;
719
720 FS::FragInfo frag_info;
721 frag_info.alpha = 1.0;
722
723 std::array<VS::PerVertexData, 4> vertices = {
724 VS::PerVertexData{{0, 0}, {0, 0}},
725 VS::PerVertexData{Point(1, 0), {1, 0}},
726 VS::PerVertexData{Point(0, 1), {0, 1}},
727 VS::PerVertexData{Point(1, 1), {1, 1}},
728 };
729 pass.SetVertexBuffer(
730 CreateVertexBuffer(vertices, renderer.GetTransientsBuffer()));
731
732 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
733 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
734 FS::BindTextureSampler(
735 pass, dst_snapshot->texture,
736 renderer.GetContext()->GetSamplerLibrary()->GetSampler({}));
737
738 if (!pass.Draw().ok()) {
739 return false;
740 }
741 }
742
743 {
744 using VS = FramebufferBlendScreenPipeline::VertexShader;
745 using FS = FramebufferBlendScreenPipeline::FragmentShader;
746
747 // Next, we render the second contents to a snapshot, or create a 1x1
748 // texture for the foreground color.
749 std::shared_ptr<Texture> src_texture;
750 if (foreground_color.has_value()) {
751 src_texture = foreground_texture;
752 } else {
753 auto src_snapshot =
754 inputs[0]->GetSnapshot("ForegroundAdvancedBlend", renderer, entity);
755 if (!src_snapshot.has_value()) {
756 return false;
757 }
758 // This doesn't really handle the case where the transforms are wildly
759 // different, but we only need to support blending two contents together
760 // in limited circumstances (mask blur).
761 src_texture = src_snapshot->texture;
762 }
763
764 std::array<VS::PerVertexData, 4> vertices = {
765 VS::PerVertexData{Point(0, 0), Point(0, 0)},
766 VS::PerVertexData{Point(1, 0), Point(1, 0)},
767 VS::PerVertexData{Point(0, 1), Point(0, 1)},
768 VS::PerVertexData{Point(1, 1), Point(1, 1)},
769 };
770
771 auto options = OptionsFromPass(pass);
772 options.blend_mode = BlendMode::kSource;
773 options.primitive_type = PrimitiveType::kTriangleStrip;
774
775 pass.SetCommandLabel("Framebuffer Advanced Blend Filter");
776 pass.SetVertexBuffer(
777 CreateVertexBuffer(vertices, renderer.GetTransientsBuffer()));
778
779 switch (blend_mode) {
780 case BlendMode::kScreen:
781 pass.SetPipeline(renderer.GetFramebufferBlendScreenPipeline(options));
782 break;
783 case BlendMode::kOverlay:
784 pass.SetPipeline(
785 renderer.GetFramebufferBlendOverlayPipeline(options));
786 break;
787 case BlendMode::kDarken:
788 pass.SetPipeline(renderer.GetFramebufferBlendDarkenPipeline(options));
789 break;
790 case BlendMode::kLighten:
791 pass.SetPipeline(
792 renderer.GetFramebufferBlendLightenPipeline(options));
793 break;
794 case BlendMode::kColorDodge:
795 pass.SetPipeline(
796 renderer.GetFramebufferBlendColorDodgePipeline(options));
797 break;
798 case BlendMode::kColorBurn:
799 pass.SetPipeline(
800 renderer.GetFramebufferBlendColorBurnPipeline(options));
801 break;
802 case BlendMode::kHardLight:
803 pass.SetPipeline(
804 renderer.GetFramebufferBlendHardLightPipeline(options));
805 break;
806 case BlendMode::kSoftLight:
807 pass.SetPipeline(
808 renderer.GetFramebufferBlendSoftLightPipeline(options));
809 break;
810 case BlendMode::kDifference:
811 pass.SetPipeline(
812 renderer.GetFramebufferBlendDifferencePipeline(options));
813 break;
814 case BlendMode::kExclusion:
815 pass.SetPipeline(
816 renderer.GetFramebufferBlendExclusionPipeline(options));
817 break;
818 case BlendMode::kMultiply:
819 pass.SetPipeline(
820 renderer.GetFramebufferBlendMultiplyPipeline(options));
821 break;
822 case BlendMode::kHue:
823 pass.SetPipeline(renderer.GetFramebufferBlendHuePipeline(options));
824 break;
825 case BlendMode::kSaturation:
826 pass.SetPipeline(
827 renderer.GetFramebufferBlendSaturationPipeline(options));
828 break;
829 case BlendMode::kColor:
830 pass.SetPipeline(renderer.GetFramebufferBlendColorPipeline(options));
831 break;
832 case BlendMode::kLuminosity:
833 pass.SetPipeline(
834 renderer.GetFramebufferBlendLuminosityPipeline(options));
835 break;
836 default:
837 return false;
838 }
839
840 VS::FrameInfo frame_info;
841 FS::FragInfo frag_info;
842
843 auto src_sampler_descriptor = SamplerDescriptor{};
844 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
845 src_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
846 src_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
847 }
848 raw_ptr<const Sampler> src_sampler =
849 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
850 src_sampler_descriptor);
851 FS::BindTextureSamplerSrc(pass, src_texture, src_sampler);
852
853 frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1));
854 frame_info.src_y_coord_scale = src_texture->GetYCoordScale();
855 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
856
857 frag_info.src_input_alpha = 1.0;
858 frag_info.dst_input_alpha =
859 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
860 ? dst_snapshot->opacity
861 : 1.0;
862 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
863
864 return pass.Draw().ok();
865 }
866 };
867
868 std::shared_ptr<CommandBuffer> cmd_buffer =
869 renderer.GetContext()->CreateCommandBuffer();
870
871 // Generate a 1x1 texture to implement foreground color blending.
872 if (foreground_color.has_value()) {
873 TextureDescriptor desc;
874 desc.size = {1, 1};
875 desc.format = PixelFormat::kR8G8B8A8UNormInt;
876 desc.storage_mode = StorageMode::kDevicePrivate;
877 foreground_texture =
878 renderer.GetContext()->GetResourceAllocator()->CreateTexture(desc);
879 if (!foreground_texture) {
880 return std::nullopt;
881 }
882 auto blit_pass = cmd_buffer->CreateBlitPass();
883 auto buffer_view = renderer.GetTransientsBuffer().Emplace(
884 foreground_color->Premultiply().ToR8G8B8A8(), /*alignment=*/4);
885
886 blit_pass->AddCopy(std::move(buffer_view), foreground_texture);
887 if (!blit_pass->EncodeCommands()) {
888 return std::nullopt;
889 }
890 }
891
892 auto render_target =
893 renderer.MakeSubpass("FramebufferBlend", dst_snapshot->texture->GetSize(),
894 cmd_buffer, subpass_callback);
895
896 if (!render_target.ok()) {
897 return std::nullopt;
898 }
899 if (!renderer.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer))) {
900 return std::nullopt;
901 }
902
903 return Entity::FromSnapshot(
904 Snapshot{
905 .texture = render_target.value().GetRenderTargetTexture(),
906 .transform = dst_snapshot->transform,
907 // Since we absorbed the transform of the inputs and used the
908 // respective snapshot sampling modes when blending, pass on
909 // the default NN clamp sampler.
910 .sampler_descriptor = {},
911 .opacity = (absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
912 ? 1.0f
913 : dst_snapshot->opacity) *
914 alpha.value_or(1.0)},
915 entity.GetBlendMode());
916 }
917
918 #define BLEND_CASE(mode) \
919 case BlendMode::k##mode: \
920 advanced_blend_proc_ = \
921 [](const FilterInput::Vector& inputs, const ContentContext& renderer, \
922 const Entity& entity, const Rect& coverage, BlendMode blend_mode, \
923 std::optional<Color> fg_color, \
924 ColorFilterContents::AbsorbOpacity absorb_opacity, \
925 std::optional<Scalar> alpha) { \
926 PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \
927 return AdvancedBlend<Blend##mode##Pipeline>( \
928 inputs, renderer, entity, coverage, blend_mode, fg_color, \
929 absorb_opacity, p, alpha); \
930 }; \
931 break;
932
933 void BlendFilterContents::SetBlendMode(BlendMode blend_mode) {
934 if (blend_mode > Entity::kLastAdvancedBlendMode) {
935 VALIDATION_LOG << "Invalid blend mode " << static_cast<int>(blend_mode)
936 << " assigned to BlendFilterContents.";
937 }
938
939 blend_mode_ = blend_mode;
940
941 if (blend_mode > Entity::kLastPipelineBlendMode) {
942 switch (blend_mode) {
943 BLEND_CASE(Screen)
944 BLEND_CASE(Overlay)
945 BLEND_CASE(Darken)
946 BLEND_CASE(Lighten)
947 BLEND_CASE(ColorDodge)
948 BLEND_CASE(ColorBurn)
949 BLEND_CASE(HardLight)
950 BLEND_CASE(SoftLight)
951 BLEND_CASE(Difference)
952 BLEND_CASE(Exclusion)
953 BLEND_CASE(Multiply)
954 BLEND_CASE(Hue)
955 BLEND_CASE(Saturation)
956 BLEND_CASE(Color)
957 BLEND_CASE(Luminosity)
958 default:
959 FML_UNREACHABLE();
960 }
961 }
962 }
963
964 void BlendFilterContents::SetForegroundColor(std::optional<Color> color) {
965 foreground_color_ = color;
966 }
967
968 std::optional<Entity> BlendFilterContents::RenderFilter(
969 const FilterInput::Vector& inputs,
970 const ContentContext& renderer,
971 const Entity& entity,
972 const Matrix& effect_transform,
973 const Rect& coverage,
974 const std::optional<Rect>& coverage_hint) const {
975 if (inputs.empty()) {
976 return std::nullopt;
977 }
978
979 if (inputs.size() == 1 && !foreground_color_.has_value()) {
980 // Nothing to blend.
981 return PipelineBlend(inputs, renderer, entity, coverage, BlendMode::kSource,
982 std::nullopt, GetAbsorbOpacity(), GetAlpha());
983 }
984
985 if (blend_mode_ <= Entity::kLastPipelineBlendMode) {
986 if (inputs.size() == 1 && foreground_color_.has_value() &&
987 GetAbsorbOpacity() == ColorFilterContents::AbsorbOpacity::kYes) {
988 return CreateForegroundPorterDuffBlend(
989 inputs[0], renderer, entity, coverage, foreground_color_.value(),
990 blend_mode_, GetAlpha(), GetAbsorbOpacity());
991 }
992 return PipelineBlend(inputs, renderer, entity, coverage, blend_mode_,
993 foreground_color_, GetAbsorbOpacity(), GetAlpha());
994 }
995
996 if (blend_mode_ <= Entity::kLastAdvancedBlendMode) {
997 if (renderer.GetDeviceCapabilities().SupportsFramebufferFetch()) {
998 return CreateFramebufferAdvancedBlend(inputs, renderer, entity, coverage,
999 foreground_color_, blend_mode_,
1000 GetAlpha(), GetAbsorbOpacity());
1001 }
1002 if (inputs.size() == 1 && foreground_color_.has_value() &&
1003 GetAbsorbOpacity() == ColorFilterContents::AbsorbOpacity::kYes) {
1004 return CreateForegroundAdvancedBlend(
1005 inputs[0], renderer, entity, coverage, foreground_color_.value(),
1006 blend_mode_, GetAlpha(), GetAbsorbOpacity());
1007 }
1008 return advanced_blend_proc_(inputs, renderer, entity, coverage, blend_mode_,
1009 foreground_color_, GetAbsorbOpacity(),
1010 GetAlpha());
1011 }
1012
1013 FML_UNREACHABLE();
1014 }
1015
1016 } // namespace impeller
anonymous_contents.h
BLEND_CASE
#define BLEND_CASE(mode)
Definition: blend_filter_contents.cc:918
blend_filter_contents.h
buffer_view
BufferView buffer_view
Definition: blit_command_gles.cc:152
impeller::AnonymousContents::Make
static std::shared_ptr< Contents > Make(RenderProc render_proc, CoverageProc coverage_proc)
Definition: anonymous_contents.cc:11
impeller::BlendFilterContents::~BlendFilterContents
~BlendFilterContents() override
impeller::BlendFilterContents::SetBlendMode
void SetBlendMode(BlendMode blend_mode)
Definition: blend_filter_contents.cc:933
impeller::BlendFilterContents::BlendFilterContents
BlendFilterContents()
Definition: blend_filter_contents.cc:86
impeller::BlendFilterContents::SetForegroundColor
void SetForegroundColor(std::optional< Color > color)
Sets a source color which is blended after all of the inputs have been blended.
Definition: blend_filter_contents.cc:964
impeller::Capabilities::SupportsFramebufferFetch
virtual bool SupportsFramebufferFetch() const =0
Whether the context backend is able to support pipelines with shaders that read from the framebuffer ...
impeller::Capabilities::SupportsDecalSamplerAddressMode
virtual bool SupportsDecalSamplerAddressMode() const =0
Whether the context backend supports SamplerAddressMode::Decal.
impeller::ColorFilterContents::GetAlpha
std::optional< Scalar > GetAlpha() const
Definition: color_filter_contents.cc:98
impeller::ColorFilterContents::AbsorbOpacity
AbsorbOpacity
Definition: color_filter_contents.h:14
impeller::ColorFilterContents::AbsorbOpacity::kYes
@ kYes
impeller::ColorFilterContents::GetAbsorbOpacity
AbsorbOpacity GetAbsorbOpacity() const
Definition: color_filter_contents.cc:89
impeller::ContentContext
Definition: content_context.h:371
impeller::ContentContext::GetTransientsBuffer
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Definition: content_context.h:866
impeller::ContentContext::MakeSubpass
fml::StatusOr< RenderTarget > MakeSubpass(std::string_view label, ISize texture_size, const std::shared_ptr< CommandBuffer > &command_buffer, const SubpassCallback &subpass_callback, bool msaa_enabled=true, bool depth_stencil_enabled=false, int32_t mip_count=1) const
Creates a new texture of size texture_size and calls subpass_callback with a RenderPass for drawing t...
Definition: content_context.cc:541
impeller::ContentContext::GetDeviceCapabilities
const Capabilities & GetDeviceCapabilities() const
Definition: content_context.cc:617
impeller::ContentContext::GetTexturePipeline
PipelineRef GetTexturePipeline(ContentContextOptions opts) const
Definition: content_context.h:456
impeller::ContentContext::SubpassCallback
std::function< bool(const ContentContext &, RenderPass &)> SubpassCallback
Definition: content_context.h:814
impeller::ContentContext::GetContext
std::shared_ptr< Context > GetContext() const
Definition: content_context.cc:613
impeller::Contents::CoverageProc
std::function< std::optional< Rect >(const Entity &entity)> CoverageProc
Definition: contents.h:40
impeller::Contents::RenderProc
std::function< bool(const ContentContext &renderer, const Entity &entity, RenderPass &pass)> RenderProc
Definition: contents.h:39
impeller::Entity
Definition: entity.h:20
impeller::Entity::FromSnapshot
static Entity FromSnapshot(const Snapshot &snapshot, BlendMode blend_mode=BlendMode::kSourceOver)
Create an entity that can be used to render a given snapshot.
Definition: entity.cc:18
impeller::Entity::GetContents
const std::shared_ptr< Contents > & GetContents() const
Definition: entity.cc:76
impeller::Entity::GetShaderTransform
Matrix GetShaderTransform(const RenderPass &pass) const
Get the vertex shader transform used for drawing this Entity.
Definition: entity.cc:48
impeller::Entity::GetBlendMode
BlendMode GetBlendMode() const
Definition: entity.cc:101
impeller::Entity::SetContents
void SetContents(std::shared_ptr< Contents > contents)
Definition: entity.cc:72
impeller::Entity::SetBlendMode
void SetBlendMode(BlendMode blend_mode)
Definition: entity.cc:97
impeller::Entity::kLastAdvancedBlendMode
static constexpr BlendMode kLastAdvancedBlendMode
Definition: entity.h:23
impeller::Entity::Render
bool Render(const ContentContext &renderer, RenderPass &parent_pass) const
Definition: entity.cc:145
impeller::Entity::kLastPipelineBlendMode
static constexpr BlendMode kLastPipelineBlendMode
Definition: entity.h:22
impeller::FilterInput::Vector
std::vector< FilterInput::Ref > Vector
Definition: filter_input.h:33
impeller::RectGeometry
Definition: rect_geometry.h:12
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:30
impeller::RenderPipelineHandle::VertexShader
VertexShader_ VertexShader
Definition: pipeline.h:113
impeller::RenderPipelineHandle::FragmentShader
FragmentShader_ FragmentShader
Definition: pipeline.h:114
impeller::raw_ptr< Pipeline< PipelineDescriptor > >
color.h
IMPELLER_FOR_EACH_BLEND_MODE
#define IMPELLER_FOR_EACH_BLEND_MODE(V)
Definition: color.h:19
color_filter_contents.h
content_context.h
contents.h
formats.h
entity.h
filter_input.h
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:214
impeller
Definition: allocation.cc:12
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
impeller::SamplerAddressMode::kDecal
@ kDecal
decal sampling mode is only supported on devices that pass the Capabilities.SupportsDecalSamplerAddre...
impeller::Saturation
static constexpr Scalar Saturation(Vector3 color)
Definition: color.cc:89
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:792
impeller::VS
GlyphAtlasPipeline::VertexShader VS
Definition: text_contents.cc:25
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::StorageMode::kDevicePrivate
@ kDevicePrivate
impeller::PipelineRef
raw_ptr< Pipeline< PipelineDescriptor > > PipelineRef
A raw ptr to a pipeline object.
Definition: pipeline.h:86
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::CreateVertexBuffer
VertexBuffer CreateVertexBuffer(std::array< VertexType, size > input, HostBuffer &host_buffer)
Create an index-less vertex buffer from a fixed size array.
Definition: vertex_buffer_builder.h:24
impeller::InvertPorterDuffBlend
std::optional< BlendMode > InvertPorterDuffBlend(BlendMode blend_mode)
Definition: blend_filter_contents.cc:51
impeller::PipelineBlend
static std::optional< Entity > PipelineBlend(const FilterInput::Vector &inputs, const ContentContext &renderer, const Entity &entity, const Rect &coverage, BlendMode blend_mode, std::optional< Color > foreground_color, ColorFilterContents::AbsorbOpacity absorb_opacity, std::optional< Scalar > alpha)
Definition: blend_filter_contents.cc:520
impeller::BlendMode
BlendMode
Definition: color.h:58
impeller::BlendMode::kDestinationOver
@ kDestinationOver
impeller::BlendMode::kExclusion
@ kExclusion
impeller::BlendMode::kSaturation
@ kSaturation
impeller::BlendMode::kColorBurn
@ kColorBurn
impeller::BlendMode::kPlus
@ kPlus
impeller::BlendMode::kLighten
@ kLighten
impeller::BlendMode::kHue
@ kHue
impeller::BlendMode::kDestinationIn
@ kDestinationIn
impeller::BlendMode::kDestinationOut
@ kDestinationOut
impeller::BlendMode::kModulate
@ kModulate
impeller::BlendMode::kMultiply
@ kMultiply
impeller::BlendMode::kColorDodge
@ kColorDodge
impeller::BlendMode::kSourceATop
@ kSourceATop
impeller::BlendMode::kScreen
@ kScreen
impeller::BlendMode::kXor
@ kXor
impeller::BlendMode::kDestination
@ kDestination
impeller::BlendMode::kSource
@ kSource
impeller::BlendMode::kLuminosity
@ kLuminosity
impeller::BlendMode::kSoftLight
@ kSoftLight
impeller::BlendMode::kDifference
@ kDifference
impeller::BlendMode::kOverlay
@ kOverlay
impeller::BlendMode::kSourceIn
@ kSourceIn
impeller::BlendMode::kColor
@ kColor
impeller::BlendMode::kDestinationATop
@ kDestinationATop
impeller::BlendMode::kHardLight
@ kHardLight
impeller::BlendMode::kDarken
@ kDarken
impeller::BlendMode::kClear
@ kClear
impeller::BlendMode::kSourceOver
@ kSourceOver
impeller::BlendMode::kSourceOut
@ kSourceOut
impeller::FS
GlyphAtlasPipeline::FragmentShader FS
Definition: text_contents.cc:26
impeller::PipelineProc
PipelineRef(ContentContext::*)(ContentContextOptions) const PipelineProc
Definition: blend_filter_contents.cc:93
impeller::OptionsFromPassAndEntity
ContentContextOptions OptionsFromPassAndEntity(const RenderPass &pass, const Entity &entity)
Definition: contents.cc:34
impeller::OptionsFromPass
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition: contents.cc:19
impeller::ISize
ISize64 ISize
Definition: size.h:174
impeller::AdvancedBlend
static std::optional< Entity > AdvancedBlend(const FilterInput::Vector &inputs, const ContentContext &renderer, const Entity &entity, const Rect &coverage, BlendMode blend_mode, std::optional< Color > foreground_color, ColorFilterContents::AbsorbOpacity absorb_opacity, PipelineProc pipeline_proc, std::optional< Scalar > alpha)
Definition: blend_filter_contents.cc:96
impeller::Luminosity
static constexpr Scalar Luminosity(Vector3 color)
Definition: color.cc:63
rect_geometry.h
render_pass.h
sampler_descriptor.h
snapshot.h
solid_color_contents.h
strings.h
impeller::Color
Definition: color.h:123
impeller::ContentContextOptions
Definition: content_context.h:279
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Matrix::MakeOrthographic
static constexpr Matrix MakeOrthographic(TSize< T > size)
Definition: matrix.h:553
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
impeller::Snapshot
Represents a texture and its intended draw transform/sampler configuration.
Definition: snapshot.h:24
impeller::Snapshot::texture
std::shared_ptr< Texture > texture
Definition: snapshot.h:25
impeller::TRect< Scalar >
impeller::TRect::GetOrigin
constexpr TPoint< Type > GetOrigin() const
Returns the upper left corner of the rectangle as specified by the left/top or x/y values when it was...
Definition: rect.h:324
impeller::TRect::Intersection
constexpr std::optional< TRect > Intersection(const TRect &o) const
Definition: rect.h:532
impeller::TRect::GetSize
constexpr TSize< Type > GetSize() const
Returns the size of the rectangle which may be negative in either width or height and may have been c...
Definition: rect.h:331
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:150
texture_descriptor.h
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91
vertex_buffer.h