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"
14 #include "impeller/entity/entity.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 
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  }
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 
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 
155 bool RenderClipRestore(const ContentContext& renderer,
156  RenderPass& pass,
157  uint32_t clip_depth,
158  std::optional<Rect> restore_coverage) {
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
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.
Definition: render_pass.cc:127
virtual void SetStencilReference(uint32_t value)
Definition: render_pass.cc:103
const Matrix & GetOrthographicTransform() const
Definition: render_pass.cc:51
virtual void SetPipeline(PipelineRef pipeline)
The pipeline to use for this command.
Definition: render_pass.cc:86
ISize GetRenderTargetSize() const
Definition: render_pass.cc:47
virtual fml::Status Draw()
Record the currently pending command.
Definition: render_pass.cc:208
virtual void SetCommandLabel(std::string_view label)
The debugging label to use for the command.
Definition: render_pass.cc:97
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.
Definition: clip_contents.h:26
PrimitiveType type
Definition: geometry.h:37
@ kNormal
The geometry has no overlapping triangles.
VertexBuffer vertex_buffer
Definition: geometry.h:38
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition: rect.h:297
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 static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:150
std::vector< Point > points