| Flutter Impeller |

clip_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 <optional>
6
7 #include "fml/logging.h"
8 #include "impeller/core/formats.h"
9 #include "impeller/entity/contents/clip_contents.h"
10 #include "impeller/entity/contents/content_context.h"
11 #include "impeller/entity/entity.h"
12 #include "impeller/renderer/render_pass.h"
13 #include "impeller/renderer/vertex_buffer_builder.h"
14
15 namespace impeller {
16
17 /*******************************************************************************
18 ******* ClipContents
19 ******************************************************************************/
20
21 ClipContents::ClipContents() = default;
22
23 ClipContents::~ClipContents() = default;
24
25 void ClipContents::SetGeometry(const std::shared_ptr<Geometry>& geometry) {
26 geometry_ = geometry;
27 }
28
29 void ClipContents::SetClipOperation(Entity::ClipOperation clip_op) {
30 clip_op_ = clip_op;
31 }
32
33 std::optional<Rect> ClipContents::GetCoverage(const Entity& entity) const {
34 return std::nullopt;
35 };
36
37 Contents::ClipCoverage ClipContents::GetClipCoverage(
38 const Entity& entity,
39 const std::optional<Rect>& current_clip_coverage) const {
40 if (!current_clip_coverage.has_value()) {
41 return {.type = ClipCoverage::Type::kAppend, .coverage = std::nullopt};
42 }
43 switch (clip_op_) {
44 case Entity::ClipOperation::kDifference:
45 // This can be optimized further by considering cases when the bounds of
46 // the current stencil will shrink.
47 return {.type = ClipCoverage::Type::kAppend,
48 .coverage = current_clip_coverage};
49 case Entity::ClipOperation::kIntersect:
50 if (!geometry_) {
51 return {.type = ClipCoverage::Type::kAppend, .coverage = std::nullopt};
52 }
53 auto coverage = geometry_->GetCoverage(entity.GetTransform());
54 if (!coverage.has_value() || !current_clip_coverage.has_value()) {
55 return {.type = ClipCoverage::Type::kAppend, .coverage = std::nullopt};
56 }
57 return {
58 .type = ClipCoverage::Type::kAppend,
59 .coverage = current_clip_coverage->Intersection(coverage.value()),
60 };
61 }
62 FML_UNREACHABLE();
63 }
64
65 bool ClipContents::ShouldRender(const Entity& entity,
66 const std::optional<Rect> clip_coverage) const {
67 return true;
68 }
69
70 bool ClipContents::CanInheritOpacity(const Entity& entity) const {
71 return true;
72 }
73
74 void ClipContents::SetInheritedOpacity(Scalar opacity) {}
75
76 bool ClipContents::Render(const ContentContext& renderer,
77 const Entity& entity,
78 RenderPass& pass) const {
79 using VS = ClipPipeline::VertexShader;
80
81 VS::FrameInfo info;
82
83 Command cmd;
84
85 auto options = OptionsFromPass(pass);
86 options.blend_mode = BlendMode::kDestination;
87 cmd.stencil_reference = entity.GetClipDepth();
88 options.stencil_compare = CompareFunction::kEqual;
89 options.stencil_operation = StencilOperation::kIncrementClamp;
90
91 if (clip_op_ == Entity::ClipOperation::kDifference) {
92 {
93 DEBUG_COMMAND_INFO(cmd, "Difference Clip (Increment)");
94
95 auto points = Rect::MakeSize(pass.GetRenderTargetSize()).GetPoints();
96 auto vertices =
97 VertexBufferBuilder<VS::PerVertexData>{}
98 .AddVertices({{points[0]}, {points[1]}, {points[2]}, {points[3]}})
99 .CreateVertexBuffer(pass.GetTransientsBuffer());
100 cmd.BindVertices(std::move(vertices));
101
102 info.mvp = pass.GetOrthographicTransform();
103 VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(info));
104
105 options.primitive_type = PrimitiveType::kTriangleStrip;
106 cmd.pipeline = renderer.GetClipPipeline(options);
107 pass.AddCommand(Command(cmd));
108 }
109
110 {
111 DEBUG_COMMAND_INFO(cmd, "Difference Clip (Punch)");
112
113 cmd.stencil_reference = entity.GetClipDepth() + 1;
114 options.stencil_compare = CompareFunction::kEqual;
115 options.stencil_operation = StencilOperation::kDecrementClamp;
116 }
117 } else {
118 DEBUG_COMMAND_INFO(cmd, "Intersect Clip");
119 options.stencil_compare = CompareFunction::kEqual;
120 options.stencil_operation = StencilOperation::kIncrementClamp;
121 }
122
123 auto geometry_result = geometry_->GetPositionBuffer(renderer, entity, pass);
124 options.primitive_type = geometry_result.type;
125 cmd.pipeline = renderer.GetClipPipeline(options);
126
127 auto allocator = renderer.GetContext()->GetResourceAllocator();
128 cmd.BindVertices(std::move(geometry_result.vertex_buffer));
129
130 info.mvp = geometry_result.transform;
131 VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(info));
132
133 pass.AddCommand(std::move(cmd));
134 return true;
135 }
136
137 /*******************************************************************************
138 ******* ClipRestoreContents
139 ******************************************************************************/
140
141 ClipRestoreContents::ClipRestoreContents() = default;
142
143 ClipRestoreContents::~ClipRestoreContents() = default;
144
145 void ClipRestoreContents::SetRestoreCoverage(
146 std::optional<Rect> restore_coverage) {
147 restore_coverage_ = restore_coverage;
148 }
149
150 std::optional<Rect> ClipRestoreContents::GetCoverage(
151 const Entity& entity) const {
152 return std::nullopt;
153 };
154
155 Contents::ClipCoverage ClipRestoreContents::GetClipCoverage(
156 const Entity& entity,
157 const std::optional<Rect>& current_clip_coverage) const {
158 return {.type = ClipCoverage::Type::kRestore, .coverage = std::nullopt};
159 }
160
161 bool ClipRestoreContents::ShouldRender(
162 const Entity& entity,
163 const std::optional<Rect> clip_coverage) const {
164 return true;
165 }
166
167 bool ClipRestoreContents::CanInheritOpacity(const Entity& entity) const {
168 return true;
169 }
170
171 void ClipRestoreContents::SetInheritedOpacity(Scalar opacity) {}
172
173 bool ClipRestoreContents::Render(const ContentContext& renderer,
174 const Entity& entity,
175 RenderPass& pass) const {
176 using VS = ClipPipeline::VertexShader;
177
178 Command cmd;
179 DEBUG_COMMAND_INFO(cmd, "Restore Clip");
180 auto options = OptionsFromPass(pass);
181 options.blend_mode = BlendMode::kDestination;
182 options.stencil_compare = CompareFunction::kLess;
183 options.stencil_operation = StencilOperation::kSetToReferenceValue;
184 options.primitive_type = PrimitiveType::kTriangleStrip;
185 cmd.pipeline = renderer.GetClipPipeline(options);
186 cmd.stencil_reference = entity.GetClipDepth();
187
188 // Create a rect that covers either the given restore area, or the whole
189 // render target texture.
190 auto ltrb =
191 restore_coverage_.value_or(Rect::MakeSize(pass.GetRenderTargetSize()))
192 .GetLTRB();
193 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
194 vtx_builder.AddVertices({
195 {Point(ltrb[0], ltrb[1])},
196 {Point(ltrb[2], ltrb[1])},
197 {Point(ltrb[0], ltrb[3])},
198 {Point(ltrb[2], ltrb[3])},
199 });
200 cmd.BindVertices(vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
201
202 VS::FrameInfo info;
203 info.mvp = pass.GetOrthographicTransform();
204 VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(info));
205
206 pass.AddCommand(std::move(cmd));
207 return true;
208 }
209
210 }; // namespace impeller
impeller::Entity::ClipOperation::kIntersect
@ kIntersect
impeller::OptionsFromPass
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition: contents.cc:20
impeller::Command
An object used to specify work to the GPU along with references to resources the GPU will used when d...
Definition: command.h:92
DEBUG_COMMAND_INFO
#define DEBUG_COMMAND_INFO(obj, arg)
Definition: command.h:28
impeller::StencilOperation::kDecrementClamp
@ kDecrementClamp
Decrement the current stencil value by 1. Clamp it to zero.
impeller::ClipRestoreContents::ClipRestoreContents
ClipRestoreContents()
impeller::Entity::ClipOperation::kDifference
@ kDifference
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::Entity::GetTransform
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition: entity.cc:49
impeller::ClipRestoreContents::GetCoverage
std::optional< Rect > GetCoverage(const Entity &entity) const override
Get the area of the render pass that will be affected when this contents is rendered.
Definition: clip_contents.cc:150
entity.h
impeller::ClipRestoreContents::CanInheritOpacity
bool CanInheritOpacity(const Entity &entity) const override
Whether or not this contents can accept the opacity peephole optimization.
Definition: clip_contents.cc:167
impeller::CompareFunction::kEqual
@ kEqual
Comparison test passes if new_value == current_value.
impeller::BlendMode::kDestination
@ kDestination
formats.h
impeller::StencilOperation::kIncrementClamp
@ kIncrementClamp
Increment the current stencil value by 1. Clamp it to the maximum.
impeller::ContentContext::GetClipPipeline
std::shared_ptr< Pipeline< PipelineDescriptor > > GetClipPipeline(ContentContextOptions opts) const
Definition: content_context.h:491
impeller::ClipContents::SetClipOperation
void SetClipOperation(Entity::ClipOperation clip_op)
Definition: clip_contents.cc:29
impeller::ClipRestoreContents::SetRestoreCoverage
void SetRestoreCoverage(std::optional< Rect > coverage)
The area on the pass texture where this clip restore will be applied. If unset, the entire pass textu...
Definition: clip_contents.cc:145
impeller::VertexBufferBuilder::AddVertices
VertexBufferBuilder & AddVertices(std::initializer_list< VertexType_ > vertices)
Definition: vertex_buffer_builder.h:70
impeller::ClipRestoreContents::~ClipRestoreContents
~ClipRestoreContents()
impeller::RenderPass::GetOrthographicTransform
const Matrix & GetOrthographicTransform() const
Definition: render_pass.cc:51
impeller::StencilOperation::kSetToReferenceValue
@ kSetToReferenceValue
Reset the stencil value to the reference value.
impeller::ClipContents::ShouldRender
bool ShouldRender(const Entity &entity, const std::optional< Rect > clip_coverage) const override
Definition: clip_contents.cc:65
impeller::TRect::GetPoints
constexpr std::array< TPoint< T >, 4 > GetPoints() const
Get the points that represent the 4 corners of this rectangle. The order is: Top left,...
Definition: rect.h:247
impeller::ClipContents::GetClipCoverage
ClipCoverage GetClipCoverage(const Entity &entity, const std::optional< Rect > &current_clip_coverage) const override
Given the current pass space bounding rectangle of the clip buffer, return the expected clip coverage...
Definition: clip_contents.cc:37
impeller::Entity
Definition: entity.h:21
impeller::RenderPass::GetRenderTargetSize
ISize GetRenderTargetSize() const
Definition: render_pass.cc:47
impeller::ClipContents::SetGeometry
void SetGeometry(const std::shared_ptr< Geometry > &geometry)
Definition: clip_contents.cc:25
impeller::ClipContents::ClipContents
ClipContents()
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
impeller::Point
TPoint< Scalar > Point
Definition: point.h:308
render_pass.h
impeller::ClipRestoreContents::Render
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Definition: clip_contents.cc:173
impeller::ClipContents::~ClipContents
~ClipContents()
impeller::ClipContents::GetCoverage
std::optional< Rect > GetCoverage(const Entity &entity) const override
Get the area of the render pass that will be affected when this contents is rendered.
Definition: clip_contents.cc:33
impeller::ContentContext::GetContext
std::shared_ptr< Context > GetContext() const
Definition: content_context.cc:479
impeller::VertexBufferBuilder
Definition: vertex_buffer_builder.h:24
impeller::Contents::ClipCoverage::type
Type type
Definition: contents.h:43
impeller::Command::BindVertices
bool BindVertices(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
Definition: command.cc:15
impeller::ClipRestoreContents::SetInheritedOpacity
void SetInheritedOpacity(Scalar opacity) override
Inherit the provided opacity.
Definition: clip_contents.cc:171
clip_contents.h
impeller::ClipContents::Render
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Definition: clip_contents.cc:76
impeller::VertexBufferBuilder::CreateVertexBuffer
VertexBuffer CreateVertexBuffer(HostBuffer &host_buffer) const
Definition: vertex_buffer_builder.h:84
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:29
impeller::Entity::GetClipDepth
uint32_t GetClipDepth() const
Definition: entity.cc:93
impeller::Command::stencil_reference
uint32_t stencil_reference
Definition: command.h:122
content_context.h
impeller::ClipRestoreContents::ShouldRender
bool ShouldRender(const Entity &entity, const std::optional< Rect > clip_coverage) const override
Definition: clip_contents.cc:161
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:44
impeller::ClipRestoreContents::GetClipCoverage
ClipCoverage GetClipCoverage(const Entity &entity, const std::optional< Rect > &current_clip_coverage) const override
Given the current pass space bounding rectangle of the clip buffer, return the expected clip coverage...
Definition: clip_contents.cc:155
impeller::Contents::ClipCoverage
Definition: contents.h:40
impeller::HostBuffer::EmplaceUniform
BufferView EmplaceUniform(const UniformType &uniform)
Emplace uniform data onto the host buffer. Ensure that backend specific uniform alignment requirement...
Definition: host_buffer.h:41
impeller::ClipContents::CanInheritOpacity
bool CanInheritOpacity(const Entity &entity) const override
Whether or not this contents can accept the opacity peephole optimization.
Definition: clip_contents.cc:70
impeller::Entity::ClipOperation
ClipOperation
Definition: entity.h:59
impeller::ClipContents::SetInheritedOpacity
void SetInheritedOpacity(Scalar opacity) override
Inherit the provided opacity.
Definition: clip_contents.cc:74
impeller::Command::pipeline
std::shared_ptr< Pipeline< PipelineDescriptor > > pipeline
Definition: command.h:96
impeller::RenderPipelineT::VertexShader
VertexShader_ VertexShader
Definition: pipeline.h:92
impeller::RenderPass::AddCommand
bool AddCommand(Command &&command)
Record a command for subsequent encoding to the underlying command buffer. No work is encoded into th...
Definition: render_pass.cc:67
impeller::CompareFunction::kLess
@ kLess
Comparison test passes if new_value < current_value.
impeller
Definition: aiks_context.cc:10
impeller::kRestore
@ kRestore
Definition: canvas_recorder.h:23
impeller::ContentContext
Definition: content_context.h:332
impeller::RenderPass::GetTransientsBuffer
HostBuffer & GetTransientsBuffer()
Definition: render_pass.cc:55
vertex_buffer_builder.h