blob: 5b0d8cc6d7a311dcd01f30c3c310e41ff171cbd7 [file] [log] [blame]
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2010 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
bsalomon@google.com1c13c962011-02-14 16:51:21 +00006 */
7
epoger@google.comec3ed6a2011-07-28 14:26:00 +00008
bsalomon@google.com1c13c962011-02-14 16:51:21 +00009#include "GrBufferAllocPool.h"
cdalton397536c2016-03-25 12:15:03 -070010#include "GrBuffer.h"
bsalomoneb1cb5c2015-05-22 08:01:09 -070011#include "GrCaps.h"
robertphillips1b8e1b52015-06-24 06:54:10 -070012#include "GrContext.h"
Robert Phillips6be756b2018-01-16 15:07:54 -050013#include "GrContextPriv.h"
bsalomon@google.comc26d94f2013-03-25 18:19:00 +000014#include "GrGpu.h"
robertphillips1b8e1b52015-06-24 06:54:10 -070015#include "GrResourceProvider.h"
bsalomon@google.com1c13c962011-02-14 16:51:21 +000016#include "GrTypes.h"
Mike Reedfe266c22018-01-17 11:55:07 -050017#include "SkSafeMath.h"
bsalomon3512eda2014-06-26 12:56:22 -070018#include "SkTraceEvent.h"
19
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000020#ifdef SK_DEBUG
bsalomon@google.com1c13c962011-02-14 16:51:21 +000021 #define VALIDATE validate
22#else
sugoi@google.come0e385c2013-03-11 18:50:03 +000023 static void VALIDATE(bool = false) {}
bsalomon@google.com1c13c962011-02-14 16:51:21 +000024#endif
25
robertphillips1b8e1b52015-06-24 06:54:10 -070026static const size_t MIN_VERTEX_BUFFER_SIZE = 1 << 15;
27static const size_t MIN_INDEX_BUFFER_SIZE = 1 << 12;
28
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000029// page size
joshualitt0709ca02015-06-04 09:13:46 -070030#define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 15)
bsalomon@google.com1c13c962011-02-14 16:51:21 +000031
bsalomon3512eda2014-06-26 12:56:22 -070032#define UNMAP_BUFFER(block) \
33do { \
Brian Osman39c08ac2017-07-26 09:36:09 -040034 TRACE_EVENT_INSTANT1("skia.gpu", \
bsalomon3512eda2014-06-26 12:56:22 -070035 "GrBufferAllocPool Unmapping Buffer", \
36 TRACE_EVENT_SCOPE_THREAD, \
37 "percent_unwritten", \
38 (float)((block).fBytesFree) / (block).fBuffer->gpuMemorySize()); \
39 (block).fBuffer->unmap(); \
40} while (false)
41
Robert Phillipsbdda0ba2017-08-31 09:17:43 -040042GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu, GrBufferType bufferType, size_t blockSize)
43 : fBlocks(8) {
bsalomon@google.com11f0b512011-03-29 20:52:23 +000044
bsalomonecb8e3e2015-04-29 04:33:52 -070045 fGpu = SkRef(gpu);
bsalomon7dea7b72015-08-19 08:26:51 -070046 fCpuData = nullptr;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000047 fBufferType = bufferType;
bsalomon7dea7b72015-08-19 08:26:51 -070048 fBufferPtr = nullptr;
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000049 fMinBlockSize = SkTMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000050
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000051 fBytesInUse = 0;
robertphillipseea2ff72015-05-14 05:24:53 -070052
cdalton397536c2016-03-25 12:15:03 -070053 fBufferMapThreshold = gpu->caps()->bufferMapThreshold();
bsalomon@google.com1c13c962011-02-14 16:51:21 +000054}
55
robertphillips1b8e1b52015-06-24 06:54:10 -070056void GrBufferAllocPool::deleteBlocks() {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000057 if (fBlocks.count()) {
cdalton397536c2016-03-25 12:15:03 -070058 GrBuffer* buffer = fBlocks.back().fBuffer;
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +000059 if (buffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -070060 UNMAP_BUFFER(fBlocks.back());
bsalomon@google.com1c13c962011-02-14 16:51:21 +000061 }
62 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +000063 while (!fBlocks.empty()) {
robertphillips91d06bc2015-05-06 04:38:36 -070064 this->destroyBlock();
bsalomon@google.com1c13c962011-02-14 16:51:21 +000065 }
robertphillips1b8e1b52015-06-24 06:54:10 -070066 SkASSERT(!fBufferPtr);
67}
68
69GrBufferAllocPool::~GrBufferAllocPool() {
70 VALIDATE();
71 this->deleteBlocks();
bsalomon7dea7b72015-08-19 08:26:51 -070072 sk_free(fCpuData);
bsalomonecb8e3e2015-04-29 04:33:52 -070073 fGpu->unref();
bsalomon@google.com1c13c962011-02-14 16:51:21 +000074}
75
76void GrBufferAllocPool::reset() {
77 VALIDATE();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000078 fBytesInUse = 0;
robertphillips1b8e1b52015-06-24 06:54:10 -070079 this->deleteBlocks();
robertphillips48d91b52016-08-18 14:01:14 -070080 this->resetCpuData(0); // delete all the cpu-side memory
bsalomon@google.com1c13c962011-02-14 16:51:21 +000081 VALIDATE();
82}
83
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +000084void GrBufferAllocPool::unmap() {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000085 VALIDATE();
86
bsalomon49f085d2014-09-05 13:34:00 -070087 if (fBufferPtr) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000088 BufferBlock& block = fBlocks.back();
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +000089 if (block.fBuffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -070090 UNMAP_BUFFER(block);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000091 } else {
commit-bot@chromium.org089a7802014-05-02 21:38:22 +000092 size_t flushSize = block.fBuffer->gpuMemorySize() - block.fBytesFree;
bsalomon3512eda2014-06-26 12:56:22 -070093 this->flushCpuData(fBlocks.back(), flushSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000094 }
bsalomon7dea7b72015-08-19 08:26:51 -070095 fBufferPtr = nullptr;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000096 }
97 VALIDATE();
98}
99
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000100#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000101void GrBufferAllocPool::validate(bool unusedBlockAllowed) const {
bsalomon71cb0c22014-11-14 12:10:14 -0800102 bool wasDestroyed = false;
bsalomon49f085d2014-09-05 13:34:00 -0700103 if (fBufferPtr) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000104 SkASSERT(!fBlocks.empty());
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000105 if (fBlocks.back().fBuffer->isMapped()) {
cdalton397536c2016-03-25 12:15:03 -0700106 GrBuffer* buf = fBlocks.back().fBuffer;
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000107 SkASSERT(buf->mapPtr() == fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000108 } else {
bsalomon7dea7b72015-08-19 08:26:51 -0700109 SkASSERT(fCpuData == fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000110 }
111 } else {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000112 SkASSERT(fBlocks.empty() || !fBlocks.back().fBuffer->isMapped());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000113 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000114 size_t bytesInUse = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000115 for (int i = 0; i < fBlocks.count() - 1; ++i) {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000116 SkASSERT(!fBlocks[i].fBuffer->isMapped());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000117 }
bsalomon71cb0c22014-11-14 12:10:14 -0800118 for (int i = 0; !wasDestroyed && i < fBlocks.count(); ++i) {
119 if (fBlocks[i].fBuffer->wasDestroyed()) {
120 wasDestroyed = true;
121 } else {
122 size_t bytes = fBlocks[i].fBuffer->gpuMemorySize() - fBlocks[i].fBytesFree;
123 bytesInUse += bytes;
124 SkASSERT(bytes || unusedBlockAllowed);
125 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000126 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000127
bsalomon71cb0c22014-11-14 12:10:14 -0800128 if (!wasDestroyed) {
129 SkASSERT(bytesInUse == fBytesInUse);
130 if (unusedBlockAllowed) {
131 SkASSERT((fBytesInUse && !fBlocks.empty()) ||
132 (!fBytesInUse && (fBlocks.count() < 2)));
133 } else {
134 SkASSERT((0 == fBytesInUse) == fBlocks.empty());
135 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000136 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000137}
138#endif
139
140void* GrBufferAllocPool::makeSpace(size_t size,
141 size_t alignment,
cdalton397536c2016-03-25 12:15:03 -0700142 const GrBuffer** buffer,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000143 size_t* offset) {
144 VALIDATE();
145
bsalomon49f085d2014-09-05 13:34:00 -0700146 SkASSERT(buffer);
147 SkASSERT(offset);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000148
bsalomon49f085d2014-09-05 13:34:00 -0700149 if (fBufferPtr) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000150 BufferBlock& back = fBlocks.back();
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000151 size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree;
robertphillips1b8e1b52015-06-24 06:54:10 -0700152 size_t pad = GrSizeAlignUpPad(usedBytes, alignment);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000153 if ((size + pad) <= back.fBytesFree) {
dongseong.hwang8f25c662015-01-22 10:40:20 -0800154 memset((void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes), 0, pad);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000155 usedBytes += pad;
156 *offset = usedBytes;
157 *buffer = back.fBuffer;
158 back.fBytesFree -= size + pad;
bsalomon@google.comd5108092012-03-08 15:10:39 +0000159 fBytesInUse += size + pad;
160 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000161 return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
162 }
163 }
164
bsalomon@google.com96e96df2011-10-10 14:49:29 +0000165 // We could honor the space request using by a partial update of the current
166 // VB (if there is room). But we don't currently use draw calls to GL that
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000167 // allow the driver to know that previously issued draws won't read from
bsalomon@google.com96e96df2011-10-10 14:49:29 +0000168 // the part of the buffer we update. Also, the GL buffer implementation
169 // may be cheating on the actual buffer size by shrinking the buffer on
170 // updateData() if the amount of data passed is less than the full buffer
171 // size.
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000172
robertphillips91d06bc2015-05-06 04:38:36 -0700173 if (!this->createBlock(size)) {
bsalomon7dea7b72015-08-19 08:26:51 -0700174 return nullptr;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000175 }
bsalomon49f085d2014-09-05 13:34:00 -0700176 SkASSERT(fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000177
178 *offset = 0;
179 BufferBlock& back = fBlocks.back();
180 *buffer = back.fBuffer;
181 back.fBytesFree -= size;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000182 fBytesInUse += size;
183 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000184 return fBufferPtr;
185}
186
Brian Osman49b7b6f2017-06-20 14:43:58 -0400187void* GrBufferAllocPool::makeSpaceAtLeast(size_t minSize,
188 size_t fallbackSize,
189 size_t alignment,
190 const GrBuffer** buffer,
191 size_t* offset,
192 size_t* actualSize) {
193 VALIDATE();
194
195 SkASSERT(buffer);
196 SkASSERT(offset);
197 SkASSERT(actualSize);
198
199 if (fBufferPtr) {
200 BufferBlock& back = fBlocks.back();
201 size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree;
202 size_t pad = GrSizeAlignUpPad(usedBytes, alignment);
203 if ((minSize + pad) <= back.fBytesFree) {
204 // Consume padding first, to make subsequent alignment math easier
205 memset((void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes), 0, pad);
206 usedBytes += pad;
207 back.fBytesFree -= pad;
208 fBytesInUse += pad;
209
210 // Give caller all remaining space in this block (but aligned correctly)
211 size_t size = GrSizeAlignDown(back.fBytesFree, alignment);
212 *offset = usedBytes;
213 *buffer = back.fBuffer;
214 *actualSize = size;
215 back.fBytesFree -= size;
216 fBytesInUse += size;
217 VALIDATE();
218 return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
219 }
220 }
221
222 // We could honor the space request using by a partial update of the current
223 // VB (if there is room). But we don't currently use draw calls to GL that
224 // allow the driver to know that previously issued draws won't read from
225 // the part of the buffer we update. Also, the GL buffer implementation
226 // may be cheating on the actual buffer size by shrinking the buffer on
227 // updateData() if the amount of data passed is less than the full buffer
228 // size.
229
230 if (!this->createBlock(fallbackSize)) {
231 return nullptr;
232 }
233 SkASSERT(fBufferPtr);
234
235 *offset = 0;
236 BufferBlock& back = fBlocks.back();
237 *buffer = back.fBuffer;
238 *actualSize = fallbackSize;
239 back.fBytesFree -= fallbackSize;
240 fBytesInUse += fallbackSize;
241 VALIDATE();
242 return fBufferPtr;
243}
244
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000245void GrBufferAllocPool::putBack(size_t bytes) {
246 VALIDATE();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000247
248 while (bytes) {
robertphillips91d06bc2015-05-06 04:38:36 -0700249 // caller shouldn't try to put back more than they've taken
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000250 SkASSERT(!fBlocks.empty());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000251 BufferBlock& block = fBlocks.back();
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000252 size_t bytesUsed = block.fBuffer->gpuMemorySize() - block.fBytesFree;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000253 if (bytes >= bytesUsed) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000254 bytes -= bytesUsed;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000255 fBytesInUse -= bytesUsed;
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000256 // if we locked a vb to satisfy the make space and we're releasing
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000257 // beyond it, then unmap it.
258 if (block.fBuffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -0700259 UNMAP_BUFFER(block);
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000260 }
261 this->destroyBlock();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000262 } else {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000263 block.fBytesFree += bytes;
264 fBytesInUse -= bytes;
265 bytes = 0;
266 break;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000267 }
268 }
robertphillips1b8e1b52015-06-24 06:54:10 -0700269
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000270 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000271}
272
273bool GrBufferAllocPool::createBlock(size_t requestSize) {
274
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000275 size_t size = SkTMax(requestSize, fMinBlockSize);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000276 SkASSERT(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000277
278 VALIDATE();
279
280 BufferBlock& block = fBlocks.push_back();
281
robertphillips1b8e1b52015-06-24 06:54:10 -0700282 block.fBuffer = this->getBuffer(size);
bsalomon7dea7b72015-08-19 08:26:51 -0700283 if (!block.fBuffer) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700284 fBlocks.pop_back();
285 return false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000286 }
287
robertphillips1b8e1b52015-06-24 06:54:10 -0700288 block.fBytesFree = block.fBuffer->gpuMemorySize();
bsalomon49f085d2014-09-05 13:34:00 -0700289 if (fBufferPtr) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000290 SkASSERT(fBlocks.count() > 1);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000291 BufferBlock& prev = fBlocks.fromBack(1);
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000292 if (prev.fBuffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -0700293 UNMAP_BUFFER(prev);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000294 } else {
bsalomon3512eda2014-06-26 12:56:22 -0700295 this->flushCpuData(prev, prev.fBuffer->gpuMemorySize() - prev.fBytesFree);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000296 }
bsalomon7dea7b72015-08-19 08:26:51 -0700297 fBufferPtr = nullptr;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000298 }
299
bsalomon7dea7b72015-08-19 08:26:51 -0700300 SkASSERT(!fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000301
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000302 // If the buffer is CPU-backed we map it because it is free to do so and saves a copy.
bsalomonecb8e3e2015-04-29 04:33:52 -0700303 // Otherwise when buffer mapping is supported we map if the buffer size is greater than the
304 // threshold.
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000305 bool attemptMap = block.fBuffer->isCPUBacked();
bsalomon4b91f762015-05-19 09:29:46 -0700306 if (!attemptMap && GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags()) {
cdalton397536c2016-03-25 12:15:03 -0700307 attemptMap = size > fBufferMapThreshold;
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +0000308 }
309
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000310 if (attemptMap) {
311 fBufferPtr = block.fBuffer->map();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000312 }
313
bsalomon7dea7b72015-08-19 08:26:51 -0700314 if (!fBufferPtr) {
315 fBufferPtr = this->resetCpuData(block.fBytesFree);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000316 }
317
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000318 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000319
320 return true;
321}
322
323void GrBufferAllocPool::destroyBlock() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000324 SkASSERT(!fBlocks.empty());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000325
326 BufferBlock& block = fBlocks.back();
robertphillips1b8e1b52015-06-24 06:54:10 -0700327
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000328 SkASSERT(!block.fBuffer->isMapped());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000329 block.fBuffer->unref();
330 fBlocks.pop_back();
bsalomon7dea7b72015-08-19 08:26:51 -0700331 fBufferPtr = nullptr;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000332}
333
bsalomon7dea7b72015-08-19 08:26:51 -0700334void* GrBufferAllocPool::resetCpuData(size_t newSize) {
335 sk_free(fCpuData);
336 if (newSize) {
337 if (fGpu->caps()->mustClearUploadedBufferData()) {
mtkleinabda35d2016-07-14 06:57:31 -0700338 fCpuData = sk_calloc_throw(newSize);
bsalomon7dea7b72015-08-19 08:26:51 -0700339 } else {
340 fCpuData = sk_malloc_throw(newSize);
341 }
342 } else {
343 fCpuData = nullptr;
344 }
345 return fCpuData;
346}
347
348
bsalomon3512eda2014-06-26 12:56:22 -0700349void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize) {
cdalton397536c2016-03-25 12:15:03 -0700350 GrBuffer* buffer = block.fBuffer;
bsalomon49f085d2014-09-05 13:34:00 -0700351 SkASSERT(buffer);
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000352 SkASSERT(!buffer->isMapped());
bsalomon7dea7b72015-08-19 08:26:51 -0700353 SkASSERT(fCpuData == fBufferPtr);
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000354 SkASSERT(flushSize <= buffer->gpuMemorySize());
bsalomon@google.comd5108092012-03-08 15:10:39 +0000355 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000356
bsalomon4b91f762015-05-19 09:29:46 -0700357 if (GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() &&
cdalton397536c2016-03-25 12:15:03 -0700358 flushSize > fBufferMapThreshold) {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000359 void* data = buffer->map();
bsalomon49f085d2014-09-05 13:34:00 -0700360 if (data) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000361 memcpy(data, fBufferPtr, flushSize);
bsalomon3512eda2014-06-26 12:56:22 -0700362 UNMAP_BUFFER(block);
bsalomon@google.com71bd1ef2011-12-12 20:42:26 +0000363 return;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000364 }
365 }
366 buffer->updateData(fBufferPtr, flushSize);
bsalomon@google.comd5108092012-03-08 15:10:39 +0000367 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000368}
369
cdalton397536c2016-03-25 12:15:03 -0700370GrBuffer* GrBufferAllocPool::getBuffer(size_t size) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700371
Robert Phillips6be756b2018-01-16 15:07:54 -0500372 auto resourceProvider = fGpu->getContext()->contextPriv().resourceProvider();
robertphillips1b8e1b52015-06-24 06:54:10 -0700373
halcanary6950de62015-11-07 05:29:00 -0800374 // Shouldn't have to use this flag (https://bug.skia.org/4156)
bsalomoneae62002015-07-31 13:59:30 -0700375 static const uint32_t kFlags = GrResourceProvider::kNoPendingIO_Flag;
Robert Phillips6be756b2018-01-16 15:07:54 -0500376 return resourceProvider->createBuffer(size, fBufferType, kDynamic_GrAccessPattern, kFlags);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000377}
378
379////////////////////////////////////////////////////////////////////////////////
380
robertphillips1b8e1b52015-06-24 06:54:10 -0700381GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu)
cdalton397536c2016-03-25 12:15:03 -0700382 : GrBufferAllocPool(gpu, kVertex_GrBufferType, MIN_VERTEX_BUFFER_SIZE) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000383}
384
jvanverth@google.coma6338982013-01-31 21:34:25 +0000385void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000386 int vertexCount,
cdalton397536c2016-03-25 12:15:03 -0700387 const GrBuffer** buffer,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000388 int* startVertex) {
389
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000390 SkASSERT(vertexCount >= 0);
bsalomon49f085d2014-09-05 13:34:00 -0700391 SkASSERT(buffer);
392 SkASSERT(startVertex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000393
Robert Phillipsc787e492017-02-28 11:26:32 -0500394 size_t offset SK_INIT_TO_AVOID_WARNING;
Mike Reedfe266c22018-01-17 11:55:07 -0500395 void* ptr = INHERITED::makeSpace(SkSafeMath::Mul(vertexSize, vertexCount),
jvanverth@google.coma6338982013-01-31 21:34:25 +0000396 vertexSize,
cdalton397536c2016-03-25 12:15:03 -0700397 buffer,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000398 &offset);
399
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000400 SkASSERT(0 == offset % vertexSize);
robertphillips@google.comadacc702013-10-14 21:53:24 +0000401 *startVertex = static_cast<int>(offset / vertexSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000402 return ptr;
403}
404
Brian Osman49b7b6f2017-06-20 14:43:58 -0400405void* GrVertexBufferAllocPool::makeSpaceAtLeast(size_t vertexSize, int minVertexCount,
406 int fallbackVertexCount, const GrBuffer** buffer,
407 int* startVertex, int* actualVertexCount) {
408
409 SkASSERT(minVertexCount >= 0);
410 SkASSERT(fallbackVertexCount >= minVertexCount);
411 SkASSERT(buffer);
412 SkASSERT(startVertex);
413 SkASSERT(actualVertexCount);
414
415 size_t offset SK_INIT_TO_AVOID_WARNING;
416 size_t actualSize SK_INIT_TO_AVOID_WARNING;
Mike Reedfe266c22018-01-17 11:55:07 -0500417 void* ptr = INHERITED::makeSpaceAtLeast(SkSafeMath::Mul(vertexSize, minVertexCount),
418 SkSafeMath::Mul(vertexSize, fallbackVertexCount),
Brian Osman49b7b6f2017-06-20 14:43:58 -0400419 vertexSize,
420 buffer,
421 &offset,
422 &actualSize);
423
424 SkASSERT(0 == offset % vertexSize);
425 *startVertex = static_cast<int>(offset / vertexSize);
426
427 SkASSERT(0 == actualSize % vertexSize);
428 SkASSERT(actualSize >= vertexSize * minVertexCount);
429 *actualVertexCount = static_cast<int>(actualSize / vertexSize);
430
431 return ptr;
432}
433
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000434////////////////////////////////////////////////////////////////////////////////
435
robertphillips1b8e1b52015-06-24 06:54:10 -0700436GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu)
cdalton397536c2016-03-25 12:15:03 -0700437 : GrBufferAllocPool(gpu, kIndex_GrBufferType, MIN_INDEX_BUFFER_SIZE) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000438}
439
440void* GrIndexBufferAllocPool::makeSpace(int indexCount,
cdalton397536c2016-03-25 12:15:03 -0700441 const GrBuffer** buffer,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000442 int* startIndex) {
443
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000444 SkASSERT(indexCount >= 0);
bsalomon49f085d2014-09-05 13:34:00 -0700445 SkASSERT(buffer);
446 SkASSERT(startIndex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000447
Robert Phillipsc787e492017-02-28 11:26:32 -0500448 size_t offset SK_INIT_TO_AVOID_WARNING;
Mike Reedfe266c22018-01-17 11:55:07 -0500449 void* ptr = INHERITED::makeSpace(SkSafeMath::Mul(indexCount, sizeof(uint16_t)),
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000450 sizeof(uint16_t),
cdalton397536c2016-03-25 12:15:03 -0700451 buffer,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000452 &offset);
453
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000454 SkASSERT(0 == offset % sizeof(uint16_t));
robertphillips@google.comadacc702013-10-14 21:53:24 +0000455 *startIndex = static_cast<int>(offset / sizeof(uint16_t));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000456 return ptr;
457}
Brian Osman49b7b6f2017-06-20 14:43:58 -0400458
459void* GrIndexBufferAllocPool::makeSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
460 const GrBuffer** buffer, int* startIndex,
461 int* actualIndexCount) {
462 SkASSERT(minIndexCount >= 0);
463 SkASSERT(fallbackIndexCount >= minIndexCount);
464 SkASSERT(buffer);
465 SkASSERT(startIndex);
466 SkASSERT(actualIndexCount);
467
468 size_t offset SK_INIT_TO_AVOID_WARNING;
469 size_t actualSize SK_INIT_TO_AVOID_WARNING;
Mike Reedfe266c22018-01-17 11:55:07 -0500470 void* ptr = INHERITED::makeSpaceAtLeast(SkSafeMath::Mul(minIndexCount, sizeof(uint16_t)),
471 SkSafeMath::Mul(fallbackIndexCount, sizeof(uint16_t)),
Brian Osman49b7b6f2017-06-20 14:43:58 -0400472 sizeof(uint16_t),
473 buffer,
474 &offset,
475 &actualSize);
476
477 SkASSERT(0 == offset % sizeof(uint16_t));
478 *startIndex = static_cast<int>(offset / sizeof(uint16_t));
479
480 SkASSERT(0 == actualSize % sizeof(uint16_t));
481 SkASSERT(actualSize >= minIndexCount * sizeof(uint16_t));
482 *actualIndexCount = static_cast<int>(actualSize / sizeof(uint16_t));
483 return ptr;
484}