diff options
author | mtklein <mtklein@chromium.org> | 2014-10-27 10:27:10 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-27 10:27:10 -0700 |
commit | 4477c3c0e6eb064772aefe8737425cd1c2ce557f (patch) | |
tree | e841aeb0174e7ddc621f0b5dca88592e8c37d975 /src/core/SkRTree.cpp | |
parent | 5e44b00392e791088b693a0b462b107b0b5a91ba (diff) |
Cut down SkBBH API more.
- The expected case is now a single bulk-load insert() call instead of N;
- reserve() and flushDeferredInserts() can fold into insert() now;
- SkBBH subclasses may take ownership of the bounds
This appears to be a performance no-op on both my Mac and N5. I guess
even the simplest indirect branch predictor ("same as last time") can predict
the repeated virtual calls to SkBBH::insert() perfectly.
BUG=skia:
Review URL: https://codereview.chromium.org/670213002
Diffstat (limited to 'src/core/SkRTree.cpp')
-rw-r--r-- | src/core/SkRTree.cpp | 77 |
1 files changed, 23 insertions, 54 deletions
diff --git a/src/core/SkRTree.cpp b/src/core/SkRTree.cpp index 4a081db26d..93f914276f 100644 --- a/src/core/SkRTree.cpp +++ b/src/core/SkRTree.cpp @@ -44,68 +44,39 @@ SkRTree::~SkRTree() { this->clear(); } -void SkRTree::insert(unsigned opIndex, const SkRect& fbounds, bool defer) { - SkIRect bounds; - if (fbounds.isLargest()) { - bounds.setLargest(); - } else { - fbounds.roundOut(&bounds); - } - +void SkRTree::insert(SkAutoTMalloc<SkRect>* boundsArray, int N) { + SkASSERT(this->isEmpty()); this->validate(); - if (bounds.isEmpty()) { - SkASSERT(false); - return; - } - Branch newBranch; - newBranch.fBounds = bounds; - newBranch.fChild.opIndex = opIndex; - if (this->isEmpty()) { - // since a bulk-load into an existing tree is as of yet unimplemented (and arguably not - // of vital importance right now), we only batch up inserts if the tree is empty. - if (defer) { - fDeferredInserts.push(newBranch); - return; - } else { - fRoot.fChild.subtree = allocateNode(0); - fRoot.fChild.subtree->fNumChildren = 0; + + SkTDArray<Branch> deferred; + deferred.setReserve(N); + + for (int i = 0; i < N; i++) { + SkIRect bounds; + (*boundsArray)[i].roundOut(&bounds); + if (bounds.isEmpty()) { + continue; } - } - Branch* newSibling = insert(fRoot.fChild.subtree, &newBranch); - fRoot.fBounds = this->computeBounds(fRoot.fChild.subtree); - - if (newSibling) { - Node* oldRoot = fRoot.fChild.subtree; - Node* newRoot = this->allocateNode(oldRoot->fLevel + 1); - newRoot->fNumChildren = 2; - *newRoot->child(0) = fRoot; - *newRoot->child(1) = *newSibling; - fRoot.fChild.subtree = newRoot; - fRoot.fBounds = this->computeBounds(fRoot.fChild.subtree); - } + Branch newBranch; + newBranch.fBounds = bounds; + newBranch.fChild.opIndex = i; - ++fCount; - this->validate(); -} + deferred.push(newBranch); + } -void SkRTree::flushDeferredInserts() { - this->validate(); - if (this->isEmpty() && fDeferredInserts.count() > 0) { - fCount = fDeferredInserts.count(); + fCount = deferred.count(); + if (fCount) { if (1 == fCount) { - fRoot.fChild.subtree = allocateNode(0); + fRoot.fChild.subtree = this->allocateNode(0); fRoot.fChild.subtree->fNumChildren = 0; - this->insert(fRoot.fChild.subtree, &fDeferredInserts[0]); - fRoot.fBounds = fDeferredInserts[0].fBounds; + this->insert(fRoot.fChild.subtree, &deferred[0]); + fRoot.fBounds = deferred[0].fBounds; } else { - fRoot = this->bulkLoad(&fDeferredInserts); + fRoot = this->bulkLoad(&deferred); } - } else { - // TODO: some algorithm for bulk loading into an already populated tree - SkASSERT(0 == fDeferredInserts.count()); } - fDeferredInserts.rewind(); + this->validate(); } @@ -113,7 +84,6 @@ void SkRTree::search(const SkRect& fquery, SkTDArray<unsigned>* results) const { SkIRect query; fquery.roundOut(&query); this->validate(); - SkASSERT(0 == fDeferredInserts.count()); // If this fails, you should have flushed. if (!this->isEmpty() && SkIRect::IntersectsNoEmptyCheck(fRoot.fBounds, query)) { this->search(fRoot.fChild.subtree, query, results); } @@ -123,7 +93,6 @@ void SkRTree::search(const SkRect& fquery, SkTDArray<unsigned>* results) const { void SkRTree::clear() { this->validate(); fNodes.reset(); - fDeferredInserts.rewind(); fCount = 0; this->validate(); } |