Flutter Engine
 
Loading...
Searching...
No Matches
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"
17
18namespace impeller {
19
20static 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
31ClipContents::ClipContents(Rect coverage_rect, bool is_axis_aligned_rect)
32 : coverage_rect_(coverage_rect),
33 is_axis_aligned_rect_(is_axis_aligned_rect) {}
34
36
38 clip_geometry_ = std::move(clip_geometry);
39}
40
42 clip_op_ = clip_op;
43}
44
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_) {
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 };
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 }
68}
69
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) {
94 pass.SetCommandLabel("Clip stencil preparation (NonZero)");
95 options.stencil_mode =
97 break;
99 pass.SetCommandLabel("Clip stencil preparation (EvenOdd)");
100 options.stencil_mode =
102 break;
105 pass.SetCommandLabel("Clip stencil preparation (Increment)");
106 options.stencil_mode =
108 break;
109 }
110 pass.SetPipeline(renderer.GetClipPipeline(options));
111
112 info.mvp = clip_geometry_.transform;
113 VS::BindFrameInfo(pass,
114 renderer.GetTransientsDataBuffer().EmplaceUniform(info));
115
116 if (!pass.Draw().ok()) {
117 return false;
118 }
119
120 /// Write depth.
121
122 options.depth_write_enabled = true;
123 options.primitive_type = PrimitiveType::kTriangleStrip;
124 Rect cover_area;
125 switch (clip_op_) {
127 pass.SetCommandLabel("Intersect Clip");
128 options.stencil_mode =
130 cover_area = Rect::MakeSize(pass.GetRenderTargetSize());
131 break;
133 pass.SetCommandLabel("Difference Clip");
135 cover_area = coverage_rect_;
136 break;
137 }
138 auto points = cover_area.GetPoints();
139 pass.SetVertexBuffer(
141
142 pass.SetPipeline(renderer.GetClipPipeline(options));
143
144 info.mvp = pass.GetOrthographicTransform();
145 VS::BindFrameInfo(pass,
146 renderer.GetTransientsDataBuffer().EmplaceUniform(info));
147
148 return pass.Draw().ok();
149}
150
151/*******************************************************************************
152 ******* ClipRestoreContents
153 ******************************************************************************/
154
156 RenderPass& pass,
157 uint32_t clip_depth,
158 std::optional<Rect> restore_coverage) {
159 using VS = ClipPipeline::VertexShader;
160
161 pass.SetCommandLabel("Restore Clip");
162 auto options = OptionsFromPass(pass);
163 options.blend_mode = BlendMode::kDst;
164 options.stencil_mode =
166 options.primitive_type = PrimitiveType::kTriangleStrip;
167 pass.SetPipeline(renderer.GetClipPipeline(options));
168 pass.SetStencilReference(0);
169
170 // Create a rect that covers either the given restore area, or the whole
171 // render target texture.
172 auto ltrb =
173 restore_coverage.value_or(Rect::MakeSize(pass.GetRenderTargetSize()))
174 .GetLTRB();
175
176 std::array<VS::PerVertexData, 4> vertices = {
177 VS::PerVertexData{Point(ltrb[0], ltrb[1])},
178 VS::PerVertexData{Point(ltrb[2], ltrb[1])},
179 VS::PerVertexData{Point(ltrb[0], ltrb[3])},
180 VS::PerVertexData{Point(ltrb[2], ltrb[3])},
181 };
182 pass.SetVertexBuffer(
183 CreateVertexBuffer(vertices, renderer.GetTransientsDataBuffer()));
184
185 VS::FrameInfo info;
186 info.depth = GetShaderClipDepth(clip_depth);
187 info.mvp = pass.GetOrthographicTransform();
188 VS::BindFrameInfo(pass,
189 renderer.GetTransientsDataBuffer().EmplaceUniform(info));
190
191 return pass.Draw().ok();
192}
193
194} // namespace impeller
bool ok() const
Definition status.h:71
ClipContents(Rect coverage_rect, bool is_axis_aligned_rect)
void SetGeometry(GeometryResult geometry)
Set the pre-tessellated clip geometry.
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...
void SetClipOperation(Entity::ClipOperation clip_op)
bool Render(const ContentContext &renderer, RenderPass &pass, uint32_t clip_depth) const
HostBuffer & GetTransientsDataBuffer() const
Retrieve the current host buffer for transient storage of other non-index data.
PipelineRef GetClipPipeline(ContentContextOptions opts) const
float GetShaderClipDepth() const
Definition entity.cc:88
BufferView EmplaceUniform(const UniformType &uniform)
Emplace uniform data onto the host buffer. Ensure that backend specific uniform alignment requirement...
Definition host_buffer.h:47
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition render_pass.h:30
virtual bool SetVertexBuffer(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
virtual void SetStencilReference(uint32_t value)
const Matrix & GetOrthographicTransform() const
virtual void SetPipeline(PipelineRef pipeline)
The pipeline to use for this command.
ISize GetRenderTargetSize() const
virtual fml::Status Draw()
Record the currently pending command.
virtual void SetCommandLabel(std::string_view label)
The debugging label to use for the command.
#define FML_UNREACHABLE()
Definition logging.h:128
float Scalar
Definition scalar.h:19
static Scalar GetShaderClipDepth(uint32_t clip_depth)
TPoint< Scalar > Point
Definition point.h:327
bool RenderClipRestore(const ContentContext &renderer, RenderPass &pass, uint32_t clip_depth, std::optional< Rect > restore_coverage)
Render a restore clip.
VertexBuffer CreateVertexBuffer(std::array< VertexType, size > input, HostBuffer &data_host_buffer)
Create an index-less vertex buffer from a fixed size array.
LinePipeline::VertexShader VS
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition contents.cc:19
std::optional< Rect > coverage
This coverage is the outer coverage of the clip.
PrimitiveType type
Definition geometry.h:37
@ kNormal
The geometry has no overlapping triangles.
VertexBuffer vertex_buffer
Definition geometry.h:38
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:414
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition rect.h:297
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:150
std::vector< Point > points