blob: c3b6521ca97fe6271a5ad5933052dbb21c072573 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/entity/contents/tiled_texture_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/tiled_texture_fill.frag.h"
#include "impeller/entity/tiled_texture_fill.vert.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/sampler_library.h"
#include "impeller/tessellator/tessellator.h"
namespace impeller {
TiledTextureContents::TiledTextureContents() = default;
TiledTextureContents::~TiledTextureContents() = default;
void TiledTextureContents::SetPath(Path path) {
path_ = std::move(path);
}
void TiledTextureContents::SetTexture(std::shared_ptr<Texture> texture) {
texture_ = std::move(texture);
}
void TiledTextureContents::SetTileModes(Entity::TileMode x_tile_mode,
Entity::TileMode y_tile_mode) {
x_tile_mode_ = x_tile_mode;
y_tile_mode_ = y_tile_mode;
}
void TiledTextureContents::SetSamplerDescriptor(SamplerDescriptor desc) {
sampler_descriptor_ = std::move(desc);
}
std::optional<Rect> TiledTextureContents::GetCoverage(
const Entity& entity) const {
return path_.GetTransformedBoundingBox(entity.GetTransformation());
};
bool TiledTextureContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
if (texture_ == nullptr) {
return true;
}
using VS = TiledTextureFillVertexShader;
using FS = TiledTextureFillFragmentShader;
const auto coverage_rect = path_.GetBoundingBox();
if (!coverage_rect.has_value()) {
return true;
}
if (coverage_rect->size.IsEmpty()) {
return true;
}
const auto texture_size = texture_->GetSize();
if (texture_size.IsEmpty()) {
return true;
}
VertexBufferBuilder<VS::PerVertexData> vertex_builder;
{
const auto tess_result =
Tessellator{}.Tessellate(path_.GetFillType(), path_.CreatePolyline(),
[&vertex_builder, &texture_size](Point vtx) {
VS::PerVertexData data;
data.position = vtx;
data.texture_coords = vtx / texture_size;
vertex_builder.AppendVertex(data);
});
if (tess_result == Tessellator::Result::kInputError) {
return true;
}
if (tess_result == Tessellator::Result::kTessellationError) {
return false;
}
}
if (!vertex_builder.HasVertices()) {
return true;
}
auto& host_buffer = pass.GetTransientsBuffer();
VS::VertInfo vert_info;
vert_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransformation();
FS::FragInfo frag_info;
frag_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
frag_info.x_tile_mode = static_cast<Scalar>(x_tile_mode_);
frag_info.y_tile_mode = static_cast<Scalar>(y_tile_mode_);
Command cmd;
cmd.label = "TiledTextureFill";
cmd.pipeline =
renderer.GetTiledTexturePipeline(OptionsFromPassAndEntity(pass, entity));
cmd.stencil_reference = entity.GetStencilDepth();
cmd.BindVertices(vertex_builder.CreateVertexBuffer(host_buffer));
VS::BindVertInfo(cmd, host_buffer.EmplaceUniform(vert_info));
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
FS::BindTextureSampler(cmd, texture_,
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
sampler_descriptor_));
pass.AddCommand(std::move(cmd));
return true;
}
} // namespace impeller