This repository was archived by the owner on Feb 25, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6k
Set SkPath::setIsVolatile based on whether the path survives at least two frames #22620
Merged
Merged
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
bc78eea
does not work yet
dnfield f2867c8
safe?
dnfield 34e2523
Merge remote-tracking branch 'upstream/master' into path_vol
dnfield 100b2ec
one more
dnfield 6a84f9e
missing mutex
dnfield 24df8c7
UIDartState/shell ownership
dnfield 280b3c9
review and fixup errors introduced
dnfield 07d2d99
test
dnfield 88d4125
benchmark and improvement
dnfield 62c238f
oops
dnfield 9fc3504
..
dnfield c8171ad
more review
dnfield 17eefed
Merge remote-tracking branch 'upstream/master' into path_vol
dnfield 9cd0ac9
deflake tests
dnfield e087e3d
fix dangling pointer issue
dnfield 50dadd3
missed one
dnfield 38281c2
NO MORE FLAKES
dnfield 7767698
unnecessary code
dnfield b1d122e
Merge remote-tracking branch 'upstream/master' into path_vol
dnfield 847a998
update new test
dnfield cfaa5b0
Merge remote-tracking branch 'upstream/master' into path_vol
dnfield 71153fe
Merge remote-tracking branch 'upstream/master' into path_vol
dnfield 1eac95f
review/update tests so I can run them with null safety
dnfield File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,43 +67,69 @@ void CanvasPath::RegisterNatives(tonic::DartLibraryNatives* natives) { | |
| FOR_EACH_BINDING(DART_REGISTER_NATIVE)}); | ||
| } | ||
|
|
||
| CanvasPath::CanvasPath() {} | ||
| CanvasPath::CanvasPath() | ||
| : path_tracker_(UIDartState::Current()->GetVolatilePathTracker()), | ||
| tracked_path_(std::make_shared<VolatilePathTracker::TrackedPath>()) { | ||
| FML_DCHECK(path_tracker_); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| CanvasPath::~CanvasPath() = default; | ||
|
|
||
| void CanvasPath::resetVolatility() { | ||
| if (!tracked_path_->tracking_volatility) { | ||
| mutable_path().setIsVolatile(true); | ||
| tracked_path_->frame_count = 0; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems redundant.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this path had previously been marked as non-volatile, but now has been mutated and is volatile again, we have to reset the frame count so that we don't immediately mark it volatile if it is only drawn for e.g. 1 frame. |
||
| tracked_path_->tracking_volatility = true; | ||
| path_tracker_->Insert(tracked_path_); | ||
| } | ||
| } | ||
|
|
||
| CanvasPath::~CanvasPath() {} | ||
| void CanvasPath::ReleaseDartWrappableReference() const { | ||
| FML_DCHECK(path_tracker_); | ||
| path_tracker_->Erase(tracked_path_); | ||
| } | ||
|
|
||
| int CanvasPath::getFillType() { | ||
| return static_cast<int>(path_.getFillType()); | ||
| return static_cast<int>(path().getFillType()); | ||
| } | ||
|
|
||
| void CanvasPath::setFillType(int fill_type) { | ||
| path_.setFillType(static_cast<SkPathFillType>(fill_type)); | ||
| mutable_path().setFillType(static_cast<SkPathFillType>(fill_type)); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::moveTo(float x, float y) { | ||
| path_.moveTo(x, y); | ||
| mutable_path().moveTo(x, y); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::relativeMoveTo(float x, float y) { | ||
| path_.rMoveTo(x, y); | ||
| mutable_path().rMoveTo(x, y); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::lineTo(float x, float y) { | ||
| path_.lineTo(x, y); | ||
| mutable_path().lineTo(x, y); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::relativeLineTo(float x, float y) { | ||
| path_.rLineTo(x, y); | ||
| mutable_path().rLineTo(x, y); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::quadraticBezierTo(float x1, float y1, float x2, float y2) { | ||
| path_.quadTo(x1, y1, x2, y2); | ||
| mutable_path().quadTo(x1, y1, x2, y2); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::relativeQuadraticBezierTo(float x1, | ||
| float y1, | ||
| float x2, | ||
| float y2) { | ||
| path_.rQuadTo(x1, y1, x2, y2); | ||
| mutable_path().rQuadTo(x1, y1, x2, y2); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::cubicTo(float x1, | ||
|
|
@@ -112,7 +138,8 @@ void CanvasPath::cubicTo(float x1, | |
| float y2, | ||
| float x3, | ||
| float y3) { | ||
| path_.cubicTo(x1, y1, x2, y2, x3, y3); | ||
| mutable_path().cubicTo(x1, y1, x2, y2, x3, y3); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::relativeCubicTo(float x1, | ||
|
|
@@ -121,19 +148,22 @@ void CanvasPath::relativeCubicTo(float x1, | |
| float y2, | ||
| float x3, | ||
| float y3) { | ||
| path_.rCubicTo(x1, y1, x2, y2, x3, y3); | ||
| mutable_path().rCubicTo(x1, y1, x2, y2, x3, y3); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::conicTo(float x1, float y1, float x2, float y2, float w) { | ||
| path_.conicTo(x1, y1, x2, y2, w); | ||
| mutable_path().conicTo(x1, y1, x2, y2, w); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::relativeConicTo(float x1, | ||
| float y1, | ||
| float x2, | ||
| float y2, | ||
| float w) { | ||
| path_.rConicTo(x1, y1, x2, y2, w); | ||
| mutable_path().rConicTo(x1, y1, x2, y2, w); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::arcTo(float left, | ||
|
|
@@ -143,9 +173,10 @@ void CanvasPath::arcTo(float left, | |
| float startAngle, | ||
| float sweepAngle, | ||
| bool forceMoveTo) { | ||
| path_.arcTo(SkRect::MakeLTRB(left, top, right, bottom), | ||
| startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI, | ||
| forceMoveTo); | ||
| mutable_path().arcTo(SkRect::MakeLTRB(left, top, right, bottom), | ||
| startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI, | ||
| forceMoveTo); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::arcToPoint(float arcEndX, | ||
|
|
@@ -160,8 +191,9 @@ void CanvasPath::arcToPoint(float arcEndX, | |
| const auto direction = | ||
| isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW; | ||
|
|
||
| path_.arcTo(radiusX, radiusY, xAxisRotation, arcSize, direction, arcEndX, | ||
| arcEndY); | ||
| mutable_path().arcTo(radiusX, radiusY, xAxisRotation, arcSize, direction, | ||
| arcEndX, arcEndY); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::relativeArcToPoint(float arcEndDeltaX, | ||
|
|
@@ -175,16 +207,19 @@ void CanvasPath::relativeArcToPoint(float arcEndDeltaX, | |
| : SkPath::ArcSize::kSmall_ArcSize; | ||
| const auto direction = | ||
| isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW; | ||
| path_.rArcTo(radiusX, radiusY, xAxisRotation, arcSize, direction, | ||
| arcEndDeltaX, arcEndDeltaY); | ||
| mutable_path().rArcTo(radiusX, radiusY, xAxisRotation, arcSize, direction, | ||
| arcEndDeltaX, arcEndDeltaY); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addRect(float left, float top, float right, float bottom) { | ||
| path_.addRect(SkRect::MakeLTRB(left, top, right, bottom)); | ||
| mutable_path().addRect(SkRect::MakeLTRB(left, top, right, bottom)); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addOval(float left, float top, float right, float bottom) { | ||
| path_.addOval(SkRect::MakeLTRB(left, top, right, bottom)); | ||
| mutable_path().addOval(SkRect::MakeLTRB(left, top, right, bottom)); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addArc(float left, | ||
|
|
@@ -193,25 +228,29 @@ void CanvasPath::addArc(float left, | |
| float bottom, | ||
| float startAngle, | ||
| float sweepAngle) { | ||
| path_.addArc(SkRect::MakeLTRB(left, top, right, bottom), | ||
| startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI); | ||
| mutable_path().addArc(SkRect::MakeLTRB(left, top, right, bottom), | ||
| startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addPolygon(const tonic::Float32List& points, bool close) { | ||
| path_.addPoly(reinterpret_cast<const SkPoint*>(points.data()), | ||
| points.num_elements() / 2, close); | ||
| mutable_path().addPoly(reinterpret_cast<const SkPoint*>(points.data()), | ||
| points.num_elements() / 2, close); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addRRect(const RRect& rrect) { | ||
| path_.addRRect(rrect.sk_rrect); | ||
| mutable_path().addRRect(rrect.sk_rrect); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addPath(CanvasPath* path, double dx, double dy) { | ||
| if (!path) { | ||
| Dart_ThrowException(ToDart("Path.addPath called with non-genuine Path.")); | ||
| return; | ||
| } | ||
| path_.addPath(path->path(), dx, dy, SkPath::kAppend_AddPathMode); | ||
| mutable_path().addPath(path->path(), dx, dy, SkPath::kAppend_AddPathMode); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addPathWithMatrix(CanvasPath* path, | ||
|
|
@@ -227,8 +266,9 @@ void CanvasPath::addPathWithMatrix(CanvasPath* path, | |
| SkMatrix matrix = ToSkMatrix(matrix4); | ||
| matrix.setTranslateX(matrix.getTranslateX() + dx); | ||
| matrix.setTranslateY(matrix.getTranslateY() + dy); | ||
| path_.addPath(path->path(), matrix, SkPath::kAppend_AddPathMode); | ||
| mutable_path().addPath(path->path(), matrix, SkPath::kAppend_AddPathMode); | ||
| matrix4.Release(); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::extendWithPath(CanvasPath* path, double dx, double dy) { | ||
|
|
@@ -237,7 +277,8 @@ void CanvasPath::extendWithPath(CanvasPath* path, double dx, double dy) { | |
| ToDart("Path.extendWithPath called with non-genuine Path.")); | ||
| return; | ||
| } | ||
| path_.addPath(path->path(), dx, dy, SkPath::kExtend_AddPathMode); | ||
| mutable_path().addPath(path->path(), dx, dy, SkPath::kExtend_AddPathMode); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::extendWithPathAndMatrix(CanvasPath* path, | ||
|
|
@@ -253,37 +294,43 @@ void CanvasPath::extendWithPathAndMatrix(CanvasPath* path, | |
| SkMatrix matrix = ToSkMatrix(matrix4); | ||
| matrix.setTranslateX(matrix.getTranslateX() + dx); | ||
| matrix.setTranslateY(matrix.getTranslateY() + dy); | ||
| path_.addPath(path->path(), matrix, SkPath::kExtend_AddPathMode); | ||
| mutable_path().addPath(path->path(), matrix, SkPath::kExtend_AddPathMode); | ||
| matrix4.Release(); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::close() { | ||
| path_.close(); | ||
| mutable_path().close(); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::reset() { | ||
| path_.reset(); | ||
| mutable_path().reset(); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| bool CanvasPath::contains(double x, double y) { | ||
| return path_.contains(x, y); | ||
| return path().contains(x, y); | ||
| } | ||
|
|
||
| void CanvasPath::shift(Dart_Handle path_handle, double dx, double dy) { | ||
| fml::RefPtr<CanvasPath> path = CanvasPath::Create(path_handle); | ||
| path_.offset(dx, dy, &path->path_); | ||
| auto& other_mutable_path = path->mutable_path(); | ||
| mutable_path().offset(dx, dy, &other_mutable_path); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::transform(Dart_Handle path_handle, | ||
| tonic::Float64List& matrix4) { | ||
| fml::RefPtr<CanvasPath> path = CanvasPath::Create(path_handle); | ||
| path_.transform(ToSkMatrix(matrix4), &path->path_); | ||
| auto& other_mutable_path = path->mutable_path(); | ||
| mutable_path().transform(ToSkMatrix(matrix4), &other_mutable_path); | ||
| matrix4.Release(); | ||
| } | ||
|
|
||
| tonic::Float32List CanvasPath::getBounds() { | ||
| tonic::Float32List rect(Dart_NewTypedData(Dart_TypedData_kFloat32, 4)); | ||
| const SkRect& bounds = path_.getBounds(); | ||
| const SkRect& bounds = path().getBounds(); | ||
| rect[0] = bounds.left(); | ||
| rect[1] = bounds.top(); | ||
| rect[2] = bounds.right(); | ||
|
|
@@ -293,21 +340,22 @@ tonic::Float32List CanvasPath::getBounds() { | |
|
|
||
| bool CanvasPath::op(CanvasPath* path1, CanvasPath* path2, int operation) { | ||
| return Op(path1->path(), path2->path(), static_cast<SkPathOp>(operation), | ||
| &path_); | ||
| &tracked_path_->path); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::clone(Dart_Handle path_handle) { | ||
| fml::RefPtr<CanvasPath> path = CanvasPath::Create(path_handle); | ||
| // per Skia docs, this will create a fast copy | ||
| // data is shared until the source path or dest path are mutated | ||
| path->path_ = path_; | ||
| path->mutable_path() = this->path(); | ||
| } | ||
|
|
||
| // This is doomed to be called too early, since Paths are mutable. | ||
| // However, it can help for some of the clone/shift/transform type methods | ||
| // where the resultant path will initially have a meaningful size. | ||
| size_t CanvasPath::GetAllocationSize() const { | ||
| return sizeof(CanvasPath) + path_.approximateBytesUsed(); | ||
| return sizeof(CanvasPath) + path().approximateBytesUsed(); | ||
| } | ||
|
|
||
| } // namespace flutter | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name
resetVolatilitysounds like it will also reset the volatility frame count but that does not seem to be the case. I believe resetting the count is the intended behavior as it's called in those methods that mutate the path.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done