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/contents.h"
6#include <optional>
7
8#include "fml/logging.h"
9#include "impeller/base/strings.h"
10#include "impeller/base/validation.h"
11#include "impeller/core/formats.h"
12#include "impeller/entity/contents/anonymous_contents.h"
13#include "impeller/entity/contents/content_context.h"
14#include "impeller/entity/contents/texture_contents.h"
15#include "impeller/renderer/command_buffer.h"
16#include "impeller/renderer/render_pass.h"
17
18namespace impeller {
19
20ContentContextOptions OptionsFromPass(const RenderPass& pass) {
21 ContentContextOptions opts;
22 opts.sample_count = pass.GetRenderTarget().GetSampleCount();
23 opts.color_attachment_pixel_format =
24 pass.GetRenderTarget().GetRenderTargetPixelFormat();
25 opts.has_stencil_attachment =
26 pass.GetRenderTarget().GetStencilAttachment().has_value();
27 return opts;
28}
29
30ContentContextOptions OptionsFromPassAndEntity(const RenderPass& pass,
31 const Entity& entity) {
32 ContentContextOptions opts = OptionsFromPass(pass);
33 opts.blend_mode = entity.GetBlendMode();
34 return opts;
35}
36
37std::shared_ptr<Contents> Contents::MakeAnonymous(
38 Contents::RenderProc render_proc,
39 Contents::CoverageProc coverage_proc) {
40 return AnonymousContents::Make(render_proc: std::move(render_proc),
41 coverage_proc: std::move(coverage_proc));
42}
43
44Contents::Contents() = default;
45
46Contents::~Contents() = default;
47
48bool Contents::IsOpaque() const {
49 return false;
50}
51
52Contents::StencilCoverage Contents::GetStencilCoverage(
53 const Entity& entity,
54 const std::optional<Rect>& current_stencil_coverage) const {
55 return {.type = StencilCoverage::Type::kNoChange,
56 .coverage = current_stencil_coverage};
57}
58
59std::optional<Snapshot> Contents::RenderToSnapshot(
60 const ContentContext& renderer,
61 const Entity& entity,
62 std::optional<Rect> coverage_limit,
63 const std::optional<SamplerDescriptor>& sampler_descriptor,
64 bool msaa_enabled,
65 const std::string& label) const {
66 auto coverage = GetCoverage(entity);
67 if (!coverage.has_value()) {
68 return std::nullopt;
69 }
70
71 // Pad Contents snapshots with 1 pixel borders to ensure correct sampling
72 // behavior. Not doing so results in a coverage leak for filters that support
73 // customizing the input sampling mode. Snapshots of contents should be
74 // theoretically treated as infinite size just like layers.
75 coverage = coverage->Expand(amount: 1);
76
77 if (coverage_limit.has_value()) {
78 coverage = coverage->Intersection(o: *coverage_limit);
79 if (!coverage.has_value()) {
80 return std::nullopt;
81 }
82 }
83
84 auto texture = renderer.MakeSubpass(
85 label, texture_size: ISize::Ceil(other: coverage->size),
86 subpass_callback: [&contents = *this, &entity, &coverage](const ContentContext& renderer,
87 RenderPass& pass) -> bool {
88 Entity sub_entity;
89 sub_entity.SetBlendMode(BlendMode::kSourceOver);
90 sub_entity.SetTransformation(
91 Matrix::MakeTranslation(t: Vector3(-coverage->origin)) *
92 entity.GetTransformation());
93 return contents.Render(renderer, entity: sub_entity, pass);
94 },
95 msaa_enabled);
96
97 if (!texture) {
98 return std::nullopt;
99 }
100
101 auto snapshot = Snapshot{
102 .texture = texture,
103 .transform = Matrix::MakeTranslation(t: coverage->origin),
104 };
105 if (sampler_descriptor.has_value()) {
106 snapshot.sampler_descriptor = sampler_descriptor.value();
107 }
108
109 return snapshot;
110}
111
112bool Contents::CanInheritOpacity(const Entity& entity) const {
113 return false;
114}
115
116void Contents::SetInheritedOpacity(Scalar opacity) {
117 VALIDATION_LOG << "Contents::SetInheritedOpacity should never be called when "
118 "Contents::CanAcceptOpacity returns false.";
119}
120
121std::optional<Color> Contents::AsBackgroundColor(const Entity& entity,
122 ISize target_size) const {
123 return {};
124}
125
126bool Contents::ApplyColorFilter(
127 const Contents::ColorFilterProc& color_filter_proc) {
128 return false;
129}
130
131bool Contents::ShouldRender(const Entity& entity,
132 const std::optional<Rect>& stencil_coverage) const {
133 if (!stencil_coverage.has_value()) {
134 return false;
135 }
136
137 auto coverage = GetCoverage(entity);
138 if (!coverage.has_value()) {
139 return false;
140 }
141 if (coverage == Rect::MakeMaximum()) {
142 return true;
143 }
144 return stencil_coverage->IntersectsWithRect(o: coverage.value());
145}
146
147void Contents::SetCoverageHint(std::optional<Rect> coverage_hint) {
148 coverage_hint_ = coverage_hint;
149}
150
151const std::optional<Rect>& Contents::GetCoverageHint() const {
152 return coverage_hint_;
153}
154
155std::optional<Size> Contents::GetColorSourceSize() const {
156 return color_source_size_;
157};
158
159void Contents::SetColorSourceSize(Size size) {
160 color_source_size_ = size;
161}
162
163} // namespace impeller
164

source code of flutter_engine/flutter/impeller/entity/contents/contents.cc