| 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(std::unique_ptr<Geometry> geometry) {
26 geometry_ = std::move(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::StencilCoverage ClipContents::GetStencilCoverage(
38 const Entity& entity,
39 const std::optional<Rect>& current_stencil_coverage) const {
40 if (!current_stencil_coverage.has_value()) {
41 return {.type = StencilCoverage::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 = StencilCoverage::Type::kAppend,
48 .coverage = current_stencil_coverage};
49 case Entity::ClipOperation::kIntersect:
50 if (!geometry_) {
51 return {.type = StencilCoverage::Type::kAppend,
52 .coverage = std::nullopt};
53 }
54 auto coverage = geometry_->GetCoverage(entity.GetTransformation());
55 if (!coverage.has_value() || !current_stencil_coverage.has_value()) {
56 return {.type = StencilCoverage::Type::kAppend,
57 .coverage = std::nullopt};
58 }
59 return {
60 .type = StencilCoverage::Type::kAppend,
61 .coverage = current_stencil_coverage->Intersection(coverage.value()),
62 };
63 }
64 FML_UNREACHABLE();
65 }
66
67 bool ClipContents::ShouldRender(
68 const Entity& entity,
69 const std::optional<Rect>& stencil_coverage) const {
70 return true;
71 }
72
73 bool ClipContents::CanInheritOpacity(const Entity& entity) const {
74 return true;
75 }
76
77 void ClipContents::SetInheritedOpacity(Scalar opacity) {}
78
79 bool ClipContents::Render(const ContentContext& renderer,
80 const Entity& entity,
81 RenderPass& pass) const {
82 using VS = ClipPipeline::VertexShader;
83
84 VS::FrameInfo info;
85
86 Command cmd;
87
88 auto options = OptionsFromPass(pass);
89 options.blend_mode = BlendMode::kDestination;
90 cmd.stencil_reference = entity.GetStencilDepth();
91 options.stencil_compare = CompareFunction::kEqual;
92 options.stencil_operation = StencilOperation::kIncrementClamp;
93
94 if (clip_op_ == Entity::ClipOperation::kDifference) {
95 {
96 DEBUG_COMMAND_INFO(cmd, "Difference Clip (Increment)");
97
98 auto points = Rect(Size(pass.GetRenderTargetSize())).GetPoints();
99 auto vertices =
100 VertexBufferBuilder<VS::PerVertexData>{}
101 .AddVertices({{points[0]}, {points[1]}, {points[2]}, {points[3]}})
102 .CreateVertexBuffer(pass.GetTransientsBuffer());
103 cmd.BindVertices(vertices);
104
105 info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize());
106 VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(info));
107
108 options.primitive_type = PrimitiveType::kTriangleStrip;
109 cmd.pipeline = renderer.GetClipPipeline(options);
110 pass.AddCommand(Command(cmd));
111 }
112
113 {
114 DEBUG_COMMAND_INFO(cmd, "Difference Clip (Punch)");
115
116 cmd.stencil_reference = entity.GetStencilDepth() + 1;
117 options.stencil_compare = CompareFunction::kEqual;
118 options.stencil_operation = StencilOperation::kDecrementClamp;
119 }
120 } else {
121 DEBUG_COMMAND_INFO(cmd, "Intersect Clip");
122 options.stencil_compare = CompareFunction::kEqual;
123 options.stencil_operation = StencilOperation::kIncrementClamp;
124 }
125
126 auto geometry_result = geometry_->GetPositionBuffer(renderer, entity, pass);
127 options.primitive_type = geometry_result.type;
128 cmd.pipeline = renderer.GetClipPipeline(options);
129
130 auto allocator = renderer.GetContext()->GetResourceAllocator();
131 cmd.BindVertices(geometry_result.vertex_buffer);
132
133 info.mvp = geometry_result.transform;
134 VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(info));
135
136 pass.AddCommand(std::move(cmd));
137 return true;
138 }
139
140 /*******************************************************************************
141 ******* ClipRestoreContents
142 ******************************************************************************/
143
144 ClipRestoreContents::ClipRestoreContents() = default;
145
146 ClipRestoreContents::~ClipRestoreContents() = default;
147
148 void ClipRestoreContents::SetRestoreCoverage(
149 std::optional<Rect> restore_coverage) {
150 restore_coverage_ = restore_coverage;
151 }
152
153 std::optional<Rect> ClipRestoreContents::GetCoverage(
154 const Entity& entity) const {
155 return std::nullopt;
156 };
157
158 Contents::StencilCoverage ClipRestoreContents::GetStencilCoverage(
159 const Entity& entity,
160 const std::optional<Rect>& current_stencil_coverage) const {
161 return {.type = StencilCoverage::Type::kRestore, .coverage = std::nullopt};
162 }
163
164 bool ClipRestoreContents::ShouldRender(
165 const Entity& entity,
166 const std::optional<Rect>& stencil_coverage) const {
167 return true;
168 }
169
170 bool ClipRestoreContents::CanInheritOpacity(const Entity& entity) const {
171 return true;
172 }
173
174 void ClipRestoreContents::SetInheritedOpacity(Scalar opacity) {}
175
176 bool ClipRestoreContents::Render(const ContentContext& renderer,
177 const Entity& entity,
178 RenderPass& pass) const {
179 using VS = ClipPipeline::VertexShader;
180
181 Command cmd;
182 DEBUG_COMMAND_INFO(cmd, "Restore Clip");
183 auto options = OptionsFromPass(pass);
184 options.blend_mode = BlendMode::kDestination;
185 options.stencil_compare = CompareFunction::kLess;
186 options.stencil_operation = StencilOperation::kSetToReferenceValue;
187 options.primitive_type = PrimitiveType::kTriangleStrip;
188 cmd.pipeline = renderer.GetClipPipeline(options);
189 cmd.stencil_reference = entity.GetStencilDepth();
190
191 // Create a rect that covers either the given restore area, or the whole
192 // render target texture.
193 auto ltrb = restore_coverage_.value_or(Rect(Size(pass.GetRenderTargetSize())))
194 .GetLTRB();
195 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
196 vtx_builder.AddVertices({
197 {Point(ltrb[0], ltrb[1])},
198 {Point(ltrb[2], ltrb[1])},
199 {Point(ltrb[0], ltrb[3])},
200 {Point(ltrb[2], ltrb[3])},
201 });
202 cmd.BindVertices(vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
203
204 VS::FrameInfo info;
205 info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize());
206 VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(info));
207
208 pass.AddCommand(std::move(cmd));
209 return true;
210 }
211
212 }; // namespace impeller
impeller::ClipRestoreContents::ShouldRender
bool ShouldRender(const Entity &entity, const std::optional< Rect > &stencil_coverage) const override
Definition: clip_contents.cc:164
impeller::Entity::ClipOperation::kIntersect
@ kIntersect
impeller::ClipRestoreContents::GetStencilCoverage
StencilCoverage GetStencilCoverage(const Entity &entity, const std::optional< Rect > &current_stencil_coverage) const override
Given the current screen space bounding rectangle of the stencil, return the expected stencil coverag...
Definition: clip_contents.cc:158
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:99
DEBUG_COMMAND_INFO
#define DEBUG_COMMAND_INFO(obj, arg)
Definition: command.h:31
impeller::Entity::GetStencilDepth
uint32_t GetStencilDepth() const
Definition: entity.cc:89
impeller::ClipRestoreContents::ClipRestoreContents
ClipRestoreContents()
impeller::Entity::ClipOperation::kDifference
@ kDifference
impeller::Scalar
float Scalar
Definition: scalar.h:15
impeller::ClipRestoreContents::GetCoverage
std::optional< Rect > GetCoverage(const Entity &entity) const override
Get the screen space bounding rectangle that this contents affects.
Definition: clip_contents.cc:153
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:170
formats.h
impeller::ContentContext::GetClipPipeline
std::shared_ptr< Pipeline< PipelineDescriptor > > GetClipPipeline(ContentContextOptions opts) const
Definition: content_context.h:486
impeller::ClipContents::SetGeometry
void SetGeometry(std::unique_ptr< Geometry > geometry)
Definition: clip_contents.cc:25
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:148
impeller::VertexBufferBuilder::AddVertices
VertexBufferBuilder & AddVertices(std::initializer_list< VertexType_ > vertices)
Definition: vertex_buffer_builder.h:64
impeller::Size
TSize< Scalar > Size
Definition: size.h:135
impeller::ClipRestoreContents::~ClipRestoreContents
~ClipRestoreContents()
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
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:187
impeller::Entity::GetTransformation
const Matrix & GetTransformation() const
Definition: entity.cc:49
impeller::Entity
Definition: entity.h:21
impeller::RenderPass::GetRenderTargetSize
ISize GetRenderTargetSize() const
Definition: render_pass.cc:30
impeller::ClipContents::ClipContents
ClipContents()
impeller::Point
TPoint< Scalar > Point
Definition: point.h:306
render_pass.h
impeller::Contents::StencilCoverage
Definition: contents.h:39
impeller::ClipRestoreContents::Render
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Definition: clip_contents.cc:176
impeller::StencilOperation::kSetToReferenceValue
@ kSetToReferenceValue
Reset the stencil value to the reference value.
impeller::BlendMode::kDestination
@ kDestination
impeller::ClipContents::~ClipContents
~ClipContents()
impeller::ClipContents::GetCoverage
std::optional< Rect > GetCoverage(const Entity &entity) const override
Get the screen space bounding rectangle that this contents affects.
Definition: clip_contents.cc:33
impeller::ContentContext::GetContext
std::shared_ptr< Context > GetContext() const
Definition: content_context.cc:440
impeller::VertexBufferBuilder
Definition: vertex_buffer_builder.h:23
impeller::ClipRestoreContents::SetInheritedOpacity
void SetInheritedOpacity(Scalar opacity) override
Inherit the provided opacity.
Definition: clip_contents.cc:174
clip_contents.h
impeller::ClipContents::GetStencilCoverage
StencilCoverage GetStencilCoverage(const Entity &entity, const std::optional< Rect > &current_stencil_coverage) const override
Given the current screen space bounding rectangle of the stencil, return the expected stencil coverag...
Definition: clip_contents.cc:37
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:306
impeller::StencilOperation::kIncrementClamp
@ kIncrementClamp
Increment the current stencil value by 1. Clamp it to the maximum.
impeller::ClipContents::Render
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Definition: clip_contents.cc:79
impeller::VertexBufferBuilder::CreateVertexBuffer
VertexBuffer CreateVertexBuffer(HostBuffer &host_buffer) const
Definition: vertex_buffer_builder.h:78
impeller::CompareFunction::kLess
@ kLess
Comparison test passes if new_value < current_value.
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:27
impeller::Command::stencil_reference
uint32_t stencil_reference
Definition: command.h:152
content_context.h
impeller::StencilOperation::kDecrementClamp
@ kDecrementClamp
Decrement the current stencil value by 1. Clamp it to zero.
impeller::ClipContents::ShouldRender
bool ShouldRender(const Entity &entity, const std::optional< Rect > &stencil_coverage) const override
Definition: clip_contents.cc:67
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:43
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:73
impeller::Contents::StencilCoverage::type
Type type
Definition: contents.h:42
impeller::Matrix::MakeOrthographic
static constexpr Matrix MakeOrthographic(TSize< T > size)
Definition: matrix.h:448
impeller::Entity::ClipOperation
ClipOperation
Definition: entity.h:59
impeller::ClipContents::SetInheritedOpacity
void SetInheritedOpacity(Scalar opacity) override
Inherit the provided opacity.
Definition: clip_contents.cc:77
impeller::CompareFunction::kEqual
@ kEqual
Comparison test passes if new_value == current_value.
impeller::Command::BindVertices
bool BindVertices(const VertexBuffer &buffer)
Specify the vertex and index buffer to use for this command.
Definition: command.cc:15
impeller::Command::pipeline
std::shared_ptr< Pipeline< PipelineDescriptor > > pipeline
Definition: command.h:103
impeller::RenderPipelineT::VertexShader
VertexShader_ VertexShader
Definition: pipeline.h:90
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:46
impeller
Definition: aiks_context.cc:10
impeller::ContentContext
Definition: content_context.h:344
impeller::RenderPass::GetTransientsBuffer
HostBuffer & GetTransientsBuffer()
Definition: render_pass.cc:34
vertex_buffer_builder.h