| 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/entity/contents/anonymous_contents.h"
17 #include "impeller/entity/contents/content_context.h"
18 #include "impeller/entity/contents/contents.h"
19 #include "impeller/entity/contents/filters/color_filter_contents.h"
20 #include "impeller/entity/contents/filters/inputs/filter_input.h"
21 #include "impeller/entity/contents/solid_color_contents.h"
22 #include "impeller/entity/entity.h"
23 #include "impeller/entity/texture_fill.frag.h"
24 #include "impeller/entity/texture_fill.vert.h"
25 #include "impeller/geometry/color.h"
26 #include "impeller/renderer/render_pass.h"
27 #include "impeller/renderer/snapshot.h"
28
29 namespace impeller {
30
31 std::optional<BlendMode> InvertPorterDuffBlend(BlendMode blend_mode) {
32 switch (blend_mode) {
33 case BlendMode::kClear:
34 return BlendMode::kClear;
35 case BlendMode::kSource:
36 return BlendMode::kDestination;
37 case BlendMode::kDestination:
38 return BlendMode::kSource;
39 case BlendMode::kSourceOver:
40 return BlendMode::kDestinationOver;
41 case BlendMode::kDestinationOver:
42 return BlendMode::kSourceOver;
43 case BlendMode::kSourceIn:
44 return BlendMode::kDestinationIn;
45 case BlendMode::kDestinationIn:
46 return BlendMode::kSourceIn;
47 case BlendMode::kSourceOut:
48 return BlendMode::kDestinationOut;
49 case BlendMode::kDestinationOut:
50 return BlendMode::kSourceOut;
51 case BlendMode::kSourceATop:
52 return BlendMode::kDestinationATop;
53 case BlendMode::kDestinationATop:
54 return BlendMode::kSourceATop;
55 case BlendMode::kXor:
56 return BlendMode::kXor;
57 case BlendMode::kPlus:
58 return BlendMode::kPlus;
59 case BlendMode::kModulate:
60 return BlendMode::kModulate;
61 default:
62 return std::nullopt;
63 }
64 }
65
66 BlendFilterContents::BlendFilterContents() {
67 SetBlendMode(BlendMode::kSourceOver);
68 }
69
70 BlendFilterContents::~BlendFilterContents() = default;
71
72 using PipelineProc = std::shared_ptr<Pipeline<PipelineDescriptor>> (
73 ContentContext::*)(ContentContextOptions) const;
74
75 template <typename TPipeline>
76 static std::optional<Entity> AdvancedBlend(
77 const FilterInput::Vector& inputs,
78 const ContentContext& renderer,
79 const Entity& entity,
80 const Rect& coverage,
81 BlendMode blend_mode,
82 std::optional<Color> foreground_color,
83 ColorFilterContents::AbsorbOpacity absorb_opacity,
84 PipelineProc pipeline_proc,
85 std::optional<Scalar> alpha) {
86 using VS = typename TPipeline::VertexShader;
87 using FS = typename TPipeline::FragmentShader;
88
89 //----------------------------------------------------------------------------
90 /// Handle inputs.
91 ///
92
93 const size_t total_inputs =
94 inputs.size() + (foreground_color.has_value() ? 1 : 0);
95 if (total_inputs < 2) {
96 return std::nullopt;
97 }
98
99 auto dst_snapshot =
100 inputs[0]->GetSnapshot("AdvancedBlend(Dst)", renderer, entity);
101 if (!dst_snapshot.has_value()) {
102 return std::nullopt;
103 }
104 auto maybe_dst_uvs = dst_snapshot->GetCoverageUVs(coverage);
105 if (!maybe_dst_uvs.has_value()) {
106 return std::nullopt;
107 }
108 auto dst_uvs = maybe_dst_uvs.value();
109
110 std::optional<Snapshot> src_snapshot;
111 std::array<Point, 4> src_uvs;
112 if (!foreground_color.has_value()) {
113 src_snapshot =
114 inputs[1]->GetSnapshot("AdvancedBlend(Src)", renderer, entity);
115 if (!src_snapshot.has_value()) {
116 if (!dst_snapshot.has_value()) {
117 return std::nullopt;
118 }
119 return Entity::FromSnapshot(dst_snapshot.value(), entity.GetBlendMode());
120 }
121 auto maybe_src_uvs = src_snapshot->GetCoverageUVs(coverage);
122 if (!maybe_src_uvs.has_value()) {
123 if (!dst_snapshot.has_value()) {
124 return std::nullopt;
125 }
126 return Entity::FromSnapshot(dst_snapshot.value(), entity.GetBlendMode());
127 }
128 src_uvs = maybe_src_uvs.value();
129 }
130
131 Rect subpass_coverage = coverage;
132 if (entity.GetContents()) {
133 auto coverage_hint = entity.GetContents()->GetCoverageHint();
134
135 if (coverage_hint.has_value()) {
136 auto maybe_subpass_coverage =
137 subpass_coverage.Intersection(*coverage_hint);
138 if (!maybe_subpass_coverage.has_value()) {
139 return std::nullopt; // Nothing to render.
140 }
141
142 subpass_coverage = *maybe_subpass_coverage;
143 }
144 }
145
146 //----------------------------------------------------------------------------
147 /// Render to texture.
148 ///
149
150 ContentContext::SubpassCallback callback = [&](const ContentContext& renderer,
151 RenderPass& pass) {
152 auto& host_buffer = renderer.GetTransientsBuffer();
153
154 auto size = pass.GetRenderTargetSize();
155 VertexBufferBuilder<typename VS::PerVertexData> vtx_builder;
156 vtx_builder.AddVertices({
157 {Point(0, 0), dst_uvs[0], src_uvs[0]},
158 {Point(size.width, 0), dst_uvs[1], src_uvs[1]},
159 {Point(0, size.height), dst_uvs[2], src_uvs[2]},
160 {Point(size.width, size.height), dst_uvs[3], src_uvs[3]},
161 });
162 auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);
163
164 auto options = OptionsFromPass(pass);
165 options.primitive_type = PrimitiveType::kTriangleStrip;
166 options.blend_mode = BlendMode::kSource;
167 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline =
168 std::invoke(pipeline_proc, renderer, options);
169
170 #ifdef IMPELLER_DEBUG
171 pass.SetCommandLabel(
172 SPrintF("Advanced Blend Filter (%s)", BlendModeToString(blend_mode)));
173 #endif // IMPELLER_DEBUG
174 pass.SetVertexBuffer(std::move(vtx_buffer));
175 pass.SetPipeline(pipeline);
176
177 typename FS::BlendInfo blend_info;
178 typename VS::FrameInfo frame_info;
179
180 auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor;
181 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
182 dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
183 dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
184 }
185 const std::unique_ptr<const Sampler>& dst_sampler =
186 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
187 dst_sampler_descriptor);
188 FS::BindTextureSamplerDst(pass, dst_snapshot->texture, dst_sampler);
189 frame_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale();
190 blend_info.dst_input_alpha =
191 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
192 ? dst_snapshot->opacity
193 : 1.0;
194
195 if (foreground_color.has_value()) {
196 blend_info.color_factor = 1;
197 blend_info.color = foreground_color.value();
198 // This texture will not be sampled from due to the color factor. But
199 // this is present so that validation doesn't trip on a missing
200 // binding.
201 FS::BindTextureSamplerSrc(pass, dst_snapshot->texture, dst_sampler);
202 } else {
203 auto src_sampler_descriptor = src_snapshot->sampler_descriptor;
204 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
205 src_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
206 src_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
207 }
208 const std::unique_ptr<const Sampler>& src_sampler =
209 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
210 src_sampler_descriptor);
211 blend_info.color_factor = 0;
212 blend_info.src_input_alpha = src_snapshot->opacity;
213 FS::BindTextureSamplerSrc(pass, src_snapshot->texture, src_sampler);
214 frame_info.src_y_coord_scale = src_snapshot->texture->GetYCoordScale();
215 }
216 auto blend_uniform = host_buffer.EmplaceUniform(blend_info);
217 FS::BindBlendInfo(pass, blend_uniform);
218
219 frame_info.mvp = pass.GetOrthographicTransform() *
220 Matrix::MakeTranslation(coverage.GetOrigin() -
221 subpass_coverage.GetOrigin());
222
223 auto uniform_view = host_buffer.EmplaceUniform(frame_info);
224 VS::BindFrameInfo(pass, uniform_view);
225
226 return pass.Draw().ok();
227 };
228
229 std::shared_ptr<CommandBuffer> command_buffer =
230 renderer.GetContext()->CreateCommandBuffer();
231 if (!command_buffer) {
232 return std::nullopt;
233 }
234 fml::StatusOr<RenderTarget> render_target = renderer.MakeSubpass(
235 "Advanced Blend Filter", ISize(subpass_coverage.GetSize()),
236 command_buffer, callback);
237 if (!render_target.ok()) {
238 return std::nullopt;
239 }
240 if (!renderer.GetContext()
241 ->GetCommandQueue()
242 ->Submit(/*buffers=*/{std::move(command_buffer)})
243 .ok()) {
244 return std::nullopt;
245 }
246
247 return Entity::FromSnapshot(
248 Snapshot{
249 .texture = render_target.value().GetRenderTargetTexture(),
250 .transform = Matrix::MakeTranslation(subpass_coverage.GetOrigin()),
251 // Since we absorbed the transform of the inputs and used the
252 // respective snapshot sampling modes when blending, pass on
253 // the default NN clamp sampler.
254 .sampler_descriptor = {},
255 .opacity = (absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
256 ? 1.0f
257 : dst_snapshot->opacity) *
258 alpha.value_or(1.0)},
259 entity.GetBlendMode());
260 }
261
262 std::optional<Entity> BlendFilterContents::CreateForegroundAdvancedBlend(
263 const std::shared_ptr<FilterInput>& input,
264 const ContentContext& renderer,
265 const Entity& entity,
266 const Rect& coverage,
267 Color foreground_color,
268 BlendMode blend_mode,
269 std::optional<Scalar> alpha,
270 ColorFilterContents::AbsorbOpacity absorb_opacity) const {
271 auto dst_snapshot =
272 input->GetSnapshot("ForegroundAdvancedBlend", renderer, entity);
273 if (!dst_snapshot.has_value()) {
274 return std::nullopt;
275 }
276
277 RenderProc render_proc = [foreground_color, dst_snapshot, blend_mode, alpha,
278 absorb_opacity](const ContentContext& renderer,
279 const Entity& entity,
280 RenderPass& pass) -> bool {
281 using VS = BlendScreenPipeline::VertexShader;
282 using FS = BlendScreenPipeline::FragmentShader;
283
284 auto& host_buffer = renderer.GetTransientsBuffer();
285
286 auto size = dst_snapshot->texture->GetSize();
287 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
288 vtx_builder.AddVertices({
289 {{0, 0}, {0, 0}, {0, 0}},
290 {Point(size.width, 0), {1, 0}, {1, 0}},
291 {Point(0, size.height), {0, 1}, {0, 1}},
292 {Point(size.width, size.height), {1, 1}, {1, 1}},
293 });
294 auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);
295
296 #ifdef IMPELLER_DEBUG
297 pass.SetCommandLabel(SPrintF("Foreground Advanced Blend Filter (%s)",
298 BlendModeToString(blend_mode)));
299 #endif // IMPELLER_DEBUG
300 pass.SetVertexBuffer(std::move(vtx_buffer));
301 auto options = OptionsFromPass(pass);
302 options.primitive_type = PrimitiveType::kTriangleStrip;
303
304 switch (blend_mode) {
305 case BlendMode::kScreen:
306 pass.SetPipeline(renderer.GetBlendScreenPipeline(options));
307 break;
308 case BlendMode::kOverlay:
309 pass.SetPipeline(renderer.GetBlendOverlayPipeline(options));
310 break;
311 case BlendMode::kDarken:
312 pass.SetPipeline(renderer.GetBlendDarkenPipeline(options));
313 break;
314 case BlendMode::kLighten:
315 pass.SetPipeline(renderer.GetBlendLightenPipeline(options));
316 break;
317 case BlendMode::kColorDodge:
318 pass.SetPipeline(renderer.GetBlendColorDodgePipeline(options));
319 break;
320 case BlendMode::kColorBurn:
321 pass.SetPipeline(renderer.GetBlendColorBurnPipeline(options));
322 break;
323 case BlendMode::kHardLight:
324 pass.SetPipeline(renderer.GetBlendHardLightPipeline(options));
325 break;
326 case BlendMode::kSoftLight:
327 pass.SetPipeline(renderer.GetBlendSoftLightPipeline(options));
328 break;
329 case BlendMode::kDifference:
330 pass.SetPipeline(renderer.GetBlendDifferencePipeline(options));
331 break;
332 case BlendMode::kExclusion:
333 pass.SetPipeline(renderer.GetBlendExclusionPipeline(options));
334 break;
335 case BlendMode::kMultiply:
336 pass.SetPipeline(renderer.GetBlendMultiplyPipeline(options));
337 break;
338 case BlendMode::kHue:
339 pass.SetPipeline(renderer.GetBlendHuePipeline(options));
340 break;
341 case BlendMode::kSaturation:
342 pass.SetPipeline(renderer.GetBlendSaturationPipeline(options));
343 break;
344 case BlendMode::kColor:
345 pass.SetPipeline(renderer.GetBlendColorPipeline(options));
346 break;
347 case BlendMode::kLuminosity:
348 pass.SetPipeline(renderer.GetBlendLuminosityPipeline(options));
349 break;
350 default:
351 return false;
352 }
353
354 FS::BlendInfo blend_info;
355 VS::FrameInfo frame_info;
356
357 auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor;
358 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
359 dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
360 dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
361 }
362 const std::unique_ptr<const Sampler>& dst_sampler =
363 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
364 dst_sampler_descriptor);
365 FS::BindTextureSamplerDst(pass, dst_snapshot->texture, dst_sampler);
366 frame_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale();
367
368 frame_info.mvp = Entity::GetShaderTransform(entity.GetShaderClipDepth(),
369 pass, dst_snapshot->transform);
370
371 blend_info.dst_input_alpha =
372 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
373 ? dst_snapshot->opacity * alpha.value_or(1.0)
374 : 1.0;
375
376 blend_info.color_factor = 1;
377 blend_info.color = foreground_color;
378 // This texture will not be sampled from due to the color factor. But
379 // this is present so that validation doesn't trip on a missing
380 // binding.
381 FS::BindTextureSamplerSrc(pass, dst_snapshot->texture, dst_sampler);
382
383 auto blend_uniform = host_buffer.EmplaceUniform(blend_info);
384 FS::BindBlendInfo(pass, blend_uniform);
385
386 auto uniform_view = host_buffer.EmplaceUniform(frame_info);
387 VS::BindFrameInfo(pass, uniform_view);
388
389 return pass.Draw().ok();
390 };
391 CoverageProc coverage_proc =
392 [coverage](const Entity& entity) -> std::optional<Rect> {
393 return coverage.TransformBounds(entity.GetTransform());
394 };
395
396 auto contents = AnonymousContents::Make(render_proc, coverage_proc);
397
398 Entity sub_entity;
399 sub_entity.SetContents(std::move(contents));
400
401 return sub_entity;
402 }
403
404 std::optional<Entity> BlendFilterContents::CreateForegroundPorterDuffBlend(
405 const std::shared_ptr<FilterInput>& input,
406 const ContentContext& renderer,
407 const Entity& entity,
408 const Rect& coverage,
409 Color foreground_color,
410 BlendMode blend_mode,
411 std::optional<Scalar> alpha,
412 ColorFilterContents::AbsorbOpacity absorb_opacity) const {
413 if (blend_mode == BlendMode::kClear) {
414 return std::nullopt;
415 }
416
417 auto dst_snapshot =
418 input->GetSnapshot("ForegroundPorterDuffBlend", renderer, entity);
419 if (!dst_snapshot.has_value()) {
420 return std::nullopt;
421 }
422
423 if (blend_mode == BlendMode::kDestination) {
424 return Entity::FromSnapshot(dst_snapshot.value(), entity.GetBlendMode());
425 }
426
427 RenderProc render_proc = [foreground_color, dst_snapshot, blend_mode,
428 absorb_opacity, alpha](
429 const ContentContext& renderer,
430 const Entity& entity, RenderPass& pass) -> bool {
431 using VS = PorterDuffBlendPipeline::VertexShader;
432 using FS = PorterDuffBlendPipeline::FragmentShader;
433
434 auto& host_buffer = renderer.GetTransientsBuffer();
435 auto size = dst_snapshot->texture->GetSize();
436 auto color = foreground_color.Premultiply();
437 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
438 vtx_builder.AddVertices({
439 {{0, 0}, {0, 0}, color},
440 {Point(size.width, 0), {1, 0}, color},
441 {Point(0, size.height), {0, 1}, color},
442 {Point(size.width, size.height), {1, 1}, color},
443 });
444 auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);
445
446 #ifdef IMPELLER_DEBUG
447 pass.SetCommandLabel(SPrintF("Foreground PorterDuff Blend Filter (%s)",
448 BlendModeToString(blend_mode)));
449 #endif // IMPELLER_DEBUG
450 pass.SetVertexBuffer(std::move(vtx_buffer));
451 auto options = OptionsFromPass(pass);
452 options.primitive_type = PrimitiveType::kTriangleStrip;
453 pass.SetPipeline(renderer.GetPorterDuffBlendPipeline(options));
454
455 FS::FragInfo frag_info;
456 VS::FrameInfo frame_info;
457
458 frame_info.mvp = Entity::GetShaderTransform(entity.GetShaderClipDepth(),
459 pass, dst_snapshot->transform);
460
461 auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor;
462 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
463 dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
464 dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
465 }
466 const std::unique_ptr<const Sampler>& dst_sampler =
467 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
468 dst_sampler_descriptor);
469 FS::BindTextureSamplerDst(pass, dst_snapshot->texture, dst_sampler);
470 frame_info.texture_sampler_y_coord_scale =
471 dst_snapshot->texture->GetYCoordScale();
472
473 frag_info.input_alpha =
474 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
475 ? dst_snapshot->opacity * alpha.value_or(1.0)
476 : 1.0;
477 frag_info.output_alpha = 1.0;
478
479 auto blend_coefficients =
480 kPorterDuffCoefficients[static_cast<int>(blend_mode)];
481 frag_info.src_coeff = blend_coefficients[0];
482 frag_info.src_coeff_dst_alpha = blend_coefficients[1];
483 frag_info.dst_coeff = blend_coefficients[2];
484 frag_info.dst_coeff_src_alpha = blend_coefficients[3];
485 frag_info.dst_coeff_src_color = blend_coefficients[4];
486
487 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
488 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
489
490 return pass.Draw().ok();
491 };
492
493 CoverageProc coverage_proc =
494 [coverage](const Entity& entity) -> std::optional<Rect> {
495 return coverage.TransformBounds(entity.GetTransform());
496 };
497
498 auto contents = AnonymousContents::Make(render_proc, coverage_proc);
499
500 Entity sub_entity;
501 sub_entity.SetContents(std::move(contents));
502
503 return sub_entity;
504 }
505
506 static std::optional<Entity> PipelineBlend(
507 const FilterInput::Vector& inputs,
508 const ContentContext& renderer,
509 const Entity& entity,
510 const Rect& coverage,
511 BlendMode blend_mode,
512 std::optional<Color> foreground_color,
513 ColorFilterContents::AbsorbOpacity absorb_opacity,
514 std::optional<Scalar> alpha) {
515 using VS = TexturePipeline::VertexShader;
516 using FS = TexturePipeline::FragmentShader;
517
518 auto dst_snapshot =
519 inputs[0]->GetSnapshot("PipelineBlend(Dst)", renderer, entity);
520 if (!dst_snapshot.has_value()) {
521 return std::nullopt; // Nothing to render.
522 }
523
524 Rect subpass_coverage = coverage;
525 if (entity.GetContents()) {
526 auto coverage_hint = entity.GetContents()->GetCoverageHint();
527
528 if (coverage_hint.has_value()) {
529 auto maybe_subpass_coverage =
530 subpass_coverage.Intersection(*coverage_hint);
531 if (!maybe_subpass_coverage.has_value()) {
532 return std::nullopt; // Nothing to render.
533 }
534
535 subpass_coverage = *maybe_subpass_coverage;
536 }
537 }
538
539 ContentContext::SubpassCallback callback = [&](const ContentContext& renderer,
540 RenderPass& pass) {
541 auto& host_buffer = renderer.GetTransientsBuffer();
542
543 #ifdef IMPELLER_DEBUG
544 pass.SetCommandLabel(
545 SPrintF("Pipeline Blend Filter (%s)", BlendModeToString(blend_mode)));
546 #endif // IMPELLER_DEBUG
547 auto options = OptionsFromPass(pass);
548 options.primitive_type = PrimitiveType::kTriangleStrip;
549
550 auto add_blend_command = [&](std::optional<Snapshot> input) {
551 if (!input.has_value()) {
552 return false;
553 }
554 auto input_coverage = input->GetCoverage();
555 if (!input_coverage.has_value()) {
556 return false;
557 }
558
559 const std::unique_ptr<const Sampler>& sampler =
560 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
561 input->sampler_descriptor);
562 FS::BindTextureSampler(pass, input->texture, sampler);
563
564 auto size = input->texture->GetSize();
565 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
566 vtx_builder.AddVertices({
567 {Point(0, 0), Point(0, 0)},
568 {Point(size.width, 0), Point(1, 0)},
569 {Point(0, size.height), Point(0, 1)},
570 {Point(size.width, size.height), Point(1, 1)},
571 });
572 pass.SetVertexBuffer(vtx_builder.CreateVertexBuffer(host_buffer));
573
574 VS::FrameInfo frame_info;
575 frame_info.mvp = pass.GetOrthographicTransform() *
576 Matrix::MakeTranslation(-subpass_coverage.GetOrigin()) *
577 input->transform;
578 frame_info.texture_sampler_y_coord_scale =
579 input->texture->GetYCoordScale();
580
581 FS::FragInfo frag_info;
582 frag_info.alpha =
583 absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
584 ? input->opacity
585 : 1.0;
586 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
587 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
588
589 return pass.Draw().ok();
590 };
591
592 // Draw the first texture using kSource.
593 options.blend_mode = BlendMode::kSource;
594 pass.SetPipeline(renderer.GetTexturePipeline(options));
595 if (!add_blend_command(dst_snapshot)) {
596 return true;
597 }
598
599 // Write subsequent textures using the selected blend mode.
600
601 if (inputs.size() >= 2) {
602 options.blend_mode = blend_mode;
603 pass.SetPipeline(renderer.GetTexturePipeline(options));
604
605 for (auto texture_i = inputs.begin() + 1; texture_i < inputs.end();
606 texture_i++) {
607 auto src_input = texture_i->get()->GetSnapshot("PipelineBlend(Src)",
608 renderer, entity);
609 if (!add_blend_command(src_input)) {
610 return true;
611 }
612 }
613 }
614
615 // If a foreground color is set, blend it in.
616
617 if (foreground_color.has_value()) {
618 auto contents = std::make_shared<SolidColorContents>();
619 contents->SetGeometry(
620 Geometry::MakeRect(Rect::MakeSize(pass.GetRenderTargetSize())));
621 contents->SetColor(foreground_color.value());
622
623 Entity foreground_entity;
624 foreground_entity.SetBlendMode(blend_mode);
625 foreground_entity.SetContents(contents);
626 if (!foreground_entity.Render(renderer, pass)) {
627 return false;
628 }
629 }
630
631 return true;
632 };
633
634 std::shared_ptr<CommandBuffer> command_buffer =
635 renderer.GetContext()->CreateCommandBuffer();
636 if (!command_buffer) {
637 return std::nullopt;
638 }
639
640 fml::StatusOr<RenderTarget> render_target = renderer.MakeSubpass(
641 "Pipeline Blend Filter", ISize(subpass_coverage.GetSize()),
642 command_buffer, callback);
643
644 if (!render_target.ok()) {
645 return std::nullopt;
646 }
647
648 if (!renderer.GetContext()
649 ->GetCommandQueue()
650 ->Submit(/*buffers=*/{std::move(command_buffer)})
651 .ok()) {
652 return std::nullopt;
653 }
654
655 return Entity::FromSnapshot(
656 Snapshot{
657 .texture = render_target.value().GetRenderTargetTexture(),
658 .transform = Matrix::MakeTranslation(subpass_coverage.GetOrigin()),
659 // Since we absorbed the transform of the inputs and used the
660 // respective snapshot sampling modes when blending, pass on
661 // the default NN clamp sampler.
662 .sampler_descriptor = {},
663 .opacity = (absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
664 ? 1.0f
665 : dst_snapshot->opacity) *
666 alpha.value_or(1.0)},
667 entity.GetBlendMode());
668 }
669
670 std::optional<Entity> BlendFilterContents::CreateFramebufferAdvancedBlend(
671 const FilterInput::Vector& inputs,
672 const ContentContext& renderer,
673 const Entity& entity,
674 const Rect& coverage,
675 std::optional<Color> foreground_color,
676 BlendMode blend_mode,
677 std::optional<Scalar> alpha,
678 ColorFilterContents::AbsorbOpacity absorb_opacity) const {
679 // This works with either 2 contents or 1 contents and a foreground color.
680 FML_DCHECK(inputs.size() == 2u ||
681 (inputs.size() == 1u && foreground_color.has_value()));
682
683 auto dst_snapshot =
684 inputs[0]->GetSnapshot("ForegroundAdvancedBlend", renderer, entity);
685 if (!dst_snapshot.has_value()) {
686 return std::nullopt;
687 }
688
689 std::shared_ptr<Texture> foreground_texture;
690
691 ContentContext::SubpassCallback subpass_callback = [&](const ContentContext&
692 renderer,
693 RenderPass& pass) {
694 // First, we create a new render pass and populate it with the contents
695 // of the first (dst) input.
696 HostBuffer& host_buffer = renderer.GetTransientsBuffer();
697
698 {
699 using FS = TextureFillFragmentShader;
700 using VS = TextureFillVertexShader;
701
702 pass.SetCommandLabel("Framebuffer Advanced Blend");
703 auto pipeline_options = OptionsFromPass(pass);
704 pipeline_options.primitive_type = PrimitiveType::kTriangleStrip;
705 pass.SetPipeline(renderer.GetTexturePipeline(pipeline_options));
706
707 VS::FrameInfo frame_info;
708 frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1));
709 frame_info.texture_sampler_y_coord_scale = 1.0;
710
711 FS::FragInfo frag_info;
712 frag_info.alpha = 1.0;
713
714 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
715 vtx_builder.AddVertices({
716 {{0, 0}, {0, 0}},
717 {Point(1, 0), {1, 0}},
718 {Point(0, 1), {0, 1}},
719 {Point(1, 1), {1, 1}},
720 });
721 auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);
722 pass.SetVertexBuffer(std::move(vtx_buffer));
723
724 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
725 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
726 FS::BindTextureSampler(
727 pass, dst_snapshot->texture,
728 renderer.GetContext()->GetSamplerLibrary()->GetSampler({}));
729
730 if (!pass.Draw().ok()) {
731 return false;
732 }
733 }
734
735 {
736 using VS = FramebufferBlendScreenPipeline::VertexShader;
737 using FS = FramebufferBlendScreenPipeline::FragmentShader;
738
739 // Next, we render the second contents to a snapshot, or create a 1x1
740 // texture for the foreground color.
741 std::shared_ptr<Texture> src_texture;
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 }
755
756 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
757 vtx_builder.AddVertices({
758 {Point(0, 0), Point(0, 0)},
759 {Point(1, 0), Point(1, 0)},
760 {Point(0, 1), Point(0, 1)},
761 {Point(1, 1), Point(1, 1)},
762 });
763
764 auto options = OptionsFromPass(pass);
765 options.blend_mode = BlendMode::kSource;
766 options.primitive_type = PrimitiveType::kTriangleStrip;
767
768 pass.SetCommandLabel("Framebuffer Advanced Blend Filter");
769 pass.SetVertexBuffer(vtx_builder.CreateVertexBuffer(host_buffer));
770
771 switch (blend_mode) {
772 case BlendMode::kScreen:
773 pass.SetPipeline(renderer.GetFramebufferBlendScreenPipeline(options));
774 break;
775 case BlendMode::kOverlay:
776 pass.SetPipeline(
777 renderer.GetFramebufferBlendOverlayPipeline(options));
778 break;
779 case BlendMode::kDarken:
780 pass.SetPipeline(renderer.GetFramebufferBlendDarkenPipeline(options));
781 break;
782 case BlendMode::kLighten:
783 pass.SetPipeline(
784 renderer.GetFramebufferBlendLightenPipeline(options));
785 break;
786 case BlendMode::kColorDodge:
787 pass.SetPipeline(
788 renderer.GetFramebufferBlendColorDodgePipeline(options));
789 break;
790 case BlendMode::kColorBurn:
791 pass.SetPipeline(
792 renderer.GetFramebufferBlendColorBurnPipeline(options));
793 break;
794 case BlendMode::kHardLight:
795 pass.SetPipeline(
796 renderer.GetFramebufferBlendHardLightPipeline(options));
797 break;
798 case BlendMode::kSoftLight:
799 pass.SetPipeline(
800 renderer.GetFramebufferBlendSoftLightPipeline(options));
801 break;
802 case BlendMode::kDifference:
803 pass.SetPipeline(
804 renderer.GetFramebufferBlendDifferencePipeline(options));
805 break;
806 case BlendMode::kExclusion:
807 pass.SetPipeline(
808 renderer.GetFramebufferBlendExclusionPipeline(options));
809 break;
810 case BlendMode::kMultiply:
811 pass.SetPipeline(
812 renderer.GetFramebufferBlendMultiplyPipeline(options));
813 break;
814 case BlendMode::kHue:
815 pass.SetPipeline(renderer.GetFramebufferBlendHuePipeline(options));
816 break;
817 case BlendMode::kSaturation:
818 pass.SetPipeline(
819 renderer.GetFramebufferBlendSaturationPipeline(options));
820 break;
821 case BlendMode::kColor:
822 pass.SetPipeline(renderer.GetFramebufferBlendColorPipeline(options));
823 break;
824 case BlendMode::kLuminosity:
825 pass.SetPipeline(
826 renderer.GetFramebufferBlendLuminosityPipeline(options));
827 break;
828 default:
829 return false;
830 }
831
832 VS::FrameInfo frame_info;
833 FS::FragInfo frag_info;
834
835 auto src_sampler_descriptor = SamplerDescriptor{};
836 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
837 src_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
838 src_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
839 }
840 const std::unique_ptr<const Sampler>& src_sampler =
841 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
842 src_sampler_descriptor);
843 FS::BindTextureSamplerSrc(pass, src_texture, src_sampler);
844
845 frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1));
846 frame_info.src_y_coord_scale = src_texture->GetYCoordScale();
847 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
848
849 frag_info.src_input_alpha = 1.0;
850 FS::BindFragInfo(pass, 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 auto blit_pass = cmd_buffer->CreateBlitPass();
871 auto buffer_view = renderer.GetTransientsBuffer().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 renderer.GetContext()->GetResourceAllocator())) {
877 return std::nullopt;
878 }
879 }
880
881 auto render_target =
882 renderer.MakeSubpass("FramebufferBlend", dst_snapshot->texture->GetSize(),
883 cmd_buffer, subpass_callback);
884
885 if (!render_target.ok()) {
886 return std::nullopt;
887 }
888
889 if (!renderer.GetContext()
890 ->GetCommandQueue()
891 ->Submit(/*buffers=*/{std::move(cmd_buffer)})
892 .ok()) {
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::kSource,
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
impeller::ContentContext::GetTexturePipeline
std::shared_ptr< Pipeline< PipelineDescriptor > > GetTexturePipeline(ContentContextOptions opts) const
Definition: content_context.h:442
impeller::ISize
ISize64 ISize
Definition: size.h:140
impeller::RenderPipelineHandle::FragmentShader
FragmentShader_ FragmentShader
Definition: pipeline.h:107
impeller::Entity::GetShaderTransform
Matrix GetShaderTransform(const RenderPass &pass) const
Get the vertex shader transform used for drawing this Entity.
Definition: entity.cc:50
impeller::OptionsFromPass
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition: contents.cc:19
BLEND_CASE
#define BLEND_CASE(mode)
Definition: blend_filter_contents.cc:911
impeller::Entity::kLastPipelineBlendMode
static constexpr BlendMode kLastPipelineBlendMode
Definition: entity.h:22
impeller::BlendModeToString
const char * BlendModeToString(BlendMode blend_mode)
Definition: color.cc:47
impeller::BlendMode::kDestinationATop
@ kDestinationATop
contents.h
impeller::BlendFilterContents::SetBlendMode
void SetBlendMode(BlendMode blend_mode)
Definition: blend_filter_contents.cc:926
impeller::Entity::SetBlendMode
void SetBlendMode(BlendMode blend_mode)
Definition: entity.cc:115
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
entity.h
impeller::BlendMode
BlendMode
Definition: color.h:59
solid_color_contents.h
impeller::Color
Definition: color.h:124
impeller::BlendMode::kLuminosity
@ kLuminosity
impeller::BlendMode::kSource
@ kSource
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::BlendMode::kColorDodge
@ kColorDodge
impeller::BlendMode::kDestination
@ kDestination
texture_descriptor.h
impeller::BlendMode::kDarken
@ kDarken
formats.h
impeller::TRect::Intersection
constexpr std::optional< TRect > Intersection(const TRect &o) const
Definition: rect.h:519
impeller::InvertPorterDuffBlend
std::optional< BlendMode > InvertPorterDuffBlend(BlendMode blend_mode)
Definition: blend_filter_contents.cc:31
impeller::BlendMode::kColor
@ kColor
impeller::BlendMode::kDestinationOver
@ kDestinationOver
impeller::BlendMode::kPlus
@ kPlus
impeller::BlendMode::kOverlay
@ kOverlay
impeller::VertexBufferBuilder::AddVertices
VertexBufferBuilder & AddVertices(std::initializer_list< VertexType_ > vertices)
Definition: vertex_buffer_builder.h:67
buffer_view
BufferView buffer_view
Definition: blit_command_gles.cc:127
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
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:310
impeller::BlendMode::kModulate
@ kModulate
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:76
impeller::BlendMode::kSourceOut
@ kSourceOut
impeller::BlendMode::kSaturation
@ kSaturation
impeller::Entity::SetContents
void SetContents(std::shared_ptr< Contents > contents)
Definition: entity.cc:90
impeller::BlendMode::kDifference
@ kDifference
impeller::VS
SolidFillVertexShader VS
Definition: stroke_path_geometry.cc:16
impeller::Entity
Definition: entity.h:20
impeller::BlendMode::kLighten
@ kLighten
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
impeller::BlendMode::kSoftLight
@ kSoftLight
impeller::Point
TPoint< Scalar > Point
Definition: point.h:322
render_pass.h
impeller::BlendMode::kColorBurn
@ kColorBurn
impeller::Entity::Render
bool Render(const ContentContext &renderer, RenderPass &parent_pass) const
Definition: entity.cc:173
impeller::BlendMode::kHardLight
@ kHardLight
impeller::SPrintF
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:231
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:22
impeller::BlendMode::kClear
@ kClear
impeller::ContentContext::GetContext
std::shared_ptr< Context > GetContext() const
Definition: content_context.cc:553
impeller::VertexBufferBuilder
Definition: vertex_buffer_builder.h:21
impeller::StorageMode::kDevicePrivate
@ kDevicePrivate
impeller::Entity::kLastAdvancedBlendMode
static constexpr BlendMode kLastAdvancedBlendMode
Definition: entity.h:23
impeller::ColorFilterContents::GetAbsorbOpacity
AbsorbOpacity GetAbsorbOpacity() const
Definition: color_filter_contents.cc:89
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:475
impeller::Snapshot
Represents a texture and its intended draw transform/sampler configuration.
Definition: snapshot.h:24
impeller::RenderPipelineHandle::VertexShader
VertexShader_ VertexShader
Definition: pipeline.h:106
impeller::kPorterDuffCoefficients
constexpr std::array< std::array< Scalar, 5 >, 15 > kPorterDuffCoefficients
Definition: blend_filter_contents.h:15
impeller::Entity::GetContents
const std::shared_ptr< Contents > & GetContents() const
Definition: entity.cc:94
impeller::PipelineProc
std::shared_ptr< Pipeline< PipelineDescriptor > >(ContentContext::*)(ContentContextOptions) const PipelineProc
Definition: blend_filter_contents.cc:73
filter_input.h
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:769
impeller::Luminosity
static constexpr Scalar Luminosity(Vector3 color)
Definition: color.cc:140
strings.h
color_filter_contents.h
impeller::BlendFilterContents::~BlendFilterContents
~BlendFilterContents() override
anonymous_contents.h
impeller::Entity::GetBlendMode
BlendMode GetBlendMode() const
Definition: entity.cc:119
impeller::VertexBufferBuilder::CreateVertexBuffer
VertexBuffer CreateVertexBuffer(HostBuffer &host_buffer) const
Definition: vertex_buffer_builder.h:81
impeller::ContentContext::SubpassCallback
std::function< bool(const ContentContext &, RenderPass &)> SubpassCallback
Definition: content_context.h:700
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:33
impeller::Geometry::MakeRect
static std::shared_ptr< Geometry > MakeRect(const Rect &rect)
Definition: geometry.cc:89
sampler_descriptor.h
impeller::BlendMode::kDestinationIn
@ kDestinationIn
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:73
impeller::BlendMode::kExclusion
@ kExclusion
content_context.h
impeller::BlendMode::kDestinationOut
@ kDestinationOut
impeller::Contents::RenderProc
std::function< bool(const ContentContext &renderer, const Entity &entity, RenderPass &pass)> RenderProc
Definition: contents.h:46
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:317
impeller::ContentContext::GetDeviceCapabilities
const Capabilities & GetDeviceCapabilities() const
Definition: content_context.cc:557
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:146
snapshot.h
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:506
impeller::BlendMode::kSourceIn
@ kSourceIn
impeller::BlendMode::kScreen
@ kScreen
impeller::Matrix::MakeOrthographic
static constexpr Matrix MakeOrthographic(TSize< T > size)
Definition: matrix.h:497
color.h
color
DlColor color
Definition: dl_golden_blur_unittests.cc:23
impeller::BlendMode::kHue
@ kHue
blend_filter_contents.h
impeller::Contents::CoverageProc
std::function< std::optional< Rect >(const Entity &entity)> CoverageProc
Definition: contents.h:47
impeller::Snapshot::texture
std::shared_ptr< Texture > texture
Definition: snapshot.h:25
impeller::ColorFilterContents::AbsorbOpacity::kYes
@ kYes
impeller::FilterInput::Vector
std::vector< FilterInput::Ref > Vector
Definition: filter_input.h:33
impeller::BlendMode::kXor
@ kXor
impeller::ColorFilterContents::GetAlpha
std::optional< Scalar > GetAlpha() const
Definition: color_filter_contents.cc:98
impeller::Capabilities::SupportsDecalSamplerAddressMode
virtual bool SupportsDecalSamplerAddressMode() const =0
Whether the context backend supports SamplerAddressMode::Decal.
impeller::ContentContextOptions
Definition: content_context.h:254
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::AbsorbOpacity
AbsorbOpacity
Definition: color_filter_contents.h:14
impeller
Definition: aiks_blend_unittests.cc:18
impeller::BlendMode::kSourceATop
@ kSourceATop
impeller::BlendMode::kMultiply
@ kMultiply
impeller::ContentContext
Definition: content_context.h:366
impeller::BlendFilterContents::BlendFilterContents
BlendFilterContents()
Definition: blend_filter_contents.cc:66
impeller::TRect< Scalar >
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::BlendMode::kSourceOver
@ kSourceOver
impeller::AnonymousContents::Make
static std::shared_ptr< Contents > Make(RenderProc render_proc, CoverageProc coverage_proc)
Definition: anonymous_contents.cc:11
impeller::ContentContext::GetTransientsBuffer
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Definition: content_context.h:752
impeller::Saturation
static constexpr Scalar Saturation(Vector3 color)
Definition: color.cc:166
impeller::SamplerAddressMode::kDecal
@ kDecal
decal sampling mode is only supported on devices that pass the Capabilities.SupportsDecalSamplerAddre...