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

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: Delete dead code 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..b3dee6b1fe90b67038f7e1d8bfcfd5c03e4dc6d7 100644
--- a/src/core/SkQuadTree.h
+++ b/src/core/SkQuadTree.h
@@ -11,6 +11,136 @@
#include "SkRect.h"
#include "SkTDArray.h"
#include "SkBBoxHierarchy.h"
+#include "SkChunkAlloc.h"
+
+/**
+ * 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 it's elements, or ever delete
tomhudson 2014/03/05 11:56:56 Nit: no apostrophe
iancottrell 2014/03/05 12:11:16 Done.
+ * 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.
+ */
+ void takeAll(SkSList<T>& other) {
+ if (isEmpty()) {
+ swap(other);
+ return;
+ }
+ while(!other.isEmpty()) {
tomhudson 2014/03/05 11:56:56 Can't we just graft the other list onto this one?
iancottrell 2014/03/05 12:11:16 Yes, I decided it made the code less readable for
+ 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() {
+ return fHead == NULL;
+ }
+
+ /**
+ * Swaps the contents of this list with another one.
+ */
+ void swap(SkSList<T>& other) {
+ SkTSwap(fHead, other.fHead);
+ }
+
+ /**
+ * Returns the count of elements in the list.
+ */
+ int getCount() {
+ 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]);
+ }
+ }
+
+};
/**
* An QuadTree implementation. In short, it is a tree containing a hierarchy of bounding rectangles
tomhudson 2014/03/05 11:56:56 Nit-among-nits: An -> A?
iancottrell 2014/03/05 12:11:16 Done.
@@ -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) {
tomhudson 2014/03/05 11:56:56 Nit: Skia style has more spaces than you do. (At l
iancottrell 2014/03/05 12:11:16 Done.
+ fChildren[index] = NULL;
+ }
+ }
+ SkSList<Entry> fEntries;
+ SkIRect fBounds;
+ SkIPoint fCenter;
tomhudson 2014/03/05 11:56:56 // Uninitialized until the Node has children (fChi
iancottrell 2014/03/05 12:11:16 Done. Also renamed for clarity.
+ union {
tomhudson 2014/03/05 11:56:56 // A Node is only in a SkFreeList when it is free,
iancottrell 2014/03/05 12:11:16 Done.
+ Node* fNext;
+ Node* fChildren[kChildCount];
+ };
+ };
+
+ SkFreeList<Entry> fAllEntries;
+ SkFreeList<Node> fAllNodes;
tomhudson 2014/03/05 11:56:56 This isn't really *All*Nodes, it's all nodes not c
iancottrell 2014/03/05 12:11:16 Done.
+ 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