| 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 <cmath>
6 #include <optional>
7
8 #include "fml/logging.h"
9 #include "impeller/core/formats.h"
10 #include "impeller/core/vertex_buffer.h"
11 #include "impeller/entity/contents/clip_contents.h"
12 #include "impeller/entity/contents/content_context.h"
13 #include "impeller/entity/contents/pipelines.h"
14 #include "impeller/entity/entity.h"
15 #include "impeller/renderer/render_pass.h"
16 #include "impeller/renderer/vertex_buffer_builder.h"
17
18 namespace impeller {
19
20 static Scalar GetShaderClipDepth(uint32_t clip_depth) {
21 // Draw the clip at the max of the clip entity's depth slice, so that other
22 // draw calls with this same depth value will be culled even if they have a
23 // perspective transform.
24 return std::nextafterf(Entity::GetShaderClipDepth(clip_depth + 1), 0.0f);
25 }
26
27 /*******************************************************************************
28 ******* ClipContents
29 ******************************************************************************/
30
31 ClipContents::ClipContents(Rect coverage_rect, bool is_axis_aligned_rect)
32 : coverage_rect_(coverage_rect),
33 is_axis_aligned_rect_(is_axis_aligned_rect) {}
34
35 ClipContents::~ClipContents() = default;
36
37 void ClipContents::SetGeometry(GeometryResult clip_geometry) {
38 clip_geometry_ = std::move(clip_geometry);
39 }
40
41 void ClipContents::SetClipOperation(Entity::ClipOperation clip_op) {
42 clip_op_ = clip_op;
43 }
44
45 ClipCoverage ClipContents::GetClipCoverage(
46 const std::optional<Rect>& current_clip_coverage) const {
47 if (!current_clip_coverage.has_value()) {
48 return ClipCoverage{.coverage = std::nullopt};
49 }
50 switch (clip_op_) {
51 case Entity::ClipOperation::kDifference:
52 // This can be optimized further by considering cases when the bounds of
53 // the current stencil will shrink.
54 return {
55 .is_difference_or_non_square = true, //
56 .coverage = current_clip_coverage //
57 };
58 case Entity::ClipOperation::kIntersect:
59 if (coverage_rect_.IsEmpty() || !current_clip_coverage.has_value()) {
60 return ClipCoverage{.coverage = std::nullopt};
61 }
62 return {
63 .is_difference_or_non_square = !is_axis_aligned_rect_, //
64 .coverage = current_clip_coverage->Intersection(coverage_rect_), //
65 };
66 }
67 FML_UNREACHABLE();
68 }
69
70 bool ClipContents::Render(const ContentContext& renderer,
71 RenderPass& pass,
72 uint32_t clip_depth) const {
73 if (!clip_geometry_.vertex_buffer) {
74 return true;
75 }
76
77 using VS = ClipPipeline::VertexShader;
78
79 VS::FrameInfo info;
80 info.depth = GetShaderClipDepth(clip_depth);
81
82 auto options = OptionsFromPass(pass);
83 options.blend_mode = BlendMode::kDst;
84
85 pass.SetStencilReference(0);
86
87 /// Stencil preparation draw.
88
89 options.depth_write_enabled = false;
90 options.primitive_type = clip_geometry_.type;
91 pass.SetVertexBuffer(clip_geometry_.vertex_buffer);
92 switch (clip_geometry_.mode) {
93 case GeometryResult::Mode::kNonZero:
94 pass.SetCommandLabel("Clip stencil preparation (NonZero)");
95 options.stencil_mode =
96 ContentContextOptions::StencilMode::kStencilNonZeroFill;
97 break;
98 case GeometryResult::Mode::kEvenOdd:
99 pass.SetCommandLabel("Clip stencil preparation (EvenOdd)");
100 options.stencil_mode =
101 ContentContextOptions::StencilMode::kStencilEvenOddFill;
102 break;
103 case GeometryResult::Mode::kNormal:
104 case GeometryResult::Mode::kPreventOverdraw:
105 pass.SetCommandLabel("Clip stencil preparation (Increment)");
106 options.stencil_mode =
107 ContentContextOptions::StencilMode::kOverdrawPreventionIncrement;
108 break;
109 }
110 pass.SetPipeline(renderer.GetClipPipeline(options));
111
112 info.mvp = clip_geometry_.transform;
113 VS::BindFrameInfo(pass, renderer.GetTransientsBuffer().EmplaceUniform(info));
114
115 if (!pass.Draw().ok()) {
116 return false;
117 }
118
119 /// Write depth.
120
121 options.depth_write_enabled = true;
122 options.primitive_type = PrimitiveType::kTriangleStrip;
123 Rect cover_area;
124 switch (clip_op_) {
125 case Entity::ClipOperation::kIntersect:
126 pass.SetCommandLabel("Intersect Clip");
127 options.stencil_mode =
128 ContentContextOptions::StencilMode::kCoverCompareInverted;
129 cover_area = Rect::MakeSize(pass.GetRenderTargetSize());
130 break;
131 case Entity::ClipOperation::kDifference:
132 pass.SetCommandLabel("Difference Clip");
133 options.stencil_mode = ContentContextOptions::StencilMode::kCoverCompare;
134 cover_area = coverage_rect_;
135 break;
136 }
137 auto points = cover_area.GetPoints();
138 pass.SetVertexBuffer(
139 CreateVertexBuffer(points, renderer.GetTransientsBuffer()));
140
141 pass.SetPipeline(renderer.GetClipPipeline(options));
142
143 info.mvp = pass.GetOrthographicTransform();
144 VS::BindFrameInfo(pass, renderer.GetTransientsBuffer().EmplaceUniform(info));
145
146 return pass.Draw().ok();
147 }
148
149 /*******************************************************************************
150 ******* ClipRestoreContents
151 ******************************************************************************/
152
153 bool RenderClipRestore(const ContentContext& renderer,
154 RenderPass& pass,
155 uint32_t clip_depth,
156 std::optional<Rect> restore_coverage) {
157 using VS = ClipPipeline::VertexShader;
158
159 pass.SetCommandLabel("Restore Clip");
160 auto options = OptionsFromPass(pass);
161 options.blend_mode = BlendMode::kDst;
162 options.stencil_mode =
163 ContentContextOptions::StencilMode::kOverdrawPreventionRestore;
164 options.primitive_type = PrimitiveType::kTriangleStrip;
165 pass.SetPipeline(renderer.GetClipPipeline(options));
166 pass.SetStencilReference(0);
167
168 // Create a rect that covers either the given restore area, or the whole
169 // render target texture.
170 auto ltrb =
171 restore_coverage.value_or(Rect::MakeSize(pass.GetRenderTargetSize()))
172 .GetLTRB();
173
174 std::array<VS::PerVertexData, 4> vertices = {
175 VS::PerVertexData{Point(ltrb[0], ltrb[1])},
176 VS::PerVertexData{Point(ltrb[2], ltrb[1])},
177 VS::PerVertexData{Point(ltrb[0], ltrb[3])},
178 VS::PerVertexData{Point(ltrb[2], ltrb[3])},
179 };
180 pass.SetVertexBuffer(
181 CreateVertexBuffer(vertices, renderer.GetTransientsBuffer()));
182
183 VS::FrameInfo info;
184 info.depth = GetShaderClipDepth(clip_depth);
185 info.mvp = pass.GetOrthographicTransform();
186 VS::BindFrameInfo(pass, renderer.GetTransientsBuffer().EmplaceUniform(info));
187
188 return pass.Draw().ok();
189 }
190
191 } // namespace impeller
impeller::ClipContents::ClipContents
ClipContents(Rect coverage_rect, bool is_axis_aligned_rect)
Definition: clip_contents.cc:31
impeller::ClipContents::SetGeometry
void SetGeometry(GeometryResult geometry)
Set the pre-tessellated clip geometry.
Definition: clip_contents.cc:37
impeller::ClipContents::~ClipContents
~ClipContents()
impeller::ClipContents::GetClipCoverage
ClipCoverage GetClipCoverage(const std::optional< Rect > &current_clip_coverage) const
Given the current pass space bounding rectangle of the clip buffer, return the expected clip coverage...
Definition: clip_contents.cc:45
impeller::ClipContents::SetClipOperation
void SetClipOperation(Entity::ClipOperation clip_op)
Definition: clip_contents.cc:41
impeller::ClipContents::Render
bool Render(const ContentContext &renderer, RenderPass &pass, uint32_t clip_depth) const
Definition: clip_contents.cc:70
impeller::ContentContext
Definition: content_context.h:138
impeller::ContentContext::GetTransientsBuffer
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Definition: content_context.h:297
impeller::ContentContext::GetClipPipeline
PipelineRef GetClipPipeline(ContentContextOptions opts) const
Definition: content_context.cc:1153
impeller::Entity::GetShaderClipDepth
float GetShaderClipDepth() const
Definition: entity.cc:88
impeller::Entity::ClipOperation
ClipOperation
Definition: entity.h:67
impeller::Entity::ClipOperation::kIntersect
@ kIntersect
impeller::Entity::ClipOperation::kDifference
@ kDifference
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:47
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:30
impeller::RenderPass::SetVertexBuffer
virtual bool SetVertexBuffer(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
Definition: render_pass.cc:127
impeller::RenderPass::SetStencilReference
virtual void SetStencilReference(uint32_t value)
Definition: render_pass.cc:103
impeller::RenderPass::GetOrthographicTransform
const Matrix & GetOrthographicTransform() const
Definition: render_pass.cc:51
impeller::RenderPass::SetPipeline
virtual void SetPipeline(PipelineRef pipeline)
The pipeline to use for this command.
Definition: render_pass.cc:86
impeller::RenderPass::GetRenderTargetSize
ISize GetRenderTargetSize() const
Definition: render_pass.cc:47
impeller::RenderPass::Draw
virtual fml::Status Draw()
Record the currently pending command.
Definition: render_pass.cc:208
impeller::RenderPass::SetCommandLabel
virtual void SetCommandLabel(std::string_view label)
The debugging label to use for the command.
Definition: render_pass.cc:97
impeller::RenderPipelineHandle::VertexShader
VertexShader_ VertexShader
Definition: pipeline.h:163
clip_contents.h
content_context.h
formats.h
entity.h
impeller
Definition: allocation.cc:12
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
impeller::Scalar
float Scalar
Definition: scalar.h:19
impeller::GetShaderClipDepth
static Scalar GetShaderClipDepth(uint32_t clip_depth)
Definition: clip_contents.cc:20
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::RenderClipRestore
bool RenderClipRestore(const ContentContext &renderer, RenderPass &pass, uint32_t clip_depth, std::optional< Rect > restore_coverage)
Render a restore clip.
Definition: clip_contents.cc:153
impeller::CreateVertexBuffer
VertexBuffer CreateVertexBuffer(std::array< VertexType, size > input, HostBuffer &host_buffer)
Create an index-less vertex buffer from a fixed size array.
Definition: vertex_buffer_builder.h:24
impeller::BlendMode::kDst
@ kDst
impeller::VS
LinePipeline::VertexShader VS
Definition: line_contents.cc:13
impeller::OptionsFromPass
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition: contents.cc:19
pipelines.h
render_pass.h
impeller::ClipCoverage
Definition: clip_contents.h:14
impeller::ClipCoverage::coverage
std::optional< Rect > coverage
This coverage is the outer coverage of the clip.
Definition: clip_contents.h:26
impeller::ContentContextOptions::StencilMode::kOverdrawPreventionRestore
@ kOverdrawPreventionRestore
impeller::ContentContextOptions::StencilMode::kStencilEvenOddFill
@ kStencilEvenOddFill
impeller::ContentContextOptions::StencilMode::kOverdrawPreventionIncrement
@ kOverdrawPreventionIncrement
impeller::ContentContextOptions::StencilMode::kCoverCompareInverted
@ kCoverCompareInverted
impeller::ContentContextOptions::StencilMode::kStencilNonZeroFill
@ kStencilNonZeroFill
impeller::ContentContextOptions::StencilMode::kCoverCompare
@ kCoverCompare
impeller::GeometryResult
Definition: geometry.h:21
impeller::GeometryResult::type
PrimitiveType type
Definition: geometry.h:37
impeller::GeometryResult::Mode::kNormal
@ kNormal
The geometry has no overlapping triangles.
impeller::GeometryResult::Mode::kEvenOdd
@ kEvenOdd
impeller::GeometryResult::Mode::kPreventOverdraw
@ kPreventOverdraw
impeller::GeometryResult::Mode::kNonZero
@ kNonZero
impeller::GeometryResult::transform
Matrix transform
Definition: geometry.h:39
impeller::GeometryResult::vertex_buffer
VertexBuffer vertex_buffer
Definition: geometry.h:38
impeller::GeometryResult::mode
Mode mode
Definition: geometry.h:40
impeller::TRect< Scalar >
impeller::TRect::IsEmpty
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition: rect.h:301
impeller::TRect::GetPoints
constexpr std::array< TPoint< T >, 4 > GetPoints() const
Get the points that represent the 4 corners of this rectangle in a Z order that is compatible with tr...
Definition: rect.h:418
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:150
points
std::vector< Point > points
Definition: tessellator_libtess.cc:76
vertex_buffer.h
vertex_buffer_builder.h