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;
238 #ifdef IMPELLER_DEBUG
241 #endif // IMPELLER_DEBUG
247 FS::FragInfo frag_info;
248 VS::FrameInfo frame_info;
250 auto dst_sampler_descriptor = sampler_descriptor_;
255 const std::unique_ptr<const Sampler>& dst_sampler =
256 renderer.
GetContext()->GetSamplerLibrary()->GetSampler(
257 dst_sampler_descriptor);
258 FS::BindTextureSamplerDst(pass, texture_, dst_sampler);
259 frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
261 frag_info.output_alpha = alpha_;
262 frag_info.input_alpha = 1.0;
264 auto inverted_blend_mode =
266 auto blend_coefficients =
268 frag_info.src_coeff = blend_coefficients[0];
269 frag_info.src_coeff_dst_alpha = blend_coefficients[1];
270 frag_info.dst_coeff = blend_coefficients[2];
271 frag_info.dst_coeff_src_alpha = blend_coefficients[3];
272 frag_info.dst_coeff_src_color = blend_coefficients[4];
274 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
278 auto uniform_view = host_buffer.EmplaceUniform(frame_info);
279 VS::BindFrameInfo(pass, uniform_view);
281 return pass.
Draw().ok();
289 auto src_contents = std::make_shared<AtlasTextureContents>(*
this);
290 src_contents->SetSubAtlas(sub_atlas);
291 src_contents->SetCoverage(sub_coverage);
293 auto dst_contents = std::make_shared<AtlasColorContents>(*
this);
294 dst_contents->SetSubAtlas(sub_atlas);
295 dst_contents->SetCoverage(sub_coverage);
297 Entity untransformed_entity;
302 contents->RenderToSnapshot(renderer,
303 untransformed_entity,
308 "AtlasContents Snapshot");
309 if (!snapshot.has_value()) {
314 child_contents.SetAlpha(alpha_);
315 child_contents.SetCoverage(coverage);
316 child_contents.SetTexture(snapshot.value().texture);
317 child_contents.SetUseDestination(
true);
318 child_contents.SetSubAtlas(sub_atlas);
319 return child_contents.Render(renderer, entity, pass);
331 const Entity& entity)
const {
340 coverage_ = coverage;
344 use_destination_ = value;
348 const std::shared_ptr<SubAtlasResult>& subatlas) {
349 subatlas_ = subatlas;
353 texture_ = std::move(texture);
359 using VS = TextureFillVertexShader;
360 using FS = TextureFillFragmentShader;
362 auto texture = texture_ ? texture_ : parent_.
GetTexture();
363 if (texture ==
nullptr) {
367 std::vector<Rect> texture_coords;
368 std::vector<Matrix> transforms;
370 texture_coords = use_destination_ ? subatlas_->result_texture_coords
371 : subatlas_->sub_texture_coords;
372 transforms = use_destination_ ? subatlas_->result_transforms
373 : subatlas_->sub_transforms;
379 const Size texture_size(texture->GetSize());
381 vertex_builder.
Reserve(texture_coords.size() * 6);
382 constexpr
size_t indices[6] = {0, 1, 2, 1, 2, 3};
383 for (
size_t i = 0; i < texture_coords.size(); i++) {
384 auto sample_rect = texture_coords[i];
385 auto matrix = transforms[i];
386 auto points = sample_rect.GetPoints();
387 auto transformed_points =
390 for (
size_t j = 0; j < 6; j++) {
391 VS::PerVertexData data;
392 data.position = transformed_points[indices[j]];
393 data.texture_coords = points[indices[j]] / texture_size;
406 VS::FrameInfo frame_info;
408 frame_info.texture_sampler_y_coord_scale = texture->GetYCoordScale();
409 frame_info.alpha = alpha_;
415 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
416 FS::BindTextureSampler(pass, texture,
417 renderer.
GetContext()->GetSamplerLibrary()->GetSampler(
419 return pass.
Draw().ok();
431 const Entity& entity)
const {
440 coverage_ = coverage;
444 const std::shared_ptr<SubAtlasResult>& subatlas) {
445 subatlas_ = subatlas;
454 std::vector<Rect> texture_coords;
455 std::vector<Matrix> transforms;
456 std::vector<Color> colors;
458 texture_coords = subatlas_->sub_texture_coords;
459 colors = subatlas_->sub_colors;
460 transforms = subatlas_->sub_transforms;
468 vertex_builder.
Reserve(texture_coords.size() * 6);
469 constexpr
size_t indices[6] = {0, 1, 2, 1, 2, 3};
470 for (
size_t i = 0; i < texture_coords.size(); i++) {
471 auto sample_rect = texture_coords[i];
472 auto matrix = transforms[i];
473 auto transformed_points =
476 for (
size_t j = 0; j < 6; j++) {
477 VS::PerVertexData data;
478 data.position = transformed_points[indices[j]];
479 data.color = colors[i].Premultiply();
492 VS::FrameInfo frame_info;
495 FS::FragInfo frag_info;
496 frag_info.alpha = alpha_;
503 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
504 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
505 return pass.
Draw().ok();