Flutter Impeller
atlas_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 
12 #include "impeller/entity/entity.h"
13 #include "impeller/entity/texture_fill.frag.h"
14 #include "impeller/entity/texture_fill.vert.h"
17 
18 namespace impeller {
19 
21  std::shared_ptr<Texture> texture,
22  const Rect& source,
23  const Rect& destination,
24  const Color& color,
25  BlendMode blend_mode,
26  const SamplerDescriptor& desc,
27  bool use_strict_src_rect)
28  : texture_(std::move(texture)),
29  source_(source),
30  destination_(destination),
31  color_(color),
32  blend_mode_(blend_mode),
33  desc_(desc),
34  use_strict_src_rect_(use_strict_src_rect) {}
35 
37 
39  return true;
40 }
41 
43  return false;
44 }
45 
47  HostBuffer& data_host_buffer) const {
48  using VS = TextureFillVertexShader;
49  constexpr size_t indices[6] = {0, 1, 2, 1, 2, 3};
50 
51  BufferView buffer_view = data_host_buffer.Emplace(
52  sizeof(VS::PerVertexData) * 6, alignof(VS::PerVertexData),
53  [&](uint8_t* raw_data) {
54  VS::PerVertexData* data =
55  reinterpret_cast<VS::PerVertexData*>(raw_data);
56  int offset = 0;
57  std::array<TPoint<float>, 4> destination_points =
58  destination_.GetPoints();
59  std::array<TPoint<float>, 4> texture_coords =
60  Rect::MakeSize(texture_->GetSize()).Project(source_).GetPoints();
61  for (size_t j = 0; j < 6; j++) {
62  data[offset].position = destination_points[indices[j]];
63  data[offset].texture_coords = texture_coords[indices[j]];
64  offset++;
65  }
66  });
67 
68  return VertexBuffer{
70  .index_buffer = {},
71  .vertex_count = 6,
72  .index_type = IndexType::kNone,
73  };
74 }
75 
77  HostBuffer& data_host_buffer) const {
78  using VS = PorterDuffBlendVertexShader;
79  constexpr size_t indices[6] = {0, 1, 2, 1, 2, 3};
80 
81  BufferView buffer_view = data_host_buffer.Emplace(
82  sizeof(VS::PerVertexData) * 6, alignof(VS::PerVertexData),
83  [&](uint8_t* raw_data) {
84  VS::PerVertexData* data =
85  reinterpret_cast<VS::PerVertexData*>(raw_data);
86  int offset = 0;
87  std::array<TPoint<float>, 4> texture_coords =
88  Rect::MakeSize(texture_->GetSize()).Project(source_).GetPoints();
89  std::array<TPoint<float>, 4> destination_points =
90  destination_.GetPoints();
91  for (size_t j = 0; j < 6; j++) {
92  data[offset].vertices = destination_points[indices[j]];
93  data[offset].texture_coords = texture_coords[indices[j]];
94  data[offset].color = color_.Premultiply();
95  offset++;
96  }
97  });
98 
99  return VertexBuffer{
101  .index_buffer = {},
102  .vertex_count = 6,
103  .index_type = IndexType::kNone,
104  };
105 }
106 
108  return destination_;
109 }
110 
111 const std::shared_ptr<Texture>& DrawImageRectAtlasGeometry::GetAtlas() const {
112  return texture_;
113 }
114 
116  const {
117  return desc_;
118 }
119 
121  return blend_mode_;
122 }
123 
125  return false;
126 }
127 
128 std::optional<Rect> DrawImageRectAtlasGeometry::GetStrictSrcRect() const {
129  if (use_strict_src_rect_) {
130  // For a strict source rect, shrink the texture coordinate range by half a
131  // texel to ensure that linear filtering does not sample anything outside
132  // the source rect bounds.
133  return Rect::MakeSize(texture_->GetSize()).Project(source_.Expand(-0.5));
134  }
135  return std::nullopt;
136 }
137 
138 ////
139 
140 AtlasContents::AtlasContents() = default;
141 
143 
144 std::optional<Rect> AtlasContents::GetCoverage(const Entity& entity) const {
145  if (!geometry_) {
146  return std::nullopt;
147  }
148  return geometry_->ComputeBoundingBox().TransformBounds(entity.GetTransform());
149 }
150 
152  geometry_ = geometry;
153 }
154 
156  alpha_ = alpha;
157 }
158 
160  const Entity& entity,
161  RenderPass& pass) const {
162  if (geometry_->ShouldSkip() || alpha_ <= 0.0) {
163  return true;
164  }
165 
166  const SamplerDescriptor& dst_sampler_descriptor =
167  geometry_->GetSamplerDescriptor();
168  raw_ptr<const Sampler> dst_sampler =
169  renderer.GetContext()->GetSamplerLibrary()->GetSampler(
170  dst_sampler_descriptor);
171 
172  auto& data_host_buffer = renderer.GetTransientsDataBuffer();
173  if (!geometry_->ShouldUseBlend()) {
174  using VS = TextureFillVertexShader;
175  using FS = TextureFillFragmentShader;
176 
177  raw_ptr<const Sampler> dst_sampler =
178  renderer.GetContext()->GetSamplerLibrary()->GetSampler(
179  dst_sampler_descriptor);
180 
181  auto pipeline_options = OptionsFromPassAndEntity(pass, entity);
182  pipeline_options.primitive_type = PrimitiveType::kTriangle;
183  pipeline_options.depth_write_enabled =
184  pipeline_options.blend_mode == BlendMode::kSrc;
185 
186  pass.SetPipeline(renderer.GetTexturePipeline(pipeline_options));
187  pass.SetVertexBuffer(geometry_->CreateSimpleVertexBuffer(data_host_buffer));
188 #ifdef IMPELLER_DEBUG
189  pass.SetCommandLabel("DrawAtlas");
190 #endif // IMPELLER_DEBUG
191 
192  VS::FrameInfo frame_info;
193  frame_info.mvp = entity.GetShaderTransform(pass);
194  frame_info.texture_sampler_y_coord_scale =
195  geometry_->GetAtlas()->GetYCoordScale();
196 
197  VS::BindFrameInfo(pass, data_host_buffer.EmplaceUniform(frame_info));
198 
199  FS::FragInfo frag_info;
200  frag_info.alpha = alpha_;
201  FS::BindFragInfo(pass, data_host_buffer.EmplaceUniform((frag_info)));
202  FS::BindTextureSampler(pass, geometry_->GetAtlas(), dst_sampler);
203  return pass.Draw().ok();
204  }
205 
206  BlendMode blend_mode = geometry_->GetBlendMode();
207 
208  if (blend_mode <= BlendMode::kModulate) {
211 
212 #ifdef IMPELLER_DEBUG
213  pass.SetCommandLabel("DrawAtlas Blend");
214 #endif // IMPELLER_DEBUG
215  pass.SetVertexBuffer(geometry_->CreateBlendVertexBuffer(data_host_buffer));
216  BlendMode inverted_blend_mode =
217  geometry_->ShouldInvertBlendMode()
218  ? (InvertPorterDuffBlend(blend_mode).value_or(BlendMode::kSrc))
219  : blend_mode;
220  pass.SetPipeline(renderer.GetPorterDuffPipeline(
221  inverted_blend_mode, OptionsFromPassAndEntity(pass, entity)));
222 
223  FS::FragInfo frag_info;
224  VS::FrameInfo frame_info;
225 
226  FS::BindTextureSamplerDst(pass, geometry_->GetAtlas(), dst_sampler);
227  frame_info.texture_sampler_y_coord_scale =
228  geometry_->GetAtlas()->GetYCoordScale();
229 
230  frag_info.input_alpha_output_alpha_tmx_tmy =
231  Vector4(1.0, alpha_, static_cast<int>(Entity::TileMode::kDecal),
232  static_cast<int>(Entity::TileMode::kDecal));
233  if (auto rect = geometry_->GetStrictSrcRect(); rect.has_value()) {
234  Rect src_rect = rect.value();
235  frag_info.source_rect =
236  Vector4(src_rect.GetX(), src_rect.GetY(), src_rect.GetRight(),
237  src_rect.GetBottom());
238  frag_info.use_strict_source_rect = 1.0;
239  } else {
240  frag_info.use_strict_source_rect = 0.0;
241  }
242 
243  FS::BindFragInfo(pass, data_host_buffer.EmplaceUniform(frag_info));
244 
245  frame_info.mvp = entity.GetShaderTransform(pass);
246 
247  auto uniform_view = data_host_buffer.EmplaceUniform(frame_info);
248  VS::BindFrameInfo(pass, uniform_view);
249 
250  return pass.Draw().ok();
251  }
252 
255 
256 #ifdef IMPELLER_DEBUG
257  pass.SetCommandLabel("DrawAtlas Advanced Blend");
258 #endif // IMPELLER_DEBUG
259  pass.SetVertexBuffer(geometry_->CreateBlendVertexBuffer(data_host_buffer));
260 
262  blend_mode, OptionsFromPassAndEntity(pass, entity)));
263  FS::BindTextureSampler(pass, geometry_->GetAtlas(), dst_sampler);
264 
265  VUS::FrameInfo frame_info;
266  FS::FragInfo frag_info;
267 
268  frame_info.texture_sampler_y_coord_scale =
269  geometry_->GetAtlas()->GetYCoordScale();
270  frame_info.mvp = entity.GetShaderTransform(pass);
271 
272  frag_info.alpha = alpha_;
273  frag_info.blend_mode = static_cast<int>(blend_mode);
274 
275  // These values are ignored on platforms that natively support decal.
276  frag_info.tmx = static_cast<int>(Entity::TileMode::kDecal);
277  frag_info.tmy = static_cast<int>(Entity::TileMode::kDecal);
278 
279  FS::BindFragInfo(pass, data_host_buffer.EmplaceUniform(frag_info));
280  VUS::BindFrameInfo(pass, data_host_buffer.EmplaceUniform(frame_info));
281 
282  return pass.Draw().ok();
283 }
284 
285 ///////////////
286 
288 
290 
292  const Entity& entity) const {
293  if (!geometry_) {
294  return std::nullopt;
295  }
296  return geometry_->ComputeBoundingBox().TransformBounds(entity.GetTransform());
297 }
298 
300  geometry_ = geometry;
301 }
302 
304  alpha_ = alpha;
305 }
306 
308  matrix_ = matrix;
309 }
310 
312  const Entity& entity,
313  RenderPass& pass) const {
314  if (geometry_->ShouldSkip() || alpha_ <= 0.0) {
315  return true;
316  }
317 
318  const SamplerDescriptor& dst_sampler_descriptor =
319  geometry_->GetSamplerDescriptor();
320 
321  raw_ptr<const Sampler> dst_sampler =
322  renderer.GetContext()->GetSamplerLibrary()->GetSampler(
323  dst_sampler_descriptor);
324 
325  auto& data_host_buffer = renderer.GetTransientsDataBuffer();
326 
329 
330 #ifdef IMPELLER_DEBUG
331  pass.SetCommandLabel("Atlas ColorFilter");
332 #endif // IMPELLER_DEBUG
333  pass.SetVertexBuffer(geometry_->CreateSimpleVertexBuffer(data_host_buffer));
334  pass.SetPipeline(
336 
337  FS::FragInfo frag_info;
338  VS::FrameInfo frame_info;
339 
340  FS::BindInputTexture(pass, geometry_->GetAtlas(), dst_sampler);
341  frame_info.texture_sampler_y_coord_scale =
342  geometry_->GetAtlas()->GetYCoordScale();
343 
344  frag_info.input_alpha = 1;
345  frag_info.output_alpha = alpha_;
346  const float* matrix = matrix_.array;
347  frag_info.color_v = Vector4(matrix[4], matrix[9], matrix[14], matrix[19]);
348  frag_info.color_m = Matrix(matrix[0], matrix[5], matrix[10], matrix[15], //
349  matrix[1], matrix[6], matrix[11], matrix[16], //
350  matrix[2], matrix[7], matrix[12], matrix[17], //
351  matrix[3], matrix[8], matrix[13], matrix[18] //
352  );
353 
354  FS::BindFragInfo(pass, data_host_buffer.EmplaceUniform(frag_info));
355 
356  frame_info.mvp = entity.GetShaderTransform(pass);
357 
358  auto uniform_view = data_host_buffer.EmplaceUniform(frame_info);
359  VS::BindFrameInfo(pass, uniform_view);
360 
361  return pass.Draw().ok();
362 }
363 
364 } // namespace impeller
BufferView buffer_view
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
void SetGeometry(AtlasGeometry *geometry)
std::optional< Rect > GetCoverage(const Entity &entity) const override
Get the area of the render pass that will be affected when this contents is rendered.
void SetAlpha(Scalar alpha)
virtual std::optional< Rect > GetStrictSrcRect() const
The source rect of the draw in texture coordinates if a strict source rect should be applied,...
virtual VertexBuffer CreateSimpleVertexBuffer(HostBuffer &host_buffer) const =0
virtual Rect ComputeBoundingBox() const =0
virtual bool ShouldInvertBlendMode() const
virtual bool ShouldUseBlend() const =0
virtual const SamplerDescriptor & GetSamplerDescriptor() const =0
virtual bool ShouldSkip() const =0
virtual VertexBuffer CreateBlendVertexBuffer(HostBuffer &host_buffer) const =0
virtual BlendMode GetBlendMode() const =0
virtual const std::shared_ptr< Texture > & GetAtlas() const =0
std::optional< Rect > GetCoverage(const Entity &entity) const override
Get the area of the render pass that will be affected when this contents is rendered.
void SetGeometry(AtlasGeometry *geometry)
void SetMatrix(ColorMatrix matrix)
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
PipelineRef GetPorterDuffPipeline(BlendMode mode, ContentContextOptions opts) const
PipelineRef GetTexturePipeline(ContentContextOptions opts) const
HostBuffer & GetTransientsDataBuffer() const
Retrieve the current host buffer for transient storage of other non-index data.
PipelineRef GetColorMatrixColorFilterPipeline(ContentContextOptions opts) const
std::shared_ptr< Context > GetContext() const
PipelineRef GetDrawVerticesUberPipeline(BlendMode blend_mode, ContentContextOptions opts) const
DrawImageRectAtlasGeometry(std::shared_ptr< Texture > texture, const Rect &source, const Rect &destination, const Color &color, BlendMode blend_mode, const SamplerDescriptor &desc, bool use_strict_src_rect=false)
Rect ComputeBoundingBox() const override
const SamplerDescriptor & GetSamplerDescriptor() const override
bool ShouldUseBlend() const override
std::optional< Rect > GetStrictSrcRect() const override
The source rect of the draw in texture coordinates if a strict source rect should be applied,...
BlendMode GetBlendMode() const override
bool ShouldInvertBlendMode() const override
VertexBuffer CreateBlendVertexBuffer(HostBuffer &host_buffer) const override
VertexBuffer CreateSimpleVertexBuffer(HostBuffer &host_buffer) const override
const std::shared_ptr< Texture > & GetAtlas() const override
Matrix GetShaderTransform(const RenderPass &pass) const
Definition: entity.cc:50
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition: entity.cc:46
BufferView Emplace(const BufferType &buffer, size_t alignment=0)
Emplace non-uniform data (like contiguous vertices) onto the host buffer.
Definition: host_buffer.h:92
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 SetPipeline(PipelineRef pipeline)
The pipeline to use for this command.
Definition: render_pass.cc:86
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
FragmentShader_ FragmentShader
Definition: pipeline.h:164
A wrapper around a raw ptr that adds additional unopt mode only checks.
Definition: raw_ptr.h:15
std::optional< PipelineDescriptor > desc_
float Scalar
Definition: scalar.h:19
@ kNone
Does not use the index buffer.
LinePipeline::FragmentShader FS
std::optional< BlendMode > InvertPorterDuffBlend(BlendMode blend_mode)
BlendMode
Definition: color.h:58
LinePipeline::VertexShader VS
ContentContextOptions OptionsFromPassAndEntity(const RenderPass &pass, const Entity &entity)
Definition: contents.cc:34
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition: contents.cc:19
Definition: comparable.h:95
constexpr Color Premultiply() const
Definition: color.h:212
Scalar array[20]
Definition: color.h:118
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
Definition: rect.h:618
constexpr auto GetBottom() const
Definition: rect.h:357
constexpr Type GetY() const
Returns the Y coordinate of the upper left corner, equivalent to |GetOrigin().y|.
Definition: rect.h:337
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition: rect.h:472
constexpr TRect< T > Project(TRect< T > source) const
Returns a new rectangle that represents the projection of the source rectangle onto this rectangle....
Definition: rect.h:669
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 Type GetX() const
Returns the X coordinate of the upper left corner, equivalent to |GetOrigin().x|.
Definition: rect.h:333
constexpr auto GetRight() const
Definition: rect.h:355
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:150
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:69