blob: c47881c6c5ea3fe69cbfc27753f3618ba2ec7a4b [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
8#include "GrBufferAllocPool.h"
Hal Canary50dbc092018-06-12 14:50:37 -04009
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"
Hal Canary50dbc092018-06-12 14:50:37 -040017#include "SkMacros.h"
Mike Reedfe266c22018-01-17 11:55:07 -050018#include "SkSafeMath.h"
bsalomon3512eda2014-06-26 12:56:22 -070019#include "SkTraceEvent.h"
20
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000021#ifdef SK_DEBUG
bsalomon@google.com1c13c962011-02-14 16:51:21 +000022 #define VALIDATE validate
23#else
sugoi@google.come0e385c2013-03-11 18:50:03 +000024 static void VALIDATE(bool = false) {}
bsalomon@google.com1c13c962011-02-14 16:51:21 +000025#endif
26
robertphillips1b8e1b52015-06-24 06:54:10 -070027static const size_t MIN_VERTEX_BUFFER_SIZE = 1 << 15;
28static const size_t MIN_INDEX_BUFFER_SIZE = 1 << 12;
29
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000030// page size
joshualitt0709ca02015-06-04 09:13:46 -070031#define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 15)
bsalomon@google.com1c13c962011-02-14 16:51:21 +000032
bsalomon3512eda2014-06-26 12:56:22 -070033#define UNMAP_BUFFER(block) \
34do { \
Brian Osman39c08ac2017-07-26 09:36:09 -040035 TRACE_EVENT_INSTANT1("skia.gpu", \
bsalomon3512eda2014-06-26 12:56:22 -070036 "GrBufferAllocPool Unmapping Buffer", \
37 TRACE_EVENT_SCOPE_THREAD, \
38 "percent_unwritten", \
39 (float)((block).fBytesFree) / (block).fBuffer->gpuMemorySize()); \
40 (block).fBuffer->unmap(); \
41} while (false)
42
Robert Phillipsbdda0ba2017-08-31 09:17:43 -040043GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu, GrBufferType bufferType, size_t blockSize)
44 : fBlocks(8) {
bsalomon@google.com11f0b512011-03-29 20:52:23 +000045
bsalomonecb8e3e2015-04-29 04:33:52 -070046 fGpu = SkRef(gpu);
bsalomon7dea7b72015-08-19 08:26:51 -070047 fCpuData = nullptr;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000048 fBufferType = bufferType;
bsalomon7dea7b72015-08-19 08:26:51 -070049 fBufferPtr = nullptr;
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000050 fMinBlockSize = SkTMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000051
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000052 fBytesInUse = 0;
robertphillipseea2ff72015-05-14 05:24:53 -070053
cdalton397536c2016-03-25 12:15:03 -070054 fBufferMapThreshold = gpu->caps()->bufferMapThreshold();
bsalomon@google.com1c13c962011-02-14 16:51:21 +000055}
56
robertphillips1b8e1b52015-06-24 06:54:10 -070057void GrBufferAllocPool::deleteBlocks() {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000058 if (fBlocks.count()) {
cdalton397536c2016-03-25 12:15:03 -070059 GrBuffer* buffer = fBlocks.back().fBuffer;
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +000060 if (buffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -070061 UNMAP_BUFFER(fBlocks.back());
bsalomon@google.com1c13c962011-02-14 16:51:21 +000062 }
63 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +000064 while (!fBlocks.empty()) {
robertphillips91d06bc2015-05-06 04:38:36 -070065 this->destroyBlock();
bsalomon@google.com1c13c962011-02-14 16:51:21 +000066 }
robertphillips1b8e1b52015-06-24 06:54:10 -070067 SkASSERT(!fBufferPtr);
68}
69
70GrBufferAllocPool::~GrBufferAllocPool() {
71 VALIDATE();
72 this->deleteBlocks();
bsalomon7dea7b72015-08-19 08:26:51 -070073 sk_free(fCpuData);
bsalomonecb8e3e2015-04-29 04:33:52 -070074 fGpu->unref();
bsalomon@google.com1c13c962011-02-14 16:51:21 +000075}
76
77void GrBufferAllocPool::reset() {
78 VALIDATE();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000079 fBytesInUse = 0;
robertphillips1b8e1b52015-06-24 06:54:10 -070080 this->deleteBlocks();
robertphillips48d91b52016-08-18 14:01:14 -070081 this->resetCpuData(0); // delete all the cpu-side memory
bsalomon@google.com1c13c962011-02-14 16:51:21 +000082 VALIDATE();
83}
84
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +000085void GrBufferAllocPool::unmap() {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000086 VALIDATE();
87
bsalomon49f085d2014-09-05 13:34:00 -070088 if (fBufferPtr) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000089 BufferBlock& block = fBlocks.back();
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +000090 if (block.fBuffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -070091 UNMAP_BUFFER(block);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000092 } else {
commit-bot@chromium.org089a7802014-05-02 21:38:22 +000093 size_t flushSize = block.fBuffer->gpuMemorySize() - block.fBytesFree;
bsalomon3512eda2014-06-26 12:56:22 -070094 this->flushCpuData(fBlocks.back(), flushSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000095 }
bsalomon7dea7b72015-08-19 08:26:51 -070096 fBufferPtr = nullptr;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000097 }
98 VALIDATE();
99}
100
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000101#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000102void GrBufferAllocPool::validate(bool unusedBlockAllowed) const {
bsalomon71cb0c22014-11-14 12:10:14 -0800103 bool wasDestroyed = false;
bsalomon49f085d2014-09-05 13:34:00 -0700104 if (fBufferPtr) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000105 SkASSERT(!fBlocks.empty());
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000106 if (fBlocks.back().fBuffer->isMapped()) {
cdalton397536c2016-03-25 12:15:03 -0700107 GrBuffer* buf = fBlocks.back().fBuffer;
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000108 SkASSERT(buf->mapPtr() == fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000109 } else {
bsalomon7dea7b72015-08-19 08:26:51 -0700110 SkASSERT(fCpuData == fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000111 }
112 } else {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000113 SkASSERT(fBlocks.empty() || !fBlocks.back().fBuffer->isMapped());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000114 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000115 size_t bytesInUse = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000116 for (int i = 0; i < fBlocks.count() - 1; ++i) {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000117 SkASSERT(!fBlocks[i].fBuffer->isMapped());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000118 }
bsalomon71cb0c22014-11-14 12:10:14 -0800119 for (int i = 0; !wasDestroyed && i < fBlocks.count(); ++i) {
120 if (fBlocks[i].fBuffer->wasDestroyed()) {
121 wasDestroyed = true;
122 } else {
123 size_t bytes = fBlocks[i].fBuffer->gpuMemorySize() - fBlocks[i].fBytesFree;
124 bytesInUse += bytes;
125 SkASSERT(bytes || unusedBlockAllowed);
126 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000127 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000128
bsalomon71cb0c22014-11-14 12:10:14 -0800129 if (!wasDestroyed) {
130 SkASSERT(bytesInUse == fBytesInUse);
131 if (unusedBlockAllowed) {
132 SkASSERT((fBytesInUse && !fBlocks.empty()) ||
133 (!fBytesInUse && (fBlocks.count() < 2)));
134 } else {
135 SkASSERT((0 == fBytesInUse) == fBlocks.empty());
136 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000137 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000138}
139#endif
140
141void* GrBufferAllocPool::makeSpace(size_t size,
142 size_t alignment,
cdalton397536c2016-03-25 12:15:03 -0700143 const GrBuffer** buffer,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000144 size_t* offset) {
145 VALIDATE();
146
bsalomon49f085d2014-09-05 13:34:00 -0700147 SkASSERT(buffer);
148 SkASSERT(offset);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000149
bsalomon49f085d2014-09-05 13:34:00 -0700150 if (fBufferPtr) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000151 BufferBlock& back = fBlocks.back();
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000152 size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree;
robertphillips1b8e1b52015-06-24 06:54:10 -0700153 size_t pad = GrSizeAlignUpPad(usedBytes, alignment);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000154 if ((size + pad) <= back.fBytesFree) {
dongseong.hwang8f25c662015-01-22 10:40:20 -0800155 memset((void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes), 0, pad);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000156 usedBytes += pad;
157 *offset = usedBytes;
158 *buffer = back.fBuffer;
159 back.fBytesFree -= size + pad;
bsalomon@google.comd5108092012-03-08 15:10:39 +0000160 fBytesInUse += size + pad;
161 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000162 return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
163 }
164 }
165
bsalomon@google.com96e96df2011-10-10 14:49:29 +0000166 // We could honor the space request using by a partial update of the current
167 // VB (if there is room). But we don't currently use draw calls to GL that
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000168 // allow the driver to know that previously issued draws won't read from
bsalomon@google.com96e96df2011-10-10 14:49:29 +0000169 // the part of the buffer we update. Also, the GL buffer implementation
170 // may be cheating on the actual buffer size by shrinking the buffer on
171 // updateData() if the amount of data passed is less than the full buffer
172 // size.
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000173
robertphillips91d06bc2015-05-06 04:38:36 -0700174 if (!this->createBlock(size)) {
bsalomon7dea7b72015-08-19 08:26:51 -0700175 return nullptr;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000176 }
bsalomon49f085d2014-09-05 13:34:00 -0700177 SkASSERT(fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000178
179 *offset = 0;
180 BufferBlock& back = fBlocks.back();
181 *buffer = back.fBuffer;
182 back.fBytesFree -= size;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000183 fBytesInUse += size;
184 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000185 return fBufferPtr;
186}
187
Brian Osman49b7b6f2017-06-20 14:43:58 -0400188void* GrBufferAllocPool::makeSpaceAtLeast(size_t minSize,
189 size_t fallbackSize,
190 size_t alignment,
191 const GrBuffer** buffer,
192 size_t* offset,
193 size_t* actualSize) {
194 VALIDATE();
195
196 SkASSERT(buffer);
197 SkASSERT(offset);
198 SkASSERT(actualSize);
199
200 if (fBufferPtr) {
201 BufferBlock& back = fBlocks.back();
202 size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree;
203 size_t pad = GrSizeAlignUpPad(usedBytes, alignment);
204 if ((minSize + pad) <= back.fBytesFree) {
205 // Consume padding first, to make subsequent alignment math easier
206 memset((void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes), 0, pad);
207 usedBytes += pad;
208 back.fBytesFree -= pad;
209 fBytesInUse += pad;
210
211 // Give caller all remaining space in this block (but aligned correctly)
212 size_t size = GrSizeAlignDown(back.fBytesFree, alignment);
213 *offset = usedBytes;
214 *buffer = back.fBuffer;
215 *actualSize = size;
216 back.fBytesFree -= size;
217 fBytesInUse += size;
218 VALIDATE();
219 return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
220 }
221 }
222
223 // We could honor the space request using by a partial update of the current
224 // VB (if there is room). But we don't currently use draw calls to GL that
225 // allow the driver to know that previously issued draws won't read from
226 // the part of the buffer we update. Also, the GL buffer implementation
227 // may be cheating on the actual buffer size by shrinking the buffer on
228 // updateData() if the amount of data passed is less than the full buffer
229 // size.
230
231 if (!this->createBlock(fallbackSize)) {
232 return nullptr;
233 }
234 SkASSERT(fBufferPtr);
235
236 *offset = 0;
237 BufferBlock& back = fBlocks.back();
238 *buffer = back.fBuffer;
239 *actualSize = fallbackSize;
240 back.fBytesFree -= fallbackSize;
241 fBytesInUse += fallbackSize;
242 VALIDATE();
243 return fBufferPtr;
244}
245
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000246void GrBufferAllocPool::putBack(size_t bytes) {
247 VALIDATE();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000248
249 while (bytes) {
robertphillips91d06bc2015-05-06 04:38:36 -0700250 // caller shouldn't 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 }
robertphillips1b8e1b52015-06-24 06:54:10 -0700270
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000271 VALIDATE();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000272}
273
274bool GrBufferAllocPool::createBlock(size_t requestSize) {
275
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000276 size_t size = SkTMax(requestSize, fMinBlockSize);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000277 SkASSERT(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000278
279 VALIDATE();
280
281 BufferBlock& block = fBlocks.push_back();
282
robertphillips1b8e1b52015-06-24 06:54:10 -0700283 block.fBuffer = this->getBuffer(size);
bsalomon7dea7b72015-08-19 08:26:51 -0700284 if (!block.fBuffer) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700285 fBlocks.pop_back();
286 return false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000287 }
288
robertphillips1b8e1b52015-06-24 06:54:10 -0700289 block.fBytesFree = block.fBuffer->gpuMemorySize();
bsalomon49f085d2014-09-05 13:34:00 -0700290 if (fBufferPtr) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000291 SkASSERT(fBlocks.count() > 1);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000292 BufferBlock& prev = fBlocks.fromBack(1);
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000293 if (prev.fBuffer->isMapped()) {
bsalomon3512eda2014-06-26 12:56:22 -0700294 UNMAP_BUFFER(prev);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000295 } else {
bsalomon3512eda2014-06-26 12:56:22 -0700296 this->flushCpuData(prev, prev.fBuffer->gpuMemorySize() - prev.fBytesFree);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000297 }
bsalomon7dea7b72015-08-19 08:26:51 -0700298 fBufferPtr = nullptr;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000299 }
300
bsalomon7dea7b72015-08-19 08:26:51 -0700301 SkASSERT(!fBufferPtr);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000302
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000303 // 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 -0700304 // Otherwise when buffer mapping is supported we map if the buffer size is greater than the
305 // threshold.
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000306 bool attemptMap = block.fBuffer->isCPUBacked();
bsalomon4b91f762015-05-19 09:29:46 -0700307 if (!attemptMap && GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags()) {
cdalton397536c2016-03-25 12:15:03 -0700308 attemptMap = size > fBufferMapThreshold;
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +0000309 }
310
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000311 if (attemptMap) {
312 fBufferPtr = block.fBuffer->map();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000313 }
314
bsalomon7dea7b72015-08-19 08:26:51 -0700315 if (!fBufferPtr) {
316 fBufferPtr = this->resetCpuData(block.fBytesFree);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000317 }
318
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000319 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000320
321 return true;
322}
323
324void GrBufferAllocPool::destroyBlock() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000325 SkASSERT(!fBlocks.empty());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000326
327 BufferBlock& block = fBlocks.back();
robertphillips1b8e1b52015-06-24 06:54:10 -0700328
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000329 SkASSERT(!block.fBuffer->isMapped());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000330 block.fBuffer->unref();
331 fBlocks.pop_back();
bsalomon7dea7b72015-08-19 08:26:51 -0700332 fBufferPtr = nullptr;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000333}
334
bsalomon7dea7b72015-08-19 08:26:51 -0700335void* GrBufferAllocPool::resetCpuData(size_t newSize) {
336 sk_free(fCpuData);
337 if (newSize) {
338 if (fGpu->caps()->mustClearUploadedBufferData()) {
mtkleinabda35d2016-07-14 06:57:31 -0700339 fCpuData = sk_calloc_throw(newSize);
bsalomon7dea7b72015-08-19 08:26:51 -0700340 } else {
341 fCpuData = sk_malloc_throw(newSize);
342 }
343 } else {
344 fCpuData = nullptr;
345 }
346 return fCpuData;
347}
348
349
bsalomon3512eda2014-06-26 12:56:22 -0700350void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize) {
cdalton397536c2016-03-25 12:15:03 -0700351 GrBuffer* buffer = block.fBuffer;
bsalomon49f085d2014-09-05 13:34:00 -0700352 SkASSERT(buffer);
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000353 SkASSERT(!buffer->isMapped());
bsalomon7dea7b72015-08-19 08:26:51 -0700354 SkASSERT(fCpuData == fBufferPtr);
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000355 SkASSERT(flushSize <= buffer->gpuMemorySize());
bsalomon@google.comd5108092012-03-08 15:10:39 +0000356 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000357
bsalomon4b91f762015-05-19 09:29:46 -0700358 if (GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() &&
cdalton397536c2016-03-25 12:15:03 -0700359 flushSize > fBufferMapThreshold) {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000360 void* data = buffer->map();
bsalomon49f085d2014-09-05 13:34:00 -0700361 if (data) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000362 memcpy(data, fBufferPtr, flushSize);
bsalomon3512eda2014-06-26 12:56:22 -0700363 UNMAP_BUFFER(block);
bsalomon@google.com71bd1ef2011-12-12 20:42:26 +0000364 return;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000365 }
366 }
367 buffer->updateData(fBufferPtr, flushSize);
bsalomon@google.comd5108092012-03-08 15:10:39 +0000368 VALIDATE(true);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000369}
370
cdalton397536c2016-03-25 12:15:03 -0700371GrBuffer* GrBufferAllocPool::getBuffer(size_t size) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700372
Robert Phillips6be756b2018-01-16 15:07:54 -0500373 auto resourceProvider = fGpu->getContext()->contextPriv().resourceProvider();
robertphillips1b8e1b52015-06-24 06:54:10 -0700374
halcanary6950de62015-11-07 05:29:00 -0800375 // Shouldn't have to use this flag (https://bug.skia.org/4156)
bsalomoneae62002015-07-31 13:59:30 -0700376 static const uint32_t kFlags = GrResourceProvider::kNoPendingIO_Flag;
Robert Phillips6be756b2018-01-16 15:07:54 -0500377 return resourceProvider->createBuffer(size, fBufferType, kDynamic_GrAccessPattern, kFlags);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000378}
379
380////////////////////////////////////////////////////////////////////////////////
381
robertphillips1b8e1b52015-06-24 06:54:10 -0700382GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu)
cdalton397536c2016-03-25 12:15:03 -0700383 : GrBufferAllocPool(gpu, kVertex_GrBufferType, MIN_VERTEX_BUFFER_SIZE) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000384}
385
jvanverth@google.coma6338982013-01-31 21:34:25 +0000386void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000387 int vertexCount,
cdalton397536c2016-03-25 12:15:03 -0700388 const GrBuffer** buffer,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000389 int* startVertex) {
390
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000391 SkASSERT(vertexCount >= 0);
bsalomon49f085d2014-09-05 13:34:00 -0700392 SkASSERT(buffer);
393 SkASSERT(startVertex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000394
Robert Phillipsc787e492017-02-28 11:26:32 -0500395 size_t offset SK_INIT_TO_AVOID_WARNING;
Mike Reedfe266c22018-01-17 11:55:07 -0500396 void* ptr = INHERITED::makeSpace(SkSafeMath::Mul(vertexSize, vertexCount),
jvanverth@google.coma6338982013-01-31 21:34:25 +0000397 vertexSize,
cdalton397536c2016-03-25 12:15:03 -0700398 buffer,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000399 &offset);
400
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000401 SkASSERT(0 == offset % vertexSize);
robertphillips@google.comadacc702013-10-14 21:53:24 +0000402 *startVertex = static_cast<int>(offset / vertexSize);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000403 return ptr;
404}
405
Brian Osman49b7b6f2017-06-20 14:43:58 -0400406void* GrVertexBufferAllocPool::makeSpaceAtLeast(size_t vertexSize, int minVertexCount,
407 int fallbackVertexCount, const GrBuffer** buffer,
408 int* startVertex, int* actualVertexCount) {
409
410 SkASSERT(minVertexCount >= 0);
411 SkASSERT(fallbackVertexCount >= minVertexCount);
412 SkASSERT(buffer);
413 SkASSERT(startVertex);
414 SkASSERT(actualVertexCount);
415
416 size_t offset SK_INIT_TO_AVOID_WARNING;
417 size_t actualSize SK_INIT_TO_AVOID_WARNING;
Mike Reedfe266c22018-01-17 11:55:07 -0500418 void* ptr = INHERITED::makeSpaceAtLeast(SkSafeMath::Mul(vertexSize, minVertexCount),
419 SkSafeMath::Mul(vertexSize, fallbackVertexCount),
Brian Osman49b7b6f2017-06-20 14:43:58 -0400420 vertexSize,
421 buffer,
422 &offset,
423 &actualSize);
424
425 SkASSERT(0 == offset % vertexSize);
426 *startVertex = static_cast<int>(offset / vertexSize);
427
428 SkASSERT(0 == actualSize % vertexSize);
429 SkASSERT(actualSize >= vertexSize * minVertexCount);
430 *actualVertexCount = static_cast<int>(actualSize / vertexSize);
431
432 return ptr;
433}
434
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000435////////////////////////////////////////////////////////////////////////////////
436
robertphillips1b8e1b52015-06-24 06:54:10 -0700437GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu)
cdalton397536c2016-03-25 12:15:03 -0700438 : GrBufferAllocPool(gpu, kIndex_GrBufferType, MIN_INDEX_BUFFER_SIZE) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000439}
440
441void* GrIndexBufferAllocPool::makeSpace(int indexCount,
cdalton397536c2016-03-25 12:15:03 -0700442 const GrBuffer** buffer,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000443 int* startIndex) {
444
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000445 SkASSERT(indexCount >= 0);
bsalomon49f085d2014-09-05 13:34:00 -0700446 SkASSERT(buffer);
447 SkASSERT(startIndex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000448
Robert Phillipsc787e492017-02-28 11:26:32 -0500449 size_t offset SK_INIT_TO_AVOID_WARNING;
Mike Reedfe266c22018-01-17 11:55:07 -0500450 void* ptr = INHERITED::makeSpace(SkSafeMath::Mul(indexCount, sizeof(uint16_t)),
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000451 sizeof(uint16_t),
cdalton397536c2016-03-25 12:15:03 -0700452 buffer,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000453 &offset);
454
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000455 SkASSERT(0 == offset % sizeof(uint16_t));
robertphillips@google.comadacc702013-10-14 21:53:24 +0000456 *startIndex = static_cast<int>(offset / sizeof(uint16_t));
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000457 return ptr;
458}
Brian Osman49b7b6f2017-06-20 14:43:58 -0400459
460void* GrIndexBufferAllocPool::makeSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
461 const GrBuffer** buffer, int* startIndex,
462 int* actualIndexCount) {
463 SkASSERT(minIndexCount >= 0);
464 SkASSERT(fallbackIndexCount >= minIndexCount);
465 SkASSERT(buffer);
466 SkASSERT(startIndex);
467 SkASSERT(actualIndexCount);
468
469 size_t offset SK_INIT_TO_AVOID_WARNING;
470 size_t actualSize SK_INIT_TO_AVOID_WARNING;
Mike Reedfe266c22018-01-17 11:55:07 -0500471 void* ptr = INHERITED::makeSpaceAtLeast(SkSafeMath::Mul(minIndexCount, sizeof(uint16_t)),
472 SkSafeMath::Mul(fallbackIndexCount, sizeof(uint16_t)),
Brian Osman49b7b6f2017-06-20 14:43:58 -0400473 sizeof(uint16_t),
474 buffer,
475 &offset,
476 &actualSize);
477
478 SkASSERT(0 == offset % sizeof(uint16_t));
479 *startIndex = static_cast<int>(offset / sizeof(uint16_t));
480
481 SkASSERT(0 == actualSize % sizeof(uint16_t));
482 SkASSERT(actualSize >= minIndexCount * sizeof(uint16_t));
483 *actualIndexCount = static_cast<int>(actualSize / sizeof(uint16_t));
484 return ptr;
485}