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  : texture_(std::move(texture)),
28  source_(source),
29  destination_(destination),
30  color_(color),
31  blend_mode_(blend_mode),
32  desc_(desc) {}
33 
35 
37  return true;
38 }
39 
41  return false;
42 }
43 
45  HostBuffer& host_buffer) const {
46  using VS = TextureFillVertexShader;
47  constexpr size_t indices[6] = {0, 1, 2, 1, 2, 3};
48 
49  BufferView buffer_view = host_buffer.Emplace(
50  sizeof(VS::PerVertexData) * 6, alignof(VS::PerVertexData),
51  [&](uint8_t* raw_data) {
52  VS::PerVertexData* data =
53  reinterpret_cast<VS::PerVertexData*>(raw_data);
54  int offset = 0;
55  std::array<TPoint<float>, 4> destination_points =
56  destination_.GetPoints();
57  std::array<TPoint<float>, 4> texture_coords =
58  Rect::MakeSize(texture_->GetSize()).Project(source_).GetPoints();
59  for (size_t j = 0; j < 6; j++) {
60  data[offset].position = destination_points[indices[j]];
61  data[offset].texture_coords = texture_coords[indices[j]];
62  offset++;
63  }
64  });
65 
66  return VertexBuffer{
68  .index_buffer = {},
69  .vertex_count = 6,
70  .index_type = IndexType::kNone,
71  };
72 }
73 
75  HostBuffer& host_buffer) const {
76  using VS = PorterDuffBlendVertexShader;
77  constexpr size_t indices[6] = {0, 1, 2, 1, 2, 3};
78 
79  BufferView buffer_view = host_buffer.Emplace(
80  sizeof(VS::PerVertexData) * 6, alignof(VS::PerVertexData),
81  [&](uint8_t* raw_data) {
82  VS::PerVertexData* data =
83  reinterpret_cast<VS::PerVertexData*>(raw_data);
84  int offset = 0;
85  std::array<TPoint<float>, 4> texture_coords =
86  Rect::MakeSize(texture_->GetSize()).Project(source_).GetPoints();
87  std::array<TPoint<float>, 4> destination_points =
88  destination_.GetPoints();
89  for (size_t j = 0; j < 6; j++) {
90  data[offset].vertices = destination_points[indices[j]];
91  data[offset].texture_coords = texture_coords[indices[j]];
92  data[offset].color = color_.Premultiply();
93  offset++;
94  }
95  });
96 
97  return VertexBuffer{
99  .index_buffer = {},
100  .vertex_count = 6,
101  .index_type = IndexType::kNone,
102  };
103 }
104 
106  return destination_;
107 }
108 
109 const std::shared_ptr<Texture>& DrawImageRectAtlasGeometry::GetAtlas() const {
110  return texture_;
111 }
112 
114  const {
115  return desc_;
116 }
117 
119  return blend_mode_;
120 }
121 
123  return false;
124 }
125 
126 ////
127 
128 AtlasContents::AtlasContents() = default;
129 
131 
132 std::optional<Rect> AtlasContents::GetCoverage(const Entity& entity) const {
133  if (!geometry_) {
134  return std::nullopt;
135  }
136  return geometry_->ComputeBoundingBox().TransformBounds(entity.GetTransform());
137 }
138 
140  geometry_ = geometry;
141 }
142 
144  alpha_ = alpha;
145 }
146 
148  const Entity& entity,
149  RenderPass& pass) const {
150  if (geometry_->ShouldSkip() || alpha_ <= 0.0) {
151  return true;
152  }
153 
154  const SamplerDescriptor& dst_sampler_descriptor =
155  geometry_->GetSamplerDescriptor();
156  raw_ptr<const Sampler> dst_sampler =
157  renderer.GetContext()->GetSamplerLibrary()->GetSampler(
158  dst_sampler_descriptor);
159 
160  auto& host_buffer = renderer.GetTransientsBuffer();
161  if (!geometry_->ShouldUseBlend()) {
162  using VS = TextureFillVertexShader;
163  using FS = TextureFillFragmentShader;
164 
165  raw_ptr<const Sampler> dst_sampler =
166  renderer.GetContext()->GetSamplerLibrary()->GetSampler(
167  dst_sampler_descriptor);
168 
169  auto pipeline_options = OptionsFromPassAndEntity(pass, entity);
170  pipeline_options.primitive_type = PrimitiveType::kTriangle;
171  pipeline_options.depth_write_enabled =
172  pipeline_options.blend_mode == BlendMode::kSrc;
173 
174  pass.SetPipeline(renderer.GetTexturePipeline(pipeline_options));
175  pass.SetVertexBuffer(geometry_->CreateSimpleVertexBuffer(host_buffer));
176 #ifdef IMPELLER_DEBUG
177  pass.SetCommandLabel("DrawAtlas");
178 #endif // IMPELLER_DEBUG
179 
180  VS::FrameInfo frame_info;
181  frame_info.mvp = entity.GetShaderTransform(pass);
182  frame_info.texture_sampler_y_coord_scale =
183  geometry_->GetAtlas()->GetYCoordScale();
184 
185  VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
186 
187  FS::FragInfo frag_info;
188  frag_info.alpha = alpha_;
189  FS::BindFragInfo(pass, host_buffer.EmplaceUniform((frag_info)));
190  FS::BindTextureSampler(pass, geometry_->GetAtlas(), dst_sampler);
191  return pass.Draw().ok();
192  }
193 
194  BlendMode blend_mode = geometry_->GetBlendMode();
195 
196  if (blend_mode <= BlendMode::kModulate) {
199 
200 #ifdef IMPELLER_DEBUG
201  pass.SetCommandLabel("DrawAtlas Blend");
202 #endif // IMPELLER_DEBUG
203  pass.SetVertexBuffer(geometry_->CreateBlendVertexBuffer(host_buffer));
204  BlendMode inverted_blend_mode =
205  geometry_->ShouldInvertBlendMode()
206  ? (InvertPorterDuffBlend(blend_mode).value_or(BlendMode::kSrc))
207  : blend_mode;
208  pass.SetPipeline(renderer.GetPorterDuffPipeline(
209  inverted_blend_mode, OptionsFromPassAndEntity(pass, entity)));
210 
211  FS::FragInfo frag_info;
212  VS::FrameInfo frame_info;
213 
214  FS::BindTextureSamplerDst(pass, geometry_->GetAtlas(), dst_sampler);
215  frame_info.texture_sampler_y_coord_scale =
216  geometry_->GetAtlas()->GetYCoordScale();
217 
218  frag_info.output_alpha = alpha_;
219  frag_info.input_alpha = 1.0;
220 
221  // These values are ignored on platforms that natively support decal.
222  frag_info.tmx = static_cast<int>(Entity::TileMode::kDecal);
223  frag_info.tmy = static_cast<int>(Entity::TileMode::kDecal);
224 
225  FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
226 
227  frame_info.mvp = entity.GetShaderTransform(pass);
228 
229  auto uniform_view = host_buffer.EmplaceUniform(frame_info);
230  VS::BindFrameInfo(pass, uniform_view);
231 
232  return pass.Draw().ok();
233  }
234 
237 
238 #ifdef IMPELLER_DEBUG
239  pass.SetCommandLabel("DrawAtlas Advanced Blend");
240 #endif // IMPELLER_DEBUG
241  pass.SetVertexBuffer(geometry_->CreateBlendVertexBuffer(host_buffer));
242 
243  renderer.GetDrawVerticesUberPipeline(blend_mode,
244  OptionsFromPassAndEntity(pass, entity));
245  FS::BindTextureSampler(pass, geometry_->GetAtlas(), dst_sampler);
246 
247  VUS::FrameInfo frame_info;
248  FS::FragInfo frag_info;
249 
250  frame_info.texture_sampler_y_coord_scale =
251  geometry_->GetAtlas()->GetYCoordScale();
252  frame_info.mvp = entity.GetShaderTransform(pass);
253 
254  frag_info.alpha = alpha_;
255  frag_info.blend_mode = static_cast<int>(blend_mode);
256 
257  // These values are ignored on platforms that natively support decal.
258  frag_info.tmx = static_cast<int>(Entity::TileMode::kDecal);
259  frag_info.tmy = static_cast<int>(Entity::TileMode::kDecal);
260 
261  FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
262  VUS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
263 
264  return pass.Draw().ok();
265 }
266 
267 ///////////////
268 
270 
272 
274  const Entity& entity) const {
275  if (!geometry_) {
276  return std::nullopt;
277  }
278  return geometry_->ComputeBoundingBox().TransformBounds(entity.GetTransform());
279 }
280 
282  geometry_ = geometry;
283 }
284 
286  alpha_ = alpha;
287 }
288 
290  matrix_ = matrix;
291 }
292 
294  const Entity& entity,
295  RenderPass& pass) const {
296  if (geometry_->ShouldSkip() || alpha_ <= 0.0) {
297  return true;
298  }
299 
300  const SamplerDescriptor& dst_sampler_descriptor =
301  geometry_->GetSamplerDescriptor();
302 
303  raw_ptr<const Sampler> dst_sampler =
304  renderer.GetContext()->GetSamplerLibrary()->GetSampler(
305  dst_sampler_descriptor);
306 
307  auto& host_buffer = renderer.GetTransientsBuffer();
308 
311 
312 #ifdef IMPELLER_DEBUG
313  pass.SetCommandLabel("Atlas ColorFilter");
314 #endif // IMPELLER_DEBUG
315  pass.SetVertexBuffer(geometry_->CreateSimpleVertexBuffer(host_buffer));
316  pass.SetPipeline(
318 
319  FS::FragInfo frag_info;
320  VS::FrameInfo frame_info;
321 
322  FS::BindInputTexture(pass, geometry_->GetAtlas(), dst_sampler);
323  frame_info.texture_sampler_y_coord_scale =
324  geometry_->GetAtlas()->GetYCoordScale();
325 
326  frag_info.input_alpha = 1;
327  frag_info.output_alpha = alpha_;
328  const float* matrix = matrix_.array;
329  frag_info.color_v = Vector4(matrix[4], matrix[9], matrix[14], matrix[19]);
330  frag_info.color_m = Matrix(matrix[0], matrix[5], matrix[10], matrix[15], //
331  matrix[1], matrix[6], matrix[11], matrix[16], //
332  matrix[2], matrix[7], matrix[12], matrix[17], //
333  matrix[3], matrix[8], matrix[13], matrix[18] //
334  );
335 
336  FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
337 
338  frame_info.mvp = entity.GetShaderTransform(pass);
339 
340  auto uniform_view = host_buffer.EmplaceUniform(frame_info);
341  VS::BindFrameInfo(pass, uniform_view);
342 
343  return pass.Draw().ok();
344 }
345 
346 } // 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 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
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
PipelineRef GetPorterDuffPipeline(BlendMode mode, ContentContextOptions opts) const
PipelineRef GetTexturePipeline(ContentContextOptions opts) const
PipelineRef GetColorMatrixColorFilterPipeline(ContentContextOptions opts) const
std::shared_ptr< Context > GetContext() const
PipelineRef GetDrawVerticesUberPipeline(BlendMode blend_mode, ContentContextOptions opts) const
Rect ComputeBoundingBox() const override
const SamplerDescriptor & GetSamplerDescriptor() const override
bool ShouldUseBlend() const override
BlendMode GetBlendMode() const override
bool ShouldInvertBlendMode() const override
VertexBuffer CreateBlendVertexBuffer(HostBuffer &host_buffer) const override
VertexBuffer CreateSimpleVertexBuffer(HostBuffer &host_buffer) const override
DrawImageRectAtlasGeometry(std::shared_ptr< Texture > texture, const Rect &source, const Rect &destination, const Color &color, BlendMode blend_mode, const SamplerDescriptor &desc)
const std::shared_ptr< Texture > & GetAtlas() const override
Matrix GetShaderTransform(const RenderPass &pass) const
Get the vertex shader transform used for drawing this Entity.
Definition: entity.cc:48
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition: entity.cc:44
BufferView Emplace(const BufferType &buffer, size_t alignment=0)
Emplace non-uniform data (like contiguous vertices) onto the host buffer.
Definition: host_buffer.h:93
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:120
A wrapper around a raw ptr that adds additional unopt mode only checks.
Definition: raw_ptr.h:15
@ kNone
Does not use the index buffer.
float Scalar
Definition: scalar.h:18
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
SeparatedVector2 offset
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 TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition: rect.h:476
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:673
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
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:150
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:67