From 18305c3d36bbb23079bae265a23349ae6d3a222b Mon Sep 17 00:00:00 2001 From: Mike Reed Date: Mon, 17 Aug 2020 17:12:13 -0400 Subject: [PATCH] pass 'nested' bool to approximateOpCount Change-Id: I5b1baf2bc3aafa03c1d0cace4f7c09a09cf4a084 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/311112 Reviewed-by: Julia Lavrova Reviewed-by: Mike Klein Commit-Queue: Mike Reed --- include/core/SkPicture.h | 4 +++- src/core/SkBigPicture.cpp | 23 ++++++++++++++++++++++- src/core/SkBigPicture.h | 2 +- src/core/SkMiniRecorder.cpp | 12 ++++++------ src/core/SkPicture.cpp | 6 +++--- tests/PictureTest.cpp | 33 +++++++++++++++++++++++++++++++++ 6 files changed, 68 insertions(+), 12 deletions(-) diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h index cb66cd244f..919840c179 100644 --- a/include/core/SkPicture.h +++ b/include/core/SkPicture.h @@ -197,11 +197,13 @@ public: recorded: some calls may be recorded as more than one operation, other calls may be optimized away. + @param nested if true, include the op-counts of nested pictures as well, else + just return count the ops in the top-level picture. @return approximate operation count example: https://fiddle.skia.org/c/@Picture_approximateOpCount */ - virtual int approximateOpCount() const = 0; + virtual int approximateOpCount(bool nested = false) const = 0; /** Returns the approximate byte size of SkPicture. Does not include large objects referenced by SkPicture. diff --git a/src/core/SkBigPicture.cpp b/src/core/SkBigPicture.cpp index a197ac1907..b6e970748b 100644 --- a/src/core/SkBigPicture.cpp +++ b/src/core/SkBigPicture.cpp @@ -53,8 +53,29 @@ void SkBigPicture::partialPlayback(SkCanvas* canvas, initialCTM); } +struct NestedApproxOpCounter { + int fCount = 0; + + template void operator()(const T& op) { + fCount += 1; + } + void operator()(const SkRecords::DrawPicture& op) { + fCount += op.picture->approximateOpCount(true); + } +}; + SkRect SkBigPicture::cullRect() const { return fCullRect; } -int SkBigPicture::approximateOpCount() const { return fRecord->count(); } +int SkBigPicture::approximateOpCount(bool nested) const { + if (nested) { + NestedApproxOpCounter visitor; + for (int i = 0; i < fRecord->count(); i++) { + fRecord->visit(i, visitor); + } + return visitor.fCount; + } else { + return fRecord->count(); + } +} size_t SkBigPicture::approximateBytesUsed() const { size_t bytes = sizeof(*this) + fRecord->bytesUsed() + fApproxBytesUsedBySubPictures; if (fBBH) { bytes += fBBH->bytesUsed(); } diff --git a/src/core/SkBigPicture.h b/src/core/SkBigPicture.h index 8538f6ca67..11191e8803 100644 --- a/src/core/SkBigPicture.h +++ b/src/core/SkBigPicture.h @@ -44,7 +44,7 @@ public: // SkPicture overrides void playback(SkCanvas*, AbortCallback*) const override; SkRect cullRect() const override; - int approximateOpCount() const override; + int approximateOpCount(bool nested) const override; size_t approximateBytesUsed() const override; const SkBigPicture* asSkBigPicture() const override { return this; } diff --git a/src/core/SkMiniRecorder.cpp b/src/core/SkMiniRecorder.cpp index db11f99ba0..80a13b3ecc 100644 --- a/src/core/SkMiniRecorder.cpp +++ b/src/core/SkMiniRecorder.cpp @@ -22,9 +22,9 @@ class SkEmptyPicture final : public SkPicture { public: void playback(SkCanvas*, AbortCallback*) const override { } - size_t approximateBytesUsed() const override { return sizeof(*this); } - int approximateOpCount() const override { return 0; } - SkRect cullRect() const override { return SkRect::MakeEmpty(); } + size_t approximateBytesUsed() const override { return sizeof(*this); } + int approximateOpCount(bool) const override { return 0; } + SkRect cullRect() const override { return SkRect::MakeEmpty(); } }; // Calculate conservative bounds for each type of draw op that can be its own mini picture. @@ -55,9 +55,9 @@ public: SkRecords::Draw(c, nullptr, nullptr, 0, nullptr)(fOp); } - size_t approximateBytesUsed() const override { return sizeof(*this); } - int approximateOpCount() const override { return 1; } - SkRect cullRect() const override { return fCull; } + size_t approximateBytesUsed() const override { return sizeof(*this); } + int approximateOpCount(bool) const override { return 1; } + SkRect cullRect() const override { return fCull; } private: SkRect fCull; diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp index 1cc8e673ef..fb7c929d0a 100644 --- a/src/core/SkPicture.cpp +++ b/src/core/SkPicture.cpp @@ -317,9 +317,9 @@ sk_sp SkPicture::MakePlaceholder(SkRect cull) { // approximateOpCount() needs to be greater than kMaxPictureOpsToUnrollInsteadOfRef // in SkCanvas.cpp to avoid that unrolling. SK_MaxS32 can't not be big enough! - int approximateOpCount() const override { return SK_MaxS32; } - size_t approximateBytesUsed() const override { return sizeof(*this); } - SkRect cullRect() const override { return fCull; } + int approximateOpCount(bool) const override { return SK_MaxS32; } + size_t approximateBytesUsed() const override { return sizeof(*this); } + SkRect cullRect() const override { return fCull; } SkRect fCull; }; diff --git a/tests/PictureTest.cpp b/tests/PictureTest.cpp index e4d9300821..095513b73c 100644 --- a/tests/PictureTest.cpp +++ b/tests/PictureTest.cpp @@ -961,3 +961,36 @@ DEF_TEST(Picture_fillsBBH, r) { "results.size() == %d, want %d\n", (int)results.size(), n); } } + +DEF_TEST(Picture_nested_op_count, r) { + auto make_pic = [](int n, sk_sp pic) { + SkPictureRecorder rec; + SkCanvas* c = rec.beginRecording({0,0, 100,100}); + for (int i = 0; i < n; i++) { + if (pic) { + c->drawPicture(pic); + } else { + c->drawRect({0,0, 100,100}, SkPaint{}); + } + } + return rec.finishRecordingAsPicture(); + }; + + auto check = [r](sk_sp pic, int shallow, int nested) { + int s = pic->approximateOpCount(false); + int n = pic->approximateOpCount(true); + REPORTER_ASSERT(r, s == shallow); + REPORTER_ASSERT(r, n == nested); + }; + + sk_sp leaf1 = make_pic(1, nullptr); + check(leaf1, 1, 1); + + sk_sp leaf10 = make_pic(10, nullptr); + check(leaf10, 10, 10); + + check(make_pic( 1, leaf1), 1, 1); + check(make_pic( 1, leaf10), 1, 10); + check(make_pic(10, leaf1), 10, 10); + check(make_pic(10, leaf10), 10, 100); +}