Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Unified Diff: src/core/SkQuadTree.h

Issue 187233002: Fast implementation of QuadTree (Closed) Base URL: https://skia.googlesource.com/skia.git@bbh_select
Patch Set: Reveiw fixes, renaming Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/core/SkQuadTree.cpp » ('j') | src/core/SkQuadTree.cpp » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkQuadTree.h
diff --git a/src/core/SkQuadTree.h b/src/core/SkQuadTree.h
index a26174960953d97a039cb94d6b2cbf895ddb7b9b..fca99a007403bd17e0dbe80d8380d484479bccb1 100644
--- a/src/core/SkQuadTree.h
+++ b/src/core/SkQuadTree.h
@@ -13,7 +13,137 @@
#include "SkBBoxHierarchy.h"
robertphillips 2014/03/05 13:08:53 Might be worth mirroring SkTInternalList.h
iancottrell 2014/03/07 15:06:34 Done.
/**
- * An QuadTree implementation. In short, it is a tree containing a hierarchy of bounding rectangles
+ * An implementation of an intrusive singly linked list.
+ * The type T must have a field fNext that is visible to the list.
+ * The list does not maintain ownership of any of its elements, or ever delete
+ * them.
+ * The fNext must be null on any object handed to push, and will be NULL when
+ * returned from pop. It is free to use while the object is not in the a list.
+ */
+template<typename T> class SkSList {
+public:
+ SkSList() : fHead(NULL), fCount(0) {}
+
+ /**
+ * Push an item onto the head of the list.
+ * This method is *not* thread safe.
+ */
+ void push(T* entry) {
+ SkASSERT(entry->fNext == NULL);
+ entry->fNext = fHead;
+ fHead = entry;
+ ++fCount;
+ }
+
+ /**
+ * Takes all the items from another list.
reed1 2014/03/05 14:33:01 Are they added to the head or the tail of this lis
iancottrell 2014/03/07 15:06:34 Done.
+ */
+ void takeAll(SkSList<T>& other) {
reed1 2014/03/05 14:33:01 typically in Skia if the argument is changed, we p
iancottrell 2014/03/07 15:06:34 Done.
+ if (isEmpty()) {
+ swap(other);
+ return;
+ }
+ while(!other.isEmpty()) {
+ push(other.pop());
+ }
+ }
+
+ /**
+ * Pop an item from the head of the list.
+ * Returns NULL if the list is empty.
+ * This method is *not* thread safe.
+ */
+ T* pop() {
+ if (fHead == NULL) {
+ return NULL;
+ }
+ T* result = fHead;
+ fHead = result->fNext;
+ result->fNext = NULL;
+ --fCount;
+ return result;
+ }
+
+ T* head() {
+ return fHead;
+ }
+
+ /**
+ * Returns true if the list has no elements.
+ */
+ bool isEmpty() {
reed1 2014/03/05 14:33:01 const
iancottrell 2014/03/07 15:06:34 Done.
+ return fHead == NULL;
reed1 2014/03/05 14:33:01 tiny nit: Skia tries to be paranoid, and writes th
iancottrell 2014/03/07 15:06:34 Done.
+ }
+
+ /**
+ * Swaps the contents of this list with another one.
+ */
+ void swap(SkSList<T>& other) {
+ SkTSwap(fHead, other.fHead);
+ SkTSwap(fCount, other.fCount);
+ }
+
+ /**
+ * Returns the count of elements in the list.
+ */
+ int getCount() {
reed1 2014/03/05 14:33:01 const
iancottrell 2014/03/07 15:06:34 Done.
+ return fCount;
+ }
+private:
+ T* fHead;
+ int fCount;
+};
+
+
+/**
+ * An implementation of a self growing free list of objects.
+ * Constructors and destructors will be called on the objects.
+ * All memory will be reclaimed when the free list is destroyed, so the free
+ * list must survive longer than you are using any item taken from it.
+ */
+template<typename T, int growth = 4096/sizeof(T)> class SkFreeList : public SkSList<T> {
+public:
+ SkFreeList() {}
+ ~SkFreeList() {
+ while(!fBlocks.isEmpty()) { SkDELETE(fBlocks.pop()); }
+ }
+ /**
+ * Get an item from the free list.
+ * If the free list has no items, it will grow.
+ * The free list will never shrink, it will use the maximum memory it has
+ * ever reached until destroyed.
+ * The returned item is only valid as long as the free list has not been
+ * destroyed, at that point all memory allocated by grow will have been
+ * reclaimed.
+ * This method is *not* thread safe.
+ */
+ T* pop() {
+ if (this->isEmpty()) { grow(); }
+ return SkSList<T>::pop();
+ }
+private:
+ /**
+ * The type for a new block of entries for the list.
+ */
+ struct Block {
+ Block() : fNext(0) {}
+ Block* fNext;
+ T entries[growth];
+ };
+ SkSList<Block> fBlocks;
+
+ void grow() {
+ Block* block = SkNEW(Block);
+ fBlocks.push(block);
+ for(int index = 0; index < growth; ++index) {
+ push(&block->entries[index]);
+ }
+ }
+
+};
+
+/**
+ * A QuadTree implementation. In short, it is a tree containing a hierarchy of bounding rectangles
* in which each internal node has exactly four children.
*
* For more details see:
@@ -43,7 +173,7 @@ public:
/**
* If any inserts have been deferred, this will add them into the tree
*/
- virtual void flushDeferredInserts() SK_OVERRIDE {}
+ virtual void flushDeferredInserts() SK_OVERRIDE;
/**
* Given a query rectangle, populates the passed-in array with the elements it intersects
@@ -60,19 +190,47 @@ public:
/**
* This gets the insertion count (rather than the node count)
*/
- virtual int getCount() const SK_OVERRIDE { return fCount; }
+ virtual int getCount() const SK_OVERRIDE { return fEntryCount; }
virtual void rewindInserts() SK_OVERRIDE;
private:
- class QuadTreeNode;
+ struct Entry {
+ Entry() : fNext(NULL), fData(NULL) {}
+ Entry* fNext;
+ SkIRect fBounds;
+ void* fData;
+ };
+
+ static const int kChildCount = 4;
+
+ struct Node {
+ Node() : fNext(NULL) {
+ for (int index=0; index<kChildCount; ++index) {
+ fChildren[index] = NULL;
+ }
+ }
+ SkSList<Entry> fEntries;
+ SkIRect fBounds;
+ SkIPoint fSplitPoint; // Only valid if the node has children.
+ union { // Unioned only to save space
+ Node* fNext; // Used when in a free list, where it has no children.
+ Node* fChildren[kChildCount];
+ };
+ };
+
+ SkFreeList<Entry> fFreeEntries;
+ SkFreeList<Node> fFreeNodes;
+ int fEntryCount;
+ Node* fRoot;
+ SkSList<Entry> fDeferred;
SkQuadTree(const SkIRect& bounds);
-
- // This is the count of data elements (rather than total nodes in the tree)
- int fCount;
-
- QuadTreeNode* fRoot;
+ Node* pickChild(Node* node, const SkIRect& bounds) const;
+ void insert(Node* node, Entry* entry);
+ void search(Node* node, const SkIRect& query, SkTDArray<void*>* results) const;
+ void clear(Node* node);
+ int getDepth(Node* node) const;
typedef SkBBoxHierarchy INHERITED;
};
« no previous file with comments | « no previous file | src/core/SkQuadTree.cpp » ('j') | src/core/SkQuadTree.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698