| 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::kSrc:
56 return BlendMode::kDst;
57 case BlendMode::kDst:
58 return BlendMode::kSrc;
59 case BlendMode::kSrcOver:
60 return BlendMode::kDstOver;
61 case BlendMode::kDstOver:
62 return BlendMode::kSrcOver;
63 case BlendMode::kSrcIn:
64 return BlendMode::kDstIn;
65 case BlendMode::kDstIn:
66 return BlendMode::kSrcIn;
67 case BlendMode::kSrcOut:
68 return BlendMode::kDstOut;
69 case BlendMode::kDstOut:
70 return BlendMode::kSrcOut;
71 case BlendMode::kSrcATop:
72 return BlendMode::kDstATop;
73 case BlendMode::kDstATop:
74 return BlendMode::kSrcATop;
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::kSrcOver);
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::kSrc;
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 raw_ptr<const Sampler> dst_sampler =
203 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
204 dst_snapshot->sampler_descriptor);
205 FS::BindTextureSamplerDst(pass, dst_snapshot->texture, dst_sampler);
206 frame_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale();
207 blend_info.dst_input_alpha =
208 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
209 ? dst_snapshot->opacity
210 : 1.0;
211
212 if (foreground_color.has_value()) {
213 blend_info.color_factor = 1;
214 blend_info.color = foreground_color.value();
215 // This texture will not be sampled from due to the color factor. But
216 // this is present so that validation doesn't trip on a missing
217 // binding.
218 FS::BindTextureSamplerSrc(pass, dst_snapshot->texture, dst_sampler);
219 } else {
220 raw_ptr<const Sampler> src_sampler =
221 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
222 src_snapshot->sampler_descriptor);
223 blend_info.color_factor = 0;
224 blend_info.src_input_alpha = src_snapshot->opacity;
225 FS::BindTextureSamplerSrc(pass, src_snapshot->texture, src_sampler);
226 frame_info.src_y_coord_scale = src_snapshot->texture->GetYCoordScale();
227 }
228 auto blend_uniform = host_buffer.EmplaceUniform(blend_info);
229 FS::BindBlendInfo(pass, blend_uniform);
230
231 frame_info.mvp = pass.GetOrthographicTransform() *
232 Matrix::MakeTranslation(coverage.GetOrigin() -
233 subpass_coverage.GetOrigin());
234
235 auto uniform_view = host_buffer.EmplaceUniform(frame_info);
236 VS::BindFrameInfo(pass, uniform_view);
237
238 return pass.Draw().ok();
239 };
240
241 std::shared_ptr<CommandBuffer> command_buffer =
242 renderer.GetContext()->CreateCommandBuffer();
243 if (!command_buffer) {
244 return std::nullopt;
245 }
246 fml::StatusOr<RenderTarget> render_target = renderer.MakeSubpass(
247 "Advanced Blend Filter", ISize(subpass_coverage.GetSize()),
248 command_buffer, callback);
249 if (!render_target.ok()) {
250 return std::nullopt;
251 }
252 if (!renderer.GetContext()->EnqueueCommandBuffer(std::move(command_buffer))) {
253 return std::nullopt;
254 }
255
256 return Entity::FromSnapshot(
257 Snapshot{
258 .texture = render_target.value().GetRenderTargetTexture(),
259 .transform = Matrix::MakeTranslation(subpass_coverage.GetOrigin()),
260 // Since we absorbed the transform of the inputs and used the
261 // respective snapshot sampling modes when blending, pass on
262 // the default NN clamp sampler.
263 .sampler_descriptor = {},
264 .opacity = (absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
265 ? 1.0f
266 : dst_snapshot->opacity) *
267 alpha.value_or(1.0)},
268 entity.GetBlendMode());
269 }
270
271 std::optional<Entity> BlendFilterContents::CreateForegroundAdvancedBlend(
272 const std::shared_ptr<FilterInput>& input,
273 const ContentContext& renderer,
274 const Entity& entity,
275 const Rect& coverage,
276 Color foreground_color,
277 BlendMode blend_mode,
278 std::optional<Scalar> alpha,
279 ColorFilterContents::AbsorbOpacity absorb_opacity) const {
280 auto dst_snapshot =
281 input->GetSnapshot("ForegroundAdvancedBlend", renderer, entity);
282 if (!dst_snapshot.has_value()) {
283 return std::nullopt;
284 }
285
286 RenderProc render_proc = [foreground_color, dst_snapshot, blend_mode, alpha,
287 absorb_opacity](const ContentContext& renderer,
288 const Entity& entity,
289 RenderPass& pass) -> bool {
290 using VS = BlendScreenPipeline::VertexShader;
291 using FS = BlendScreenPipeline::FragmentShader;
292
293 auto& host_buffer = renderer.GetTransientsBuffer();
294 auto size = dst_snapshot->texture->GetSize();
295
296 std::array<VS::PerVertexData, 4> vertices = {
297 VS::PerVertexData{{0, 0}, {0, 0}, {0, 0}},
298 VS::PerVertexData{Point(size.width, 0), {1, 0}, {1, 0}},
299 VS::PerVertexData{Point(0, size.height), {0, 1}, {0, 1}},
300 VS::PerVertexData{Point(size.width, size.height), {1, 1}, {1, 1}},
301 };
302 auto vtx_buffer =
303 CreateVertexBuffer(vertices, renderer.GetTransientsBuffer());
304
305 #ifdef IMPELLER_DEBUG
306 pass.SetCommandLabel(BlendModeToFilterString(blend_mode));
307 #endif // IMPELLER_DEBUG
308 pass.SetVertexBuffer(std::move(vtx_buffer));
309 auto options = OptionsFromPassAndEntity(pass, entity);
310 options.primitive_type = PrimitiveType::kTriangleStrip;
311
312 switch (blend_mode) {
313 case BlendMode::kScreen:
314 pass.SetPipeline(renderer.GetBlendScreenPipeline(options));
315 break;
316 case BlendMode::kOverlay:
317 pass.SetPipeline(renderer.GetBlendOverlayPipeline(options));
318 break;
319 case BlendMode::kDarken:
320 pass.SetPipeline(renderer.GetBlendDarkenPipeline(options));
321 break;
322 case BlendMode::kLighten:
323 pass.SetPipeline(renderer.GetBlendLightenPipeline(options));
324 break;
325 case BlendMode::kColorDodge:
326 pass.SetPipeline(renderer.GetBlendColorDodgePipeline(options));
327 break;
328 case BlendMode::kColorBurn:
329 pass.SetPipeline(renderer.GetBlendColorBurnPipeline(options));
330 break;
331 case BlendMode::kHardLight:
332 pass.SetPipeline(renderer.GetBlendHardLightPipeline(options));
333 break;
334 case BlendMode::kSoftLight:
335 pass.SetPipeline(renderer.GetBlendSoftLightPipeline(options));
336 break;
337 case BlendMode::kDifference:
338 pass.SetPipeline(renderer.GetBlendDifferencePipeline(options));
339 break;
340 case BlendMode::kExclusion:
341 pass.SetPipeline(renderer.GetBlendExclusionPipeline(options));
342 break;
343 case BlendMode::kMultiply:
344 pass.SetPipeline(renderer.GetBlendMultiplyPipeline(options));
345 break;
346 case BlendMode::kHue:
347 pass.SetPipeline(renderer.GetBlendHuePipeline(options));
348 break;
349 case BlendMode::kSaturation:
350 pass.SetPipeline(renderer.GetBlendSaturationPipeline(options));
351 break;
352 case BlendMode::kColor:
353 pass.SetPipeline(renderer.GetBlendColorPipeline(options));
354 break;
355 case BlendMode::kLuminosity:
356 pass.SetPipeline(renderer.GetBlendLuminosityPipeline(options));
357 break;
358 default:
359 return false;
360 }
361
362 FS::BlendInfo blend_info;
363 VS::FrameInfo frame_info;
364
365 raw_ptr<const Sampler> dst_sampler =
366 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
367 dst_snapshot->sampler_descriptor);
368 FS::BindTextureSamplerDst(pass, dst_snapshot->texture, dst_sampler);
369 frame_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale();
370
371 frame_info.mvp = Entity::GetShaderTransform(
372 entity.GetShaderClipDepth(), pass,
373 entity.GetTransform() * dst_snapshot->transform);
374
375 blend_info.dst_input_alpha =
376 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
377 ? dst_snapshot->opacity * alpha.value_or(1.0)
378 : 1.0;
379
380 blend_info.color_factor = 1;
381 blend_info.color = foreground_color;
382 // This texture will not be sampled from due to the color factor. But
383 // this is present so that validation doesn't trip on a missing
384 // binding.
385 FS::BindTextureSamplerSrc(pass, dst_snapshot->texture, dst_sampler);
386
387 auto blend_uniform = host_buffer.EmplaceUniform(blend_info);
388 FS::BindBlendInfo(pass, blend_uniform);
389
390 auto uniform_view = host_buffer.EmplaceUniform(frame_info);
391 VS::BindFrameInfo(pass, uniform_view);
392
393 return pass.Draw().ok();
394 };
395 CoverageProc coverage_proc =
396 [coverage](const Entity& entity) -> std::optional<Rect> {
397 return coverage.TransformBounds(entity.GetTransform());
398 };
399
400 auto contents = AnonymousContents::Make(render_proc, coverage_proc);
401
402 Entity sub_entity;
403 sub_entity.SetContents(std::move(contents));
404 sub_entity.SetBlendMode(entity.GetBlendMode());
405
406 return sub_entity;
407 }
408
409 std::optional<Entity> BlendFilterContents::CreateForegroundPorterDuffBlend(
410 const std::shared_ptr<FilterInput>& input,
411 const ContentContext& renderer,
412 const Entity& entity,
413 const Rect& coverage,
414 Color foreground_color,
415 BlendMode blend_mode,
416 std::optional<Scalar> alpha,
417 ColorFilterContents::AbsorbOpacity absorb_opacity) const {
418 if (blend_mode == BlendMode::kClear) {
419 return std::nullopt;
420 }
421
422 auto dst_snapshot =
423 input->GetSnapshot("ForegroundPorterDuffBlend", renderer, entity);
424 if (!dst_snapshot.has_value()) {
425 return std::nullopt;
426 }
427
428 if (blend_mode == BlendMode::kDst) {
429 return Entity::FromSnapshot(dst_snapshot.value(), entity.GetBlendMode());
430 }
431
432 RenderProc render_proc = [foreground_color, dst_snapshot, blend_mode,
433 absorb_opacity, alpha](
434 const ContentContext& renderer,
435 const Entity& entity, RenderPass& pass) -> bool {
436 using VS = PorterDuffBlendPipeline::VertexShader;
437 using FS = PorterDuffBlendPipeline::FragmentShader;
438
439 auto& host_buffer = renderer.GetTransientsBuffer();
440 auto size = dst_snapshot->texture->GetSize();
441 auto color = foreground_color.Premultiply();
442
443 std::array<VS::PerVertexData, 4> vertices = {
444 VS::PerVertexData{{0, 0}, {0, 0}, color},
445 VS::PerVertexData{Point(size.width, 0), {1, 0}, color},
446 VS::PerVertexData{Point(0, size.height), {0, 1}, color},
447 VS::PerVertexData{Point(size.width, size.height), {1, 1}, color},
448 };
449 auto vtx_buffer =
450 CreateVertexBuffer(vertices, renderer.GetTransientsBuffer());
451
452 #ifdef IMPELLER_DEBUG
453 pass.SetCommandLabel(BlendModeToFilterString(blend_mode));
454 #endif // IMPELLER_DEBUG
455 pass.SetVertexBuffer(std::move(vtx_buffer));
456 auto options = OptionsFromPassAndEntity(pass, entity);
457 options.primitive_type = PrimitiveType::kTriangleStrip;
458 pass.SetPipeline(renderer.GetPorterDuffPipeline(blend_mode, options));
459
460 FS::FragInfo frag_info;
461 VS::FrameInfo frame_info;
462
463 frame_info.mvp = Entity::GetShaderTransform(
464 entity.GetShaderClipDepth(), pass,
465 entity.GetTransform() * dst_snapshot->transform);
466
467 raw_ptr<const Sampler> dst_sampler =
468 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
469 dst_snapshot->sampler_descriptor);
470 FS::BindTextureSamplerDst(pass, dst_snapshot->texture, dst_sampler);
471 frame_info.texture_sampler_y_coord_scale =
472 dst_snapshot->texture->GetYCoordScale();
473
474 frag_info.input_alpha =
475 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
476 ? dst_snapshot->opacity * alpha.value_or(1.0)
477 : 1.0;
478 frag_info.output_alpha = 1.0;
479
480 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
481 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
482
483 return pass.Draw().ok();
484 };
485
486 CoverageProc coverage_proc =
487 [coverage](const Entity& entity) -> std::optional<Rect> {
488 return coverage.TransformBounds(entity.GetTransform());
489 };
490
491 auto contents = AnonymousContents::Make(render_proc, coverage_proc);
492
493 Entity sub_entity;
494 sub_entity.SetContents(std::move(contents));
495 sub_entity.SetBlendMode(entity.GetBlendMode());
496
497 return sub_entity;
498 }
499
500 static std::optional<Entity> PipelineBlend(
501 const FilterInput::Vector& inputs,
502 const ContentContext& renderer,
503 const Entity& entity,
504 const Rect& coverage,
505 BlendMode blend_mode,
506 std::optional<Color> foreground_color,
507 ColorFilterContents::AbsorbOpacity absorb_opacity,
508 std::optional<Scalar> alpha) {
509 using VS = TexturePipeline::VertexShader;
510 using FS = TexturePipeline::FragmentShader;
511
512 auto dst_snapshot =
513 inputs[0]->GetSnapshot("PipelineBlend(Dst)", renderer, entity);
514 if (!dst_snapshot.has_value()) {
515 return std::nullopt; // Nothing to render.
516 }
517
518 Rect subpass_coverage = coverage;
519 if (entity.GetContents()) {
520 auto coverage_hint = entity.GetContents()->GetCoverageHint();
521
522 if (coverage_hint.has_value()) {
523 auto maybe_subpass_coverage =
524 subpass_coverage.Intersection(*coverage_hint);
525 if (!maybe_subpass_coverage.has_value()) {
526 return std::nullopt; // Nothing to render.
527 }
528
529 subpass_coverage = *maybe_subpass_coverage;
530 }
531 }
532
533 ContentContext::SubpassCallback callback = [&](const ContentContext& renderer,
534 RenderPass& pass) {
535 auto& host_buffer = renderer.GetTransientsBuffer();
536
537 #ifdef IMPELLER_DEBUG
538 pass.SetCommandLabel(BlendModeToFilterString(blend_mode));
539 #endif // IMPELLER_DEBUG
540 auto options = OptionsFromPass(pass);
541 options.primitive_type = PrimitiveType::kTriangleStrip;
542
543 auto add_blend_command = [&](std::optional<Snapshot> input) {
544 if (!input.has_value()) {
545 return false;
546 }
547 auto input_coverage = input->GetCoverage();
548 if (!input_coverage.has_value()) {
549 return false;
550 }
551
552 raw_ptr<const Sampler> sampler =
553 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
554 input->sampler_descriptor);
555 FS::BindTextureSampler(pass, input->texture, sampler);
556
557 auto size = input->texture->GetSize();
558 std::array<VS::PerVertexData, 4> vertices = {
559 VS::PerVertexData{Point(0, 0), Point(0, 0)},
560 VS::PerVertexData{Point(size.width, 0), Point(1, 0)},
561 VS::PerVertexData{Point(0, size.height), Point(0, 1)},
562 VS::PerVertexData{Point(size.width, size.height), Point(1, 1)},
563 };
564 pass.SetVertexBuffer(
565 CreateVertexBuffer(vertices, renderer.GetTransientsBuffer()));
566
567 VS::FrameInfo frame_info;
568 frame_info.mvp = pass.GetOrthographicTransform() *
569 Matrix::MakeTranslation(-subpass_coverage.GetOrigin()) *
570 input->transform;
571 frame_info.texture_sampler_y_coord_scale =
572 input->texture->GetYCoordScale();
573
574 FS::FragInfo frag_info;
575 frag_info.alpha =
576 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
577 ? input->opacity
578 : 1.0;
579 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
580 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
581
582 return pass.Draw().ok();
583 };
584
585 // Draw the first texture using kSource.
586 options.blend_mode = BlendMode::kSrc;
587 pass.SetPipeline(renderer.GetTexturePipeline(options));
588 if (!add_blend_command(dst_snapshot)) {
589 return true;
590 }
591
592 // Write subsequent textures using the selected blend mode.
593
594 if (inputs.size() >= 2) {
595 options.blend_mode = blend_mode;
596 pass.SetPipeline(renderer.GetTexturePipeline(options));
597
598 for (auto texture_i = inputs.begin() + 1; texture_i < inputs.end();
599 texture_i++) {
600 auto src_input = texture_i->get()->GetSnapshot("PipelineBlend(Src)",
601 renderer, entity);
602 if (!add_blend_command(src_input)) {
603 return true;
604 }
605 }
606 }
607
608 // If a foreground color is set, blend it in.
609
610 if (foreground_color.has_value()) {
611 auto contents = std::make_shared<SolidColorContents>();
612 RectGeometry geom(Rect::MakeSize(pass.GetRenderTargetSize()));
613 contents->SetGeometry(&geom);
614 contents->SetColor(foreground_color.value());
615
616 Entity foreground_entity;
617 foreground_entity.SetBlendMode(blend_mode);
618 foreground_entity.SetContents(contents);
619 if (!foreground_entity.Render(renderer, pass)) {
620 return false;
621 }
622 }
623
624 return true;
625 };
626
627 std::shared_ptr<CommandBuffer> command_buffer =
628 renderer.GetContext()->CreateCommandBuffer();
629 if (!command_buffer) {
630 return std::nullopt;
631 }
632
633 fml::StatusOr<RenderTarget> render_target = renderer.MakeSubpass(
634 "Pipeline Blend Filter", ISize(subpass_coverage.GetSize()),
635 command_buffer, callback);
636
637 if (!render_target.ok()) {
638 return std::nullopt;
639 }
640 if (!renderer.GetContext()->EnqueueCommandBuffer(std::move(command_buffer))) {
641 return std::nullopt;
642 }
643
644 return Entity::FromSnapshot(
645 Snapshot{
646 .texture = render_target.value().GetRenderTargetTexture(),
647 .transform = Matrix::MakeTranslation(subpass_coverage.GetOrigin()),
648 // Since we absorbed the transform of the inputs and used the
649 // respective snapshot sampling modes when blending, pass on
650 // the default NN clamp sampler.
651 .sampler_descriptor = {},
652 .opacity = (absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
653 ? 1.0f
654 : dst_snapshot->opacity) *
655 alpha.value_or(1.0)},
656 entity.GetBlendMode());
657 }
658
659 std::optional<Entity> BlendFilterContents::CreateFramebufferAdvancedBlend(
660 const FilterInput::Vector& inputs,
661 const ContentContext& renderer,
662 const Entity& entity,
663 const Rect& coverage,
664 std::optional<Color> foreground_color,
665 BlendMode blend_mode,
666 std::optional<Scalar> alpha,
667 ColorFilterContents::AbsorbOpacity absorb_opacity) const {
668 // This works with either 2 contents or 1 contents and a foreground color.
669 FML_DCHECK(inputs.size() == 2u ||
670 (inputs.size() == 1u && foreground_color.has_value()));
671
672 auto dst_snapshot =
673 inputs[0]->GetSnapshot("ForegroundAdvancedBlend", renderer, entity);
674 if (!dst_snapshot.has_value()) {
675 return std::nullopt;
676 }
677
678 std::shared_ptr<Texture> foreground_texture;
679
680 ContentContext::SubpassCallback subpass_callback = [&](const ContentContext&
681 renderer,
682 RenderPass& pass) {
683 // First, we create a new render pass and populate it with the contents
684 // of the first (dst) input.
685 HostBuffer& host_buffer = renderer.GetTransientsBuffer();
686
687 {
688 using FS = TextureFillFragmentShader;
689 using VS = TextureFillVertexShader;
690
691 pass.SetCommandLabel("Framebuffer Advanced Blend");
692 auto pipeline_options = OptionsFromPass(pass);
693 pipeline_options.primitive_type = PrimitiveType::kTriangleStrip;
694 pass.SetPipeline(renderer.GetTexturePipeline(pipeline_options));
695
696 VS::FrameInfo frame_info;
697 frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1));
698 frame_info.texture_sampler_y_coord_scale = 1.0;
699
700 FS::FragInfo frag_info;
701 frag_info.alpha = 1.0;
702
703 std::array<VS::PerVertexData, 4> vertices = {
704 VS::PerVertexData{{0, 0}, {0, 0}},
705 VS::PerVertexData{Point(1, 0), {1, 0}},
706 VS::PerVertexData{Point(0, 1), {0, 1}},
707 VS::PerVertexData{Point(1, 1), {1, 1}},
708 };
709 pass.SetVertexBuffer(
710 CreateVertexBuffer(vertices, renderer.GetTransientsBuffer()));
711
712 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
713 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
714 FS::BindTextureSampler(
715 pass, dst_snapshot->texture,
716 renderer.GetContext()->GetSamplerLibrary()->GetSampler({}));
717
718 if (!pass.Draw().ok()) {
719 return false;
720 }
721 }
722
723 {
724 using VS = FramebufferBlendScreenPipeline::VertexShader;
725 using FS = FramebufferBlendScreenPipeline::FragmentShader;
726
727 // Next, we render the second contents to a snapshot, or create a 1x1
728 // texture for the foreground color.
729 std::shared_ptr<Texture> src_texture;
730 SamplerDescriptor src_sampler_descriptor = SamplerDescriptor{};
731 if (foreground_color.has_value()) {
732 src_texture = foreground_texture;
733 } else {
734 auto src_snapshot =
735 inputs[0]->GetSnapshot("ForegroundAdvancedBlend", renderer, entity);
736 if (!src_snapshot.has_value()) {
737 return false;
738 }
739 // This doesn't really handle the case where the transforms are wildly
740 // different, but we only need to support blending two contents together
741 // in limited circumstances (mask blur).
742 src_texture = src_snapshot->texture;
743 src_sampler_descriptor = src_snapshot->sampler_descriptor;
744 }
745
746 std::array<VS::PerVertexData, 4> vertices = {
747 VS::PerVertexData{Point(0, 0), Point(0, 0)},
748 VS::PerVertexData{Point(1, 0), Point(1, 0)},
749 VS::PerVertexData{Point(0, 1), Point(0, 1)},
750 VS::PerVertexData{Point(1, 1), Point(1, 1)},
751 };
752
753 auto options = OptionsFromPass(pass);
754 options.blend_mode = BlendMode::kSrc;
755 options.primitive_type = PrimitiveType::kTriangleStrip;
756
757 pass.SetCommandLabel("Framebuffer Advanced Blend Filter");
758 pass.SetVertexBuffer(
759 CreateVertexBuffer(vertices, renderer.GetTransientsBuffer()));
760
761 switch (blend_mode) {
762 case BlendMode::kScreen:
763 pass.SetPipeline(renderer.GetFramebufferBlendScreenPipeline(options));
764 break;
765 case BlendMode::kOverlay:
766 pass.SetPipeline(
767 renderer.GetFramebufferBlendOverlayPipeline(options));
768 break;
769 case BlendMode::kDarken:
770 pass.SetPipeline(renderer.GetFramebufferBlendDarkenPipeline(options));
771 break;
772 case BlendMode::kLighten:
773 pass.SetPipeline(
774 renderer.GetFramebufferBlendLightenPipeline(options));
775 break;
776 case BlendMode::kColorDodge:
777 pass.SetPipeline(
778 renderer.GetFramebufferBlendColorDodgePipeline(options));
779 break;
780 case BlendMode::kColorBurn:
781 pass.SetPipeline(
782 renderer.GetFramebufferBlendColorBurnPipeline(options));
783 break;
784 case BlendMode::kHardLight:
785 pass.SetPipeline(
786 renderer.GetFramebufferBlendHardLightPipeline(options));
787 break;
788 case BlendMode::kSoftLight:
789 pass.SetPipeline(
790 renderer.GetFramebufferBlendSoftLightPipeline(options));
791 break;
792 case BlendMode::kDifference:
793 pass.SetPipeline(
794 renderer.GetFramebufferBlendDifferencePipeline(options));
795 break;
796 case BlendMode::kExclusion:
797 pass.SetPipeline(
798 renderer.GetFramebufferBlendExclusionPipeline(options));
799 break;
800 case BlendMode::kMultiply:
801 pass.SetPipeline(
802 renderer.GetFramebufferBlendMultiplyPipeline(options));
803 break;
804 case BlendMode::kHue:
805 pass.SetPipeline(renderer.GetFramebufferBlendHuePipeline(options));
806 break;
807 case BlendMode::kSaturation:
808 pass.SetPipeline(
809 renderer.GetFramebufferBlendSaturationPipeline(options));
810 break;
811 case BlendMode::kColor:
812 pass.SetPipeline(renderer.GetFramebufferBlendColorPipeline(options));
813 break;
814 case BlendMode::kLuminosity:
815 pass.SetPipeline(
816 renderer.GetFramebufferBlendLuminosityPipeline(options));
817 break;
818 default:
819 return false;
820 }
821
822 VS::FrameInfo frame_info;
823 FS::FragInfo frag_info;
824
825 raw_ptr<const Sampler> src_sampler =
826 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
827 src_sampler_descriptor);
828 FS::BindTextureSamplerSrc(pass, src_texture, src_sampler);
829
830 frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1));
831 frame_info.src_y_coord_scale = src_texture->GetYCoordScale();
832 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
833
834 frag_info.src_input_alpha = 1.0;
835 frag_info.dst_input_alpha =
836 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
837 ? dst_snapshot->opacity
838 : 1.0;
839 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
840
841 return pass.Draw().ok();
842 }
843 };
844
845 std::shared_ptr<CommandBuffer> cmd_buffer =
846 renderer.GetContext()->CreateCommandBuffer();
847
848 // Generate a 1x1 texture to implement foreground color blending.
849 if (foreground_color.has_value()) {
850 TextureDescriptor desc;
851 desc.size = {1, 1};
852 desc.format = PixelFormat::kR8G8B8A8UNormInt;
853 desc.storage_mode = StorageMode::kDevicePrivate;
854 foreground_texture =
855 renderer.GetContext()->GetResourceAllocator()->CreateTexture(desc);
856 if (!foreground_texture) {
857 return std::nullopt;
858 }
859 auto blit_pass = cmd_buffer->CreateBlitPass();
860 auto buffer_view = renderer.GetTransientsBuffer().Emplace(
861 foreground_color->Premultiply().ToR8G8B8A8(), /*alignment=*/4);
862
863 blit_pass->AddCopy(std::move(buffer_view), foreground_texture);
864 if (!blit_pass->EncodeCommands()) {
865 return std::nullopt;
866 }
867 }
868
869 auto render_target =
870 renderer.MakeSubpass("FramebufferBlend", dst_snapshot->texture->GetSize(),
871 cmd_buffer, subpass_callback);
872
873 if (!render_target.ok()) {
874 return std::nullopt;
875 }
876 if (!renderer.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer))) {
877 return std::nullopt;
878 }
879
880 return Entity::FromSnapshot(
881 Snapshot{
882 .texture = render_target.value().GetRenderTargetTexture(),
883 .transform = dst_snapshot->transform,
884 // Since we absorbed the transform of the inputs and used the
885 // respective snapshot sampling modes when blending, pass on
886 // the default NN clamp sampler.
887 .sampler_descriptor = {},
888 .opacity = (absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
889 ? 1.0f
890 : dst_snapshot->opacity) *
891 alpha.value_or(1.0)},
892 entity.GetBlendMode());
893 }
894
895 #define BLEND_CASE(mode) \
896 case BlendMode::k##mode: \
897 advanced_blend_proc_ = \
898 [](const FilterInput::Vector& inputs, const ContentContext& renderer, \
899 const Entity& entity, const Rect& coverage, BlendMode blend_mode, \
900 std::optional<Color> fg_color, \
901 ColorFilterContents::AbsorbOpacity absorb_opacity, \
902 std::optional<Scalar> alpha) { \
903 PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \
904 return AdvancedBlend<Blend##mode##Pipeline>( \
905 inputs, renderer, entity, coverage, blend_mode, fg_color, \
906 absorb_opacity, p, alpha); \
907 }; \
908 break;
909
910 void BlendFilterContents::SetBlendMode(BlendMode blend_mode) {
911 if (blend_mode > Entity::kLastAdvancedBlendMode) {
912 VALIDATION_LOG << "Invalid blend mode " << static_cast<int>(blend_mode)
913 << " assigned to BlendFilterContents.";
914 }
915
916 blend_mode_ = blend_mode;
917
918 if (blend_mode > Entity::kLastPipelineBlendMode) {
919 switch (blend_mode) {
920 BLEND_CASE(Screen)
921 BLEND_CASE(Overlay)
922 BLEND_CASE(Darken)
923 BLEND_CASE(Lighten)
924 BLEND_CASE(ColorDodge)
925 BLEND_CASE(ColorBurn)
926 BLEND_CASE(HardLight)
927 BLEND_CASE(SoftLight)
928 BLEND_CASE(Difference)
929 BLEND_CASE(Exclusion)
930 BLEND_CASE(Multiply)
931 BLEND_CASE(Hue)
932 BLEND_CASE(Saturation)
933 BLEND_CASE(Color)
934 BLEND_CASE(Luminosity)
935 default:
936 FML_UNREACHABLE();
937 }
938 }
939 }
940
941 void BlendFilterContents::SetForegroundColor(std::optional<Color> color) {
942 foreground_color_ = color;
943 }
944
945 std::optional<Entity> BlendFilterContents::RenderFilter(
946 const FilterInput::Vector& inputs,
947 const ContentContext& renderer,
948 const Entity& entity,
949 const Matrix& effect_transform,
950 const Rect& coverage,
951 const std::optional<Rect>& coverage_hint) const {
952 if (inputs.empty()) {
953 return std::nullopt;
954 }
955
956 if (inputs.size() == 1 && !foreground_color_.has_value()) {
957 // Nothing to blend.
958 return PipelineBlend(inputs, renderer, entity, coverage, BlendMode::kSrc,
959 std::nullopt, GetAbsorbOpacity(), GetAlpha());
960 }
961
962 if (blend_mode_ <= Entity::kLastPipelineBlendMode) {
963 if (inputs.size() == 1 && foreground_color_.has_value() &&
964 GetAbsorbOpacity() == ColorFilterContents::AbsorbOpacity::kYes) {
965 return CreateForegroundPorterDuffBlend(
966 inputs[0], renderer, entity, coverage, foreground_color_.value(),
967 blend_mode_, GetAlpha(), GetAbsorbOpacity());
968 }
969 return PipelineBlend(inputs, renderer, entity, coverage, blend_mode_,
970 foreground_color_, GetAbsorbOpacity(), GetAlpha());
971 }
972
973 if (blend_mode_ <= Entity::kLastAdvancedBlendMode) {
974 if (renderer.GetDeviceCapabilities().SupportsFramebufferFetch()) {
975 return CreateFramebufferAdvancedBlend(inputs, renderer, entity, coverage,
976 foreground_color_, blend_mode_,
977 GetAlpha(), GetAbsorbOpacity());
978 }
979 if (inputs.size() == 1 && foreground_color_.has_value() &&
980 GetAbsorbOpacity() == ColorFilterContents::AbsorbOpacity::kYes) {
981 return CreateForegroundAdvancedBlend(
982 inputs[0], renderer, entity, coverage, foreground_color_.value(),
983 blend_mode_, GetAlpha(), GetAbsorbOpacity());
984 }
985 return advanced_blend_proc_(inputs, renderer, entity, coverage, blend_mode_,
986 foreground_color_, GetAbsorbOpacity(),
987 GetAlpha());
988 }
989
990 FML_UNREACHABLE();
991 }
992
993 } // namespace impeller
anonymous_contents.h
BLEND_CASE
#define BLEND_CASE(mode)
Definition: blend_filter_contents.cc:895
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:910
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:941
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::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:138
impeller::ContentContext::GetTransientsBuffer
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Definition: content_context.h:296
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:841
impeller::ContentContext::GetDeviceCapabilities
const Capabilities & GetDeviceCapabilities() const
Definition: content_context.cc:917
impeller::ContentContext::GetTexturePipeline
PipelineRef GetTexturePipeline(ContentContextOptions opts) const
Definition: content_context.cc:1070
impeller::ContentContext::SubpassCallback
std::function< bool(const ContentContext &, RenderPass &)> SubpassCallback
Definition: content_context.h:244
impeller::ContentContext::GetContext
std::shared_ptr< Context > GetContext() const
Definition: content_context.cc:913
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::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:144
impeller::Entity::kLastPipelineBlendMode
static constexpr BlendMode kLastPipelineBlendMode
Definition: entity.h:22
impeller::Entity::FromSnapshot
static Entity FromSnapshot(const Snapshot &snapshot, BlendMode blend_mode=BlendMode::kSrcOver)
Create an entity that can be used to render a given snapshot.
Definition: entity.cc:18
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:119
impeller::RenderPipelineHandle::FragmentShader
FragmentShader_ FragmentShader
Definition: pipeline.h:120
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::Saturation
static constexpr Scalar Saturation(Vector3 color)
Definition: color.cc:89
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:792
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:88
impeller::FS
LinePipeline::FragmentShader FS
Definition: line_contents.cc:14
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:500
impeller::BlendMode
BlendMode
Definition: color.h:58
impeller::BlendMode::kSrcOut
@ kSrcOut
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::kDst
@ kDst
impeller::BlendMode::kDstIn
@ kDstIn
impeller::BlendMode::kModulate
@ kModulate
impeller::BlendMode::kMultiply
@ kMultiply
impeller::BlendMode::kColorDodge
@ kColorDodge
impeller::BlendMode::kScreen
@ kScreen
impeller::BlendMode::kSrcOver
@ kSrcOver
impeller::BlendMode::kXor
@ kXor
impeller::BlendMode::kSrc
@ kSrc
impeller::BlendMode::kLuminosity
@ kLuminosity
impeller::BlendMode::kSoftLight
@ kSoftLight
impeller::BlendMode::kDifference
@ kDifference
impeller::BlendMode::kOverlay
@ kOverlay
impeller::BlendMode::kSrcATop
@ kSrcATop
impeller::BlendMode::kDstATop
@ kDstATop
impeller::BlendMode::kDstOver
@ kDstOver
impeller::BlendMode::kColor
@ kColor
impeller::BlendMode::kHardLight
@ kHardLight
impeller::BlendMode::kDstOut
@ kDstOut
impeller::BlendMode::kDarken
@ kDarken
impeller::BlendMode::kSrcIn
@ kSrcIn
impeller::BlendMode::kClear
@ kClear
impeller::VS
LinePipeline::VertexShader VS
Definition: line_contents.cc:13
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:162
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:124
impeller::ContentContextOptions
Definition: content_context.h:40
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:566
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