blob: f23311877bd4c8387e21fc31f13ea56ad54ec488 [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 {
bsalomon71cb0c22014-11-14 12:10:14 -0800134 bool wasDestroyed = false;
bsalomon49f085d2014-09-05 13:34:00 -0700135 if (fBufferPtr) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000136 SkASSERT(!fBlocks.empty());
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000137 if (fBlocks.back().fBuffer->isMapped()) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000138 GrGeometryBuffer* buf = fBlocks.back().fBuffer;
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000139 SkASSERT(buf->mapPtr() == fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000140 } else {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000141 SkASSERT(fCpuData.get() == fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000142 }
143 } else {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000144 SkASSERT(fBlocks.empty() || !fBlocks.back().fBuffer->isMapped());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000145 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000146 size_t bytesInUse = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000147 for (int i = 0; i < fBlocks.count() - 1; ++i) {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000148 SkASSERT(!fBlocks[i].fBuffer->isMapped());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000149 }
bsalomon71cb0c22014-11-14 12:10:14 -0800150 for (int i = 0; !wasDestroyed && i < fBlocks.count(); ++i) {
151 if (fBlocks[i].fBuffer->wasDestroyed()) {
152 wasDestroyed = true;
153 } else {
154 size_t bytes = fBlocks[i].fBuffer->gpuMemorySize() - fBlocks[i].fBytesFree;
155 bytesInUse += bytes;
156 SkASSERT(bytes || unusedBlockAllowed);
157 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000158 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000159
bsalomon71cb0c22014-11-14 12:10:14 -0800160 if (!wasDestroyed) {
161 SkASSERT(bytesInUse == fBytesInUse);
162 if (unusedBlockAllowed) {
163 SkASSERT((fBytesInUse && !fBlocks.empty()) ||
164 (!fBytesInUse && (fBlocks.count() < 2)));
165 } else {
166 SkASSERT((0 == fBytesInUse) == fBlocks.empty());
167 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000168 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000169}
170#endif
171
172void* GrBufferAllocPool::makeSpace(size_t size,
173 size_t alignment,
174 const GrGeometryBuffer** buffer,
175 size_t* offset) {
176 VALIDATE();
177
bsalomon49f085d2014-09-05 13:34:00 -0700178 SkASSERT(buffer);
179 SkASSERT(offset);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000180
bsalomon49f085d2014-09-05 13:34:00 -0700181 if (fBufferPtr) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000182 BufferBlock& back = fBlocks.back();
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000183 size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000184 size_t pad = GrSizeAlignUpPad(usedBytes,
185 alignment);
186 if ((size + pad) <= back.fBytesFree) {
dongseong.hwang8f25c662015-01-22 10:40:20 -0800187 memset((void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes), 0, pad);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000188 usedBytes += pad;
189 *offset = usedBytes;
190 *buffer = back.fBuffer;
191 back.fBytesFree -= size + pad;
bsalomon@google.comd5108092012-03-08 15:10:39 +0000192 fBytesInUse += size + pad;
193 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000194 return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
195 }
196 }
197
bsalomon@google.com96e96df2011-10-10 14:49:29 +0000198 // We could honor the space request using by a partial update of the current
199 // VB (if there is room). But we don't currently use draw calls to GL that
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000200 // allow the driver to know that previously issued draws won't read from
bsalomon@google.com96e96df2011-10-10 14:49:29 +0000201 // the part of the buffer we update. Also, the GL buffer implementation
202 // may be cheating on the actual buffer size by shrinking the buffer on
203 // updateData() if the amount of data passed is less than the full buffer
204 // size.
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000205
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000206 if (!createBlock(size)) {
207 return NULL;
208 }
bsalomon49f085d2014-09-05 13:34:00 -0700209 SkASSERT(fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000210
211 *offset = 0;
212 BufferBlock& back = fBlocks.back();
213 *buffer = back.fBuffer;
214 back.fBytesFree -= size;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000215 fBytesInUse += size;
216 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000217 return fBufferPtr;
218}
219
220int GrBufferAllocPool::currentBufferItems(size_t itemSize) const {
221 VALIDATE();
bsalomon49f085d2014-09-05 13:34:00 -0700222 if (fBufferPtr) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000223 const BufferBlock& back = fBlocks.back();
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000224 size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000225 size_t pad = GrSizeAlignUpPad(usedBytes, itemSize);
robertphillips@google.comadacc702013-10-14 21:53:24 +0000226 return static_cast<int>((back.fBytesFree - pad) / itemSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000227 } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
robertphillips@google.comadacc702013-10-14 21:53:24 +0000228 return static_cast<int>(fMinBlockSize / itemSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000229 }
230 return 0;
231}
232
233int GrBufferAllocPool::preallocatedBuffersRemaining() const {
234 return fPreallocBuffers.count() - fPreallocBuffersInUse;
235}
236
237int GrBufferAllocPool::preallocatedBufferCount() const {
238 return fPreallocBuffers.count();
239}
240
241void GrBufferAllocPool::putBack(size_t bytes) {
242 VALIDATE();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000243
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000244 // if the putBack unwinds all the preallocated buffers then we will
245 // advance the starting index. As blocks are destroyed fPreallocBuffersInUse
246 // will be decremented. I will reach zero if all blocks using preallocated
247 // buffers are released.
248 int preallocBuffersInUse = fPreallocBuffersInUse;
249
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000250 while (bytes) {
251 // caller shouldnt try to put back more than they've taken
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000252 SkASSERT(!fBlocks.empty());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000253 BufferBlock& block = fBlocks.back();
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000254 size_t bytesUsed = block.fBuffer->gpuMemorySize() - block.fBytesFree;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000255 if (bytes >= bytesUsed) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000256 bytes -= bytesUsed;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000257 fBytesInUse -= bytesUsed;
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000258 // if we locked a vb to satisfy the make space and we're releasing
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000259 // beyond it, then unmap it.
260 if (block.fBuffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -0700261 UNMAP_BUFFER(block);
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000262 }
263 this->destroyBlock();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000264 } else {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000265 block.fBytesFree += bytes;
266 fBytesInUse -= bytes;
267 bytes = 0;
268 break;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000269 }
270 }
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000271 if (!fPreallocBuffersInUse && fPreallocBuffers.count()) {
272 fPreallocBufferStartIdx = (fPreallocBufferStartIdx +
273 preallocBuffersInUse) %
274 fPreallocBuffers.count();
275 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000276 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000277}
278
279bool GrBufferAllocPool::createBlock(size_t requestSize) {
280
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000281 size_t size = SkTMax(requestSize, fMinBlockSize);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000282 SkASSERT(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000283
284 VALIDATE();
285
286 BufferBlock& block = fBlocks.push_back();
287
288 if (size == fMinBlockSize &&
289 fPreallocBuffersInUse < fPreallocBuffers.count()) {
290
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000291 uint32_t nextBuffer = (fPreallocBuffersInUse +
292 fPreallocBufferStartIdx) %
293 fPreallocBuffers.count();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000294 block.fBuffer = fPreallocBuffers[nextBuffer];
295 block.fBuffer->ref();
296 ++fPreallocBuffersInUse;
297 } else {
298 block.fBuffer = this->createBuffer(size);
299 if (NULL == block.fBuffer) {
300 fBlocks.pop_back();
301 return false;
302 }
303 }
304
305 block.fBytesFree = size;
bsalomon49f085d2014-09-05 13:34:00 -0700306 if (fBufferPtr) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000307 SkASSERT(fBlocks.count() > 1);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000308 BufferBlock& prev = fBlocks.fromBack(1);
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000309 if (prev.fBuffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -0700310 UNMAP_BUFFER(prev);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000311 } else {
bsalomon3512eda2014-06-26 12:56:22 -0700312 this->flushCpuData(prev, prev.fBuffer->gpuMemorySize() - prev.fBytesFree);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000313 }
314 fBufferPtr = NULL;
315 }
316
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000317 SkASSERT(NULL == fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000318
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000319 // If the buffer is CPU-backed we map it because it is free to do so and saves a copy.
320 // Otherwise when buffer mapping is supported:
321 // 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 +0000322 // 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 +0000323 // b) If the hint is not set we map if the buffer size is greater than the threshold.
324 bool attemptMap = block.fBuffer->isCPUBacked();
325 if (!attemptMap && GrDrawTargetCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags()) {
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +0000326 if (fFrequentResetHint) {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000327 attemptMap = requestSize > GR_GEOM_BUFFER_MAP_THRESHOLD;
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +0000328 } else {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000329 attemptMap = size > GR_GEOM_BUFFER_MAP_THRESHOLD;
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +0000330 }
331 }
332
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000333 if (attemptMap) {
334 fBufferPtr = block.fBuffer->map();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000335 }
336
337 if (NULL == fBufferPtr) {
bsalomon@google.com7d4679a2011-09-02 22:06:24 +0000338 fBufferPtr = fCpuData.reset(size);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000339 }
340
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000341 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000342
343 return true;
344}
345
346void GrBufferAllocPool::destroyBlock() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000347 SkASSERT(!fBlocks.empty());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000348
349 BufferBlock& block = fBlocks.back();
350 if (fPreallocBuffersInUse > 0) {
351 uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000352 fPreallocBufferStartIdx +
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000353 (fPreallocBuffers.count() - 1)) %
354 fPreallocBuffers.count();
355 if (block.fBuffer == fPreallocBuffers[prevPreallocBuffer]) {
356 --fPreallocBuffersInUse;
357 }
358 }
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000359 SkASSERT(!block.fBuffer->isMapped());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000360 block.fBuffer->unref();
361 fBlocks.pop_back();
362 fBufferPtr = NULL;
363}
364
bsalomon3512eda2014-06-26 12:56:22 -0700365void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize) {
366 GrGeometryBuffer* buffer = block.fBuffer;
bsalomon49f085d2014-09-05 13:34:00 -0700367 SkASSERT(buffer);
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000368 SkASSERT(!buffer->isMapped());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000369 SkASSERT(fCpuData.get() == fBufferPtr);
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000370 SkASSERT(flushSize <= buffer->gpuMemorySize());
bsalomon@google.comd5108092012-03-08 15:10:39 +0000371 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000372
commit-bot@chromium.org160b4782014-05-05 12:32:37 +0000373 if (GrDrawTargetCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() &&
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000374 flushSize > GR_GEOM_BUFFER_MAP_THRESHOLD) {
375 void* data = buffer->map();
bsalomon49f085d2014-09-05 13:34:00 -0700376 if (data) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000377 memcpy(data, fBufferPtr, flushSize);
bsalomon3512eda2014-06-26 12:56:22 -0700378 UNMAP_BUFFER(block);
bsalomon@google.com71bd1ef2011-12-12 20:42:26 +0000379 return;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000380 }
381 }
382 buffer->updateData(fBufferPtr, flushSize);
bsalomon@google.comd5108092012-03-08 15:10:39 +0000383 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000384}
385
386GrGeometryBuffer* GrBufferAllocPool::createBuffer(size_t size) {
387 if (kIndex_BufferType == fBufferType) {
388 return fGpu->createIndexBuffer(size, true);
389 } else {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000390 SkASSERT(kVertex_BufferType == fBufferType);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000391 return fGpu->createVertexBuffer(size, true);
392 }
393}
394
395////////////////////////////////////////////////////////////////////////////////
396
397GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
398 bool frequentResetHint,
399 size_t bufferSize,
400 int preallocBufferCnt)
401: GrBufferAllocPool(gpu,
402 kVertex_BufferType,
403 frequentResetHint,
404 bufferSize,
405 preallocBufferCnt) {
406}
407
jvanverth@google.coma6338982013-01-31 21:34:25 +0000408void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000409 int vertexCount,
410 const GrVertexBuffer** buffer,
411 int* startVertex) {
412
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000413 SkASSERT(vertexCount >= 0);
bsalomon49f085d2014-09-05 13:34:00 -0700414 SkASSERT(buffer);
415 SkASSERT(startVertex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000416
bsalomon@google.com8b484412011-04-18 19:07:44 +0000417 size_t offset = 0; // assign to suppress warning
418 const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
jvanverth@google.coma6338982013-01-31 21:34:25 +0000419 void* ptr = INHERITED::makeSpace(vertexSize * vertexCount,
420 vertexSize,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000421 &geomBuffer,
422 &offset);
423
424 *buffer = (const GrVertexBuffer*) geomBuffer;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000425 SkASSERT(0 == offset % vertexSize);
robertphillips@google.comadacc702013-10-14 21:53:24 +0000426 *startVertex = static_cast<int>(offset / vertexSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000427 return ptr;
428}
429
jvanverth@google.coma6338982013-01-31 21:34:25 +0000430int GrVertexBufferAllocPool::preallocatedBufferVertices(size_t vertexSize) const {
robertphillips@google.comadacc702013-10-14 21:53:24 +0000431 return static_cast<int>(INHERITED::preallocatedBufferSize() / vertexSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000432}
433
jvanverth@google.coma6338982013-01-31 21:34:25 +0000434int GrVertexBufferAllocPool::currentBufferVertices(size_t vertexSize) const {
435 return currentBufferItems(vertexSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000436}
437
438////////////////////////////////////////////////////////////////////////////////
439
440GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu,
441 bool frequentResetHint,
442 size_t bufferSize,
443 int preallocBufferCnt)
444: GrBufferAllocPool(gpu,
445 kIndex_BufferType,
446 frequentResetHint,
447 bufferSize,
448 preallocBufferCnt) {
449}
450
451void* GrIndexBufferAllocPool::makeSpace(int indexCount,
452 const GrIndexBuffer** buffer,
453 int* startIndex) {
454
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000455 SkASSERT(indexCount >= 0);
bsalomon49f085d2014-09-05 13:34:00 -0700456 SkASSERT(buffer);
457 SkASSERT(startIndex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000458
bsalomon@google.com8b484412011-04-18 19:07:44 +0000459 size_t offset = 0; // assign to suppress warning
460 const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000461 void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t),
462 sizeof(uint16_t),
463 &geomBuffer,
464 &offset);
465
466 *buffer = (const GrIndexBuffer*) geomBuffer;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000467 SkASSERT(0 == offset % sizeof(uint16_t));
robertphillips@google.comadacc702013-10-14 21:53:24 +0000468 *startIndex = static_cast<int>(offset / sizeof(uint16_t));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000469 return ptr;
470}
471
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000472int GrIndexBufferAllocPool::preallocatedBufferIndices() const {
robertphillips@google.comadacc702013-10-14 21:53:24 +0000473 return static_cast<int>(INHERITED::preallocatedBufferSize() / sizeof(uint16_t));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000474}
475
476int GrIndexBufferAllocPool::currentBufferIndices() const {
477 return currentBufferItems(sizeof(uint16_t));
478}