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