pass 'nested' bool to approximateOpCount

Change-Id: I5b1baf2bc3aafa03c1d0cace4f7c09a09cf4a084
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/311112
Reviewed-by: Julia Lavrova <jlavrova@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2020-08-17 17:12:13 -04:00 committed by Skia Commit-Bot
parent 1a5b9b0628
commit 18305c3d36
6 changed files with 68 additions and 12 deletions

View File

@ -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.

View File

@ -53,8 +53,29 @@ void SkBigPicture::partialPlayback(SkCanvas* canvas,
initialCTM);
}
struct NestedApproxOpCounter {
int fCount = 0;
template <typename T> 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(); }

View File

@ -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; }

View File

@ -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;

View File

@ -317,9 +317,9 @@ sk_sp<SkPicture> 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;
};

View File

@ -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<SkPicture> 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<SkPicture> 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<SkPicture> leaf1 = make_pic(1, nullptr);
check(leaf1, 1, 1);
sk_sp<SkPicture> 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);
}