OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2010 Google Inc. | 3 * Copyright 2010 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "GrBufferAllocPool.h" | 10 #include "GrBufferAllocPool.h" |
(...skipping 28 matching lines...) Expand all Loading... |
39 (float)((block).fBytesFree) / (block).fBuffer->gpuMemor
ySize()); \ | 39 (float)((block).fBytesFree) / (block).fBuffer->gpuMemor
ySize()); \ |
40 (block).fBuffer->unmap();
\ | 40 (block).fBuffer->unmap();
\ |
41 } while (false) | 41 } while (false) |
42 | 42 |
43 GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu, | 43 GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu, |
44 BufferType bufferType, | 44 BufferType bufferType, |
45 size_t blockSize) | 45 size_t blockSize) |
46 : fBlocks(8) { | 46 : fBlocks(8) { |
47 | 47 |
48 fGpu = SkRef(gpu); | 48 fGpu = SkRef(gpu); |
49 | 49 fCpuData = nullptr; |
50 fBufferType = bufferType; | 50 fBufferType = bufferType; |
51 fBufferPtr = NULL; | 51 fBufferPtr = nullptr; |
52 fMinBlockSize = SkTMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize); | 52 fMinBlockSize = SkTMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize); |
53 | 53 |
54 fBytesInUse = 0; | 54 fBytesInUse = 0; |
55 | 55 |
56 fGeometryBufferMapThreshold = gpu->caps()->geometryBufferMapThreshold(); | 56 fGeometryBufferMapThreshold = gpu->caps()->geometryBufferMapThreshold(); |
57 } | 57 } |
58 | 58 |
59 void GrBufferAllocPool::deleteBlocks() { | 59 void GrBufferAllocPool::deleteBlocks() { |
60 if (fBlocks.count()) { | 60 if (fBlocks.count()) { |
61 GrGeometryBuffer* buffer = fBlocks.back().fBuffer; | 61 GrGeometryBuffer* buffer = fBlocks.back().fBuffer; |
62 if (buffer->isMapped()) { | 62 if (buffer->isMapped()) { |
63 UNMAP_BUFFER(fBlocks.back()); | 63 UNMAP_BUFFER(fBlocks.back()); |
64 } | 64 } |
65 } | 65 } |
66 while (!fBlocks.empty()) { | 66 while (!fBlocks.empty()) { |
67 this->destroyBlock(); | 67 this->destroyBlock(); |
68 } | 68 } |
69 SkASSERT(!fBufferPtr); | 69 SkASSERT(!fBufferPtr); |
70 } | 70 } |
71 | 71 |
72 GrBufferAllocPool::~GrBufferAllocPool() { | 72 GrBufferAllocPool::~GrBufferAllocPool() { |
73 VALIDATE(); | 73 VALIDATE(); |
74 this->deleteBlocks(); | 74 this->deleteBlocks(); |
| 75 sk_free(fCpuData); |
75 fGpu->unref(); | 76 fGpu->unref(); |
76 } | 77 } |
77 | 78 |
78 void GrBufferAllocPool::reset() { | 79 void GrBufferAllocPool::reset() { |
79 VALIDATE(); | 80 VALIDATE(); |
80 fBytesInUse = 0; | 81 fBytesInUse = 0; |
81 this->deleteBlocks(); | 82 this->deleteBlocks(); |
82 // we may have created a large cpu mirror of a large VB. Reset the size | 83 |
83 // to match our minimum. | 84 // we may have created a large cpu mirror of a large VB. Reset the size to m
atch our minimum. |
84 fCpuData.reset(fMinBlockSize); | 85 this->resetCpuData(fMinBlockSize); |
| 86 |
85 VALIDATE(); | 87 VALIDATE(); |
86 } | 88 } |
87 | 89 |
88 void GrBufferAllocPool::unmap() { | 90 void GrBufferAllocPool::unmap() { |
89 VALIDATE(); | 91 VALIDATE(); |
90 | 92 |
91 if (fBufferPtr) { | 93 if (fBufferPtr) { |
92 BufferBlock& block = fBlocks.back(); | 94 BufferBlock& block = fBlocks.back(); |
93 if (block.fBuffer->isMapped()) { | 95 if (block.fBuffer->isMapped()) { |
94 UNMAP_BUFFER(block); | 96 UNMAP_BUFFER(block); |
95 } else { | 97 } else { |
96 size_t flushSize = block.fBuffer->gpuMemorySize() - block.fBytesFree
; | 98 size_t flushSize = block.fBuffer->gpuMemorySize() - block.fBytesFree
; |
97 this->flushCpuData(fBlocks.back(), flushSize); | 99 this->flushCpuData(fBlocks.back(), flushSize); |
98 } | 100 } |
99 fBufferPtr = NULL; | 101 fBufferPtr = nullptr; |
100 } | 102 } |
101 VALIDATE(); | 103 VALIDATE(); |
102 } | 104 } |
103 | 105 |
104 #ifdef SK_DEBUG | 106 #ifdef SK_DEBUG |
105 void GrBufferAllocPool::validate(bool unusedBlockAllowed) const { | 107 void GrBufferAllocPool::validate(bool unusedBlockAllowed) const { |
106 bool wasDestroyed = false; | 108 bool wasDestroyed = false; |
107 if (fBufferPtr) { | 109 if (fBufferPtr) { |
108 SkASSERT(!fBlocks.empty()); | 110 SkASSERT(!fBlocks.empty()); |
109 if (fBlocks.back().fBuffer->isMapped()) { | 111 if (fBlocks.back().fBuffer->isMapped()) { |
110 GrGeometryBuffer* buf = fBlocks.back().fBuffer; | 112 GrGeometryBuffer* buf = fBlocks.back().fBuffer; |
111 SkASSERT(buf->mapPtr() == fBufferPtr); | 113 SkASSERT(buf->mapPtr() == fBufferPtr); |
112 } else { | 114 } else { |
113 SkASSERT(fCpuData.get() == fBufferPtr); | 115 SkASSERT(fCpuData == fBufferPtr); |
114 } | 116 } |
115 } else { | 117 } else { |
116 SkASSERT(fBlocks.empty() || !fBlocks.back().fBuffer->isMapped()); | 118 SkASSERT(fBlocks.empty() || !fBlocks.back().fBuffer->isMapped()); |
117 } | 119 } |
118 size_t bytesInUse = 0; | 120 size_t bytesInUse = 0; |
119 for (int i = 0; i < fBlocks.count() - 1; ++i) { | 121 for (int i = 0; i < fBlocks.count() - 1; ++i) { |
120 SkASSERT(!fBlocks[i].fBuffer->isMapped()); | 122 SkASSERT(!fBlocks[i].fBuffer->isMapped()); |
121 } | 123 } |
122 for (int i = 0; !wasDestroyed && i < fBlocks.count(); ++i) { | 124 for (int i = 0; !wasDestroyed && i < fBlocks.count(); ++i) { |
123 if (fBlocks[i].fBuffer->wasDestroyed()) { | 125 if (fBlocks[i].fBuffer->wasDestroyed()) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 | 170 |
169 // We could honor the space request using by a partial update of the current | 171 // We could honor the space request using by a partial update of the current |
170 // VB (if there is room). But we don't currently use draw calls to GL that | 172 // VB (if there is room). But we don't currently use draw calls to GL that |
171 // allow the driver to know that previously issued draws won't read from | 173 // allow the driver to know that previously issued draws won't read from |
172 // the part of the buffer we update. Also, the GL buffer implementation | 174 // the part of the buffer we update. Also, the GL buffer implementation |
173 // may be cheating on the actual buffer size by shrinking the buffer on | 175 // may be cheating on the actual buffer size by shrinking the buffer on |
174 // updateData() if the amount of data passed is less than the full buffer | 176 // updateData() if the amount of data passed is less than the full buffer |
175 // size. | 177 // size. |
176 | 178 |
177 if (!this->createBlock(size)) { | 179 if (!this->createBlock(size)) { |
178 return NULL; | 180 return nullptr; |
179 } | 181 } |
180 SkASSERT(fBufferPtr); | 182 SkASSERT(fBufferPtr); |
181 | 183 |
182 *offset = 0; | 184 *offset = 0; |
183 BufferBlock& back = fBlocks.back(); | 185 BufferBlock& back = fBlocks.back(); |
184 *buffer = back.fBuffer; | 186 *buffer = back.fBuffer; |
185 back.fBytesFree -= size; | 187 back.fBytesFree -= size; |
186 fBytesInUse += size; | 188 fBytesInUse += size; |
187 VALIDATE(); | 189 VALIDATE(); |
188 return fBufferPtr; | 190 return fBufferPtr; |
(...skipping 30 matching lines...) Expand all Loading... |
219 bool GrBufferAllocPool::createBlock(size_t requestSize) { | 221 bool GrBufferAllocPool::createBlock(size_t requestSize) { |
220 | 222 |
221 size_t size = SkTMax(requestSize, fMinBlockSize); | 223 size_t size = SkTMax(requestSize, fMinBlockSize); |
222 SkASSERT(size >= GrBufferAllocPool_MIN_BLOCK_SIZE); | 224 SkASSERT(size >= GrBufferAllocPool_MIN_BLOCK_SIZE); |
223 | 225 |
224 VALIDATE(); | 226 VALIDATE(); |
225 | 227 |
226 BufferBlock& block = fBlocks.push_back(); | 228 BufferBlock& block = fBlocks.push_back(); |
227 | 229 |
228 block.fBuffer = this->getBuffer(size); | 230 block.fBuffer = this->getBuffer(size); |
229 if (NULL == block.fBuffer) { | 231 if (!block.fBuffer) { |
230 fBlocks.pop_back(); | 232 fBlocks.pop_back(); |
231 return false; | 233 return false; |
232 } | 234 } |
233 | 235 |
234 block.fBytesFree = block.fBuffer->gpuMemorySize(); | 236 block.fBytesFree = block.fBuffer->gpuMemorySize(); |
235 if (fBufferPtr) { | 237 if (fBufferPtr) { |
236 SkASSERT(fBlocks.count() > 1); | 238 SkASSERT(fBlocks.count() > 1); |
237 BufferBlock& prev = fBlocks.fromBack(1); | 239 BufferBlock& prev = fBlocks.fromBack(1); |
238 if (prev.fBuffer->isMapped()) { | 240 if (prev.fBuffer->isMapped()) { |
239 UNMAP_BUFFER(prev); | 241 UNMAP_BUFFER(prev); |
240 } else { | 242 } else { |
241 this->flushCpuData(prev, prev.fBuffer->gpuMemorySize() - prev.fBytes
Free); | 243 this->flushCpuData(prev, prev.fBuffer->gpuMemorySize() - prev.fBytes
Free); |
242 } | 244 } |
243 fBufferPtr = NULL; | 245 fBufferPtr = nullptr; |
244 } | 246 } |
245 | 247 |
246 SkASSERT(NULL == fBufferPtr); | 248 SkASSERT(!fBufferPtr); |
247 | 249 |
248 // If the buffer is CPU-backed we map it because it is free to do so and sav
es a copy. | 250 // If the buffer is CPU-backed we map it because it is free to do so and sav
es a copy. |
249 // Otherwise when buffer mapping is supported we map if the buffer size is g
reater than the | 251 // Otherwise when buffer mapping is supported we map if the buffer size is g
reater than the |
250 // threshold. | 252 // threshold. |
251 bool attemptMap = block.fBuffer->isCPUBacked(); | 253 bool attemptMap = block.fBuffer->isCPUBacked(); |
252 if (!attemptMap && GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags())
{ | 254 if (!attemptMap && GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags())
{ |
253 attemptMap = size > fGeometryBufferMapThreshold; | 255 attemptMap = size > fGeometryBufferMapThreshold; |
254 } | 256 } |
255 | 257 |
256 if (attemptMap) { | 258 if (attemptMap) { |
257 fBufferPtr = block.fBuffer->map(); | 259 fBufferPtr = block.fBuffer->map(); |
258 } | 260 } |
259 | 261 |
260 if (NULL == fBufferPtr) { | 262 if (!fBufferPtr) { |
261 fBufferPtr = fCpuData.reset(block.fBytesFree); | 263 fBufferPtr = this->resetCpuData(block.fBytesFree); |
262 } | 264 } |
263 | 265 |
264 VALIDATE(true); | 266 VALIDATE(true); |
265 | 267 |
266 return true; | 268 return true; |
267 } | 269 } |
268 | 270 |
269 void GrBufferAllocPool::destroyBlock() { | 271 void GrBufferAllocPool::destroyBlock() { |
270 SkASSERT(!fBlocks.empty()); | 272 SkASSERT(!fBlocks.empty()); |
271 | 273 |
272 BufferBlock& block = fBlocks.back(); | 274 BufferBlock& block = fBlocks.back(); |
273 | 275 |
274 SkASSERT(!block.fBuffer->isMapped()); | 276 SkASSERT(!block.fBuffer->isMapped()); |
275 block.fBuffer->unref(); | 277 block.fBuffer->unref(); |
276 fBlocks.pop_back(); | 278 fBlocks.pop_back(); |
277 fBufferPtr = NULL; | 279 fBufferPtr = nullptr; |
278 } | 280 } |
279 | 281 |
| 282 void* GrBufferAllocPool::resetCpuData(size_t newSize) { |
| 283 sk_free(fCpuData); |
| 284 if (newSize) { |
| 285 if (fGpu->caps()->mustClearUploadedBufferData()) { |
| 286 fCpuData = sk_calloc(newSize); |
| 287 } else { |
| 288 fCpuData = sk_malloc_throw(newSize); |
| 289 } |
| 290 } else { |
| 291 fCpuData = nullptr; |
| 292 } |
| 293 return fCpuData; |
| 294 } |
| 295 |
| 296 |
280 void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize)
{ | 297 void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize)
{ |
281 GrGeometryBuffer* buffer = block.fBuffer; | 298 GrGeometryBuffer* buffer = block.fBuffer; |
282 SkASSERT(buffer); | 299 SkASSERT(buffer); |
283 SkASSERT(!buffer->isMapped()); | 300 SkASSERT(!buffer->isMapped()); |
284 SkASSERT(fCpuData.get() == fBufferPtr); | 301 SkASSERT(fCpuData == fBufferPtr); |
285 SkASSERT(flushSize <= buffer->gpuMemorySize()); | 302 SkASSERT(flushSize <= buffer->gpuMemorySize()); |
286 VALIDATE(true); | 303 VALIDATE(true); |
287 | 304 |
288 if (GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() && | 305 if (GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() && |
289 flushSize > fGeometryBufferMapThreshold) { | 306 flushSize > fGeometryBufferMapThreshold) { |
290 void* data = buffer->map(); | 307 void* data = buffer->map(); |
291 if (data) { | 308 if (data) { |
292 memcpy(data, fBufferPtr, flushSize); | 309 memcpy(data, fBufferPtr, flushSize); |
293 UNMAP_BUFFER(block); | 310 UNMAP_BUFFER(block); |
294 return; | 311 return; |
(...skipping 27 matching lines...) Expand all Loading... |
322 void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize, | 339 void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize, |
323 int vertexCount, | 340 int vertexCount, |
324 const GrVertexBuffer** buffer, | 341 const GrVertexBuffer** buffer, |
325 int* startVertex) { | 342 int* startVertex) { |
326 | 343 |
327 SkASSERT(vertexCount >= 0); | 344 SkASSERT(vertexCount >= 0); |
328 SkASSERT(buffer); | 345 SkASSERT(buffer); |
329 SkASSERT(startVertex); | 346 SkASSERT(startVertex); |
330 | 347 |
331 size_t offset = 0; // assign to suppress warning | 348 size_t offset = 0; // assign to suppress warning |
332 const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning | 349 const GrGeometryBuffer* geomBuffer = nullptr; // assign to suppress warning |
333 void* ptr = INHERITED::makeSpace(vertexSize * vertexCount, | 350 void* ptr = INHERITED::makeSpace(vertexSize * vertexCount, |
334 vertexSize, | 351 vertexSize, |
335 &geomBuffer, | 352 &geomBuffer, |
336 &offset); | 353 &offset); |
337 | 354 |
338 *buffer = (const GrVertexBuffer*) geomBuffer; | 355 *buffer = (const GrVertexBuffer*) geomBuffer; |
339 SkASSERT(0 == offset % vertexSize); | 356 SkASSERT(0 == offset % vertexSize); |
340 *startVertex = static_cast<int>(offset / vertexSize); | 357 *startVertex = static_cast<int>(offset / vertexSize); |
341 return ptr; | 358 return ptr; |
342 } | 359 } |
343 | 360 |
344 //////////////////////////////////////////////////////////////////////////////// | 361 //////////////////////////////////////////////////////////////////////////////// |
345 | 362 |
346 GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu) | 363 GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu) |
347 : GrBufferAllocPool(gpu, kIndex_BufferType, MIN_INDEX_BUFFER_SIZE) { | 364 : GrBufferAllocPool(gpu, kIndex_BufferType, MIN_INDEX_BUFFER_SIZE) { |
348 } | 365 } |
349 | 366 |
350 void* GrIndexBufferAllocPool::makeSpace(int indexCount, | 367 void* GrIndexBufferAllocPool::makeSpace(int indexCount, |
351 const GrIndexBuffer** buffer, | 368 const GrIndexBuffer** buffer, |
352 int* startIndex) { | 369 int* startIndex) { |
353 | 370 |
354 SkASSERT(indexCount >= 0); | 371 SkASSERT(indexCount >= 0); |
355 SkASSERT(buffer); | 372 SkASSERT(buffer); |
356 SkASSERT(startIndex); | 373 SkASSERT(startIndex); |
357 | 374 |
358 size_t offset = 0; // assign to suppress warning | 375 size_t offset = 0; // assign to suppress warning |
359 const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning | 376 const GrGeometryBuffer* geomBuffer = nullptr; // assign to suppress warning |
360 void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t), | 377 void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t), |
361 sizeof(uint16_t), | 378 sizeof(uint16_t), |
362 &geomBuffer, | 379 &geomBuffer, |
363 &offset); | 380 &offset); |
364 | 381 |
365 *buffer = (const GrIndexBuffer*) geomBuffer; | 382 *buffer = (const GrIndexBuffer*) geomBuffer; |
366 SkASSERT(0 == offset % sizeof(uint16_t)); | 383 SkASSERT(0 == offset % sizeof(uint16_t)); |
367 *startIndex = static_cast<int>(offset / sizeof(uint16_t)); | 384 *startIndex = static_cast<int>(offset / sizeof(uint16_t)); |
368 return ptr; | 385 return ptr; |
369 } | 386 } |
370 | |
371 | |
OLD | NEW |