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

Unified Diff: src/gpu/GrTBaseList.h

Issue 628453002: Create a single command buffer for GrInOrderDrawBuffer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 2 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
« src/gpu/GrInOrderDrawBuffer.cpp ('K') | « src/gpu/GrInOrderDrawBuffer.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrTBaseList.h
diff --git a/src/gpu/GrTBaseList.h b/src/gpu/GrTBaseList.h
new file mode 100644
index 0000000000000000000000000000000000000000..91125d9eab35b76ab67d275006bc45ed61c15d3e
--- /dev/null
+++ b/src/gpu/GrTBaseList.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTBaseList_DEFINED
+#define GrTBaseList_DEFINED
+
+#include "SkTemplates.h"
+#include "SkTypes.h"
+
+template<typename TBase, typename TAlign> class GrTBaseList;
+template<typename T> class GrTBaseListAllocDesc;
+
+template <typename TBase, typename TAlign, typename T>
+void* operator new(size_t, GrTBaseList<TBase, TAlign>&, const GrTBaseListAllocDesc<T>&);
+
+/**
+ * List of objects with a common base type and permanent memory addresses.
bsalomon 2014/10/08 19:51:44 This thing seems complicated enough, and isolated
Chris Dalton 2014/10/09 00:06:59 Done.
+ *
+ * This class preallocates its own chunks of memory for storing items in the list, so new
+ * objects can be created without excessive calls to malloc().
bsalomon 2014/10/08 19:51:44 Comment about macros to push back? Casual user of
Chris Dalton 2014/10/09 00:06:59 Done.
+ *
+ * @param TBase Common base type of items in the list. If TBase is not a class with a
+ * virtual destructor, the client is responsible for invoking any necessary
+ * destructors.
+ *
+ * For now, any subclass used in the list must have the same start address
+ * as TBase (or in other words, the types must be convertible via
+ * reinterpret_cast<>). Classes with multiple inheritance (or any subclass
+ * on an obscure compiler) may not be compatible. This is verified at
bsalomon 2014/10/08 19:51:45 Can we say "runtime asserted in debug builds" rath
Chris Dalton 2014/10/09 00:06:59 Done.
+ * runtime.
+ *
+ * @param TAlign A type whose size is the desired memory alignment for object allocations.
+ * This should be the largest known alignment requirement for all objects
+ * that may be stored in the buffer.
+ */
+template<typename TBase, typename TAlign> class GrTBaseList : SkNoncopyable {
bsalomon 2014/10/08 19:51:44 I'm having trouble coming up with a better name
+public:
+ class Iter;
+
+ /**
+ * Create a contiguous list
bsalomon 2014/10/08 19:51:44 Can we not say contiguous? That seems like an impl
Chris Dalton 2014/10/09 00:06:59 Oops, I missed that one from before. Done.
+ *
+ * @param initialSizeInBytes The amount of memory reserved by the list initially, and
+ * and after calls to reset().
+ */
+ GrTBaseList(int initialSizeInBytes)
+ : fHeadBlock(bytes_to_length(initialSizeInBytes)),
+ fTailBlock(&fHeadBlock),
+ fLastItem(NULL) {}
+
+ ~GrTBaseList() { this->reset(); }
+
+ bool empty() { return NULL == fLastItem; }
+
+ TBase& back() {
+ SkASSERT(!this->empty());
+ return *fLastItem;
+ }
+
+ /**
+ * Destruct all items in the list and reset to empty.
+ */
+ void reset();
+
+private:
+ static int bytes_to_length(int bytes) { return (bytes + sizeof(TAlign) - 1) / sizeof(TAlign); }
+
+ struct ItemHeader {
+ int fTotalLength;
+ };
+ enum { kHeaderLength = (sizeof(ItemHeader) + sizeof(TAlign) - 1) / sizeof(TAlign) };
+
+ template<typename T> void* alloc_back(const GrTBaseListAllocDesc<T>&);
+
+ struct MemBlock {
+ MemBlock(int length) : fLength(length), fBack(0), fBuffer(fLength) {}
+ const int fLength;
+ int fBack;
+ SkAutoTMalloc<TAlign> fBuffer;
+ SkAutoTDelete<MemBlock> fNext;
+ };
+ MemBlock fHeadBlock;
+ MemBlock* fTailBlock;
+
+ TBase* fLastItem;
+
+ template <typename UBase, typename UAlign, typename U>
+ friend void* operator new(size_t, GrTBaseList<UBase, UAlign>&, const GrTBaseListAllocDesc<U>&);
+
+ friend class Iter;
+};
+
+/**
+ * Describes a new object allocation for GrTBaseList. Captures type and size.
+ */
+template<typename T> class GrTBaseListAllocDesc {
+public:
+ GrTBaseListAllocDesc(int sizeInBytes = sizeof(T)) : fSizeInBytes(sizeInBytes) {}
+ int sizeInBytes() const { return fSizeInBytes; }
+private:
+ const int fSizeInBytes;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename TBase, typename TAlign, typename T>
+void* operator new(size_t expectedClassSize,
bsalomon 2014/10/08 19:51:44 I think you'll need an operator delete. We don't c
Chris Dalton 2014/10/09 00:06:59 Done.
+ GrTBaseList<TBase, TAlign>& list,
+ const GrTBaseListAllocDesc<T>& desc) {
+ SkASSERT(expectedClassSize == sizeof(T));
+ SkASSERT(desc.sizeInBytes() >= (int)sizeof(T));
+ return list.alloc_back(desc);
+}
+
+template<typename TBase, typename TAlign>
+template<typename T>
+void* GrTBaseList<TBase, TAlign>::alloc_back(const GrTBaseListAllocDesc<T>& desc) {
+ SkASSERT(desc.sizeInBytes() >= (int)sizeof(T));
+ const int totalLength = kHeaderLength + bytes_to_length(desc.sizeInBytes());
+
+ if (fTailBlock->fBack + totalLength > fTailBlock->fLength) {
+ SkASSERT(NULL == fTailBlock->fNext.get());
+ MemBlock* next = SkNEW_ARGS(MemBlock, (SkTMax(2 * fTailBlock->fLength, totalLength)));
+ fTailBlock->fNext.reset(next);
+ fTailBlock = next;
+ }
+
+ ItemHeader* header = reinterpret_cast<ItemHeader*>(&fTailBlock->fBuffer[fTailBlock->fBack]);
+ TBase* rawPtr = reinterpret_cast<T*>(&fTailBlock->fBuffer[fTailBlock->fBack + kHeaderLength]);
+ fTailBlock->fBack += totalLength;
+
+ header->fTotalLength = totalLength;
+
+ fLastItem = rawPtr;
+
+ // FIXME: We currently require that the base and subclass share the same start address.
+ // This is not required by the C++ spec, and is likely to not be true in the case of
+ // multiple inheritance or a base class that doesn't have virtual methods (when the
+ // subclass does). It would be ideal to find a more robust solution that comes at no
+ // extra cost to performance or code generality.
+ SkDEBUGCODE(void* baseAddr = fLastItem;
+ void* subclassAddr = rawPtr);
+ SkASSERT(baseAddr == subclassAddr);
+
+ return rawPtr;
+}
+
+template<typename TBase, typename TAlign>
+class GrTBaseList<TBase, TAlign>::Iter {
+public:
+ Iter(GrTBaseList& list) : fBlock(&list.fHeadBlock), fPosition(0), fItem(NULL) {}
+
+ bool next() {
+ if (fPosition >= fBlock->fBack) {
+ SkASSERT(fPosition == fBlock->fBack);
+ if (NULL == fBlock->fNext.get()) {
+ return false;
+ }
+ SkASSERT(0 != fBlock->fNext->fBack);
+ fBlock = fBlock->fNext.get();
+ fPosition = 0;
+ }
+
+ ItemHeader* header = reinterpret_cast<ItemHeader*>(&fBlock->fBuffer[fPosition]);
+ fItem = reinterpret_cast<TBase*>(&fBlock->fBuffer[fPosition + kHeaderLength]);
+ fPosition += header->fTotalLength;
+ return true;
+ }
+
+ TBase* operator->() const {
+ SkASSERT(fItem);
+ return fItem;
+ }
+
+private:
+ MemBlock* fBlock;
+ int fPosition;
+ TBase* fItem;
+};
+
+template<typename TBase, typename TAlign>
+void GrTBaseList<TBase, TAlign>::reset() {
+ Iter iter(*this);
+ while (iter.next()) {
+ iter->~TBase();
+ }
+ fHeadBlock.fBack = 0;
+ fHeadBlock.fNext.free();
+ fTailBlock = &fHeadBlock;
+ fLastItem = NULL;
+}
+
+#define GrNEW_APPEND_TO_TBASELIST(list, type_name, args) \
+ (new (list, GrTBaseListAllocDesc<type_name>()) type_name args)
+
+#define GrNEW_SIZE_APPEND_TO_TBASELIST(list, size, type_name, args) \
+ (new (list, GrTBaseListAllocDesc<type_name>(size)) type_name args)
+
+#endif
« src/gpu/GrInOrderDrawBuffer.cpp ('K') | « src/gpu/GrInOrderDrawBuffer.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698