6 #include <unordered_map>
16 #include "impeller/entity/texture_fill.frag.h"
17 #include "impeller/entity/texture_fill.vert.h"
29 texture_ = std::move(texture);
37 transforms_ = std::move(transforms);
38 bounding_box_cache_.reset();
42 texture_coords_ = std::move(texture_coords);
43 bounding_box_cache_.reset();
47 colors_ = std::move(colors);
55 blend_mode_ = blend_mode;
59 cull_rect_ = cull_rect;
87 std::unordered_map<AtlasBlenderKey, std::vector<Matrix>,
91 for (
auto i = 0u; i < texture_coords_.size(); i++) {
93 .rect = texture_coords_[i],
95 if (sub_atlas.find(key) == sub_atlas.end()) {
96 sub_atlas[key] = {transforms_[i]};
98 sub_atlas[key].push_back(transforms_[i]);
102 auto result = std::make_shared<SubAtlasResult>();
108 for (
auto it = sub_atlas.begin(); it != sub_atlas.end(); it++) {
113 if (x_offset >= 1000) {
114 y_offset = y_extent + 1;
118 auto key = it->first;
119 auto transforms = it->second;
121 auto new_rect =
Rect::MakeXYWH(x_offset, y_offset, key.rect.GetWidth(),
122 key.rect.GetHeight());
125 x_offset += std::ceil(key.rect.GetWidth()) + 1.0;
127 result->sub_texture_coords.push_back(key.rect);
128 result->sub_colors.push_back(key.color);
129 result->sub_transforms.push_back(sub_transform);
131 x_extent = std::max(x_extent, x_offset);
132 y_extent = std::max(y_extent, std::ceil(y_offset + key.rect.GetHeight()));
134 for (
auto transform : transforms) {
135 result->result_texture_coords.push_back(new_rect);
136 result->result_transforms.push_back(transform);
139 result->size =
ISize(std::ceil(x_extent), std::ceil(y_extent));
144 if (cull_rect_.has_value()) {
145 return cull_rect_.value().TransformBounds(entity.
GetTransform());
150 Rect AtlasContents::ComputeBoundingBox()
const {
151 if (!bounding_box_cache_.has_value()) {
152 Rect bounding_box = {};
153 for (
size_t i = 0; i < texture_coords_.size(); i++) {
154 auto matrix = transforms_[i];
155 auto sample_rect = texture_coords_[i];
158 bounding_box = bounds.
Union(bounding_box);
160 bounding_box_cache_ = bounding_box;
162 return bounding_box_cache_.value();
166 sampler_descriptor_ = std::move(desc);
170 return sampler_descriptor_;
178 return texture_coords_;
195 auto coverage = ComputeBoundingBox();
199 child_contents.SetAlpha(alpha_);
200 child_contents.SetCoverage(coverage);
201 return child_contents.Render(renderer, entity, pass);
205 child_contents.SetAlpha(alpha_);
206 child_contents.SetCoverage(coverage);
207 return child_contents.Render(renderer, entity, pass);
210 constexpr
size_t indices[6] = {0, 1, 2, 1, 2, 3};
218 vtx_builder.
Reserve(texture_coords_.size() * 6);
219 const auto texture_size = texture_->GetSize();
222 for (
size_t i = 0; i < texture_coords_.size(); i++) {
223 auto sample_rect = texture_coords_[i];
224 auto matrix = transforms_[i];
225 auto points = sample_rect.GetPoints();
226 auto transformed_points =
228 auto color = colors_[i].Premultiply();
229 for (
size_t j = 0; j < 6; j++) {
230 VS::PerVertexData data;
231 data.vertices = transformed_points[indices[j]];
232 data.texture_coords = points[indices[j]] / texture_size;
246 FS::FragInfo frag_info;
247 VS::FrameInfo frame_info;
249 auto dst_sampler_descriptor = sampler_descriptor_;
254 auto dst_sampler = renderer.
GetContext()->GetSamplerLibrary()->GetSampler(
255 dst_sampler_descriptor);
256 FS::BindTextureSamplerDst(cmd, texture_, dst_sampler);
257 frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
259 frag_info.output_alpha = alpha_;
260 frag_info.input_alpha = 1.0;
262 auto inverted_blend_mode =
264 auto blend_coefficients =
266 frag_info.src_coeff = blend_coefficients[0];
267 frag_info.src_coeff_dst_alpha = blend_coefficients[1];
268 frag_info.dst_coeff = blend_coefficients[2];
269 frag_info.dst_coeff_src_alpha = blend_coefficients[3];
270 frag_info.dst_coeff_src_color = blend_coefficients[4];
272 FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
276 auto uniform_view = host_buffer.EmplaceUniform(frame_info);
277 VS::BindFrameInfo(cmd, uniform_view);
287 auto src_contents = std::make_shared<AtlasTextureContents>(*
this);
288 src_contents->SetSubAtlas(sub_atlas);
289 src_contents->SetCoverage(sub_coverage);
291 auto dst_contents = std::make_shared<AtlasColorContents>(*
this);
292 dst_contents->SetSubAtlas(sub_atlas);
293 dst_contents->SetCoverage(sub_coverage);
295 Entity untransformed_entity;
300 contents->RenderToSnapshot(renderer,
301 untransformed_entity,
305 "AtlasContents Snapshot");
306 if (!snapshot.has_value()) {
311 child_contents.SetAlpha(alpha_);
312 child_contents.SetCoverage(coverage);
313 child_contents.SetTexture(snapshot.value().texture);
314 child_contents.SetUseDestination(
true);
315 child_contents.SetSubAtlas(sub_atlas);
316 return child_contents.Render(renderer, entity, pass);
328 const Entity& entity)
const {
337 coverage_ = coverage;
341 use_destination_ = value;
345 const std::shared_ptr<SubAtlasResult>& subatlas) {
346 subatlas_ = subatlas;
350 texture_ = std::move(texture);
356 using VS = TextureFillVertexShader;
357 using FS = TextureFillFragmentShader;
359 auto texture = texture_ ? texture_ : parent_.
GetTexture();
360 if (texture ==
nullptr) {
364 std::vector<Rect> texture_coords;
365 std::vector<Matrix> transforms;
367 texture_coords = use_destination_ ? subatlas_->result_texture_coords
368 : subatlas_->sub_texture_coords;
369 transforms = use_destination_ ? subatlas_->result_transforms
370 : subatlas_->sub_transforms;
376 const Size texture_size(texture->GetSize());
378 vertex_builder.
Reserve(texture_coords.size() * 6);
379 constexpr
size_t indices[6] = {0, 1, 2, 1, 2, 3};
380 for (
size_t i = 0; i < texture_coords.size(); i++) {
381 auto sample_rect = texture_coords[i];
382 auto matrix = transforms[i];
383 auto points = sample_rect.GetPoints();
384 auto transformed_points =
387 for (
size_t j = 0; j < 6; j++) {
388 VS::PerVertexData data;
389 data.position = transformed_points[indices[j]];
390 data.texture_coords = points[indices[j]] / texture_size;
404 VS::FrameInfo frame_info;
406 frame_info.texture_sampler_y_coord_scale = texture->GetYCoordScale();
407 frame_info.alpha = alpha_;
413 VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
414 FS::BindTextureSampler(cmd, texture,
415 renderer.
GetContext()->GetSamplerLibrary()->GetSampler(
429 const Entity& entity)
const {
438 coverage_ = coverage;
442 const std::shared_ptr<SubAtlasResult>& subatlas) {
443 subatlas_ = subatlas;
452 std::vector<Rect> texture_coords;
453 std::vector<Matrix> transforms;
454 std::vector<Color> colors;
456 texture_coords = subatlas_->sub_texture_coords;
457 colors = subatlas_->sub_colors;
458 transforms = subatlas_->sub_transforms;
466 vertex_builder.
Reserve(texture_coords.size() * 6);
467 constexpr
size_t indices[6] = {0, 1, 2, 1, 2, 3};
468 for (
size_t i = 0; i < texture_coords.size(); i++) {
469 auto sample_rect = texture_coords[i];
470 auto matrix = transforms[i];
471 auto transformed_points =
474 for (
size_t j = 0; j < 6; j++) {
475 VS::PerVertexData data;
476 data.position = transformed_points[indices[j]];
477 data.color = colors[i].Premultiply();
491 VS::FrameInfo frame_info;
494 FS::FragInfo frag_info;
495 frag_info.alpha = alpha_;
502 VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
503 FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));