1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/GrAllocator.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,268 @@ 1.4 +/* 1.5 + * Copyright 2010 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#ifndef GrAllocator_DEFINED 1.12 +#define GrAllocator_DEFINED 1.13 + 1.14 +#include "GrConfig.h" 1.15 +#include "GrTypes.h" 1.16 +#include "SkTArray.h" 1.17 +#include "SkTypes.h" 1.18 + 1.19 +class GrAllocator : public SkNoncopyable { 1.20 +public: 1.21 + ~GrAllocator() { 1.22 + reset(); 1.23 + } 1.24 + 1.25 + /** 1.26 + * Create an allocator 1.27 + * 1.28 + * @param itemSize the size of each item to allocate 1.29 + * @param itemsPerBlock the number of items to allocate at once 1.30 + * @param initialBlock optional memory to use for the first block. 1.31 + * Must be at least itemSize*itemsPerBlock sized. 1.32 + * Caller is responsible for freeing this memory. 1.33 + */ 1.34 + GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) : 1.35 + fItemSize(itemSize), 1.36 + fItemsPerBlock(itemsPerBlock), 1.37 + fOwnFirstBlock(NULL == initialBlock), 1.38 + fCount(0) { 1.39 + SkASSERT(itemsPerBlock > 0); 1.40 + fBlockSize = fItemSize * fItemsPerBlock; 1.41 + fBlocks.push_back() = initialBlock; 1.42 + SkDEBUGCODE(if (!fOwnFirstBlock) {*((char*)initialBlock+fBlockSize-1)='a';} ); 1.43 + } 1.44 + 1.45 + /* 1.46 + * Set first block of memory to write into. Must be called before any other methods. 1.47 + * This requires that you have passed NULL in the constructor. 1.48 + * 1.49 + * @param initialBlock optional memory to use for the first block. 1.50 + * Must be at least itemSize*itemsPerBlock sized. 1.51 + * Caller is responsible for freeing this memory. 1.52 + */ 1.53 + void setInitialBlock(void* initialBlock) { 1.54 + SkASSERT(0 == fCount); 1.55 + SkASSERT(1 == fBlocks.count()); 1.56 + SkASSERT(NULL == fBlocks.back()); 1.57 + fOwnFirstBlock = false; 1.58 + fBlocks.back() = initialBlock; 1.59 + } 1.60 + 1.61 + /** 1.62 + * Adds an item and returns pointer to it. 1.63 + * 1.64 + * @return pointer to the added item. 1.65 + */ 1.66 + void* push_back() { 1.67 + int indexInBlock = fCount % fItemsPerBlock; 1.68 + // we always have at least one block 1.69 + if (0 == indexInBlock) { 1.70 + if (0 != fCount) { 1.71 + fBlocks.push_back() = sk_malloc_throw(fBlockSize); 1.72 + } else if (fOwnFirstBlock) { 1.73 + fBlocks[0] = sk_malloc_throw(fBlockSize); 1.74 + } 1.75 + } 1.76 + void* ret = (char*)fBlocks[fCount/fItemsPerBlock] + 1.77 + fItemSize * indexInBlock; 1.78 + ++fCount; 1.79 + return ret; 1.80 + } 1.81 + 1.82 + /** 1.83 + * removes all added items 1.84 + */ 1.85 + void reset() { 1.86 + int blockCount = GrMax((unsigned)1, 1.87 + GrUIDivRoundUp(fCount, fItemsPerBlock)); 1.88 + for (int i = 1; i < blockCount; ++i) { 1.89 + sk_free(fBlocks[i]); 1.90 + } 1.91 + if (fOwnFirstBlock) { 1.92 + sk_free(fBlocks[0]); 1.93 + fBlocks[0] = NULL; 1.94 + } 1.95 + fBlocks.pop_back_n(blockCount-1); 1.96 + fCount = 0; 1.97 + } 1.98 + 1.99 + /** 1.100 + * count of items 1.101 + */ 1.102 + int count() const { 1.103 + return fCount; 1.104 + } 1.105 + 1.106 + /** 1.107 + * is the count 0 1.108 + */ 1.109 + bool empty() const { return fCount == 0; } 1.110 + 1.111 + /** 1.112 + * access last item, only call if count() != 0 1.113 + */ 1.114 + void* back() { 1.115 + SkASSERT(fCount); 1.116 + return (*this)[fCount-1]; 1.117 + } 1.118 + 1.119 + /** 1.120 + * access last item, only call if count() != 0 1.121 + */ 1.122 + const void* back() const { 1.123 + SkASSERT(fCount); 1.124 + return (*this)[fCount-1]; 1.125 + } 1.126 + 1.127 + /** 1.128 + * access item by index. 1.129 + */ 1.130 + void* operator[] (int i) { 1.131 + SkASSERT(i >= 0 && i < fCount); 1.132 + return (char*)fBlocks[i / fItemsPerBlock] + 1.133 + fItemSize * (i % fItemsPerBlock); 1.134 + } 1.135 + 1.136 + /** 1.137 + * access item by index. 1.138 + */ 1.139 + const void* operator[] (int i) const { 1.140 + SkASSERT(i >= 0 && i < fCount); 1.141 + return (const char*)fBlocks[i / fItemsPerBlock] + 1.142 + fItemSize * (i % fItemsPerBlock); 1.143 + } 1.144 + 1.145 +private: 1.146 + static const int NUM_INIT_BLOCK_PTRS = 8; 1.147 + 1.148 + SkSTArray<NUM_INIT_BLOCK_PTRS, void*> fBlocks; 1.149 + size_t fBlockSize; 1.150 + size_t fItemSize; 1.151 + int fItemsPerBlock; 1.152 + bool fOwnFirstBlock; 1.153 + int fCount; 1.154 + 1.155 + typedef SkNoncopyable INHERITED; 1.156 +}; 1.157 + 1.158 +template <typename T> 1.159 +class GrTAllocator : public SkNoncopyable { 1.160 +public: 1.161 + virtual ~GrTAllocator() { this->reset(); }; 1.162 + 1.163 + /** 1.164 + * Create an allocator 1.165 + * 1.166 + * @param itemsPerBlock the number of items to allocate at once 1.167 + */ 1.168 + explicit GrTAllocator(int itemsPerBlock) 1.169 + : fAllocator(sizeof(T), itemsPerBlock, NULL) {} 1.170 + 1.171 + /** 1.172 + * Adds an item and returns it. 1.173 + * 1.174 + * @return the added item. 1.175 + */ 1.176 + T& push_back() { 1.177 + void* item = fAllocator.push_back(); 1.178 + SkASSERT(NULL != item); 1.179 + SkNEW_PLACEMENT(item, T); 1.180 + return *(T*)item; 1.181 + } 1.182 + 1.183 + T& push_back(const T& t) { 1.184 + void* item = fAllocator.push_back(); 1.185 + SkASSERT(NULL != item); 1.186 + SkNEW_PLACEMENT_ARGS(item, T, (t)); 1.187 + return *(T*)item; 1.188 + } 1.189 + 1.190 + /** 1.191 + * removes all added items 1.192 + */ 1.193 + void reset() { 1.194 + int c = fAllocator.count(); 1.195 + for (int i = 0; i < c; ++i) { 1.196 + ((T*)fAllocator[i])->~T(); 1.197 + } 1.198 + fAllocator.reset(); 1.199 + } 1.200 + 1.201 + /** 1.202 + * count of items 1.203 + */ 1.204 + int count() const { 1.205 + return fAllocator.count(); 1.206 + } 1.207 + 1.208 + /** 1.209 + * is the count 0 1.210 + */ 1.211 + bool empty() const { return fAllocator.empty(); } 1.212 + 1.213 + /** 1.214 + * access last item, only call if count() != 0 1.215 + */ 1.216 + T& back() { 1.217 + return *(T*)fAllocator.back(); 1.218 + } 1.219 + 1.220 + /** 1.221 + * access last item, only call if count() != 0 1.222 + */ 1.223 + const T& back() const { 1.224 + return *(const T*)fAllocator.back(); 1.225 + } 1.226 + 1.227 + /** 1.228 + * access item by index. 1.229 + */ 1.230 + T& operator[] (int i) { 1.231 + return *(T*)(fAllocator[i]); 1.232 + } 1.233 + 1.234 + /** 1.235 + * access item by index. 1.236 + */ 1.237 + const T& operator[] (int i) const { 1.238 + return *(const T*)(fAllocator[i]); 1.239 + } 1.240 + 1.241 +protected: 1.242 + /* 1.243 + * Set first block of memory to write into. Must be called before any other methods. 1.244 + * 1.245 + * @param initialBlock optional memory to use for the first block. 1.246 + * Must be at least size(T)*itemsPerBlock sized. 1.247 + * Caller is responsible for freeing this memory. 1.248 + */ 1.249 + void setInitialBlock(void* initialBlock) { 1.250 + fAllocator.setInitialBlock(initialBlock); 1.251 + } 1.252 + 1.253 +private: 1.254 + GrAllocator fAllocator; 1.255 + typedef SkNoncopyable INHERITED; 1.256 +}; 1.257 + 1.258 +template <int N, typename T> class GrSTAllocator : public GrTAllocator<T> { 1.259 +private: 1.260 + typedef GrTAllocator<T> INHERITED; 1.261 + 1.262 +public: 1.263 + GrSTAllocator() : INHERITED(N) { 1.264 + this->setInitialBlock(fStorage.get()); 1.265 + } 1.266 + 1.267 +private: 1.268 + SkAlignedSTStorage<N, T> fStorage; 1.269 +}; 1.270 + 1.271 +#endif