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