6 #include <unordered_map>
9 #include "flutter/fml/macros.h"
21 #include "impeller/entity/texture_fill.frag.h"
22 #include "impeller/entity/texture_fill.vert.h"
35 texture_ = std::move(texture);
43 transforms_ = std::move(transforms);
44 bounding_box_cache_.reset();
48 texture_coords_ = std::move(texture_coords);
49 bounding_box_cache_.reset();
53 colors_ = std::move(colors);
61 blend_mode_ = blend_mode;
65 cull_rect_ = cull_rect;
93 std::unordered_map<AtlasBlenderKey, std::vector<Matrix>,
97 for (
auto i = 0u; i < texture_coords_.size(); i++) {
99 .rect = texture_coords_[i],
101 if (sub_atlas.find(key) == sub_atlas.end()) {
102 sub_atlas[key] = {transforms_[i]};
104 sub_atlas[key].push_back(transforms_[i]);
108 auto result = std::make_shared<SubAtlasResult>();
114 for (
auto it = sub_atlas.begin(); it != sub_atlas.end(); it++) {
119 if (x_offset >= 1000) {
120 y_offset = y_extent + 1;
124 auto key = it->first;
125 auto transforms = it->second;
127 auto new_rect =
Rect::MakeXYWH(x_offset, y_offset, key.rect.size.width,
128 key.rect.size.height);
131 x_offset += std::ceil(key.rect.size.width) + 1.0;
133 result->sub_texture_coords.push_back(key.rect);
134 result->sub_colors.push_back(key.color);
135 result->sub_transforms.push_back(sub_transform);
137 x_extent = std::max(x_extent, x_offset);
138 y_extent = std::max(y_extent, std::ceil(y_offset + key.rect.size.height));
140 for (
auto transform : transforms) {
141 result->result_texture_coords.push_back(new_rect);
142 result->result_transforms.push_back(transform);
145 result->size =
ISize(std::ceil(x_extent), std::ceil(y_extent));
150 if (cull_rect_.has_value()) {
156 Rect AtlasContents::ComputeBoundingBox()
const {
157 if (!bounding_box_cache_.has_value()) {
158 Rect bounding_box = {};
159 for (
size_t i = 0; i < texture_coords_.size(); i++) {
160 auto matrix = transforms_[i];
161 auto sample_rect = texture_coords_[i];
163 bounding_box = bounds.
Union(bounding_box);
165 bounding_box_cache_ = bounding_box;
167 return bounding_box_cache_.value();
171 sampler_descriptor_ = std::move(desc);
175 return sampler_descriptor_;
183 return texture_coords_;
200 auto coverage = ComputeBoundingBox();
204 child_contents.SetAlpha(alpha_);
205 child_contents.SetCoverage(coverage);
206 return child_contents.Render(renderer, entity, pass);
210 child_contents.SetAlpha(alpha_);
211 child_contents.SetCoverage(coverage);
212 return child_contents.Render(renderer, entity, pass);
215 constexpr
size_t indices[6] = {0, 1, 2, 1, 2, 3};
216 constexpr
Scalar width[6] = {0, 1, 0, 1, 0, 1};
217 constexpr
Scalar height[6] = {0, 0, 1, 0, 1, 1};
225 vtx_builder.
Reserve(texture_coords_.size() * 6);
226 const auto texture_size = texture_->GetSize();
229 for (
size_t i = 0; i < texture_coords_.size(); i++) {
230 auto sample_rect = texture_coords_[i];
231 auto matrix = transforms_[i];
232 auto transformed_points =
234 auto color = colors_[i].Premultiply();
235 for (
size_t j = 0; j < 6; j++) {
236 VS::PerVertexData data;
237 data.vertices = transformed_points[indices[j]];
238 data.texture_coords =
239 (sample_rect.origin +
Point(sample_rect.size.width * width[j],
240 sample_rect.size.height * height[j])) /
257 FS::FragInfo frag_info;
258 VS::FrameInfo frame_info;
260 auto dst_sampler_descriptor = sampler_descriptor_;
265 auto dst_sampler = renderer.
GetContext()->GetSamplerLibrary()->GetSampler(
266 dst_sampler_descriptor);
267 FS::BindTextureSamplerDst(cmd, texture_, dst_sampler);
268 frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
270 frag_info.output_alpha = alpha_;
271 frag_info.input_alpha = 1.0;
273 auto inverted_blend_mode =
275 auto blend_coefficients =
277 frag_info.src_coeff = blend_coefficients[0];
278 frag_info.src_coeff_dst_alpha = blend_coefficients[1];
279 frag_info.dst_coeff = blend_coefficients[2];
280 frag_info.dst_coeff_src_alpha = blend_coefficients[3];
281 frag_info.dst_coeff_src_color = blend_coefficients[4];
283 FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
288 auto uniform_view = host_buffer.EmplaceUniform(frame_info);
289 VS::BindFrameInfo(cmd, uniform_view);
299 auto src_contents = std::make_shared<AtlasTextureContents>(*
this);
300 src_contents->SetSubAtlas(sub_atlas);
301 src_contents->SetCoverage(sub_coverage);
303 auto dst_contents = std::make_shared<AtlasColorContents>(*
this);
304 dst_contents->SetSubAtlas(sub_atlas);
305 dst_contents->SetCoverage(sub_coverage);
307 Entity untransformed_entity;
312 contents->RenderToSnapshot(renderer,
313 untransformed_entity,
317 "AtlasContents Snapshot");
318 if (!snapshot.has_value()) {
323 child_contents.SetAlpha(alpha_);
324 child_contents.SetCoverage(coverage);
325 child_contents.SetTexture(snapshot.value().texture);
326 child_contents.SetUseDestination(
true);
327 child_contents.SetSubAtlas(sub_atlas);
328 return child_contents.Render(renderer, entity, pass);
340 const Entity& entity)
const {
349 coverage_ = coverage;
353 use_destination_ = value;
357 const std::shared_ptr<SubAtlasResult>& subatlas) {
358 subatlas_ = subatlas;
362 texture_ = std::move(texture);
368 using VS = TextureFillVertexShader;
369 using FS = TextureFillFragmentShader;
371 auto texture = texture_ ? texture_ : parent_.
GetTexture();
372 if (texture ==
nullptr) {
376 std::vector<Rect> texture_coords;
377 std::vector<Matrix> transforms;
379 texture_coords = use_destination_ ? subatlas_->result_texture_coords
380 : subatlas_->sub_texture_coords;
381 transforms = use_destination_ ? subatlas_->result_transforms
382 : subatlas_->sub_transforms;
388 const Size texture_size(texture->GetSize());
390 vertex_builder.
Reserve(texture_coords.size() * 6);
391 constexpr
size_t indices[6] = {0, 1, 2, 1, 2, 3};
392 constexpr
Scalar width[6] = {0, 1, 0, 1, 0, 1};
393 constexpr
Scalar height[6] = {0, 0, 1, 0, 1, 1};
394 for (
size_t i = 0; i < texture_coords.size(); i++) {
395 auto sample_rect = texture_coords[i];
396 auto matrix = transforms[i];
397 auto transformed_points =
400 for (
size_t j = 0; j < 6; j++) {
401 VS::PerVertexData data;
402 data.position = transformed_points[indices[j]];
403 data.texture_coords =
404 (sample_rect.origin +
Point(sample_rect.size.width * width[j],
405 sample_rect.size.height * height[j])) /
420 VS::FrameInfo frame_info;
423 frame_info.texture_sampler_y_coord_scale = texture->GetYCoordScale();
424 frame_info.alpha = alpha_;
430 VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
431 FS::BindTextureSampler(cmd, texture,
432 renderer.
GetContext()->GetSamplerLibrary()->GetSampler(
446 const Entity& entity)
const {
455 coverage_ = coverage;
459 const std::shared_ptr<SubAtlasResult>& subatlas) {
460 subatlas_ = subatlas;
469 std::vector<Rect> texture_coords;
470 std::vector<Matrix> transforms;
471 std::vector<Color> colors;
473 texture_coords = subatlas_->sub_texture_coords;
474 colors = subatlas_->sub_colors;
475 transforms = subatlas_->sub_transforms;
483 vertex_builder.
Reserve(texture_coords.size() * 6);
484 constexpr
size_t indices[6] = {0, 1, 2, 1, 2, 3};
485 for (
size_t i = 0; i < texture_coords.size(); i++) {
486 auto sample_rect = texture_coords[i];
487 auto matrix = transforms[i];
488 auto transformed_points =
491 for (
size_t j = 0; j < 6; j++) {
492 VS::PerVertexData data;
493 data.position = transformed_points[indices[j]];
494 data.color = colors[i].Premultiply();
508 VS::FrameInfo frame_info;
512 FS::FragInfo frag_info;
513 frag_info.alpha = alpha_;
520 VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
521 FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));