diff --git a/engine/src/flutter/impeller/display_list/canvas.cc b/engine/src/flutter/impeller/display_list/canvas.cc index ea7c667a17..eae343d2fc 100644 --- a/engine/src/flutter/impeller/display_list/canvas.cc +++ b/engine/src/flutter/impeller/display_list/canvas.cc @@ -638,7 +638,8 @@ void Canvas::ClipGeometry(const Geometry& geometry, clip_depth); } -void Canvas::DrawPoints(std::vector points, +void Canvas::DrawPoints(const Point points[], + uint32_t count, Scalar radius, const Paint& paint, PointStyle point_style) { @@ -650,7 +651,7 @@ void Canvas::DrawPoints(std::vector points, entity.SetTransform(GetCurrentTransform()); entity.SetBlendMode(paint.blend_mode); - PointFieldGeometry geom(std::move(points), radius, + PointFieldGeometry geom(points, count, radius, /*round=*/point_style == PointStyle::kRound); AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint); } diff --git a/engine/src/flutter/impeller/display_list/canvas.h b/engine/src/flutter/impeller/display_list/canvas.h index 0ce1c63808..fbb4a8bb0a 100644 --- a/engine/src/flutter/impeller/display_list/canvas.h +++ b/engine/src/flutter/impeller/display_list/canvas.h @@ -200,7 +200,8 @@ class Canvas { void DrawCircle(const Point& center, Scalar radius, const Paint& paint); - void DrawPoints(std::vector points, + void DrawPoints(const Point points[], + uint32_t count, Scalar radius, const Paint& paint, PointStyle point_style); diff --git a/engine/src/flutter/impeller/display_list/dl_dispatcher.cc b/engine/src/flutter/impeller/display_list/dl_dispatcher.cc index 47685d929d..1bdad62aff 100644 --- a/engine/src/flutter/impeller/display_list/dl_dispatcher.cc +++ b/engine/src/flutter/impeller/display_list/dl_dispatcher.cc @@ -27,7 +27,6 @@ #include "impeller/entity/entity.h" #include "impeller/entity/geometry/ellipse_geometry.h" #include "impeller/entity/geometry/fill_path_geometry.h" -#include "impeller/entity/geometry/geometry.h" #include "impeller/entity/geometry/rect_geometry.h" #include "impeller/entity/geometry/round_rect_geometry.h" #include "impeller/geometry/color.h" @@ -663,14 +662,14 @@ void DlDispatcherBase::drawPoints(PointMode mode, switch (mode) { case flutter::DlCanvas::PointMode::kPoints: { // Cap::kButt is also treated as a square. - auto point_style = paint.stroke_cap == Cap::kRound ? PointStyle::kRound - : PointStyle::kSquare; - auto radius = paint.stroke_width; + PointStyle point_style = paint.stroke_cap == Cap::kRound + ? PointStyle::kRound + : PointStyle::kSquare; + Scalar radius = paint.stroke_width; if (radius > 0) { radius /= 2.0; } - GetCanvas().DrawPoints(skia_conversions::ToPoints(points, count), radius, - paint, point_style); + GetCanvas().DrawPoints(points, count, radius, paint, point_style); } break; case flutter::DlCanvas::PointMode::kLines: for (uint32_t i = 1; i < count; i += 2) { diff --git a/engine/src/flutter/impeller/entity/entity_unittests.cc b/engine/src/flutter/impeller/entity/entity_unittests.cc index 1b1a9a9039..cccc436bc7 100644 --- a/engine/src/flutter/impeller/entity/entity_unittests.cc +++ b/engine/src/flutter/impeller/entity/entity_unittests.cc @@ -35,6 +35,7 @@ #include "impeller/entity/entity.h" #include "impeller/entity/entity_playground.h" #include "impeller/entity/geometry/geometry.h" +#include "impeller/entity/geometry/point_field_geometry.h" #include "impeller/entity/geometry/stroke_path_geometry.h" #include "impeller/entity/geometry/superellipse_geometry.h" #include "impeller/geometry/color.h" @@ -2095,9 +2096,9 @@ TEST_P(EntityTest, TiledTextureContentsIsOpaque) { TEST_P(EntityTest, PointFieldGeometryCoverage) { std::vector points = {{10, 20}, {100, 200}}; - auto geometry = Geometry::MakePointField(points, 5.0, false); - ASSERT_EQ(*geometry->GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205)); - ASSERT_EQ(*geometry->GetCoverage(Matrix::MakeTranslation({30, 0, 0})), + PointFieldGeometry geometry(points.data(), 2, 5.0, false); + ASSERT_EQ(geometry.GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205)); + ASSERT_EQ(geometry.GetCoverage(Matrix::MakeTranslation({30, 0, 0})), Rect::MakeLTRB(35, 15, 135, 205)); } diff --git a/engine/src/flutter/impeller/entity/geometry/geometry.cc b/engine/src/flutter/impeller/entity/geometry/geometry.cc index 3e9df2cf2a..0f3185fce9 100644 --- a/engine/src/flutter/impeller/entity/geometry/geometry.cc +++ b/engine/src/flutter/impeller/entity/geometry/geometry.cc @@ -13,7 +13,6 @@ #include "impeller/entity/geometry/ellipse_geometry.h" #include "impeller/entity/geometry/fill_path_geometry.h" #include "impeller/entity/geometry/line_geometry.h" -#include "impeller/entity/geometry/point_field_geometry.h" #include "impeller/entity/geometry/rect_geometry.h" #include "impeller/entity/geometry/round_rect_geometry.h" #include "impeller/entity/geometry/stroke_path_geometry.h" @@ -63,12 +62,6 @@ std::unique_ptr Geometry::MakeFillPath( return std::make_unique(path, inner_rect); } -std::unique_ptr Geometry::MakePointField(std::vector points, - Scalar radius, - bool round) { - return std::make_unique(std::move(points), radius, round); -} - std::unique_ptr Geometry::MakeStrokePath(const Path& path, Scalar stroke_width, Scalar miter_limit, diff --git a/engine/src/flutter/impeller/entity/geometry/geometry.h b/engine/src/flutter/impeller/entity/geometry/geometry.h index 3884551fe5..d5c504d79e 100644 --- a/engine/src/flutter/impeller/entity/geometry/geometry.h +++ b/engine/src/flutter/impeller/entity/geometry/geometry.h @@ -83,10 +83,6 @@ class Geometry { static std::unique_ptr MakeRoundRect(const Rect& rect, const Size& radii); - static std::unique_ptr MakePointField(std::vector points, - Scalar radius, - bool round); - virtual GeometryResult GetPositionBuffer(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const = 0; diff --git a/engine/src/flutter/impeller/entity/geometry/point_field_geometry.cc b/engine/src/flutter/impeller/entity/geometry/point_field_geometry.cc index 0548d61dbb..2a8429a2d7 100644 --- a/engine/src/flutter/impeller/entity/geometry/point_field_geometry.cc +++ b/engine/src/flutter/impeller/entity/geometry/point_field_geometry.cc @@ -12,10 +12,14 @@ namespace impeller { -PointFieldGeometry::PointFieldGeometry(std::vector points, +PointFieldGeometry::PointFieldGeometry(const Point* points, + size_t point_count, Scalar radius, bool round) - : points_(std::move(points)), radius_(radius), round_(round) {} + : point_count_(point_count), + radius_(radius), + round_(round), + points_(points) {} PointFieldGeometry::~PointFieldGeometry() = default; @@ -23,7 +27,7 @@ GeometryResult PointFieldGeometry::GetPositionBuffer( const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { - if (radius_ < 0.0 || points_.empty()) { + if (radius_ < 0.0 || point_count_ == 0) { return {}; } const Matrix& transform = entity.GetTransform(); @@ -52,7 +56,7 @@ GeometryResult PointFieldGeometry::GetPositionBuffer( }); FML_DCHECK(circle_vertices.size() == generator.GetVertexCount()); - vertex_count = (circle_vertices.size() + 2) * points_.size() - 2; + vertex_count = (circle_vertices.size() + 2) * point_count_ - 2; buffer_view = host_buffer.Emplace( vertex_count * sizeof(Point), alignof(Point), [&](uint8_t* data) { Point* output = reinterpret_cast(data); @@ -66,7 +70,7 @@ GeometryResult PointFieldGeometry::GetPositionBuffer( // the strip. This could be optimized out if we switched to using // primitive restart. Point last_point = circle_vertices.back() + center; - for (size_t i = 1; i < points_.size(); i++) { + for (size_t i = 1; i < point_count_; i++) { Point center = points_[i]; output[offset++] = last_point; output[offset++] = Point(center + circle_vertices[0]); @@ -77,7 +81,7 @@ GeometryResult PointFieldGeometry::GetPositionBuffer( } }); } else { - vertex_count = 6 * points_.size() - 2; + vertex_count = 6 * point_count_ - 2; buffer_view = host_buffer.Emplace( vertex_count * sizeof(Point), alignof(Point), [&](uint8_t* data) { Point* output = reinterpret_cast(data); @@ -97,7 +101,7 @@ GeometryResult PointFieldGeometry::GetPositionBuffer( // For all subequent points, insert a degenerate triangle to break // the strip. This could be optimized out if we switched to using // primitive restart. - for (size_t i = 1; i < points_.size(); i++) { + for (size_t i = 1; i < point_count_; i++) { Point point = points_[i]; Point first = Point(point.x - radius, point.y - radius); @@ -129,22 +133,21 @@ GeometryResult PointFieldGeometry::GetPositionBuffer( // |Geometry| std::optional PointFieldGeometry::GetCoverage( const Matrix& transform) const { - if (points_.size() > 0) { + if (point_count_ > 0) { // Doesn't use MakePointBounds as this isn't resilient to points that // all lie along the same axis. - auto first = points_.begin(); - auto last = points_.end(); - auto left = first->x; - auto top = first->y; - auto right = first->x; - auto bottom = first->y; - for (auto it = first + 1; it < last; ++it) { - left = std::min(left, it->x); - top = std::min(top, it->y); - right = std::max(right, it->x); - bottom = std::max(bottom, it->y); + Scalar left = points_[0].x; + Scalar top = points_[0].y; + Scalar right = points_[0].x; + Scalar bottom = points_[0].y; + for (auto i = 1u; i < point_count_; i++) { + const Point point = points_[i]; + left = std::min(left, point.x); + top = std::min(top, point.y); + right = std::max(right, point.x); + bottom = std::max(bottom, point.y); } - auto coverage = Rect::MakeLTRB(left - radius_, top - radius_, + Rect coverage = Rect::MakeLTRB(left - radius_, top - radius_, right + radius_, bottom + radius_); return coverage.TransformBounds(transform); } diff --git a/engine/src/flutter/impeller/entity/geometry/point_field_geometry.h b/engine/src/flutter/impeller/entity/geometry/point_field_geometry.h index cdbb192886..8ab8e8b4ae 100644 --- a/engine/src/flutter/impeller/entity/geometry/point_field_geometry.h +++ b/engine/src/flutter/impeller/entity/geometry/point_field_geometry.h @@ -10,24 +10,31 @@ namespace impeller { /// @brief A geometry class specialized for Canvas::DrawPoints. +/// +/// Does not hold ownership of the allocated point data, which is expected to be +/// maintained via the display list structure. class PointFieldGeometry final : public Geometry { public: - PointFieldGeometry(std::vector points, Scalar radius, bool round); + PointFieldGeometry(const Point* points, + size_t point_count, + Scalar radius, + bool round); ~PointFieldGeometry() override; + // |Geometry| + std::optional GetCoverage(const Matrix& transform) const override; + private: // |Geometry| GeometryResult GetPositionBuffer(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const override; - // |Geometry| - std::optional GetCoverage(const Matrix& transform) const override; - - std::vector points_; + size_t point_count_; Scalar radius_; bool round_; + const Point* points_; PointFieldGeometry(const PointFieldGeometry&) = delete;