Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkRTree.h"
      9 #include "SkTSort.h"
     10 
     11 static inline uint32_t get_area(const SkIRect& rect);
     12 static inline uint32_t get_overlap(const SkIRect& rect1, const SkIRect& rect2);
     13 static inline uint32_t get_margin(const SkIRect& rect);
     14 static inline uint32_t get_area_increase(const SkIRect& rect1, SkIRect rect2);
     15 static inline void join_no_empty_check(const SkIRect& joinWith, SkIRect* out);
     16 
     17 ///////////////////////////////////////////////////////////////////////////////////////////////////
     18 
     19 SkRTree* SkRTree::Create(int minChildren, int maxChildren, SkScalar aspectRatio,
     20             bool sortWhenBulkLoading) {
     21     if (minChildren < maxChildren && (maxChildren + 1) / 2 >= minChildren &&
     22         minChildren > 0 && maxChildren < static_cast<int>(SK_MaxU16)) {
     23         return new SkRTree(minChildren, maxChildren, aspectRatio, sortWhenBulkLoading);
     24     }
     25     return NULL;
     26 }
     27 
     28 SkRTree::SkRTree(int minChildren, int maxChildren, SkScalar aspectRatio,
     29         bool sortWhenBulkLoading)
     30     : fMinChildren(minChildren)
     31     , fMaxChildren(maxChildren)
     32     , fNodeSize(sizeof(Node) + sizeof(Branch) * maxChildren)
     33     , fCount(0)
     34     , fNodes(fNodeSize * 256)
     35     , fAspectRatio(aspectRatio)
     36     , fSortWhenBulkLoading(sortWhenBulkLoading) {
     37     SkASSERT(minChildren < maxChildren && minChildren > 0 && maxChildren <
     38              static_cast<int>(SK_MaxU16));
     39     SkASSERT((maxChildren + 1) / 2 >= minChildren);
     40     this->validate();
     41 }
     42 
     43 SkRTree::~SkRTree() {
     44     this->clear();
     45 }
     46 
     47 void SkRTree::insert(void* data, const SkRect& fbounds, bool defer) {
     48     SkIRect bounds;
     49     if (fbounds.isLargest()) {
     50         bounds.setLargest();
     51     } else {
     52         fbounds.roundOut(&bounds);
     53     }
     54 
     55     this->validate();
     56     if (bounds.isEmpty()) {
     57         SkASSERT(false);
     58         return;
     59     }
     60     Branch newBranch;
     61     newBranch.fBounds = bounds;
     62     newBranch.fChild.data = data;
     63     if (this->isEmpty()) {
     64         // since a bulk-load into an existing tree is as of yet unimplemented (and arguably not
     65         // of vital importance right now), we only batch up inserts if the tree is empty.
     66         if (defer) {
     67             fDeferredInserts.push(newBranch);
     68             return;
     69         } else {
     70             fRoot.fChild.subtree = allocateNode(0);
     71             fRoot.fChild.subtree->fNumChildren = 0;
     72         }
     73     }
     74 
     75     Branch* newSibling = insert(fRoot.fChild.subtree, &newBranch);
     76     fRoot.fBounds = this->computeBounds(fRoot.fChild.subtree);
     77 
     78     if (newSibling) {
     79         Node* oldRoot = fRoot.fChild.subtree;
     80         Node* newRoot = this->allocateNode(oldRoot->fLevel + 1);
     81         newRoot->fNumChildren = 2;
     82         *newRoot->child(0) = fRoot;
     83         *newRoot->child(1) = *newSibling;
     84         fRoot.fChild.subtree = newRoot;
     85         fRoot.fBounds = this->computeBounds(fRoot.fChild.subtree);
     86     }
     87 
     88     ++fCount;
     89     this->validate();
     90 }
     91 
     92 void SkRTree::flushDeferredInserts() {
     93     this->validate();
     94     if (this->isEmpty() && fDeferredInserts.count() > 0) {
     95         fCount = fDeferredInserts.count();
     96         if (1 == fCount) {
     97             fRoot.fChild.subtree = allocateNode(0);
     98             fRoot.fChild.subtree->fNumChildren = 0;
     99             this->insert(fRoot.fChild.subtree, &fDeferredInserts[0]);
    100             fRoot.fBounds = fDeferredInserts[0].fBounds;
    101         } else {
    102             fRoot = this->bulkLoad(&fDeferredInserts);
    103         }
    104     } else {
    105         // TODO: some algorithm for bulk loading into an already populated tree
    106         SkASSERT(0 == fDeferredInserts.count());
    107     }
    108     fDeferredInserts.rewind();
    109     this->validate();
    110 }
    111 
    112 void SkRTree::search(const SkRect& fquery, SkTDArray<void*>* results) const {
    113     SkIRect query;
    114     fquery.roundOut(&query);
    115     this->validate();
    116     SkASSERT(0 == fDeferredInserts.count());  // If this fails, you should have flushed.
    117     if (!this->isEmpty() && SkIRect::IntersectsNoEmptyCheck(fRoot.fBounds, query)) {
    118         this->search(fRoot.fChild.subtree, query, results);
    119     }
    120     this->validate();
    121 }
    122 
    123 void SkRTree::clear() {
    124     this->validate();
    125     fNodes.reset();
    126     fDeferredInserts.rewind();
    127     fCount = 0;
    128     this->validate();
    129 }
    130 
    131 SkRTree::Node* SkRTree::allocateNode(uint16_t level) {
    132     Node* out = static_cast<Node*>(fNodes.allocThrow(fNodeSize));
    133     out->fNumChildren = 0;
    134     out->fLevel = level;
    135     return out;
    136 }
    137 
    138 SkRTree::Branch* SkRTree::insert(Node* root, Branch* branch, uint16_t level) {
    139     Branch* toInsert = branch;
    140     if (root->fLevel != level) {
    141         int childIndex = this->chooseSubtree(root, branch);
    142         toInsert = this->insert(root->child(childIndex)->fChild.subtree, branch, level);
    143         root->child(childIndex)->fBounds = this->computeBounds(
    144             root->child(childIndex)->fChild.subtree);
    145     }
    146     if (toInsert) {
    147         if (root->fNumChildren == fMaxChildren) {
    148             // handle overflow by splitting. TODO: opportunistic reinsertion
    149 
    150             // decide on a distribution to divide with
    151             Node* newSibling = this->allocateNode(root->fLevel);
    152             Branch* toDivide = SkNEW_ARRAY(Branch, fMaxChildren + 1);
    153             for (int i = 0; i < fMaxChildren; ++i) {
    154                 toDivide[i] = *root->child(i);
    155             }
    156             toDivide[fMaxChildren] = *toInsert;
    157             int splitIndex = this->distributeChildren(toDivide);
    158 
    159             // divide up the branches
    160             root->fNumChildren = splitIndex;
    161             newSibling->fNumChildren = fMaxChildren + 1 - splitIndex;
    162             for (int i = 0; i < splitIndex; ++i) {
    163                 *root->child(i) = toDivide[i];
    164             }
    165             for (int i = splitIndex; i < fMaxChildren + 1; ++i) {
    166                 *newSibling->child(i - splitIndex) = toDivide[i];
    167             }
    168             SkDELETE_ARRAY(toDivide);
    169 
    170             // pass the new sibling branch up to the parent
    171             branch->fChild.subtree = newSibling;
    172             branch->fBounds = this->computeBounds(newSibling);
    173             return branch;
    174         } else {
    175             *root->child(root->fNumChildren) = *toInsert;
    176             ++root->fNumChildren;
    177             return NULL;
    178         }
    179     }
    180     return NULL;
    181 }
    182 
    183 int SkRTree::chooseSubtree(Node* root, Branch* branch) {
    184     SkASSERT(!root->isLeaf());
    185     if (1 < root->fLevel) {
    186         // root's child pointers do not point to leaves, so minimize area increase
    187         int32_t minAreaIncrease = SK_MaxS32;
    188         int32_t minArea         = SK_MaxS32;
    189         int32_t bestSubtree     = -1;
    190         for (int i = 0; i < root->fNumChildren; ++i) {
    191             const SkIRect& subtreeBounds = root->child(i)->fBounds;
    192             int32_t areaIncrease = get_area_increase(subtreeBounds, branch->fBounds);
    193             // break ties in favor of subtree with smallest area
    194             if (areaIncrease < minAreaIncrease || (areaIncrease == minAreaIncrease &&
    195                 static_cast<int32_t>(get_area(subtreeBounds)) < minArea)) {
    196                 minAreaIncrease = areaIncrease;
    197                 minArea = get_area(subtreeBounds);
    198                 bestSubtree = i;
    199             }
    200         }
    201         SkASSERT(-1 != bestSubtree);
    202         return bestSubtree;
    203     } else if (1 == root->fLevel) {
    204         // root's child pointers do point to leaves, so minimize overlap increase
    205         int32_t minOverlapIncrease = SK_MaxS32;
    206         int32_t minAreaIncrease    = SK_MaxS32;
    207         int32_t bestSubtree = -1;
    208         for (int32_t i = 0; i < root->fNumChildren; ++i) {
    209             const SkIRect& subtreeBounds = root->child(i)->fBounds;
    210             SkIRect expandedBounds = subtreeBounds;
    211             join_no_empty_check(branch->fBounds, &expandedBounds);
    212             int32_t overlap = 0;
    213             for (int32_t j = 0; j < root->fNumChildren; ++j) {
    214                 if (j == i) continue;
    215                 // Note: this would be more correct if we subtracted the original pre-expanded
    216                 // overlap, but computing overlaps is expensive and omitting it doesn't seem to
    217                 // hurt query performance. See get_overlap_increase()
    218                 overlap += get_overlap(expandedBounds, root->child(j)->fBounds);
    219             }
    220             // break ties with lowest area increase
    221             if (overlap < minOverlapIncrease || (overlap == minOverlapIncrease &&
    222                 static_cast<int32_t>(get_area_increase(branch->fBounds, subtreeBounds)) <
    223                 minAreaIncrease)) {
    224                 minOverlapIncrease = overlap;
    225                 minAreaIncrease = get_area_increase(branch->fBounds, subtreeBounds);
    226                 bestSubtree = i;
    227             }
    228         }
    229         return bestSubtree;
    230     } else {
    231         SkASSERT(false);
    232         return 0;
    233     }
    234 }
    235 
    236 SkIRect SkRTree::computeBounds(Node* n) {
    237     SkIRect r = n->child(0)->fBounds;
    238     for (int i = 1; i < n->fNumChildren; ++i) {
    239         join_no_empty_check(n->child(i)->fBounds, &r);
    240     }
    241     return r;
    242 }
    243 
    244 int SkRTree::distributeChildren(Branch* children) {
    245     // We have two sides to sort by on each of two axes:
    246     const static SortSide sorts[2][2] = {
    247         {&SkIRect::fLeft, &SkIRect::fRight},
    248         {&SkIRect::fTop, &SkIRect::fBottom}
    249     };
    250 
    251     // We want to choose an axis to split on, then a distribution along that axis; we'll need
    252     // three pieces of info: the split axis, the side to sort by on that axis, and the index
    253     // to split the sorted array on.
    254     int32_t sortSide = -1;
    255     int32_t k        = -1;
    256     int32_t axis     = -1;
    257     int32_t bestS    = SK_MaxS32;
    258 
    259     // Evaluate each axis, we want the min summed margin-value (s) over all distributions
    260     for (int i = 0; i < 2; ++i) {
    261         int32_t minOverlap   = SK_MaxS32;
    262         int32_t minArea      = SK_MaxS32;
    263         int32_t axisBestK    = 0;
    264         int32_t axisBestSide = 0;
    265         int32_t s = 0;
    266 
    267         // Evaluate each sort
    268         for (int j = 0; j < 2; ++j) {
    269             SkTQSort(children, children + fMaxChildren, RectLessThan(sorts[i][j]));
    270 
    271             // Evaluate each split index
    272             for (int32_t k = 1; k <= fMaxChildren - 2 * fMinChildren + 2; ++k) {
    273                 SkIRect r1 = children[0].fBounds;
    274                 SkIRect r2 = children[fMinChildren + k - 1].fBounds;
    275                 for (int32_t l = 1; l < fMinChildren - 1 + k; ++l) {
    276                     join_no_empty_check(children[l].fBounds, &r1);
    277                 }
    278                 for (int32_t l = fMinChildren + k; l < fMaxChildren + 1; ++l) {
    279                     join_no_empty_check(children[l].fBounds, &r2);
    280                 }
    281 
    282                 int32_t area = get_area(r1) + get_area(r2);
    283                 int32_t overlap = get_overlap(r1, r2);
    284                 s += get_margin(r1) + get_margin(r2);
    285 
    286                 if (overlap < minOverlap || (overlap == minOverlap && area < minArea)) {
    287                     minOverlap = overlap;
    288                     minArea = area;
    289                     axisBestSide = j;
    290                     axisBestK = k;
    291                 }
    292             }
    293         }
    294 
    295         if (s < bestS) {
    296             bestS = s;
    297             axis = i;
    298             sortSide = axisBestSide;
    299             k = axisBestK;
    300         }
    301     }
    302 
    303     // replicate the sort of the winning distribution, (we can skip this if the last
    304     // sort ended up being best)
    305     if (!(axis == 1 && sortSide == 1)) {
    306         SkTQSort(children, children + fMaxChildren, RectLessThan(sorts[axis][sortSide]));
    307     }
    308 
    309     return fMinChildren - 1 + k;
    310 }
    311 
    312 void SkRTree::search(Node* root, const SkIRect query, SkTDArray<void*>* results) const {
    313     for (int i = 0; i < root->fNumChildren; ++i) {
    314         if (SkIRect::IntersectsNoEmptyCheck(root->child(i)->fBounds, query)) {
    315             if (root->isLeaf()) {
    316                 results->push(root->child(i)->fChild.data);
    317             } else {
    318                 this->search(root->child(i)->fChild.subtree, query, results);
    319             }
    320         }
    321     }
    322 }
    323 
    324 SkRTree::Branch SkRTree::bulkLoad(SkTDArray<Branch>* branches, int level) {
    325     if (branches->count() == 1) {
    326         // Only one branch: it will be the root
    327         Branch out = (*branches)[0];
    328         branches->rewind();
    329         return out;
    330     } else {
    331         // We sort the whole list by y coordinates, if we are told to do so.
    332         //
    333         // We expect Webkit / Blink to give us a reasonable x,y order.
    334         // Avoiding this call resulted in a 17% win for recording with
    335         // negligible difference in playback speed.
    336         if (fSortWhenBulkLoading) {
    337             SkTQSort(branches->begin(), branches->end() - 1, RectLessY());
    338         }
    339 
    340         int numBranches = branches->count() / fMaxChildren;
    341         int remainder = branches->count() % fMaxChildren;
    342         int newBranches = 0;
    343 
    344         if (0 != remainder) {
    345             ++numBranches;
    346             // If the remainder isn't enough to fill a node, we'll need to add fewer nodes to
    347             // some other branches to make up for it
    348             if (remainder >= fMinChildren) {
    349                 remainder = 0;
    350             } else {
    351                 remainder = fMinChildren - remainder;
    352             }
    353         }
    354 
    355         int numStrips = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(numBranches) *
    356                                      SkScalarInvert(fAspectRatio)));
    357         int numTiles = SkScalarCeilToInt(SkIntToScalar(numBranches) /
    358                                     SkIntToScalar(numStrips));
    359         int currentBranch = 0;
    360 
    361         for (int i = 0; i < numStrips; ++i) {
    362             // Once again, if we are told to do so, we sort by x.
    363             if (fSortWhenBulkLoading) {
    364                 int begin = currentBranch;
    365                 int end = currentBranch + numTiles * fMaxChildren - SkMin32(remainder,
    366                         (fMaxChildren - fMinChildren) * numTiles);
    367                 if (end > branches->count()) {
    368                     end = branches->count();
    369                 }
    370 
    371                 // Now we sort horizontal strips of rectangles by their x coords
    372                 SkTQSort(branches->begin() + begin, branches->begin() + end - 1, RectLessX());
    373             }
    374 
    375             for (int j = 0; j < numTiles && currentBranch < branches->count(); ++j) {
    376                 int incrementBy = fMaxChildren;
    377                 if (remainder != 0) {
    378                     // if need be, omit some nodes to make up for remainder
    379                     if (remainder <= fMaxChildren - fMinChildren) {
    380                         incrementBy -= remainder;
    381                         remainder = 0;
    382                     } else {
    383                         incrementBy = fMinChildren;
    384                         remainder -= fMaxChildren - fMinChildren;
    385                     }
    386                 }
    387                 Node* n = allocateNode(level);
    388                 n->fNumChildren = 1;
    389                 *n->child(0) = (*branches)[currentBranch];
    390                 Branch b;
    391                 b.fBounds = (*branches)[currentBranch].fBounds;
    392                 b.fChild.subtree = n;
    393                 ++currentBranch;
    394                 for (int k = 1; k < incrementBy && currentBranch < branches->count(); ++k) {
    395                     b.fBounds.join((*branches)[currentBranch].fBounds);
    396                     *n->child(k) = (*branches)[currentBranch];
    397                     ++n->fNumChildren;
    398                     ++currentBranch;
    399                 }
    400                 (*branches)[newBranches] = b;
    401                 ++newBranches;
    402             }
    403         }
    404         branches->setCount(newBranches);
    405         return this->bulkLoad(branches, level + 1);
    406     }
    407 }
    408 
    409 void SkRTree::validate() const {
    410 #ifdef SK_DEBUG
    411     if (this->isEmpty()) {
    412         return;
    413     }
    414     SkASSERT(fCount == this->validateSubtree(fRoot.fChild.subtree, fRoot.fBounds, true));
    415 #endif
    416 }
    417 
    418 int SkRTree::validateSubtree(Node* root, SkIRect bounds, bool isRoot) const {
    419     // make sure the pointer is pointing to a valid place
    420     SkASSERT(fNodes.contains(static_cast<void*>(root)));
    421 
    422     if (isRoot) {
    423         // If the root of this subtree is the overall root, we have looser standards:
    424         if (root->isLeaf()) {
    425             SkASSERT(root->fNumChildren >= 1 && root->fNumChildren <= fMaxChildren);
    426         } else {
    427             SkASSERT(root->fNumChildren >= 2 && root->fNumChildren <= fMaxChildren);
    428         }
    429     } else {
    430         SkASSERT(root->fNumChildren >= fMinChildren && root->fNumChildren <= fMaxChildren);
    431     }
    432 
    433     for (int i = 0; i < root->fNumChildren; ++i) {
    434         SkASSERT(bounds.contains(root->child(i)->fBounds));
    435     }
    436 
    437     if (root->isLeaf()) {
    438         SkASSERT(0 == root->fLevel);
    439         return root->fNumChildren;
    440     } else {
    441         int childCount = 0;
    442         for (int i = 0; i < root->fNumChildren; ++i) {
    443             SkASSERT(root->child(i)->fChild.subtree->fLevel == root->fLevel - 1);
    444             childCount += this->validateSubtree(root->child(i)->fChild.subtree,
    445                                                 root->child(i)->fBounds);
    446         }
    447         return childCount;
    448     }
    449 }
    450 
    451 void SkRTree::rewindInserts() {
    452     SkASSERT(this->isEmpty()); // Currently only supports deferred inserts
    453     while (!fDeferredInserts.isEmpty() &&
    454            fClient->shouldRewind(fDeferredInserts.top().fChild.data)) {
    455         fDeferredInserts.pop();
    456     }
    457 }
    458 
    459 ///////////////////////////////////////////////////////////////////////////////////////////////////
    460 
    461 static inline uint32_t get_area(const SkIRect& rect) {
    462     return rect.width() * rect.height();
    463 }
    464 
    465 static inline uint32_t get_overlap(const SkIRect& rect1, const SkIRect& rect2) {
    466     // I suspect there's a more efficient way of computing this...
    467     return SkMax32(0, SkMin32(rect1.fRight, rect2.fRight) - SkMax32(rect1.fLeft, rect2.fLeft)) *
    468            SkMax32(0, SkMin32(rect1.fBottom, rect2.fBottom) - SkMax32(rect1.fTop, rect2.fTop));
    469 }
    470 
    471 // Get the margin (aka perimeter)
    472 static inline uint32_t get_margin(const SkIRect& rect) {
    473     return 2 * (rect.width() + rect.height());
    474 }
    475 
    476 static inline uint32_t get_area_increase(const SkIRect& rect1, SkIRect rect2) {
    477     join_no_empty_check(rect1, &rect2);
    478     return get_area(rect2) - get_area(rect1);
    479 }
    480 
    481 // Expand 'out' to include 'joinWith'
    482 static inline void join_no_empty_check(const SkIRect& joinWith, SkIRect* out) {
    483     // since we check for empty bounds on insert, we know we'll never have empty rects
    484     // and we can save the empty check that SkIRect::join requires
    485     if (joinWith.fLeft < out->fLeft) { out->fLeft = joinWith.fLeft; }
    486     if (joinWith.fTop < out->fTop) { out->fTop = joinWith.fTop; }
    487     if (joinWith.fRight > out->fRight) { out->fRight = joinWith.fRight; }
    488     if (joinWith.fBottom > out->fBottom) { out->fBottom = joinWith.fBottom; }
    489 }
    490