Flutter Impeller
conical_gradient_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 
6 
10 #include "impeller/entity/entity.h"
14 
15 namespace impeller {
16 
17 namespace {
18 ConicalKind GetConicalKind(Point center,
19  Scalar radius,
20  std::optional<Point> focus,
21  Scalar focus_radius) {
23  if (!focus.has_value() ||
24  center.GetDistance(focus.value()) < kEhCloseEnough) {
25  kind = ConicalKind::kRadial;
26  }
27  if (focus.has_value() && std::fabsf(radius - focus_radius) < kEhCloseEnough) {
28  if (kind == ConicalKind::kRadial) {
30  } else {
31  kind = ConicalKind::kStrip;
32  }
33  }
34  return kind;
35 }
36 
37 } // namespace
38 
40  : geometry_(geometry) {}
41 
43 
45  return geometry_;
46 }
47 
49  center_ = center;
50  radius_ = radius;
51 }
52 
54  tile_mode_ = tile_mode;
55 }
56 
57 void ConicalGradientContents::SetColors(std::vector<Color> colors) {
58  colors_ = std::move(colors);
59 }
60 
61 void ConicalGradientContents::SetStops(std::vector<Scalar> stops) {
62  stops_ = std::move(stops);
63 }
64 
65 const std::vector<Color>& ConicalGradientContents::GetColors() const {
66  return colors_;
67 }
68 
69 const std::vector<Scalar>& ConicalGradientContents::GetStops() const {
70  return stops_;
71 }
72 
73 void ConicalGradientContents::SetFocus(std::optional<Point> focus,
74  Scalar radius) {
75  focus_ = focus;
76  focus_radius_ = radius;
77 }
78 
79 #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
80 #define UNIFORM_FRAG_INFO(t) \
81  t##GradientUniformFillConicalPipeline::FragmentShader::FragInfo
82 #define UNIFORM_COLOR_SIZE ARRAY_LEN(UNIFORM_FRAG_INFO(Conical)::colors)
83 #define UNIFORM_STOP_SIZE ARRAY_LEN(UNIFORM_FRAG_INFO(Conical)::stop_pairs)
85 static_assert(UNIFORM_STOP_SIZE == kMaxUniformGradientStops / 2);
86 
88  const Entity& entity,
89  RenderPass& pass) const {
90  if (renderer.GetDeviceCapabilities().SupportsSSBO()) {
91  return RenderSSBO(renderer, entity, pass);
92  }
93  if (colors_.size() <= kMaxUniformGradientStops &&
94  stops_.size() <= kMaxUniformGradientStops) {
95  return RenderUniform(renderer, entity, pass);
96  }
97  return RenderTexture(renderer, entity, pass);
98 }
99 
100 bool ConicalGradientContents::RenderSSBO(const ContentContext& renderer,
101  const Entity& entity,
102  RenderPass& pass) const {
105 
106  VS::FrameInfo frame_info;
107  frame_info.matrix = GetInverseEffectTransform();
108 
109  ConicalKind kind = GetConicalKind(center_, radius_, focus_, focus_radius_);
110  PipelineBuilderCallback pipeline_callback =
111  [&renderer, kind](ContentContextOptions options) {
112  return renderer.GetConicalGradientSSBOFillPipeline(options, kind);
113  };
114  return ColorSourceContents::DrawGeometry<VS>(
115  renderer, entity, pass, pipeline_callback, frame_info,
116  [this, &renderer, &entity](RenderPass& pass) {
117  FS::FragInfo frag_info;
118  frag_info.center = center_;
119  frag_info.radius = radius_;
120  frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
121  frag_info.decal_border_color = decal_border_color_;
122  frag_info.alpha =
123  GetOpacityFactor() *
125  if (focus_) {
126  frag_info.focus = focus_.value();
127  frag_info.focus_radius = focus_radius_;
128  } else {
129  frag_info.focus = center_;
130  frag_info.focus_radius = 0.0;
131  }
132 
133  auto& data_host_buffer = renderer.GetTransientsDataBuffer();
134  auto colors = CreateGradientColors(colors_, stops_);
135 
136  frag_info.colors_length = colors.size();
137  auto color_buffer = data_host_buffer.Emplace(
138  colors.data(), colors.size() * sizeof(StopData),
139  renderer.GetDeviceCapabilities()
141 
142  FS::BindFragInfo(pass, data_host_buffer.EmplaceUniform(frag_info));
143  FS::BindColorData(pass, color_buffer);
144 
145  pass.SetCommandLabel("ConicalGradientSSBOFill");
146  return true;
147  });
148 }
149 
150 bool ConicalGradientContents::RenderUniform(const ContentContext& renderer,
151  const Entity& entity,
152  RenderPass& pass) const {
155 
156  VS::FrameInfo frame_info;
157  frame_info.matrix = GetInverseEffectTransform();
158 
159  ConicalKind kind = GetConicalKind(center_, radius_, focus_, focus_radius_);
160  PipelineBuilderCallback pipeline_callback =
161  [&renderer, kind](ContentContextOptions options) {
162  return renderer.GetConicalGradientUniformFillPipeline(options, kind);
163  };
164  return ColorSourceContents::DrawGeometry<VS>(
165  renderer, entity, pass, pipeline_callback, frame_info,
166  [this, &renderer, &entity](RenderPass& pass) {
167  FS::FragInfo frag_info;
168  frag_info.center = center_;
169  if (focus_) {
170  frag_info.focus = focus_.value();
171  frag_info.focus_radius = focus_radius_;
172  } else {
173  frag_info.focus = center_;
174  frag_info.focus_radius = 0.0;
175  }
176  frag_info.radius = radius_;
177  frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
178  frag_info.alpha =
179  GetOpacityFactor() *
180  GetGeometry()->ComputeAlphaCoverage(entity.GetTransform());
181  frag_info.colors_length = PopulateUniformGradientColors(
182  colors_, stops_, frag_info.colors, frag_info.stop_pairs);
183  frag_info.decal_border_color = decal_border_color_;
184 
185  pass.SetCommandLabel("ConicalGradientUniformFill");
186 
187  FS::BindFragInfo(
188  pass, renderer.GetTransientsDataBuffer().EmplaceUniform(frag_info));
189 
190  return true;
191  });
192 }
193 
194 bool ConicalGradientContents::RenderTexture(const ContentContext& renderer,
195  const Entity& entity,
196  RenderPass& pass) const {
199 
200  auto gradient_data = CreateGradientBuffer(colors_, stops_);
201  auto gradient_texture =
202  CreateGradientTexture(gradient_data, renderer.GetContext());
203  if (gradient_texture == nullptr) {
204  return false;
205  }
206 
207  VS::FrameInfo frame_info;
208  frame_info.matrix = GetInverseEffectTransform();
209 
210  ConicalKind kind = GetConicalKind(center_, radius_, focus_, focus_radius_);
211  PipelineBuilderCallback pipeline_callback =
212  [&renderer, kind](ContentContextOptions options) {
213  return renderer.GetConicalGradientFillPipeline(options, kind);
214  };
215  return ColorSourceContents::DrawGeometry<VS>(
216  renderer, entity, pass, pipeline_callback, frame_info,
217  [this, &renderer, &gradient_texture, &entity](RenderPass& pass) {
218  FS::FragInfo frag_info;
219  frag_info.center = center_;
220  frag_info.radius = radius_;
221  frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
222  frag_info.decal_border_color = decal_border_color_;
223  frag_info.texture_sampler_y_coord_scale =
224  gradient_texture->GetYCoordScale();
225  frag_info.alpha =
226  GetOpacityFactor() *
227  GetGeometry()->ComputeAlphaCoverage(entity.GetTransform());
228  frag_info.half_texel =
229  Vector2(0.5 / gradient_texture->GetSize().width,
230  0.5 / gradient_texture->GetSize().height);
231  if (focus_) {
232  frag_info.focus = focus_.value();
233  frag_info.focus_radius = focus_radius_;
234  } else {
235  frag_info.focus = center_;
236  frag_info.focus_radius = 0.0;
237  }
238 
239  pass.SetCommandLabel("ConicalGradientFill");
240 
241  FS::BindFragInfo(
242  pass, renderer.GetTransientsDataBuffer().EmplaceUniform(frag_info));
243  SamplerDescriptor sampler_desc;
244  sampler_desc.min_filter = MinMagFilter::kLinear;
245  sampler_desc.mag_filter = MinMagFilter::kLinear;
246  FS::BindTextureSampler(
247  pass, gradient_texture,
248  renderer.GetContext()->GetSamplerLibrary()->GetSampler(
249  sampler_desc));
250 
251  return true;
252  });
253 }
254 
256  const ColorFilterProc& color_filter_proc) {
257  for (Color& color : colors_) {
258  color = color_filter_proc(color);
259  }
260  decal_border_color_ = color_filter_proc(decal_border_color_);
261  return true;
262 }
263 
264 } // namespace impeller
virtual size_t GetMinimumStorageBufferAlignment() const
The minimum alignment of storage buffer value offsets in bytes.
Definition: capabilities.cc:14
virtual bool SupportsSSBO() const =0
Whether the context backend supports binding Shader Storage Buffer Objects (SSBOs) to pipelines.
Scalar GetOpacityFactor() const
Get the opacity factor for this color source.
const Matrix & GetInverseEffectTransform() const
Set the inverted effect transform for this color source.
std::function< PipelineRef(ContentContextOptions)> PipelineBuilderCallback
void SetFocus(std::optional< Point > focus, Scalar radius)
bool ApplyColorFilter(const ColorFilterProc &color_filter_proc) override
If possible, applies a color filter to this contents inputs on the CPU.
void SetStops(std::vector< Scalar > stops)
void SetCenterAndRadius(Point center, Scalar radius)
const Geometry * GetGeometry() const override
Get the geometry that this contents will use to render.
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
const std::vector< Scalar > & GetStops() const
void SetTileMode(Entity::TileMode tile_mode)
const std::vector< Color > & GetColors() const
ConicalGradientContents(const Geometry *geometry)
void SetColors(std::vector< Color > colors)
const Capabilities & GetDeviceCapabilities() const
HostBuffer & GetTransientsDataBuffer() const
Retrieve the current host buffer for transient storage of other non-index data.
PipelineRef GetConicalGradientSSBOFillPipeline(ContentContextOptions opts, ConicalKind kind) const
std::function< Color(Color)> ColorFilterProc
Definition: contents.h:35
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition: entity.cc:46
virtual Scalar ComputeAlphaCoverage(const Matrix &transform) const
Definition: geometry.h:125
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:30
FragmentShader_ FragmentShader
Definition: pipeline.h:169
#define UNIFORM_STOP_SIZE
#define UNIFORM_COLOR_SIZE
Point Vector2
Definition: point.h:430
float Scalar
Definition: scalar.h:19
constexpr float kEhCloseEnough
Definition: constants.h:57
TPoint< Scalar > Point
Definition: point.h:426
LinePipeline::FragmentShader FS
int PopulateUniformGradientColors(const std::vector< Color > &colors, const std::vector< Scalar > &stops, Vector4 frag_info_colors[kMaxUniformGradientStops], Vector4 frag_info_stop_pairs[kMaxUniformGradientStops/2])
Populate 2 arrays with the colors and stop data for a gradient.
std::vector< StopData > CreateGradientColors(const std::vector< Color > &colors, const std::vector< Scalar > &stops)
Populate a vector with the color and stop data for a gradient.
LinePipeline::VertexShader VS
std::shared_ptr< Texture > CreateGradientTexture(const GradientData &gradient_data, const std::shared_ptr< impeller::Context > &context)
Create a host visible texture that contains the gradient defined by the provided gradient data.
GradientData CreateGradientBuffer(const std::vector< Color > &colors, const std::vector< Scalar > &stops)
Populate a vector with the interpolated color bytes for the linear gradient described by colors and s...
Definition: gradient.cc:20
static constexpr uint32_t kMaxUniformGradientStops
Scalar alpha
Definition: color.h:143