blob: 226f45196e4afdb002ac989c4940534ad9306317 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2010 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
bsalomon@google.com1c13c962011-02-14 16:51:21 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
bsalomon@google.com1c13c962011-02-14 16:51:21 +000010#include "GrBufferAllocPool.h"
bsalomon@google.comc26d94f2013-03-25 18:19:00 +000011#include "GrDrawTargetCaps.h"
12#include "GrGpu.h"
13#include "GrIndexBuffer.h"
bsalomon@google.com1c13c962011-02-14 16:51:21 +000014#include "GrTypes.h"
15#include "GrVertexBuffer.h"
bsalomon@google.com1c13c962011-02-14 16:51:21 +000016
bsalomon3512eda2014-06-26 12:56:22 -070017#include "SkTraceEvent.h"
18
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000019#ifdef SK_DEBUG
bsalomon@google.com1c13c962011-02-14 16:51:21 +000020 #define VALIDATE validate
21#else
sugoi@google.come0e385c2013-03-11 18:50:03 +000022 static void VALIDATE(bool = false) {}
bsalomon@google.com1c13c962011-02-14 16:51:21 +000023#endif
24
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000025// page size
bsalomon@google.com1c13c962011-02-14 16:51:21 +000026#define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 12)
27
bsalomon3512eda2014-06-26 12:56:22 -070028#define UNMAP_BUFFER(block) \
29do { \
30 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), \
31 "GrBufferAllocPool Unmapping Buffer", \
32 TRACE_EVENT_SCOPE_THREAD, \
33 "percent_unwritten", \
34 (float)((block).fBytesFree) / (block).fBuffer->gpuMemorySize()); \
35 (block).fBuffer->unmap(); \
36} while (false)
37
bsalomon@google.com1c13c962011-02-14 16:51:21 +000038GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu,
39 BufferType bufferType,
40 bool frequentResetHint,
41 size_t blockSize,
42 int preallocBufferCnt) :
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000043 fBlocks(SkTMax(8, 2*preallocBufferCnt)) {
bsalomon@google.com11f0b512011-03-29 20:52:23 +000044
bsalomon49f085d2014-09-05 13:34:00 -070045 SkASSERT(gpu);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000046 fGpu = gpu;
bsalomon@google.com11f0b512011-03-29 20:52:23 +000047 fGpu->ref();
48 fGpuIsReffed = true;
49
bsalomon@google.com1c13c962011-02-14 16:51:21 +000050 fBufferType = bufferType;
51 fFrequentResetHint = frequentResetHint;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000052 fBufferPtr = NULL;
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000053 fMinBlockSize = SkTMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000054
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000055 fBytesInUse = 0;
bsalomon@google.comb665a6b2012-03-01 20:59:28 +000056
bsalomon@google.com1c13c962011-02-14 16:51:21 +000057 fPreallocBuffersInUse = 0;
bsalomon@google.comb665a6b2012-03-01 20:59:28 +000058 fPreallocBufferStartIdx = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000059 for (int i = 0; i < preallocBufferCnt; ++i) {
60 GrGeometryBuffer* buffer = this->createBuffer(fMinBlockSize);
bsalomon49f085d2014-09-05 13:34:00 -070061 if (buffer) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000062 *fPreallocBuffers.append() = buffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000063 }
64 }
65}
66
67GrBufferAllocPool::~GrBufferAllocPool() {
68 VALIDATE();
69 if (fBlocks.count()) {
70 GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +000071 if (buffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -070072 UNMAP_BUFFER(fBlocks.back());
bsalomon@google.com1c13c962011-02-14 16:51:21 +000073 }
74 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +000075 while (!fBlocks.empty()) {
76 destroyBlock();
77 }
bsalomon@google.com11f0b512011-03-29 20:52:23 +000078 fPreallocBuffers.unrefAll();
79 releaseGpuRef();
80}
81
82void GrBufferAllocPool::releaseGpuRef() {
83 if (fGpuIsReffed) {
84 fGpu->unref();
85 fGpuIsReffed = false;
86 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +000087}
88
89void GrBufferAllocPool::reset() {
90 VALIDATE();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000091 fBytesInUse = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000092 if (fBlocks.count()) {
93 GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +000094 if (buffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -070095 UNMAP_BUFFER(fBlocks.back());
bsalomon@google.com1c13c962011-02-14 16:51:21 +000096 }
97 }
bsalomon@google.comb665a6b2012-03-01 20:59:28 +000098 // fPreallocBuffersInUse will be decremented down to zero in the while loop
99 int preallocBuffersInUse = fPreallocBuffersInUse;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000100 while (!fBlocks.empty()) {
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000101 this->destroyBlock();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000102 }
103 if (fPreallocBuffers.count()) {
104 // must set this after above loop.
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000105 fPreallocBufferStartIdx = (fPreallocBufferStartIdx +
106 preallocBuffersInUse) %
107 fPreallocBuffers.count();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000108 }
bsalomon@google.com987dbc02011-12-14 14:44:19 +0000109 // we may have created a large cpu mirror of a large VB. Reset the size
110 // to match our pre-allocated VBs.
111 fCpuData.reset(fMinBlockSize);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000112 SkASSERT(0 == fPreallocBuffersInUse);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000113 VALIDATE();
114}
115
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000116void GrBufferAllocPool::unmap() {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000117 VALIDATE();
118
bsalomon49f085d2014-09-05 13:34:00 -0700119 if (fBufferPtr) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000120 BufferBlock& block = fBlocks.back();
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000121 if (block.fBuffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -0700122 UNMAP_BUFFER(block);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000123 } else {
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000124 size_t flushSize = block.fBuffer->gpuMemorySize() - block.fBytesFree;
bsalomon3512eda2014-06-26 12:56:22 -0700125 this->flushCpuData(fBlocks.back(), flushSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000126 }
127 fBufferPtr = NULL;
128 }
129 VALIDATE();
130}
131
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000132#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000133void GrBufferAllocPool::validate(bool unusedBlockAllowed) const {
bsalomon49f085d2014-09-05 13:34:00 -0700134 if (fBufferPtr) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000135 SkASSERT(!fBlocks.empty());
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000136 if (fBlocks.back().fBuffer->isMapped()) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000137 GrGeometryBuffer* buf = fBlocks.back().fBuffer;
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000138 SkASSERT(buf->mapPtr() == fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000139 } else {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000140 SkASSERT(fCpuData.get() == fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000141 }
142 } else {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000143 SkASSERT(fBlocks.empty() || !fBlocks.back().fBuffer->isMapped());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000144 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000145 size_t bytesInUse = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000146 for (int i = 0; i < fBlocks.count() - 1; ++i) {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000147 SkASSERT(!fBlocks[i].fBuffer->isMapped());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000148 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000149 for (int i = 0; i < fBlocks.count(); ++i) {
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000150 size_t bytes = fBlocks[i].fBuffer->gpuMemorySize() - fBlocks[i].fBytesFree;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000151 bytesInUse += bytes;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000152 SkASSERT(bytes || unusedBlockAllowed);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000153 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000154
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000155 SkASSERT(bytesInUse == fBytesInUse);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000156 if (unusedBlockAllowed) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000157 SkASSERT((fBytesInUse && !fBlocks.empty()) ||
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000158 (!fBytesInUse && (fBlocks.count() < 2)));
159 } else {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000160 SkASSERT((0 == fBytesInUse) == fBlocks.empty());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000161 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000162}
163#endif
164
165void* GrBufferAllocPool::makeSpace(size_t size,
166 size_t alignment,
167 const GrGeometryBuffer** buffer,
168 size_t* offset) {
169 VALIDATE();
170
bsalomon49f085d2014-09-05 13:34:00 -0700171 SkASSERT(buffer);
172 SkASSERT(offset);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000173
bsalomon49f085d2014-09-05 13:34:00 -0700174 if (fBufferPtr) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000175 BufferBlock& back = fBlocks.back();
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000176 size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000177 size_t pad = GrSizeAlignUpPad(usedBytes,
178 alignment);
179 if ((size + pad) <= back.fBytesFree) {
180 usedBytes += pad;
181 *offset = usedBytes;
182 *buffer = back.fBuffer;
183 back.fBytesFree -= size + pad;
bsalomon@google.comd5108092012-03-08 15:10:39 +0000184 fBytesInUse += size + pad;
185 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000186 return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
187 }
188 }
189
bsalomon@google.com96e96df2011-10-10 14:49:29 +0000190 // We could honor the space request using by a partial update of the current
191 // VB (if there is room). But we don't currently use draw calls to GL that
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000192 // allow the driver to know that previously issued draws won't read from
bsalomon@google.com96e96df2011-10-10 14:49:29 +0000193 // the part of the buffer we update. Also, the GL buffer implementation
194 // may be cheating on the actual buffer size by shrinking the buffer on
195 // updateData() if the amount of data passed is less than the full buffer
196 // size.
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000197
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000198 if (!createBlock(size)) {
199 return NULL;
200 }
bsalomon49f085d2014-09-05 13:34:00 -0700201 SkASSERT(fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000202
203 *offset = 0;
204 BufferBlock& back = fBlocks.back();
205 *buffer = back.fBuffer;
206 back.fBytesFree -= size;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000207 fBytesInUse += size;
208 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000209 return fBufferPtr;
210}
211
212int GrBufferAllocPool::currentBufferItems(size_t itemSize) const {
213 VALIDATE();
bsalomon49f085d2014-09-05 13:34:00 -0700214 if (fBufferPtr) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000215 const BufferBlock& back = fBlocks.back();
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000216 size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000217 size_t pad = GrSizeAlignUpPad(usedBytes, itemSize);
robertphillips@google.comadacc702013-10-14 21:53:24 +0000218 return static_cast<int>((back.fBytesFree - pad) / itemSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000219 } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
robertphillips@google.comadacc702013-10-14 21:53:24 +0000220 return static_cast<int>(fMinBlockSize / itemSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000221 }
222 return 0;
223}
224
225int GrBufferAllocPool::preallocatedBuffersRemaining() const {
226 return fPreallocBuffers.count() - fPreallocBuffersInUse;
227}
228
229int GrBufferAllocPool::preallocatedBufferCount() const {
230 return fPreallocBuffers.count();
231}
232
233void GrBufferAllocPool::putBack(size_t bytes) {
234 VALIDATE();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000235
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000236 // if the putBack unwinds all the preallocated buffers then we will
237 // advance the starting index. As blocks are destroyed fPreallocBuffersInUse
238 // will be decremented. I will reach zero if all blocks using preallocated
239 // buffers are released.
240 int preallocBuffersInUse = fPreallocBuffersInUse;
241
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000242 while (bytes) {
243 // caller shouldnt try to put back more than they've taken
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000244 SkASSERT(!fBlocks.empty());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000245 BufferBlock& block = fBlocks.back();
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000246 size_t bytesUsed = block.fBuffer->gpuMemorySize() - block.fBytesFree;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000247 if (bytes >= bytesUsed) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000248 bytes -= bytesUsed;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000249 fBytesInUse -= bytesUsed;
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000250 // if we locked a vb to satisfy the make space and we're releasing
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000251 // beyond it, then unmap it.
252 if (block.fBuffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -0700253 UNMAP_BUFFER(block);
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000254 }
255 this->destroyBlock();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000256 } else {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000257 block.fBytesFree += bytes;
258 fBytesInUse -= bytes;
259 bytes = 0;
260 break;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000261 }
262 }
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000263 if (!fPreallocBuffersInUse && fPreallocBuffers.count()) {
264 fPreallocBufferStartIdx = (fPreallocBufferStartIdx +
265 preallocBuffersInUse) %
266 fPreallocBuffers.count();
267 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000268 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000269}
270
271bool GrBufferAllocPool::createBlock(size_t requestSize) {
272
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000273 size_t size = SkTMax(requestSize, fMinBlockSize);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000274 SkASSERT(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000275
276 VALIDATE();
277
278 BufferBlock& block = fBlocks.push_back();
279
280 if (size == fMinBlockSize &&
281 fPreallocBuffersInUse < fPreallocBuffers.count()) {
282
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000283 uint32_t nextBuffer = (fPreallocBuffersInUse +
284 fPreallocBufferStartIdx) %
285 fPreallocBuffers.count();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000286 block.fBuffer = fPreallocBuffers[nextBuffer];
287 block.fBuffer->ref();
288 ++fPreallocBuffersInUse;
289 } else {
290 block.fBuffer = this->createBuffer(size);
291 if (NULL == block.fBuffer) {
292 fBlocks.pop_back();
293 return false;
294 }
295 }
296
297 block.fBytesFree = size;
bsalomon49f085d2014-09-05 13:34:00 -0700298 if (fBufferPtr) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000299 SkASSERT(fBlocks.count() > 1);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000300 BufferBlock& prev = fBlocks.fromBack(1);
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000301 if (prev.fBuffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -0700302 UNMAP_BUFFER(prev);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000303 } else {
bsalomon3512eda2014-06-26 12:56:22 -0700304 this->flushCpuData(prev, prev.fBuffer->gpuMemorySize() - prev.fBytesFree);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000305 }
306 fBufferPtr = NULL;
307 }
308
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000309 SkASSERT(NULL == fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000310
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000311 // If the buffer is CPU-backed we map it because it is free to do so and saves a copy.
312 // Otherwise when buffer mapping is supported:
313 // a) If the frequently reset hint is set we only map when the requested size meets a
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +0000314 // threshold (since we don't expect it is likely that we will see more vertex data)
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000315 // b) If the hint is not set we map if the buffer size is greater than the threshold.
316 bool attemptMap = block.fBuffer->isCPUBacked();
317 if (!attemptMap && GrDrawTargetCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags()) {
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +0000318 if (fFrequentResetHint) {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000319 attemptMap = requestSize > GR_GEOM_BUFFER_MAP_THRESHOLD;
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +0000320 } else {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000321 attemptMap = size > GR_GEOM_BUFFER_MAP_THRESHOLD;
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +0000322 }
323 }
324
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000325 if (attemptMap) {
326 fBufferPtr = block.fBuffer->map();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000327 }
328
329 if (NULL == fBufferPtr) {
bsalomon@google.com7d4679a2011-09-02 22:06:24 +0000330 fBufferPtr = fCpuData.reset(size);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000331 }
332
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000333 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000334
335 return true;
336}
337
338void GrBufferAllocPool::destroyBlock() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000339 SkASSERT(!fBlocks.empty());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000340
341 BufferBlock& block = fBlocks.back();
342 if (fPreallocBuffersInUse > 0) {
343 uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000344 fPreallocBufferStartIdx +
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000345 (fPreallocBuffers.count() - 1)) %
346 fPreallocBuffers.count();
347 if (block.fBuffer == fPreallocBuffers[prevPreallocBuffer]) {
348 --fPreallocBuffersInUse;
349 }
350 }
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000351 SkASSERT(!block.fBuffer->isMapped());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000352 block.fBuffer->unref();
353 fBlocks.pop_back();
354 fBufferPtr = NULL;
355}
356
bsalomon3512eda2014-06-26 12:56:22 -0700357void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize) {
358 GrGeometryBuffer* buffer = block.fBuffer;
bsalomon49f085d2014-09-05 13:34:00 -0700359 SkASSERT(buffer);
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000360 SkASSERT(!buffer->isMapped());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000361 SkASSERT(fCpuData.get() == fBufferPtr);
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000362 SkASSERT(flushSize <= buffer->gpuMemorySize());
bsalomon@google.comd5108092012-03-08 15:10:39 +0000363 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000364
commit-bot@chromium.org160b4782014-05-05 12:32:37 +0000365 if (GrDrawTargetCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() &&
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000366 flushSize > GR_GEOM_BUFFER_MAP_THRESHOLD) {
367 void* data = buffer->map();
bsalomon49f085d2014-09-05 13:34:00 -0700368 if (data) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000369 memcpy(data, fBufferPtr, flushSize);
bsalomon3512eda2014-06-26 12:56:22 -0700370 UNMAP_BUFFER(block);
bsalomon@google.com71bd1ef2011-12-12 20:42:26 +0000371 return;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000372 }
373 }
374 buffer->updateData(fBufferPtr, flushSize);
bsalomon@google.comd5108092012-03-08 15:10:39 +0000375 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000376}
377
378GrGeometryBuffer* GrBufferAllocPool::createBuffer(size_t size) {
379 if (kIndex_BufferType == fBufferType) {
380 return fGpu->createIndexBuffer(size, true);
381 } else {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000382 SkASSERT(kVertex_BufferType == fBufferType);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000383 return fGpu->createVertexBuffer(size, true);
384 }
385}
386
387////////////////////////////////////////////////////////////////////////////////
388
389GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
390 bool frequentResetHint,
391 size_t bufferSize,
392 int preallocBufferCnt)
393: GrBufferAllocPool(gpu,
394 kVertex_BufferType,
395 frequentResetHint,
396 bufferSize,
397 preallocBufferCnt) {
398}
399
jvanverth@google.coma6338982013-01-31 21:34:25 +0000400void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000401 int vertexCount,
402 const GrVertexBuffer** buffer,
403 int* startVertex) {
404
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000405 SkASSERT(vertexCount >= 0);
bsalomon49f085d2014-09-05 13:34:00 -0700406 SkASSERT(buffer);
407 SkASSERT(startVertex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000408
bsalomon@google.com8b484412011-04-18 19:07:44 +0000409 size_t offset = 0; // assign to suppress warning
410 const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
jvanverth@google.coma6338982013-01-31 21:34:25 +0000411 void* ptr = INHERITED::makeSpace(vertexSize * vertexCount,
412 vertexSize,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000413 &geomBuffer,
414 &offset);
415
416 *buffer = (const GrVertexBuffer*) geomBuffer;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000417 SkASSERT(0 == offset % vertexSize);
robertphillips@google.comadacc702013-10-14 21:53:24 +0000418 *startVertex = static_cast<int>(offset / vertexSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000419 return ptr;
420}
421
jvanverth@google.coma6338982013-01-31 21:34:25 +0000422bool GrVertexBufferAllocPool::appendVertices(size_t vertexSize,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000423 int vertexCount,
424 const void* vertices,
425 const GrVertexBuffer** buffer,
426 int* startVertex) {
jvanverth@google.coma6338982013-01-31 21:34:25 +0000427 void* space = makeSpace(vertexSize, vertexCount, buffer, startVertex);
bsalomon49f085d2014-09-05 13:34:00 -0700428 if (space) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000429 memcpy(space,
430 vertices,
jvanverth@google.coma6338982013-01-31 21:34:25 +0000431 vertexSize * vertexCount);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000432 return true;
433 } else {
434 return false;
435 }
436}
437
jvanverth@google.coma6338982013-01-31 21:34:25 +0000438int GrVertexBufferAllocPool::preallocatedBufferVertices(size_t vertexSize) const {
robertphillips@google.comadacc702013-10-14 21:53:24 +0000439 return static_cast<int>(INHERITED::preallocatedBufferSize() / vertexSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000440}
441
jvanverth@google.coma6338982013-01-31 21:34:25 +0000442int GrVertexBufferAllocPool::currentBufferVertices(size_t vertexSize) const {
443 return currentBufferItems(vertexSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000444}
445
446////////////////////////////////////////////////////////////////////////////////
447
448GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu,
449 bool frequentResetHint,
450 size_t bufferSize,
451 int preallocBufferCnt)
452: GrBufferAllocPool(gpu,
453 kIndex_BufferType,
454 frequentResetHint,
455 bufferSize,
456 preallocBufferCnt) {
457}
458
459void* GrIndexBufferAllocPool::makeSpace(int indexCount,
460 const GrIndexBuffer** buffer,
461 int* startIndex) {
462
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000463 SkASSERT(indexCount >= 0);
bsalomon49f085d2014-09-05 13:34:00 -0700464 SkASSERT(buffer);
465 SkASSERT(startIndex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000466
bsalomon@google.com8b484412011-04-18 19:07:44 +0000467 size_t offset = 0; // assign to suppress warning
468 const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000469 void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t),
470 sizeof(uint16_t),
471 &geomBuffer,
472 &offset);
473
474 *buffer = (const GrIndexBuffer*) geomBuffer;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000475 SkASSERT(0 == offset % sizeof(uint16_t));
robertphillips@google.comadacc702013-10-14 21:53:24 +0000476 *startIndex = static_cast<int>(offset / sizeof(uint16_t));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000477 return ptr;
478}
479
480bool GrIndexBufferAllocPool::appendIndices(int indexCount,
481 const void* indices,
482 const GrIndexBuffer** buffer,
483 int* startIndex) {
484 void* space = makeSpace(indexCount, buffer, startIndex);
bsalomon49f085d2014-09-05 13:34:00 -0700485 if (space) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000486 memcpy(space, indices, sizeof(uint16_t) * indexCount);
487 return true;
488 } else {
489 return false;
490 }
491}
492
493int GrIndexBufferAllocPool::preallocatedBufferIndices() const {
robertphillips@google.comadacc702013-10-14 21:53:24 +0000494 return static_cast<int>(INHERITED::preallocatedBufferSize() / sizeof(uint16_t));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000495}
496
497int GrIndexBufferAllocPool::currentBufferIndices() const {
498 return currentBufferItems(sizeof(uint16_t));
499}