Update SkPicture cull rects with RTree information
When computed, the RTree for an SkPicture will have a root bounds that reflects the best bounding information available, rather than the best estimate at the time the picture recorder is created. Given that creators frequently don't know ahead of time what will be drawn, the RTree bound is often tighter. Perf testing on Chrome indicates a small raster performance advantage. For upcoming painting changes in Chrome the performance advantage is much larger. BUG= Review URL: https://codereview.chromium.org/971803002
This commit is contained in:
parent
dc812222a7
commit
2dd3b6647d
@ -34,6 +34,9 @@ public:
|
||||
|
||||
virtual size_t bytesUsed() const = 0;
|
||||
|
||||
// Get the root bound.
|
||||
virtual SkRect getRootBound() const = 0;
|
||||
|
||||
SK_DECLARE_INST_COUNT(SkBBoxHierarchy)
|
||||
private:
|
||||
typedef SkRefCnt INHERITED;
|
||||
|
@ -60,6 +60,10 @@ SkPicture* SkPictureRecorder::endRecordingAsPicture() {
|
||||
} else {
|
||||
SkRecordFillBounds(fCullRect, *fRecord, fBBH.get());
|
||||
}
|
||||
SkRect bbhBound = fBBH->getRootBound();
|
||||
SkASSERT((bbhBound.isEmpty() || fCullRect.contains(bbhBound))
|
||||
|| (bbhBound.isEmpty() && fCullRect.isEmpty()));
|
||||
fCullRect = bbhBound;
|
||||
}
|
||||
|
||||
SkPicture* pict = SkNEW_ARGS(SkPicture, (fCullRect, fRecord, pictList, fBBH));
|
||||
|
@ -9,6 +9,14 @@
|
||||
|
||||
SkRTree::SkRTree(SkScalar aspectRatio) : fCount(0), fAspectRatio(aspectRatio) {}
|
||||
|
||||
SkRect SkRTree::getRootBound() const {
|
||||
if (fCount) {
|
||||
return fRoot.fBounds;
|
||||
} else {
|
||||
return SkRect::MakeEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
void SkRTree::insert(const SkRect boundsArray[], int N) {
|
||||
SkASSERT(0 == fCount);
|
||||
|
||||
|
@ -52,6 +52,9 @@ public:
|
||||
// Insertion count (not overall node count, which may be greater).
|
||||
int getCount() const { return fCount; }
|
||||
|
||||
// Get the root bound.
|
||||
SkRect getRootBound() const SK_OVERRIDE;
|
||||
|
||||
// These values were empirically determined to produce reasonable performance in most cases.
|
||||
static const int kMinChildren = 6,
|
||||
kMaxChildren = 11;
|
||||
|
@ -387,8 +387,12 @@ private:
|
||||
Bounds bounds(const DrawPaint&) const { return fCurrentClipBounds; }
|
||||
Bounds bounds(const NoOp&) const { return Bounds::MakeEmpty(); } // NoOps don't draw.
|
||||
|
||||
Bounds bounds(const DrawSprite& op) const { // Ignores the matrix.
|
||||
return Bounds::MakeXYWH(op.left, op.top, op.bitmap.width(), op.bitmap.height());
|
||||
Bounds bounds(const DrawSprite& op) const { // Ignores the matrix, but respects the clip.
|
||||
SkRect rect = Bounds::MakeXYWH(op.left, op.top, op.bitmap.width(), op.bitmap.height());
|
||||
if (!rect.intersect(fCurrentClipBounds)) {
|
||||
return Bounds::MakeEmpty();
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
Bounds bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect, &op.paint); }
|
||||
|
@ -1248,8 +1248,9 @@ DEF_TEST(DontOptimizeSaveLayerDrawDrawRestore, reporter) {
|
||||
|
||||
struct CountingBBH : public SkBBoxHierarchy {
|
||||
mutable int searchCalls;
|
||||
SkRect rootBound;
|
||||
|
||||
CountingBBH() : searchCalls(0) {}
|
||||
CountingBBH(const SkRect& bound) : searchCalls(0), rootBound(bound) {}
|
||||
|
||||
void search(const SkRect& query, SkTDArray<unsigned>* results) const SK_OVERRIDE {
|
||||
this->searchCalls++;
|
||||
@ -1257,6 +1258,7 @@ struct CountingBBH : public SkBBoxHierarchy {
|
||||
|
||||
void insert(const SkRect[], int) SK_OVERRIDE {}
|
||||
virtual size_t bytesUsed() const SK_OVERRIDE { return 0; }
|
||||
SkRect getRootBound() const SK_OVERRIDE { return rootBound; }
|
||||
};
|
||||
|
||||
class SpoonFedBBHFactory : public SkBBHFactory {
|
||||
@ -1271,11 +1273,12 @@ private:
|
||||
|
||||
// When the canvas clip covers the full picture, we don't need to call the BBH.
|
||||
DEF_TEST(Picture_SkipBBH, r) {
|
||||
CountingBBH bbh;
|
||||
SkRect bound = SkRect::MakeWH(320, 240);
|
||||
CountingBBH bbh(bound);
|
||||
SpoonFedBBHFactory factory(&bbh);
|
||||
|
||||
SkPictureRecorder recorder;
|
||||
recorder.beginRecording(320, 240, &factory);
|
||||
recorder.beginRecording(bound, &factory);
|
||||
SkAutoTUnref<const SkPicture> picture(recorder.endRecording());
|
||||
|
||||
SkCanvas big(640, 480), small(300, 200);
|
||||
|
@ -133,6 +133,7 @@ struct TestBBH : public SkBBoxHierarchy {
|
||||
|
||||
void search(const SkRect& query, SkTDArray<unsigned>* results) const SK_OVERRIDE {}
|
||||
size_t bytesUsed() const SK_OVERRIDE { return 0; }
|
||||
SkRect getRootBound() const SK_OVERRIDE { return SkRect::MakeEmpty(); }
|
||||
|
||||
struct Entry {
|
||||
unsigned opIndex;
|
||||
|
Loading…
Reference in New Issue
Block a user