[Impeller] texture coordinates implementation (#39781)
[Impeller] texture coordinates implementation
diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc
index 6ba4d87..59d4c0d 100644
--- a/impeller/aiks/canvas.cc
+++ b/impeller/aiks/canvas.cc
@@ -21,6 +21,23 @@
namespace impeller {
+static bool UseColorSourceContents(
+ const std::shared_ptr<VerticesGeometry>& vertices,
+ const Paint::ColorSourceType& type) {
+ // If there are no vertex color or texture coordinates. Or if there
+ // are vertex coordinates then only if the contents are an image or
+ // a solid color.
+ if (vertices->HasVertexColors()) {
+ return false;
+ }
+ if (vertices->HasTextureCoordinates() &&
+ (type == Paint::ColorSourceType::kImage ||
+ type == Paint::ColorSourceType::kColor)) {
+ return true;
+ }
+ return !vertices->HasTextureCoordinates();
+}
+
Canvas::Canvas() {
Initialize();
}
@@ -386,7 +403,9 @@
entity.SetStencilDepth(GetStencilDepth());
entity.SetBlendMode(paint.blend_mode);
- if (!vertices->HasVertexColors()) {
+ // If there are no vertex color or texture coordinates. Or if there
+ // are vertex coordinates then only if the contents are an image.
+ if (UseColorSourceContents(vertices, paint.color_source_type)) {
auto contents = paint.CreateContentsForGeometry(vertices);
entity.SetContents(paint.WithFilters(std::move(contents)));
GetCurrentPass().AddEntity(entity);
@@ -395,7 +414,27 @@
auto src_paint = paint;
src_paint.color = paint.color.WithAlpha(1.0);
- auto src_contents = src_paint.CreateContentsForGeometry(vertices);
+
+ std::shared_ptr<Contents> src_contents =
+ src_paint.CreateContentsForGeometry(vertices);
+ if (vertices->HasTextureCoordinates() &&
+ paint.color_source_type != Paint::ColorSourceType::kImage) {
+ // If the color source has an intrinsic size, then we use that to
+ // create the src contents as a simplification. Otherwise we use
+ // the extent of the texture coordinates to determine how large
+ // the src contents should be. If neither has a value we fall back
+ // to using the geometry coverage data.
+ Rect src_coverage;
+ auto size = src_contents->ColorSourceSize();
+ if (size.has_value()) {
+ src_coverage = Rect::MakeXYWH(0, 0, size->width, size->height);
+ } else {
+ src_coverage = vertices->GetTextureCoordinateCoverge().value_or(
+ vertices->GetCoverage(Matrix{}).value());
+ }
+ src_contents =
+ src_paint.CreateContentsForGeometry(Geometry::MakeRect(src_coverage));
+ }
auto contents = std::make_shared<VerticesContents>();
contents->SetAlpha(paint.color.alpha);
diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc
index 02e8516..1d5dba8 100644
--- a/impeller/display_list/display_list_dispatcher.cc
+++ b/impeller/display_list/display_list_dispatcher.cc
@@ -396,6 +396,13 @@
contents->SetEndPoints(start_point, end_point);
contents->SetTileMode(tile_mode);
contents->SetEffectTransform(matrix);
+
+ std::vector<Point> bounds{start_point, end_point};
+ auto intrinsic_size =
+ Rect::MakePointBounds(bounds.begin(), bounds.end());
+ if (intrinsic_size.has_value()) {
+ contents->SetColorSourceSize(intrinsic_size->size);
+ }
return contents;
};
return;
@@ -420,6 +427,14 @@
contents->SetCenterAndRadius(center, radius);
contents->SetTileMode(tile_mode);
contents->SetEffectTransform(matrix);
+
+ auto radius_pt = Point(radius, radius);
+ std::vector<Point> bounds{center + radius_pt, center - radius_pt};
+ auto intrinsic_size =
+ Rect::MakePointBounds(bounds.begin(), bounds.end());
+ if (intrinsic_size.has_value()) {
+ contents->SetColorSourceSize(intrinsic_size->size);
+ }
return contents;
};
return;
@@ -447,6 +462,7 @@
contents->SetStops(stops);
contents->SetTileMode(tile_mode);
contents->SetEffectTransform(matrix);
+
return contents;
};
return;
@@ -468,6 +484,7 @@
contents->SetSamplerDescriptor(desc);
contents->SetEffectTransform(matrix);
contents->SetColorFilter(paint.color_filter);
+ contents->SetColorSourceSize(Size::Ceil(texture->GetSize()));
return contents;
};
return;
diff --git a/impeller/display_list/display_list_unittests.cc b/impeller/display_list/display_list_unittests.cc
index 20e5e0c..a9e23ef 100644
--- a/impeller/display_list/display_list_unittests.cc
+++ b/impeller/display_list/display_list_unittests.cc
@@ -1151,6 +1151,60 @@
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
+TEST_P(DisplayListTest, DrawVerticesLinearGradientWithTextureCoordinates) {
+ std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
+ SkPoint::Make(200, 100),
+ SkPoint::Make(300, 300)};
+ std::vector<SkPoint> texture_coordinates = {SkPoint::Make(300, 100),
+ SkPoint::Make(100, 200),
+ SkPoint::Make(300, 300)};
+
+ auto vertices = flutter::DlVertices::Make(
+ flutter::DlVertexMode::kTriangles, 3, positions.data(),
+ texture_coordinates.data(), /*colors=*/nullptr);
+
+ std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
+ flutter::DlColor::kRed()};
+ const float stops[2] = {0.0, 1.0};
+
+ auto linear = flutter::DlColorSource::MakeLinear(
+ {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
+ flutter::DlTileMode::kRepeat);
+
+ flutter::DisplayListBuilder builder;
+ flutter::DlPaint paint;
+
+ paint.setColorSource(linear);
+ builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
+
+ ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
+}
+
+TEST_P(DisplayListTest, DrawVerticesImageSourceWithTextureCoordinates) {
+ auto texture = CreateTextureForFixture("embarcadero.jpg");
+ auto dl_image = DlImageImpeller::Make(texture);
+ std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
+ SkPoint::Make(200, 100),
+ SkPoint::Make(300, 300)};
+ std::vector<SkPoint> texture_coordinates = {
+ SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
+
+ auto vertices = flutter::DlVertices::Make(
+ flutter::DlVertexMode::kTriangles, 3, positions.data(),
+ texture_coordinates.data(), /*colors=*/nullptr);
+
+ flutter::DisplayListBuilder builder;
+ flutter::DlPaint paint;
+
+ auto image_source = flutter::DlImageColorSource(
+ dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
+
+ paint.setColorSource(&image_source);
+ builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
+
+ ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
+}
+
TEST_P(DisplayListTest, DrawVerticesSolidColorTrianglesWithIndices) {
std::vector<SkPoint> positions = {
SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
diff --git a/impeller/display_list/display_list_vertices_geometry.cc b/impeller/display_list/display_list_vertices_geometry.cc
index 52caeea..1966229 100644
--- a/impeller/display_list/display_list_vertices_geometry.cc
+++ b/impeller/display_list/display_list_vertices_geometry.cc
@@ -7,6 +7,7 @@
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/entity.h"
#include "impeller/entity/position_color.vert.h"
+#include "impeller/entity/texture_fill.vert.h"
#include "impeller/geometry/matrix.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/geometry/point.h"
@@ -100,10 +101,38 @@
}
}
+std::optional<Rect> DLVerticesGeometry::GetTextureCoordinateCoverge() const {
+ if (!HasTextureCoordinates()) {
+ return std::nullopt;
+ }
+ auto vertex_count = vertices_->vertex_count();
+ auto* dl_texture_coordinates = vertices_->texture_coordinates();
+ if (vertex_count == 0) {
+ return std::nullopt;
+ }
+
+ auto left = dl_texture_coordinates[0].x();
+ auto top = dl_texture_coordinates[0].y();
+ auto right = dl_texture_coordinates[0].x();
+ auto bottom = dl_texture_coordinates[0].y();
+
+ for (auto i = 0; i < vertex_count; i++) {
+ left = std::min(left, dl_texture_coordinates[i].x());
+ top = std::min(top, dl_texture_coordinates[i].y());
+ right = std::max(right, dl_texture_coordinates[i].x());
+ bottom = std::max(bottom, dl_texture_coordinates[i].y());
+ }
+ return Rect::MakeLTRB(left, top, right, bottom);
+}
+
bool DLVerticesGeometry::HasVertexColors() const {
return vertices_->colors() != nullptr;
}
+bool DLVerticesGeometry::HasTextureCoordinates() const {
+ return vertices_->texture_coordinates() != nullptr;
+}
+
GeometryResult DLVerticesGeometry::GetPositionBuffer(
const ContentContext& renderer,
const Entity& entity,
@@ -225,12 +254,80 @@
}
GeometryResult DLVerticesGeometry::GetPositionUVBuffer(
+ Rect texture_coverage,
+ Matrix effect_transform,
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) {
- // TODO(jonahwilliams): support texture coordinates in vertices
- // https://github.com/flutter/flutter/issues/109956
- return {};
+ using VS = TexturePipeline::VertexShader;
+
+ auto index_count = normalized_indices_.size() == 0
+ ? vertices_->index_count()
+ : normalized_indices_.size();
+ auto vertex_count = vertices_->vertex_count();
+ auto* dl_indices = normalized_indices_.size() == 0
+ ? vertices_->indices()
+ : normalized_indices_.data();
+ auto* dl_vertices = vertices_->vertices();
+ auto* dl_texture_coordinates = vertices_->texture_coordinates();
+
+ auto size = texture_coverage.size;
+ auto origin = texture_coverage.origin;
+ std::vector<VS::PerVertexData> vertex_data(vertex_count);
+ {
+ for (auto i = 0; i < vertex_count; i++) {
+ auto sk_point = dl_vertices[i];
+ auto texture_coord = dl_texture_coordinates[i];
+ auto uv = effect_transform *
+ Point((texture_coord.x() - origin.x) / size.width,
+ (texture_coord.y() - origin.y) / size.height);
+ // From experimentation we need to clamp these values to < 1.0 or else
+ // there can be flickering.
+ vertex_data[i] = {
+ .position = Point(sk_point.x(), sk_point.y()),
+ .texture_coords =
+ Point(std::clamp(uv.x, 0.0f, 1.0f - kEhCloseEnough),
+ std::clamp(uv.y, 0.0f, 1.0f - kEhCloseEnough)),
+ };
+ }
+ }
+
+ size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData);
+ size_t total_idx_bytes = index_count * sizeof(uint16_t);
+
+ DeviceBufferDescriptor buffer_desc;
+ buffer_desc.size = total_vtx_bytes + total_idx_bytes;
+ buffer_desc.storage_mode = StorageMode::kHostVisible;
+
+ auto buffer =
+ renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc);
+
+ if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(vertex_data.data()),
+ Range{0, total_vtx_bytes}, 0)) {
+ return {};
+ }
+ if (!buffer->CopyHostBuffer(
+ reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(dl_indices)),
+ Range{0, total_idx_bytes}, total_vtx_bytes)) {
+ return {};
+ }
+
+ return GeometryResult{
+ .type = GetPrimitiveType(vertices_),
+ .vertex_buffer =
+ {
+ .vertex_buffer = {.buffer = buffer,
+ .range = Range{0, total_vtx_bytes}},
+ .index_buffer = {.buffer = buffer,
+ .range =
+ Range{total_vtx_bytes, total_idx_bytes}},
+ .index_count = index_count,
+ .index_type = IndexType::k16bit,
+ },
+ .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
+ entity.GetTransformation(),
+ .prevent_overdraw = false,
+ };
}
GeometryVertexType DLVerticesGeometry::GetVertexType() const {
@@ -238,6 +335,11 @@
if (dl_colors != nullptr) {
return GeometryVertexType::kColor;
}
+ auto* dl_texture_coordinates = vertices_->texture_coordinates();
+ if (dl_texture_coordinates != nullptr) {
+ return GeometryVertexType::kUV;
+ }
+
return GeometryVertexType::kPosition;
}
diff --git a/impeller/display_list/display_list_vertices_geometry.h b/impeller/display_list/display_list_vertices_geometry.h
index 3ebfa89..9a668f9 100644
--- a/impeller/display_list/display_list_vertices_geometry.h
+++ b/impeller/display_list/display_list_vertices_geometry.h
@@ -32,7 +32,9 @@
RenderPass& pass) override;
// |VerticesGeometry|
- GeometryResult GetPositionUVBuffer(const ContentContext& renderer,
+ GeometryResult GetPositionUVBuffer(Rect texture_coverage,
+ Matrix effect_transform,
+ const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) override;
@@ -50,6 +52,12 @@
// |VerticesGeometry|
bool HasVertexColors() const override;
+ // |VerticesGeometry|
+ bool HasTextureCoordinates() const override;
+
+ // |VerticesGeometry|
+ std::optional<Rect> GetTextureCoordinateCoverge() const override;
+
private:
void NormalizeIndices();
diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc
index 2799a91..fda3198 100644
--- a/impeller/entity/contents/content_context.cc
+++ b/impeller/entity/contents/content_context.cc
@@ -250,6 +250,8 @@
texture_blend_pipelines_[{}] =
CreateDefaultPipeline<BlendPipeline>(*context_);
texture_pipelines_[{}] = CreateDefaultPipeline<TexturePipeline>(*context_);
+ position_uv_pipelines_[{}] =
+ CreateDefaultPipeline<PositionUVPipeline>(*context_);
tiled_texture_pipelines_[{}] =
CreateDefaultPipeline<TiledTexturePipeline>(*context_);
gaussian_blur_pipelines_[{}] =
diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h
index 65bd2a0..c5a5788 100644
--- a/impeller/entity/contents/content_context.h
+++ b/impeller/entity/contents/content_context.h
@@ -54,7 +54,6 @@
#include "impeller/entity/position.vert.h"
#include "impeller/entity/position_color.vert.h"
-#include "impeller/entity/position_uv.vert.h"
#include "impeller/scene/scene_context.h"
#include "impeller/typographer/glyph_atlas.h"
@@ -123,6 +122,8 @@
using BlendPipeline = RenderPipelineT<BlendVertexShader, BlendFragmentShader>;
using TexturePipeline =
RenderPipelineT<TextureFillVertexShader, TextureFillFragmentShader>;
+using PositionUVPipeline =
+ RenderPipelineT<TextureFillVertexShader, TiledTextureFillFragmentShader>;
using TiledTexturePipeline = RenderPipelineT<TiledTextureFillVertexShader,
TiledTextureFillFragmentShader>;
using GaussianBlurPipeline =
@@ -362,6 +363,11 @@
return GetPipeline(texture_pipelines_, opts);
}
+ std::shared_ptr<Pipeline<PipelineDescriptor>> GetPositionUVPipeline(
+ ContentContextOptions opts) const {
+ return GetPipeline(position_uv_pipelines_, opts);
+ }
+
std::shared_ptr<Pipeline<PipelineDescriptor>> GetTiledTexturePipeline(
ContentContextOptions opts) const {
return GetPipeline(tiled_texture_pipelines_, opts);
@@ -626,6 +632,7 @@
mutable Variants<RRectBlurPipeline> rrect_blur_pipelines_;
mutable Variants<BlendPipeline> texture_blend_pipelines_;
mutable Variants<TexturePipeline> texture_pipelines_;
+ mutable Variants<PositionUVPipeline> position_uv_pipelines_;
mutable Variants<TiledTexturePipeline> tiled_texture_pipelines_;
mutable Variants<GaussianBlurPipeline> gaussian_blur_pipelines_;
mutable Variants<GaussianBlurDecalPipeline> gaussian_blur_decal_pipelines_;
diff --git a/impeller/entity/contents/contents.h b/impeller/entity/contents/contents.h
index 2c5f3ab..a4ff06b 100644
--- a/impeller/entity/contents/contents.h
+++ b/impeller/entity/contents/contents.h
@@ -75,9 +75,19 @@
virtual bool ShouldRender(const Entity& entity,
const std::optional<Rect>& stencil_coverage) const;
+ /// @brief Return the color source's intrinsic size, if available.
+ ///
+ /// For example, a gradient has a size based on its end and beginning points,
+ /// ignoring any tiling. Solid colors and runtime effects have no size.
+ std::optional<Size> ColorSourceSize() const { return color_source_size_; }
+
+ void SetColorSourceSize(Size size) { color_source_size_ = size; }
+
protected:
private:
+ std::optional<Size> color_source_size_;
+
FML_DISALLOW_COPY_AND_ASSIGN(Contents);
};
diff --git a/impeller/entity/contents/tiled_texture_contents.cc b/impeller/entity/contents/tiled_texture_contents.cc
index d50af65..d9e8a80 100644
--- a/impeller/entity/contents/tiled_texture_contents.cc
+++ b/impeller/entity/contents/tiled_texture_contents.cc
@@ -56,6 +56,13 @@
if (texture_ == nullptr) {
return true;
}
+ // TODO(jonahwilliams): this is a special case for VerticesGeometry which
+ // implements GetPositionUVBuffer. The general geometry case does not use
+ // this method (see note below).
+ auto geometry = GetGeometry();
+ if (geometry->GetVertexType() == GeometryVertexType::kUV) {
+ return RenderVertices(renderer, entity, pass);
+ }
using VS = TiledTextureFillVertexShader;
using FS = TiledTextureFillFragmentShader;
@@ -67,7 +74,6 @@
auto& host_buffer = pass.GetTransientsBuffer();
- auto geometry = GetGeometry();
auto geometry_result =
GetGeometry()->GetPositionBuffer(renderer, entity, pass);
@@ -132,4 +138,72 @@
return true;
}
+bool TiledTextureContents::RenderVertices(const ContentContext& renderer,
+ const Entity& entity,
+ RenderPass& pass) const {
+ using VS = PositionUVPipeline::VertexShader;
+ using FS = PositionUVPipeline::FragmentShader;
+
+ const auto texture_size = texture_->GetSize();
+ if (texture_size.IsEmpty()) {
+ return true;
+ }
+
+ auto& host_buffer = pass.GetTransientsBuffer();
+
+ auto geometry_result = GetGeometry()->GetPositionUVBuffer(
+ Rect::MakeSize(texture_size), GetInverseMatrix(), renderer, entity, pass);
+
+ VS::FrameInfo frame_info;
+ frame_info.mvp = geometry_result.transform;
+
+ 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_);
+ frag_info.alpha = GetAlpha();
+
+ Command cmd;
+ cmd.label = "PositionUV";
+ cmd.stencil_reference = entity.GetStencilDepth();
+
+ auto options = OptionsFromPassAndEntity(pass, entity);
+ if (geometry_result.prevent_overdraw) {
+ options.stencil_compare = CompareFunction::kEqual;
+ options.stencil_operation = StencilOperation::kIncrementClamp;
+ }
+ options.primitive_type = geometry_result.type;
+ cmd.pipeline = renderer.GetPositionUVPipeline(options);
+
+ cmd.BindVertices(geometry_result.vertex_buffer);
+ VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
+ FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
+ if (color_filter_.has_value()) {
+ auto filtered_texture = CreateFilterTexture(renderer);
+ if (!filtered_texture.has_value()) {
+ return false;
+ }
+ FS::BindTextureSampler(
+ cmd, filtered_texture.value(),
+ renderer.GetContext()->GetSamplerLibrary()->GetSampler(
+ sampler_descriptor_));
+ } else {
+ FS::BindTextureSampler(
+ cmd, texture_,
+ renderer.GetContext()->GetSamplerLibrary()->GetSampler(
+ sampler_descriptor_));
+ }
+
+ if (!pass.AddCommand(std::move(cmd))) {
+ return false;
+ }
+
+ if (geometry_result.prevent_overdraw) {
+ auto restore = ClipRestoreContents();
+ restore.SetRestoreCoverage(GetCoverage(entity));
+ return restore.Render(renderer, entity, pass);
+ }
+ return true;
+}
+
} // namespace impeller
diff --git a/impeller/entity/contents/tiled_texture_contents.h b/impeller/entity/contents/tiled_texture_contents.h
index f1db94f..0f0c6b3 100644
--- a/impeller/entity/contents/tiled_texture_contents.h
+++ b/impeller/entity/contents/tiled_texture_contents.h
@@ -53,6 +53,10 @@
std::optional<std::shared_ptr<Texture>> CreateFilterTexture(
const ContentContext& renderer) const;
+ bool RenderVertices(const ContentContext& renderer,
+ const Entity& entity,
+ RenderPass& pass) const;
+
std::shared_ptr<Texture> texture_;
SamplerDescriptor sampler_descriptor_ = {};
Entity::TileMode x_tile_mode_ = Entity::TileMode::kClamp;
diff --git a/impeller/entity/contents/vertices_contents.cc b/impeller/entity/contents/vertices_contents.cc
index a7b6c0d..de2954b 100644
--- a/impeller/entity/contents/vertices_contents.cc
+++ b/impeller/entity/contents/vertices_contents.cc
@@ -10,7 +10,6 @@
#include "impeller/entity/contents/texture_contents.h"
#include "impeller/entity/position.vert.h"
#include "impeller/entity/position_color.vert.h"
-#include "impeller/entity/position_uv.vert.h"
#include "impeller/entity/vertices.frag.h"
#include "impeller/geometry/color.h"
#include "impeller/renderer/formats.h"
@@ -48,23 +47,101 @@
blend_mode_ = blend_mode;
}
+const std::shared_ptr<Contents>& VerticesContents::GetSourceContents() const {
+ return src_contents_;
+}
+
bool VerticesContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
if (blend_mode_ == BlendMode::kClear) {
return true;
}
+ std::shared_ptr<Contents> src_contents = src_contents_;
+ if (geometry_->HasTextureCoordinates()) {
+ auto contents = std::make_shared<VerticesUVContents>(*this);
+ if (!geometry_->HasVertexColors()) {
+ contents->SetAlpha(alpha_);
+ return contents->Render(renderer, entity, pass);
+ }
+ src_contents = contents;
+ }
+
auto dst_contents = std::make_shared<VerticesColorContents>(*this);
auto contents = ColorFilterContents::MakeBlend(
blend_mode_, {FilterInput::Make(dst_contents, false),
- FilterInput::Make(src_contents_, false)});
+ FilterInput::Make(src_contents, false)});
contents->SetAlpha(alpha_);
return contents->Render(renderer, entity, pass);
}
//------------------------------------------------------
+// VerticesUVContents
+
+VerticesUVContents::VerticesUVContents(const VerticesContents& parent)
+ : parent_(parent) {}
+
+VerticesUVContents::~VerticesUVContents() {}
+
+std::optional<Rect> VerticesUVContents::GetCoverage(
+ const Entity& entity) const {
+ return parent_.GetCoverage(entity);
+}
+
+void VerticesUVContents::SetAlpha(Scalar alpha) {
+ alpha_ = alpha;
+}
+
+bool VerticesUVContents::Render(const ContentContext& renderer,
+ const Entity& entity,
+ RenderPass& pass) const {
+ using VS = TexturePipeline::VertexShader;
+ using FS = TexturePipeline::FragmentShader;
+
+ auto src_contents = parent_.GetSourceContents();
+
+ auto snapshot = src_contents->RenderToSnapshot(renderer, entity);
+ if (!snapshot.has_value()) {
+ return false;
+ }
+
+ Command cmd;
+ cmd.label = "VerticesUV";
+ auto& host_buffer = pass.GetTransientsBuffer();
+ auto geometry = parent_.GetGeometry();
+
+ auto coverage = src_contents->GetCoverage(Entity{});
+ if (!coverage.has_value()) {
+ return false;
+ }
+ auto geometry_result = geometry->GetPositionUVBuffer(
+ coverage.value(), Matrix(), renderer, entity, pass);
+ auto opts = OptionsFromPassAndEntity(pass, entity);
+ opts.primitive_type = geometry_result.type;
+ cmd.pipeline = renderer.GetTexturePipeline(opts);
+ cmd.stencil_reference = entity.GetStencilDepth();
+ cmd.BindVertices(geometry_result.vertex_buffer);
+
+ VS::FrameInfo frame_info;
+ frame_info.mvp = geometry_result.transform;
+ frame_info.texture_sampler_y_coord_scale =
+ snapshot->texture->GetYCoordScale();
+ VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
+
+ FS::FragInfo frag_info;
+ frag_info.alpha = alpha_ * snapshot->opacity;
+ FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
+
+ FS::BindTextureSampler(cmd, snapshot->texture,
+ renderer.GetContext()->GetSamplerLibrary()->GetSampler(
+ snapshot->sampler_descriptor));
+
+ return pass.AddCommand(std::move(cmd));
+}
+
+//------------------------------------------------------
// VerticesColorContents
VerticesColorContents::VerticesColorContents(const VerticesContents& parent)
@@ -72,7 +149,6 @@
VerticesColorContents::~VerticesColorContents() {}
-// |Contents|
std::optional<Rect> VerticesColorContents::GetCoverage(
const Entity& entity) const {
return parent_.GetCoverage(entity);
@@ -82,7 +158,6 @@
alpha_ = alpha;
}
-// |Contents|
bool VerticesColorContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
@@ -99,6 +174,7 @@
auto opts = OptionsFromPassAndEntity(pass, entity);
opts.primitive_type = geometry_result.type;
cmd.pipeline = renderer.GetGeometryColorPipeline(opts);
+ cmd.stencil_reference = entity.GetStencilDepth();
cmd.BindVertices(geometry_result.vertex_buffer);
VS::FrameInfo frame_info;
diff --git a/impeller/entity/contents/vertices_contents.h b/impeller/entity/contents/vertices_contents.h
index b2459d5..88facd3 100644
--- a/impeller/entity/contents/vertices_contents.h
+++ b/impeller/entity/contents/vertices_contents.h
@@ -35,6 +35,8 @@
std::shared_ptr<VerticesGeometry> GetGeometry() const;
+ const std::shared_ptr<Contents>& GetSourceContents() const;
+
// |Contents|
std::optional<Rect> GetCoverage(const Entity& entity) const override;
@@ -75,4 +77,27 @@
FML_DISALLOW_COPY_AND_ASSIGN(VerticesColorContents);
};
+class VerticesUVContents final : public Contents {
+ public:
+ explicit VerticesUVContents(const VerticesContents& parent);
+
+ ~VerticesUVContents() override;
+
+ // |Contents|
+ std::optional<Rect> GetCoverage(const Entity& entity) const override;
+
+ // |Contents|
+ bool Render(const ContentContext& renderer,
+ const Entity& entity,
+ RenderPass& pass) const override;
+
+ void SetAlpha(Scalar alpha);
+
+ private:
+ const VerticesContents& parent_;
+ Scalar alpha_ = 1.0;
+
+ FML_DISALLOW_COPY_AND_ASSIGN(VerticesUVContents);
+};
+
} // namespace impeller
diff --git a/impeller/entity/geometry.cc b/impeller/entity/geometry.cc
index c86eaa6..b610e03 100644
--- a/impeller/entity/geometry.cc
+++ b/impeller/entity/geometry.cc
@@ -17,6 +17,14 @@
Geometry::~Geometry() = default;
+GeometryResult Geometry::GetPositionUVBuffer(Rect texture_coverage,
+ Matrix effect_transform,
+ const ContentContext& renderer,
+ const Entity& entity,
+ RenderPass& pass) {
+ return {};
+}
+
// static
std::unique_ptr<Geometry> Geometry::MakeFillPath(const Path& path) {
return std::make_unique<FillPathGeometry>(path);
diff --git a/impeller/entity/geometry.h b/impeller/entity/geometry.h
index f595eee..edc59cd 100644
--- a/impeller/entity/geometry.h
+++ b/impeller/entity/geometry.h
@@ -65,6 +65,12 @@
const Entity& entity,
RenderPass& pass) = 0;
+ virtual GeometryResult GetPositionUVBuffer(Rect texture_coverage,
+ Matrix effect_transform,
+ const ContentContext& renderer,
+ const Entity& entity,
+ RenderPass& pass);
+
virtual GeometryVertexType GetVertexType() const = 0;
virtual std::optional<Rect> GetCoverage(const Matrix& transform) const = 0;
@@ -77,11 +83,11 @@
const Entity& entity,
RenderPass& pass) = 0;
- virtual GeometryResult GetPositionUVBuffer(const ContentContext& renderer,
- const Entity& entity,
- RenderPass& pass) = 0;
-
virtual bool HasVertexColors() const = 0;
+
+ virtual bool HasTextureCoordinates() const = 0;
+
+ virtual std::optional<Rect> GetTextureCoordinateCoverge() const = 0;
};
/// @brief A geometry that is created from a filled path object.