Revert "Revert "[Impeller] Correctly compute UVs in texture fill" (#43087)"
This reverts commit 218fae168360233ce8ad05910e97d78928f55a96.
diff --git a/impeller/aiks/paint_pass_delegate.cc b/impeller/aiks/paint_pass_delegate.cc
index 019a676..b46d270 100644
--- a/impeller/aiks/paint_pass_delegate.cc
+++ b/impeller/aiks/paint_pass_delegate.cc
@@ -4,6 +4,8 @@
#include "impeller/aiks/paint_pass_delegate.h"
+#include "impeller/core/formats.h"
+#include "impeller/core/sampler_descriptor.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/contents/texture_contents.h"
#include "impeller/entity/entity_pass.h"
@@ -46,6 +48,13 @@
contents->SetSourceRect(Rect::MakeSize(target->GetSize()));
contents->SetOpacity(paint_.color.alpha);
contents->SetDeferApplyingOpacity(true);
+
+ SamplerDescriptor sampler_desc;
+ sampler_desc.label = "Subpass";
+ sampler_desc.width_address_mode = SamplerAddressMode::kDecal;
+ sampler_desc.height_address_mode = SamplerAddressMode::kDecal;
+ contents->SetSamplerDescriptor(sampler_desc);
+
return paint_.WithFiltersForSubpassTarget(std::move(contents),
effect_transform);
}
@@ -140,6 +149,13 @@
contents->SetSourceRect(Rect::MakeSize(target->GetSize()));
contents->SetOpacity(paint_.color.alpha);
contents->SetDeferApplyingOpacity(true);
+
+ SamplerDescriptor sampler_desc;
+ sampler_desc.label = "Subpass";
+ sampler_desc.width_address_mode = SamplerAddressMode::kDecal;
+ sampler_desc.height_address_mode = SamplerAddressMode::kDecal;
+ contents->SetSamplerDescriptor(sampler_desc);
+
return paint_.WithFiltersForSubpassTarget(std::move(contents),
effect_transform);
}
diff --git a/impeller/entity/contents/texture_contents.cc b/impeller/entity/contents/texture_contents.cc
index 90b3e15..553d53c 100644
--- a/impeller/entity/contents/texture_contents.cc
+++ b/impeller/entity/contents/texture_contents.cc
@@ -26,7 +26,7 @@
std::shared_ptr<TextureContents> TextureContents::MakeRect(Rect destination) {
auto contents = std::make_shared<TextureContents>();
- contents->rect_ = destination;
+ contents->destination_rect_ = destination;
return contents;
}
@@ -34,8 +34,8 @@
label_ = std::move(label);
}
-void TextureContents::SetRect(Rect rect) {
- rect_ = rect;
+void TextureContents::SetDestinationRect(Rect rect) {
+ destination_rect_ = rect;
}
void TextureContents::SetTexture(std::shared_ptr<Texture> texture) {
@@ -70,7 +70,7 @@
if (GetOpacity() == 0) {
return std::nullopt;
}
- return rect_.TransformBounds(entity.GetTransformation());
+ return destination_rect_.TransformBounds(entity.GetTransformation());
};
std::optional<Snapshot> TextureContents::RenderToSnapshot(
@@ -82,7 +82,7 @@
const std::string& label) const {
// Passthrough textures that have simple rectangle paths and complete source
// rects.
- auto bounds = rect_;
+ auto bounds = destination_rect_;
auto opacity = GetOpacity();
if (source_rect_ == Rect::MakeSize(texture_->GetSize()) &&
(opacity >= 1 - kEhCloseEnough || defer_applying_opacity_)) {
@@ -104,37 +104,30 @@
label); // label
}
-static TextureFillVertexShader::PerVertexData ComputeVertexData(
- const Point& position,
- const Rect& coverage_rect,
- const ISize& texture_size,
- const Rect& source_rect) {
- TextureFillVertexShader::PerVertexData data;
- data.position = position;
- auto coverage_coords = (position - coverage_rect.origin) / coverage_rect.size;
- data.texture_coords =
- (source_rect.origin + source_rect.size * coverage_coords) / texture_size;
- return data;
-}
-
bool TextureContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
using VS = TextureFillVertexShader;
using FS = TextureFillFragmentShader;
- const auto coverage_rect = rect_;
-
- if (coverage_rect.size.IsEmpty() || source_rect_.IsEmpty() ||
+ if (destination_rect_.size.IsEmpty() || source_rect_.IsEmpty() ||
texture_ == nullptr || texture_->GetSize().IsEmpty()) {
- return true;
+ return true; // Nothing to render.
}
+ // Expand the source rect by half a texel, which aligns sampled texels to the
+ // pixel grid if the source rect is the same size as the destination rect.
+ auto texture_coords =
+ Rect::MakeSize(texture_->GetSize()).Project(source_rect_.Expand(0.5));
+
VertexBufferBuilder<VS::PerVertexData> vertex_builder;
- for (const auto position : rect_.GetPoints()) {
- vertex_builder.AppendVertex(ComputeVertexData(
- position, coverage_rect, texture_->GetSize(), source_rect_));
- }
+
+ vertex_builder.AddVertices({
+ {destination_rect_.GetLeftTop(), texture_coords.GetLeftTop()},
+ {destination_rect_.GetRightTop(), texture_coords.GetRightTop()},
+ {destination_rect_.GetLeftBottom(), texture_coords.GetLeftBottom()},
+ {destination_rect_.GetRightBottom(), texture_coords.GetRightBottom()},
+ });
auto& host_buffer = pass.GetTransientsBuffer();
diff --git a/impeller/entity/contents/texture_contents.h b/impeller/entity/contents/texture_contents.h
index 567e95a..4da57c1 100644
--- a/impeller/entity/contents/texture_contents.h
+++ b/impeller/entity/contents/texture_contents.h
@@ -30,7 +30,7 @@
void SetLabel(std::string label);
- void SetRect(Rect rect);
+ void SetDestinationRect(Rect rect);
void SetTexture(std::shared_ptr<Texture> texture);
@@ -78,7 +78,7 @@
private:
std::string label_;
- Rect rect_;
+ Rect destination_rect_;
bool stencil_enabled_ = true;
std::shared_ptr<Texture> texture_;
diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc
index 65ceaf2..6c88a45 100644
--- a/impeller/entity/entity_unittests.cc
+++ b/impeller/entity/entity_unittests.cc
@@ -1069,7 +1069,7 @@
if (selected_input_type == 0) {
auto texture = std::make_shared<TextureContents>();
texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
- texture->SetRect(input_rect);
+ texture->SetDestinationRect(input_rect);
texture->SetTexture(boston);
texture->SetOpacity(input_color.alpha);
@@ -1192,7 +1192,7 @@
Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
auto texture = std::make_shared<TextureContents>();
texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
- texture->SetRect(input_rect);
+ texture->SetDestinationRect(input_rect);
texture->SetTexture(boston);
texture->SetOpacity(input_color.alpha);
diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc
index 11a5706..3a123c6 100644
--- a/impeller/geometry/geometry_unittests.cc
+++ b/impeller/geometry/geometry_unittests.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "gtest/gtest.h"
#include "impeller/geometry/geometry_asserts.h"
#include <limits>
@@ -2142,6 +2143,20 @@
}
}
+TEST(GeometryTest, RectDirections) {
+ auto r = Rect::MakeLTRB(1, 2, 3, 4);
+
+ ASSERT_EQ(r.GetLeft(), 1);
+ ASSERT_EQ(r.GetTop(), 2);
+ ASSERT_EQ(r.GetRight(), 3);
+ ASSERT_EQ(r.GetBottom(), 4);
+
+ ASSERT_POINT_NEAR(r.GetLeftTop(), Point(1, 2));
+ ASSERT_POINT_NEAR(r.GetRightTop(), Point(3, 2));
+ ASSERT_POINT_NEAR(r.GetLeftBottom(), Point(1, 4));
+ ASSERT_POINT_NEAR(r.GetRightBottom(), Point(3, 4));
+}
+
TEST(GeometryTest, RectProject) {
{
auto r = Rect::MakeLTRB(-100, -100, 100, 100);
diff --git a/impeller/geometry/rect.h b/impeller/geometry/rect.h
index 7a2c18b..0bda614 100644
--- a/impeller/geometry/rect.h
+++ b/impeller/geometry/rect.h
@@ -162,6 +162,16 @@
return std::max(origin.y, origin.y + size.height);
}
+ constexpr TPoint<T> GetLeftTop() const { return {GetLeft(), GetTop()}; }
+
+ constexpr TPoint<T> GetRightTop() const { return {GetRight(), GetTop()}; }
+
+ constexpr TPoint<T> GetLeftBottom() const { return {GetLeft(), GetBottom()}; }
+
+ constexpr TPoint<T> GetRightBottom() const {
+ return {GetRight(), GetBottom()};
+ }
+
constexpr std::array<T, 4> GetLTRB() const {
return {GetLeft(), GetTop(), GetRight(), GetBottom()};
}