11#include "flutter/fml/logging.h"
23#include "impeller/entity/texture_fill.frag.h"
24#include "impeller/entity/texture_fill.vert.h"
72using PipelineProc = std::shared_ptr<Pipeline<PipelineDescriptor>> (
75template <
typename TPipeline>
85 std::optional<Scalar> alpha) {
86 using VS =
typename TPipeline::VertexShader;
87 using FS =
typename TPipeline::FragmentShader;
93 const size_t total_inputs =
95 if (total_inputs < 2) {
101 if (!dst_snapshot.has_value()) {
104 auto maybe_dst_uvs = dst_snapshot->GetCoverageUVs(
coverage);
105 if (!maybe_dst_uvs.has_value()) {
108 auto dst_uvs = maybe_dst_uvs.value();
110 std::optional<Snapshot> src_snapshot;
111 std::array<Point, 4> src_uvs;
115 if (!src_snapshot.has_value()) {
116 if (!dst_snapshot.has_value()) {
121 auto maybe_src_uvs = src_snapshot->GetCoverageUVs(
coverage);
122 if (!maybe_src_uvs.has_value()) {
123 if (!dst_snapshot.has_value()) {
128 src_uvs = maybe_src_uvs.value();
133 auto coverage_hint = entity.
GetContents()->GetCoverageHint();
135 if (coverage_hint.has_value()) {
136 auto maybe_subpass_coverage =
138 if (!maybe_subpass_coverage.has_value()) {
142 subpass_coverage = *maybe_subpass_coverage;
152 auto& host_buffer =
renderer.GetTransientsBuffer();
154 auto size = pass.GetRenderTargetSize();
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]},
167 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline =
171 pass.SetCommandLabel(
174 pass.SetVertexBuffer(std::move(vtx_buffer));
175 pass.SetPipeline(pipeline);
177 typename FS::BlendInfo blend_info;
178 typename VS::FrameInfo frame_info;
180 auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor;
181 if (
renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
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 =
192 ? dst_snapshot->opacity
196 blend_info.color_factor = 1;
201 FS::BindTextureSamplerSrc(pass, dst_snapshot->texture, dst_sampler);
203 auto src_sampler_descriptor = src_snapshot->sampler_descriptor;
204 if (
renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
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();
216 auto blend_uniform = host_buffer.EmplaceUniform(blend_info);
217 FS::BindBlendInfo(pass, blend_uniform);
219 frame_info.mvp = pass.GetOrthographicTransform() *
223 auto uniform_view = host_buffer.EmplaceUniform(frame_info);
224 VS::BindFrameInfo(pass, uniform_view);
226 return pass.Draw().ok();
229 std::shared_ptr<CommandBuffer> command_buffer =
230 renderer.GetContext()->CreateCommandBuffer();
231 if (!command_buffer) {
235 "Advanced Blend Filter",
ISize(subpass_coverage.
GetSize()),
237 if (!render_target.
ok()) {
242 ->Submit({std::move(command_buffer)})
249 .
texture = render_target.
value().GetRenderTargetTexture(),
254 .sampler_descriptor = {},
257 : dst_snapshot->opacity) *
258 alpha.value_or(1.0)},
262std::optional<Entity> BlendFilterContents::CreateForegroundAdvancedBlend(
263 const std::shared_ptr<FilterInput>& input,
265 const Entity& entity,
269 std::optional<Scalar> alpha,
272 input->GetSnapshot(
"ForegroundAdvancedBlend",
renderer, entity);
273 if (!dst_snapshot.has_value()) {
278 absorb_opacity](
const ContentContext&
renderer,
279 const Entity& entity,
280 RenderPass& pass) ->
bool {
284 auto& host_buffer =
renderer.GetTransientsBuffer();
286 auto size = dst_snapshot->texture->GetSize();
287 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
288 vtx_builder.AddVertices({
289 {{0, 0}, {0, 0}, {0, 0}},
294 auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);
297 pass.SetCommandLabel(
SPrintF(
"Foreground Advanced Blend Filter (%s)",
300 pass.SetVertexBuffer(std::move(vtx_buffer));
304 switch (blend_mode) {
354 FS::BlendInfo blend_info;
355 VS::FrameInfo frame_info;
357 auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor;
358 if (
renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
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();
368 frame_info.mvp = pass.GetOrthographicTransform() * dst_snapshot->transform;
370 blend_info.dst_input_alpha =
372 ? dst_snapshot->opacity * alpha.value_or(1.0)
375 blend_info.color_factor = 1;
380 FS::BindTextureSamplerSrc(pass, dst_snapshot->texture, dst_sampler);
382 auto blend_uniform = host_buffer.EmplaceUniform(blend_info);
383 FS::BindBlendInfo(pass, blend_uniform);
385 auto uniform_view = host_buffer.EmplaceUniform(frame_info);
386 VS::BindFrameInfo(pass, uniform_view);
388 return pass.Draw().ok();
391 [
coverage](
const Entity& entity) -> std::optional<Rect> {
392 return coverage.TransformBounds(entity.GetTransform());
398 sub_entity.SetContents(std::move(contents));
403std::optional<Entity> BlendFilterContents::CreateForegroundPorterDuffBlend(
404 const std::shared_ptr<FilterInput>& input,
406 const Entity& entity,
410 std::optional<Scalar> alpha,
417 input->GetSnapshot(
"ForegroundPorterDuffBlend",
renderer, entity);
418 if (!dst_snapshot.has_value()) {
427 absorb_opacity, alpha](
429 const Entity& entity, RenderPass& pass) ->
bool {
433 auto& host_buffer =
renderer.GetTransientsBuffer();
434 auto size = dst_snapshot->texture->GetSize();
436 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
437 vtx_builder.AddVertices({
438 {{0, 0}, {0, 0},
color},
443 auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);
446 pass.SetCommandLabel(
SPrintF(
"Foreground PorterDuff Blend Filter (%s)",
449 pass.SetVertexBuffer(std::move(vtx_buffer));
454 FS::FragInfo frag_info;
455 VS::FrameInfo frame_info;
457 frame_info.mvp = pass.GetOrthographicTransform() * dst_snapshot->transform;
459 auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor;
460 if (
renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
464 const std::unique_ptr<const Sampler>& dst_sampler =
465 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
466 dst_sampler_descriptor);
467 FS::BindTextureSamplerDst(pass, dst_snapshot->texture, dst_sampler);
468 frame_info.texture_sampler_y_coord_scale =
469 dst_snapshot->texture->GetYCoordScale();
471 frag_info.input_alpha =
473 ? dst_snapshot->opacity * alpha.value_or(1.0)
475 frag_info.output_alpha = 1.0;
477 auto blend_coefficients =
479 frag_info.src_coeff = blend_coefficients[0];
480 frag_info.src_coeff_dst_alpha = blend_coefficients[1];
481 frag_info.dst_coeff = blend_coefficients[2];
482 frag_info.dst_coeff_src_alpha = blend_coefficients[3];
483 frag_info.dst_coeff_src_color = blend_coefficients[4];
485 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
486 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
488 return pass.Draw().ok();
492 [
coverage](
const Entity& entity) -> std::optional<Rect> {
493 return coverage.TransformBounds(entity.GetTransform());
499 sub_entity.SetContents(std::move(contents));
512 std::optional<Scalar> alpha) {
518 if (!dst_snapshot.has_value()) {
524 auto coverage_hint = entity.
GetContents()->GetCoverageHint();
526 if (coverage_hint.has_value()) {
527 auto maybe_subpass_coverage =
529 if (!maybe_subpass_coverage.has_value()) {
533 subpass_coverage = *maybe_subpass_coverage;
539 auto& host_buffer =
renderer.GetTransientsBuffer();
542 pass.SetCommandLabel(
548 auto add_blend_command = [&](std::optional<Snapshot> input) {
549 if (!input.has_value()) {
552 auto input_coverage = input->GetCoverage();
553 if (!input_coverage.has_value()) {
557 const std::unique_ptr<const Sampler>& sampler =
558 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
559 input->sampler_descriptor);
560 FS::BindTextureSampler(pass, input->texture, sampler);
562 auto size = input->texture->GetSize();
572 VS::FrameInfo frame_info;
573 frame_info.mvp = pass.GetOrthographicTransform() *
576 frame_info.texture_sampler_y_coord_scale =
577 input->texture->GetYCoordScale();
579 FS::FragInfo frag_info;
584 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
585 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
587 return pass.Draw().ok();
593 if (!add_blend_command(dst_snapshot)) {
600 options.blend_mode = blend_mode;
603 for (
auto texture_i =
inputs.begin() + 1; texture_i <
inputs.end();
605 auto src_input = texture_i->get()->GetSnapshot(
"PipelineBlend(Src)",
607 if (!add_blend_command(src_input)) {
616 auto contents = std::make_shared<SolidColorContents>();
617 contents->SetGeometry(
632 std::shared_ptr<CommandBuffer> command_buffer =
633 renderer.GetContext()->CreateCommandBuffer();
634 if (!command_buffer) {
639 "Pipeline Blend Filter",
ISize(subpass_coverage.
GetSize()),
642 if (!render_target.
ok()) {
648 ->Submit({std::move(command_buffer)})
655 .
texture = render_target.
value().GetRenderTargetTexture(),
660 .sampler_descriptor = {},
663 : dst_snapshot->opacity) *
664 alpha.value_or(1.0)},
668std::optional<Entity> BlendFilterContents::CreateFramebufferAdvancedBlend(
671 const Entity& entity,
675 std::optional<Scalar> alpha,
682 inputs[0]->GetSnapshot(
"ForegroundAdvancedBlend",
renderer, entity);
683 if (!dst_snapshot.has_value()) {
687 std::shared_ptr<Texture> foreground_texture;
694 HostBuffer& host_buffer =
renderer.GetTransientsBuffer();
697 using FS = TextureFillFragmentShader;
698 using VS = TextureFillVertexShader;
700 pass.SetCommandLabel(
"Framebuffer Advanced Blend");
703 pass.SetPipeline(
renderer.GetTexturePipeline(pipeline_options));
705 VS::FrameInfo frame_info;
707 frame_info.texture_sampler_y_coord_scale = 1.0;
709 FS::FragInfo frag_info;
710 frag_info.alpha = 1.0;
712 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
713 vtx_builder.AddVertices({
715 {
Point(1, 0), {1, 0}},
716 {
Point(0, 1), {0, 1}},
717 {
Point(1, 1), {1, 1}},
719 auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);
720 pass.SetVertexBuffer(std::move(vtx_buffer));
722 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
723 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
724 FS::BindTextureSampler(
725 pass, dst_snapshot->texture,
726 renderer.GetContext()->GetSamplerLibrary()->GetSampler({}));
728 if (!pass.Draw().ok()) {
739 std::shared_ptr<Texture> src_texture;
741 src_texture = foreground_texture;
744 inputs[0]->GetSnapshot(
"ForegroundAdvancedBlend",
renderer, entity);
745 if (!src_snapshot.has_value()) {
751 src_texture = src_snapshot->texture;
754 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
755 vtx_builder.AddVertices({
766 pass.SetCommandLabel(
"Framebuffer Advanced Blend Filter");
767 pass.SetVertexBuffer(vtx_builder.CreateVertexBuffer(host_buffer));
769 switch (blend_mode) {
830 VS::FrameInfo frame_info;
831 FS::FragInfo frag_info;
833 auto src_sampler_descriptor = SamplerDescriptor{};
834 if (
renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
838 const std::unique_ptr<const Sampler>& src_sampler =
839 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
840 src_sampler_descriptor);
841 FS::BindTextureSamplerSrc(pass, src_texture, src_sampler);
844 frame_info.src_y_coord_scale = src_texture->GetYCoordScale();
845 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
847 frag_info.src_input_alpha = 1.0;
848 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
850 return pass.Draw().ok();
854 std::shared_ptr<CommandBuffer> cmd_buffer =
855 renderer.GetContext()->CreateCommandBuffer();
859 TextureDescriptor
desc;
864 renderer.GetContext()->GetResourceAllocator()->CreateTexture(
desc);
865 if (!foreground_texture) {
868 auto blit_pass = cmd_buffer->CreateBlitPass();
872 blit_pass->AddCopy(std::move(
buffer_view), foreground_texture);
873 if (!blit_pass->EncodeCommands(
874 renderer.GetContext()->GetResourceAllocator())) {
880 renderer.MakeSubpass(
"FramebufferBlend", dst_snapshot->texture->GetSize(),
881 cmd_buffer, subpass_callback);
883 if (!render_target.ok()) {
889 ->Submit({std::move(cmd_buffer)})
896 .texture = render_target.value().GetRenderTargetTexture(),
901 .sampler_descriptor = {},
904 : dst_snapshot->opacity) *
905 alpha.value_or(1.0)},
906 entity.GetBlendMode());
909#define BLEND_CASE(mode) \
910 case BlendMode::k##mode: \
911 advanced_blend_proc_ = \
912 [](const FilterInput::Vector& inputs, const ContentContext& renderer, \
913 const Entity& entity, const Rect& coverage, BlendMode blend_mode, \
914 std::optional<Color> fg_color, \
915 ColorFilterContents::AbsorbOpacity absorb_opacity, \
916 std::optional<Scalar> alpha) { \
917 PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \
918 return AdvancedBlend<Blend##mode##Pipeline>( \
919 inputs, renderer, entity, coverage, blend_mode, fg_color, \
920 absorb_opacity, p, alpha); \
926 VALIDATION_LOG <<
"Invalid blend mode " <<
static_cast<int>(blend_mode)
927 <<
" assigned to BlendFilterContents.";
930 blend_mode_ = blend_mode;
933 switch (blend_mode) {
956 foreground_color_ =
color;
959std::optional<Entity> BlendFilterContents::RenderFilter(
963 const Matrix& effect_transform,
965 const std::optional<Rect>& coverage_hint)
const {
970 if (
inputs.size() == 1 && !foreground_color_.has_value()) {
977 if (
inputs.size() == 1 && foreground_color_.has_value() &&
979 return CreateForegroundPorterDuffBlend(
988 if (
renderer.GetDeviceCapabilities().SupportsFramebufferFetch()) {
990 foreground_color_, blend_mode_,
993 if (
inputs.size() == 1 && foreground_color_.has_value() &&
995 return CreateForegroundAdvancedBlend(
static std::shared_ptr< Contents > Make(RenderProc render_proc, CoverageProc coverage_proc)
~BlendFilterContents() override
void SetBlendMode(BlendMode blend_mode)
void SetForegroundColor(std::optional< Color > color)
Sets a source color which is blended after all of the inputs have been blended.
std::optional< Scalar > GetAlpha() const
AbsorbOpacity GetAbsorbOpacity() const
std::function< bool(const ContentContext &, RenderPass &)> SubpassCallback
std::function< std::optional< Rect >(const Entity &entity)> CoverageProc
std::function< bool(const ContentContext &renderer, const Entity &entity, RenderPass &pass)> RenderProc
static Entity FromSnapshot(const Snapshot &snapshot, BlendMode blend_mode=BlendMode::kSourceOver)
Create an entity that can be used to render a given snapshot.
const std::shared_ptr< Contents > & GetContents() const
BlendMode GetBlendMode() const
void SetContents(std::shared_ptr< Contents > contents)
void SetBlendMode(BlendMode blend_mode)
static constexpr BlendMode kLastAdvancedBlendMode
bool Render(const ContentContext &renderer, RenderPass &parent_pass) const
static constexpr BlendMode kLastPipelineBlendMode
static std::shared_ptr< Geometry > MakeRect(const Rect &rect)
Render passes encode render commands directed as one specific render target into an underlying comman...
VertexShader_ VertexShader
FragmentShader_ FragmentShader
VertexBuffer CreateVertexBuffer(HostBuffer &host_buffer) const
VertexBufferBuilder & AddVertices(std::initializer_list< VertexType_ > vertices)
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
#define FML_UNREACHABLE()
#define FML_DCHECK(condition)
SK_API sk_sp< SkShader > Color(SkColor)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static constexpr Scalar Saturation(Vector3 color)
const char * BlendModeToString(BlendMode blend_mode)
@ kDecal
decal sampling mode is only supported on devices that pass the Capabilities.SupportsDecalSamplerAddre...
std::string SPrintF(const char *format,...)
constexpr std::array< std::array< Scalar, 5 >, 15 > kPorterDuffCoefficients
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)
std::optional< BlendMode > InvertPorterDuffBlend(BlendMode blend_mode)
std::shared_ptr< Pipeline< PipelineDescriptor > >(ContentContext::*)(ContentContextOptions) const PipelineProc
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)
ContentContextOptions OptionsFromPass(const RenderPass &pass)
static constexpr Scalar Luminosity(Vector3 color)
const uint32_t foreground_color[]
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeOrthographic(TSize< T > size)
static constexpr Matrix MakeTranslation(const Vector3 &t)
Represents a texture and its intended draw transform/sampler configuration.
std::shared_ptr< Texture > texture
constexpr std::optional< TRect > Intersection(const TRect &o) const
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...
static constexpr TRect MakeSize(const TSize< U > &size)
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...