blob: 26a1d1583725ee120b33d59797d92f926fae824e [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) {
187 usedBytes += pad;
188 *offset = usedBytes;
189 *buffer = back.fBuffer;
190 back.fBytesFree -= size + pad;
bsalomon@google.comd5108092012-03-08 15:10:39 +0000191 fBytesInUse += size + pad;
192 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000193 return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
194 }
195 }
196
bsalomon@google.com96e96df2011-10-10 14:49:29 +0000197 // We could honor the space request using by a partial update of the current
198 // VB (if there is room). But we don't currently use draw calls to GL that
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000199 // allow the driver to know that previously issued draws won't read from
bsalomon@google.com96e96df2011-10-10 14:49:29 +0000200 // the part of the buffer we update. Also, the GL buffer implementation
201 // may be cheating on the actual buffer size by shrinking the buffer on
202 // updateData() if the amount of data passed is less than the full buffer
203 // size.
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000204
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000205 if (!createBlock(size)) {
206 return NULL;
207 }
bsalomon49f085d2014-09-05 13:34:00 -0700208 SkASSERT(fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000209
210 *offset = 0;
211 BufferBlock& back = fBlocks.back();
212 *buffer = back.fBuffer;
213 back.fBytesFree -= size;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000214 fBytesInUse += size;
215 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000216 return fBufferPtr;
217}
218
219int GrBufferAllocPool::currentBufferItems(size_t itemSize) const {
220 VALIDATE();
bsalomon49f085d2014-09-05 13:34:00 -0700221 if (fBufferPtr) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000222 const BufferBlock& back = fBlocks.back();
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000223 size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000224 size_t pad = GrSizeAlignUpPad(usedBytes, itemSize);
robertphillips@google.comadacc702013-10-14 21:53:24 +0000225 return static_cast<int>((back.fBytesFree - pad) / itemSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000226 } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
robertphillips@google.comadacc702013-10-14 21:53:24 +0000227 return static_cast<int>(fMinBlockSize / itemSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000228 }
229 return 0;
230}
231
232int GrBufferAllocPool::preallocatedBuffersRemaining() const {
233 return fPreallocBuffers.count() - fPreallocBuffersInUse;
234}
235
236int GrBufferAllocPool::preallocatedBufferCount() const {
237 return fPreallocBuffers.count();
238}
239
240void GrBufferAllocPool::putBack(size_t bytes) {
241 VALIDATE();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000242
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000243 // if the putBack unwinds all the preallocated buffers then we will
244 // advance the starting index. As blocks are destroyed fPreallocBuffersInUse
245 // will be decremented. I will reach zero if all blocks using preallocated
246 // buffers are released.
247 int preallocBuffersInUse = fPreallocBuffersInUse;
248
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000249 while (bytes) {
250 // caller shouldnt try to put back more than they've taken
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000251 SkASSERT(!fBlocks.empty());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000252 BufferBlock& block = fBlocks.back();
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000253 size_t bytesUsed = block.fBuffer->gpuMemorySize() - block.fBytesFree;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000254 if (bytes >= bytesUsed) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000255 bytes -= bytesUsed;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000256 fBytesInUse -= bytesUsed;
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000257 // if we locked a vb to satisfy the make space and we're releasing
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000258 // beyond it, then unmap it.
259 if (block.fBuffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -0700260 UNMAP_BUFFER(block);
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000261 }
262 this->destroyBlock();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000263 } else {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000264 block.fBytesFree += bytes;
265 fBytesInUse -= bytes;
266 bytes = 0;
267 break;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000268 }
269 }
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000270 if (!fPreallocBuffersInUse && fPreallocBuffers.count()) {
271 fPreallocBufferStartIdx = (fPreallocBufferStartIdx +
272 preallocBuffersInUse) %
273 fPreallocBuffers.count();
274 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000275 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000276}
277
278bool GrBufferAllocPool::createBlock(size_t requestSize) {
279
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000280 size_t size = SkTMax(requestSize, fMinBlockSize);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000281 SkASSERT(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000282
283 VALIDATE();
284
285 BufferBlock& block = fBlocks.push_back();
286
287 if (size == fMinBlockSize &&
288 fPreallocBuffersInUse < fPreallocBuffers.count()) {
289
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000290 uint32_t nextBuffer = (fPreallocBuffersInUse +
291 fPreallocBufferStartIdx) %
292 fPreallocBuffers.count();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000293 block.fBuffer = fPreallocBuffers[nextBuffer];
294 block.fBuffer->ref();
295 ++fPreallocBuffersInUse;
296 } else {
297 block.fBuffer = this->createBuffer(size);
298 if (NULL == block.fBuffer) {
299 fBlocks.pop_back();
300 return false;
301 }
302 }
303
304 block.fBytesFree = size;
bsalomon49f085d2014-09-05 13:34:00 -0700305 if (fBufferPtr) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000306 SkASSERT(fBlocks.count() > 1);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000307 BufferBlock& prev = fBlocks.fromBack(1);
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000308 if (prev.fBuffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -0700309 UNMAP_BUFFER(prev);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000310 } else {
bsalomon3512eda2014-06-26 12:56:22 -0700311 this->flushCpuData(prev, prev.fBuffer->gpuMemorySize() - prev.fBytesFree);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000312 }
313 fBufferPtr = NULL;
314 }
315
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000316 SkASSERT(NULL == fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000317
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000318 // If the buffer is CPU-backed we map it because it is free to do so and saves a copy.
319 // Otherwise when buffer mapping is supported:
320 // 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 +0000321 // 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 +0000322 // b) If the hint is not set we map if the buffer size is greater than the threshold.
323 bool attemptMap = block.fBuffer->isCPUBacked();
324 if (!attemptMap && GrDrawTargetCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags()) {
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +0000325 if (fFrequentResetHint) {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000326 attemptMap = requestSize > GR_GEOM_BUFFER_MAP_THRESHOLD;
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +0000327 } else {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000328 attemptMap = size > GR_GEOM_BUFFER_MAP_THRESHOLD;
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +0000329 }
330 }
331
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000332 if (attemptMap) {
333 fBufferPtr = block.fBuffer->map();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000334 }
335
336 if (NULL == fBufferPtr) {
bsalomon@google.com7d4679a2011-09-02 22:06:24 +0000337 fBufferPtr = fCpuData.reset(size);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000338 }
339
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000340 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000341
342 return true;
343}
344
345void GrBufferAllocPool::destroyBlock() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000346 SkASSERT(!fBlocks.empty());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000347
348 BufferBlock& block = fBlocks.back();
349 if (fPreallocBuffersInUse > 0) {
350 uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
bsalomon@google.comb665a6b2012-03-01 20:59:28 +0000351 fPreallocBufferStartIdx +
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000352 (fPreallocBuffers.count() - 1)) %
353 fPreallocBuffers.count();
354 if (block.fBuffer == fPreallocBuffers[prevPreallocBuffer]) {
355 --fPreallocBuffersInUse;
356 }
357 }
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000358 SkASSERT(!block.fBuffer->isMapped());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000359 block.fBuffer->unref();
360 fBlocks.pop_back();
361 fBufferPtr = NULL;
362}
363
bsalomon3512eda2014-06-26 12:56:22 -0700364void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize) {
365 GrGeometryBuffer* buffer = block.fBuffer;
bsalomon49f085d2014-09-05 13:34:00 -0700366 SkASSERT(buffer);
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000367 SkASSERT(!buffer->isMapped());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000368 SkASSERT(fCpuData.get() == fBufferPtr);
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000369 SkASSERT(flushSize <= buffer->gpuMemorySize());
bsalomon@google.comd5108092012-03-08 15:10:39 +0000370 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000371
commit-bot@chromium.org160b4782014-05-05 12:32:37 +0000372 if (GrDrawTargetCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() &&
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000373 flushSize > GR_GEOM_BUFFER_MAP_THRESHOLD) {
374 void* data = buffer->map();
bsalomon49f085d2014-09-05 13:34:00 -0700375 if (data) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000376 memcpy(data, fBufferPtr, flushSize);
bsalomon3512eda2014-06-26 12:56:22 -0700377 UNMAP_BUFFER(block);
bsalomon@google.com71bd1ef2011-12-12 20:42:26 +0000378 return;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000379 }
380 }
381 buffer->updateData(fBufferPtr, flushSize);
bsalomon@google.comd5108092012-03-08 15:10:39 +0000382 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000383}
384
385GrGeometryBuffer* GrBufferAllocPool::createBuffer(size_t size) {
386 if (kIndex_BufferType == fBufferType) {
387 return fGpu->createIndexBuffer(size, true);
388 } else {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000389 SkASSERT(kVertex_BufferType == fBufferType);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000390 return fGpu->createVertexBuffer(size, true);
391 }
392}
393
394////////////////////////////////////////////////////////////////////////////////
395
396GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
397 bool frequentResetHint,
398 size_t bufferSize,
399 int preallocBufferCnt)
400: GrBufferAllocPool(gpu,
401 kVertex_BufferType,
402 frequentResetHint,
403 bufferSize,
404 preallocBufferCnt) {
405}
406
jvanverth@google.coma6338982013-01-31 21:34:25 +0000407void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000408 int vertexCount,
409 const GrVertexBuffer** buffer,
410 int* startVertex) {
411
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000412 SkASSERT(vertexCount >= 0);
bsalomon49f085d2014-09-05 13:34:00 -0700413 SkASSERT(buffer);
414 SkASSERT(startVertex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000415
bsalomon@google.com8b484412011-04-18 19:07:44 +0000416 size_t offset = 0; // assign to suppress warning
417 const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
jvanverth@google.coma6338982013-01-31 21:34:25 +0000418 void* ptr = INHERITED::makeSpace(vertexSize * vertexCount,
419 vertexSize,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000420 &geomBuffer,
421 &offset);
422
423 *buffer = (const GrVertexBuffer*) geomBuffer;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000424 SkASSERT(0 == offset % vertexSize);
robertphillips@google.comadacc702013-10-14 21:53:24 +0000425 *startVertex = static_cast<int>(offset / vertexSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000426 return ptr;
427}
428
jvanverth@google.coma6338982013-01-31 21:34:25 +0000429int GrVertexBufferAllocPool::preallocatedBufferVertices(size_t vertexSize) const {
robertphillips@google.comadacc702013-10-14 21:53:24 +0000430 return static_cast<int>(INHERITED::preallocatedBufferSize() / vertexSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000431}
432
jvanverth@google.coma6338982013-01-31 21:34:25 +0000433int GrVertexBufferAllocPool::currentBufferVertices(size_t vertexSize) const {
434 return currentBufferItems(vertexSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000435}
436
437////////////////////////////////////////////////////////////////////////////////
438
439GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu,
440 bool frequentResetHint,
441 size_t bufferSize,
442 int preallocBufferCnt)
443: GrBufferAllocPool(gpu,
444 kIndex_BufferType,
445 frequentResetHint,
446 bufferSize,
447 preallocBufferCnt) {
448}
449
450void* GrIndexBufferAllocPool::makeSpace(int indexCount,
451 const GrIndexBuffer** buffer,
452 int* startIndex) {
453
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000454 SkASSERT(indexCount >= 0);
bsalomon49f085d2014-09-05 13:34:00 -0700455 SkASSERT(buffer);
456 SkASSERT(startIndex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000457
bsalomon@google.com8b484412011-04-18 19:07:44 +0000458 size_t offset = 0; // assign to suppress warning
459 const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000460 void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t),
461 sizeof(uint16_t),
462 &geomBuffer,
463 &offset);
464
465 *buffer = (const GrIndexBuffer*) geomBuffer;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000466 SkASSERT(0 == offset % sizeof(uint16_t));
robertphillips@google.comadacc702013-10-14 21:53:24 +0000467 *startIndex = static_cast<int>(offset / sizeof(uint16_t));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000468 return ptr;
469}
470
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000471int GrIndexBufferAllocPool::preallocatedBufferIndices() const {
robertphillips@google.comadacc702013-10-14 21:53:24 +0000472 return static_cast<int>(INHERITED::preallocatedBufferSize() / sizeof(uint16_t));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000473}
474
475int GrIndexBufferAllocPool::currentBufferIndices() const {
476 return currentBufferItems(sizeof(uint16_t));
477}