mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Impeller] Compute UV coordinates lazily in PositionUVWriter (flutter/engine#50879)
The stroking code was performing texture coordinate conversion on each created vertex. Since there were often very few calculations needed for each vertex, interspersing a coordinate transform with each vertex append was clogging up the code. This change will defer the calculation of the texture coordinates until the end of the stroking process so that the polyline widening code can do its job efficiently and then later the coordinate conversion code can do its job also efficiently in a tight loop. This change also opened up the opportunity to optimize a common case (no effect transform) even more than before.
This commit is contained in:
parent
68c773fb26
commit
4aa93cbf61
@ -165,6 +165,26 @@ TEST(EntityGeometryTest, StrokePathGeometryTransformOfLine) {
|
||||
|
||||
EXPECT_SOLID_VERTICES_NEAR(vertices, expected);
|
||||
|
||||
{
|
||||
auto uv_vertices =
|
||||
ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVerticesUV(
|
||||
polyline, 10.0f, 10.0f, Join::kBevel, Cap::kButt, 1.0, //
|
||||
Point(50.0f, 40.0f), Size(20.0f, 40.0f), Matrix());
|
||||
// uvx = (x - 50) / 20
|
||||
// uvy = (y - 40) / 40
|
||||
auto uv = [](const Point& p) {
|
||||
return Point((p.x - 50.0f) / 20.0f, //
|
||||
(p.y - 40.0f) / 40.0f);
|
||||
};
|
||||
std::vector<TextureFillVertexShader::PerVertexData> uv_expected;
|
||||
for (size_t i = 0; i < expected.size(); i++) {
|
||||
auto p = expected[i].position;
|
||||
uv_expected.push_back({.position = p, .texture_coords = uv(p)});
|
||||
}
|
||||
|
||||
EXPECT_TEXTURE_VERTICES_NEAR(uv_vertices, uv_expected);
|
||||
}
|
||||
|
||||
{
|
||||
auto uv_vertices =
|
||||
ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVerticesUV(
|
||||
|
||||
@ -47,27 +47,45 @@ class PositionWriter {
|
||||
|
||||
class PositionUVWriter {
|
||||
public:
|
||||
PositionUVWriter(Point texture_origin,
|
||||
Size texture_coverage,
|
||||
PositionUVWriter(const Point& texture_origin,
|
||||
const Size& texture_size,
|
||||
const Matrix& effect_transform)
|
||||
: uv_transform_(Matrix::MakeScale(1 / texture_coverage) *
|
||||
Matrix::MakeTranslation(-texture_origin) *
|
||||
effect_transform) {}
|
||||
: texture_origin_(texture_origin),
|
||||
texture_size_(texture_size),
|
||||
effect_transform_(effect_transform) {}
|
||||
|
||||
const std::vector<TextureFillVertexShader::PerVertexData>& GetData() const {
|
||||
const std::vector<TextureFillVertexShader::PerVertexData>& GetData() {
|
||||
if (effect_transform_.IsIdentity()) {
|
||||
auto origin = texture_origin_;
|
||||
auto scale = 1.0 / texture_size_;
|
||||
|
||||
for (auto& pvd : data_) {
|
||||
pvd.texture_coords = (pvd.position - origin) * scale;
|
||||
}
|
||||
} else {
|
||||
auto texture_rect = Rect::MakeOriginSize(texture_origin_, texture_size_);
|
||||
Matrix uv_transform =
|
||||
texture_rect.GetNormalizingTransform() * effect_transform_;
|
||||
|
||||
for (auto& pvd : data_) {
|
||||
pvd.texture_coords = uv_transform * pvd.position;
|
||||
}
|
||||
}
|
||||
return data_;
|
||||
}
|
||||
|
||||
void AppendVertex(const Point& point) {
|
||||
data_.emplace_back(TextureFillVertexShader::PerVertexData{
|
||||
.position = point,
|
||||
.texture_coords = uv_transform_ * point,
|
||||
// .texture_coords = default, will be filled in during |GetData()|
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<TextureFillVertexShader::PerVertexData> data_ = {};
|
||||
const Matrix uv_transform_;
|
||||
const Point texture_origin_;
|
||||
const Size texture_size_;
|
||||
const Matrix effect_transform_;
|
||||
};
|
||||
|
||||
template <typename VertexWriter>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user