| 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" |
| 11 #include "GrBuffer.h" | |
| 12 #include "GrCaps.h" | 11 #include "GrCaps.h" |
| 13 #include "GrContext.h" | 12 #include "GrContext.h" |
| 14 #include "GrGpu.h" | 13 #include "GrGpu.h" |
| 14 #include "GrIndexBuffer.h" |
| 15 #include "GrResourceProvider.h" | 15 #include "GrResourceProvider.h" |
| 16 #include "GrTypes.h" | 16 #include "GrTypes.h" |
| 17 #include "GrVertexBuffer.h" |
| 17 | 18 |
| 18 #include "SkTraceEvent.h" | 19 #include "SkTraceEvent.h" |
| 19 | 20 |
| 20 #ifdef SK_DEBUG | 21 #ifdef SK_DEBUG |
| 21 #define VALIDATE validate | 22 #define VALIDATE validate |
| 22 #else | 23 #else |
| 23 static void VALIDATE(bool = false) {} | 24 static void VALIDATE(bool = false) {} |
| 24 #endif | 25 #endif |
| 25 | 26 |
| 26 static const size_t MIN_VERTEX_BUFFER_SIZE = 1 << 15; | 27 static const size_t MIN_VERTEX_BUFFER_SIZE = 1 << 15; |
| 27 static const size_t MIN_INDEX_BUFFER_SIZE = 1 << 12; | 28 static const size_t MIN_INDEX_BUFFER_SIZE = 1 << 12; |
| 28 | 29 |
| 29 // page size | 30 // page size |
| 30 #define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 15) | 31 #define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 15) |
| 31 | 32 |
| 32 #define UNMAP_BUFFER(block)
\ | 33 #define UNMAP_BUFFER(block)
\ |
| 33 do {
\ | 34 do {
\ |
| 34 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"),
\ | 35 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"),
\ |
| 35 "GrBufferAllocPool Unmapping Buffer",
\ | 36 "GrBufferAllocPool Unmapping Buffer",
\ |
| 36 TRACE_EVENT_SCOPE_THREAD,
\ | 37 TRACE_EVENT_SCOPE_THREAD,
\ |
| 37 "percent_unwritten",
\ | 38 "percent_unwritten",
\ |
| 38 (float)((block).fBytesFree) / (block).fBuffer->gpuMemor
ySize()); \ | 39 (float)((block).fBytesFree) / (block).fBuffer->gpuMemor
ySize()); \ |
| 39 (block).fBuffer->unmap();
\ | 40 (block).fBuffer->unmap();
\ |
| 40 } while (false) | 41 } while (false) |
| 41 | 42 |
| 42 GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu, | 43 GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu, |
| 43 GrBufferType bufferType, | 44 BufferType bufferType, |
| 44 size_t blockSize) | 45 size_t blockSize) |
| 45 : fBlocks(8) { | 46 : fBlocks(8) { |
| 46 | 47 |
| 47 fGpu = SkRef(gpu); | 48 fGpu = SkRef(gpu); |
| 48 fCpuData = nullptr; | 49 fCpuData = nullptr; |
| 49 fBufferType = bufferType; | 50 fBufferType = bufferType; |
| 50 fBufferPtr = nullptr; | 51 fBufferPtr = nullptr; |
| 51 fMinBlockSize = SkTMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize); | 52 fMinBlockSize = SkTMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize); |
| 52 | 53 |
| 53 fBytesInUse = 0; | 54 fBytesInUse = 0; |
| 54 | 55 |
| 55 fBufferMapThreshold = gpu->caps()->bufferMapThreshold(); | 56 fGeometryBufferMapThreshold = gpu->caps()->geometryBufferMapThreshold(); |
| 56 } | 57 } |
| 57 | 58 |
| 58 void GrBufferAllocPool::deleteBlocks() { | 59 void GrBufferAllocPool::deleteBlocks() { |
| 59 if (fBlocks.count()) { | 60 if (fBlocks.count()) { |
| 60 GrBuffer* buffer = fBlocks.back().fBuffer; | 61 GrGeometryBuffer* buffer = fBlocks.back().fBuffer; |
| 61 if (buffer->isMapped()) { | 62 if (buffer->isMapped()) { |
| 62 UNMAP_BUFFER(fBlocks.back()); | 63 UNMAP_BUFFER(fBlocks.back()); |
| 63 } | 64 } |
| 64 } | 65 } |
| 65 while (!fBlocks.empty()) { | 66 while (!fBlocks.empty()) { |
| 66 this->destroyBlock(); | 67 this->destroyBlock(); |
| 67 } | 68 } |
| 68 SkASSERT(!fBufferPtr); | 69 SkASSERT(!fBufferPtr); |
| 69 } | 70 } |
| 70 | 71 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 101 } | 102 } |
| 102 VALIDATE(); | 103 VALIDATE(); |
| 103 } | 104 } |
| 104 | 105 |
| 105 #ifdef SK_DEBUG | 106 #ifdef SK_DEBUG |
| 106 void GrBufferAllocPool::validate(bool unusedBlockAllowed) const { | 107 void GrBufferAllocPool::validate(bool unusedBlockAllowed) const { |
| 107 bool wasDestroyed = false; | 108 bool wasDestroyed = false; |
| 108 if (fBufferPtr) { | 109 if (fBufferPtr) { |
| 109 SkASSERT(!fBlocks.empty()); | 110 SkASSERT(!fBlocks.empty()); |
| 110 if (fBlocks.back().fBuffer->isMapped()) { | 111 if (fBlocks.back().fBuffer->isMapped()) { |
| 111 GrBuffer* buf = fBlocks.back().fBuffer; | 112 GrGeometryBuffer* buf = fBlocks.back().fBuffer; |
| 112 SkASSERT(buf->mapPtr() == fBufferPtr); | 113 SkASSERT(buf->mapPtr() == fBufferPtr); |
| 113 } else { | 114 } else { |
| 114 SkASSERT(fCpuData == fBufferPtr); | 115 SkASSERT(fCpuData == fBufferPtr); |
| 115 } | 116 } |
| 116 } else { | 117 } else { |
| 117 SkASSERT(fBlocks.empty() || !fBlocks.back().fBuffer->isMapped()); | 118 SkASSERT(fBlocks.empty() || !fBlocks.back().fBuffer->isMapped()); |
| 118 } | 119 } |
| 119 size_t bytesInUse = 0; | 120 size_t bytesInUse = 0; |
| 120 for (int i = 0; i < fBlocks.count() - 1; ++i) { | 121 for (int i = 0; i < fBlocks.count() - 1; ++i) { |
| 121 SkASSERT(!fBlocks[i].fBuffer->isMapped()); | 122 SkASSERT(!fBlocks[i].fBuffer->isMapped()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 137 (!fBytesInUse && (fBlocks.count() < 2))); | 138 (!fBytesInUse && (fBlocks.count() < 2))); |
| 138 } else { | 139 } else { |
| 139 SkASSERT((0 == fBytesInUse) == fBlocks.empty()); | 140 SkASSERT((0 == fBytesInUse) == fBlocks.empty()); |
| 140 } | 141 } |
| 141 } | 142 } |
| 142 } | 143 } |
| 143 #endif | 144 #endif |
| 144 | 145 |
| 145 void* GrBufferAllocPool::makeSpace(size_t size, | 146 void* GrBufferAllocPool::makeSpace(size_t size, |
| 146 size_t alignment, | 147 size_t alignment, |
| 147 const GrBuffer** buffer, | 148 const GrGeometryBuffer** buffer, |
| 148 size_t* offset) { | 149 size_t* offset) { |
| 149 VALIDATE(); | 150 VALIDATE(); |
| 150 | 151 |
| 151 SkASSERT(buffer); | 152 SkASSERT(buffer); |
| 152 SkASSERT(offset); | 153 SkASSERT(offset); |
| 153 | 154 |
| 154 if (fBufferPtr) { | 155 if (fBufferPtr) { |
| 155 BufferBlock& back = fBlocks.back(); | 156 BufferBlock& back = fBlocks.back(); |
| 156 size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree; | 157 size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree; |
| 157 size_t pad = GrSizeAlignUpPad(usedBytes, alignment); | 158 size_t pad = GrSizeAlignUpPad(usedBytes, alignment); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 fBufferPtr = nullptr; | 245 fBufferPtr = nullptr; |
| 245 } | 246 } |
| 246 | 247 |
| 247 SkASSERT(!fBufferPtr); | 248 SkASSERT(!fBufferPtr); |
| 248 | 249 |
| 249 // 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. |
| 250 // 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 |
| 251 // threshold. | 252 // threshold. |
| 252 bool attemptMap = block.fBuffer->isCPUBacked(); | 253 bool attemptMap = block.fBuffer->isCPUBacked(); |
| 253 if (!attemptMap && GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags())
{ | 254 if (!attemptMap && GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags())
{ |
| 254 attemptMap = size > fBufferMapThreshold; | 255 attemptMap = size > fGeometryBufferMapThreshold; |
| 255 } | 256 } |
| 256 | 257 |
| 257 if (attemptMap) { | 258 if (attemptMap) { |
| 258 fBufferPtr = block.fBuffer->map(); | 259 fBufferPtr = block.fBuffer->map(); |
| 259 } | 260 } |
| 260 | 261 |
| 261 if (!fBufferPtr) { | 262 if (!fBufferPtr) { |
| 262 fBufferPtr = this->resetCpuData(block.fBytesFree); | 263 fBufferPtr = this->resetCpuData(block.fBytesFree); |
| 263 } | 264 } |
| 264 | 265 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 287 fCpuData = sk_malloc_throw(newSize); | 288 fCpuData = sk_malloc_throw(newSize); |
| 288 } | 289 } |
| 289 } else { | 290 } else { |
| 290 fCpuData = nullptr; | 291 fCpuData = nullptr; |
| 291 } | 292 } |
| 292 return fCpuData; | 293 return fCpuData; |
| 293 } | 294 } |
| 294 | 295 |
| 295 | 296 |
| 296 void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize)
{ | 297 void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize)
{ |
| 297 GrBuffer* buffer = block.fBuffer; | 298 GrGeometryBuffer* buffer = block.fBuffer; |
| 298 SkASSERT(buffer); | 299 SkASSERT(buffer); |
| 299 SkASSERT(!buffer->isMapped()); | 300 SkASSERT(!buffer->isMapped()); |
| 300 SkASSERT(fCpuData == fBufferPtr); | 301 SkASSERT(fCpuData == fBufferPtr); |
| 301 SkASSERT(flushSize <= buffer->gpuMemorySize()); | 302 SkASSERT(flushSize <= buffer->gpuMemorySize()); |
| 302 VALIDATE(true); | 303 VALIDATE(true); |
| 303 | 304 |
| 304 if (GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() && | 305 if (GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() && |
| 305 flushSize > fBufferMapThreshold) { | 306 flushSize > fGeometryBufferMapThreshold) { |
| 306 void* data = buffer->map(); | 307 void* data = buffer->map(); |
| 307 if (data) { | 308 if (data) { |
| 308 memcpy(data, fBufferPtr, flushSize); | 309 memcpy(data, fBufferPtr, flushSize); |
| 309 UNMAP_BUFFER(block); | 310 UNMAP_BUFFER(block); |
| 310 return; | 311 return; |
| 311 } | 312 } |
| 312 } | 313 } |
| 313 buffer->updateData(fBufferPtr, flushSize); | 314 buffer->updateData(fBufferPtr, flushSize); |
| 314 VALIDATE(true); | 315 VALIDATE(true); |
| 315 } | 316 } |
| 316 | 317 |
| 317 GrBuffer* GrBufferAllocPool::getBuffer(size_t size) { | 318 GrGeometryBuffer* GrBufferAllocPool::getBuffer(size_t size) { |
| 318 | 319 |
| 319 GrResourceProvider* rp = fGpu->getContext()->resourceProvider(); | 320 GrResourceProvider* rp = fGpu->getContext()->resourceProvider(); |
| 320 | 321 |
| 322 static const GrResourceProvider::BufferUsage kUsage = GrResourceProvider::kD
ynamic_BufferUsage; |
| 321 // Shouldn't have to use this flag (https://bug.skia.org/4156) | 323 // Shouldn't have to use this flag (https://bug.skia.org/4156) |
| 322 static const uint32_t kFlags = GrResourceProvider::kNoPendingIO_Flag; | 324 static const uint32_t kFlags = GrResourceProvider::kNoPendingIO_Flag; |
| 323 return rp->createBuffer(fBufferType, size, kDynamic_GrAccessPattern, kFlags)
; | 325 if (kIndex_BufferType == fBufferType) { |
| 326 return rp->createIndexBuffer(size, kUsage, kFlags); |
| 327 } else { |
| 328 SkASSERT(kVertex_BufferType == fBufferType); |
| 329 return rp->createVertexBuffer(size, kUsage, kFlags); |
| 330 } |
| 324 } | 331 } |
| 325 | 332 |
| 326 //////////////////////////////////////////////////////////////////////////////// | 333 //////////////////////////////////////////////////////////////////////////////// |
| 327 | 334 |
| 328 GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu) | 335 GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu) |
| 329 : GrBufferAllocPool(gpu, kVertex_GrBufferType, MIN_VERTEX_BUFFER_SIZE) { | 336 : GrBufferAllocPool(gpu, kVertex_BufferType, MIN_VERTEX_BUFFER_SIZE) { |
| 330 } | 337 } |
| 331 | 338 |
| 332 void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize, | 339 void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize, |
| 333 int vertexCount, | 340 int vertexCount, |
| 334 const GrBuffer** buffer, | 341 const GrVertexBuffer** buffer, |
| 335 int* startVertex) { | 342 int* startVertex) { |
| 336 | 343 |
| 337 SkASSERT(vertexCount >= 0); | 344 SkASSERT(vertexCount >= 0); |
| 338 SkASSERT(buffer); | 345 SkASSERT(buffer); |
| 339 SkASSERT(startVertex); | 346 SkASSERT(startVertex); |
| 340 | 347 |
| 341 size_t offset = 0; // assign to suppress warning | 348 size_t offset = 0; // assign to suppress warning |
| 349 const GrGeometryBuffer* geomBuffer = nullptr; // assign to suppress warning |
| 342 void* ptr = INHERITED::makeSpace(vertexSize * vertexCount, | 350 void* ptr = INHERITED::makeSpace(vertexSize * vertexCount, |
| 343 vertexSize, | 351 vertexSize, |
| 344 buffer, | 352 &geomBuffer, |
| 345 &offset); | 353 &offset); |
| 346 | 354 |
| 355 *buffer = (const GrVertexBuffer*) geomBuffer; |
| 347 SkASSERT(0 == offset % vertexSize); | 356 SkASSERT(0 == offset % vertexSize); |
| 348 *startVertex = static_cast<int>(offset / vertexSize); | 357 *startVertex = static_cast<int>(offset / vertexSize); |
| 349 return ptr; | 358 return ptr; |
| 350 } | 359 } |
| 351 | 360 |
| 352 //////////////////////////////////////////////////////////////////////////////// | 361 //////////////////////////////////////////////////////////////////////////////// |
| 353 | 362 |
| 354 GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu) | 363 GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu) |
| 355 : GrBufferAllocPool(gpu, kIndex_GrBufferType, MIN_INDEX_BUFFER_SIZE) { | 364 : GrBufferAllocPool(gpu, kIndex_BufferType, MIN_INDEX_BUFFER_SIZE) { |
| 356 } | 365 } |
| 357 | 366 |
| 358 void* GrIndexBufferAllocPool::makeSpace(int indexCount, | 367 void* GrIndexBufferAllocPool::makeSpace(int indexCount, |
| 359 const GrBuffer** buffer, | 368 const GrIndexBuffer** buffer, |
| 360 int* startIndex) { | 369 int* startIndex) { |
| 361 | 370 |
| 362 SkASSERT(indexCount >= 0); | 371 SkASSERT(indexCount >= 0); |
| 363 SkASSERT(buffer); | 372 SkASSERT(buffer); |
| 364 SkASSERT(startIndex); | 373 SkASSERT(startIndex); |
| 365 | 374 |
| 366 size_t offset = 0; // assign to suppress warning | 375 size_t offset = 0; // assign to suppress warning |
| 376 const GrGeometryBuffer* geomBuffer = nullptr; // assign to suppress warning |
| 367 void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t), | 377 void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t), |
| 368 sizeof(uint16_t), | 378 sizeof(uint16_t), |
| 369 buffer, | 379 &geomBuffer, |
| 370 &offset); | 380 &offset); |
| 371 | 381 |
| 382 *buffer = (const GrIndexBuffer*) geomBuffer; |
| 372 SkASSERT(0 == offset % sizeof(uint16_t)); | 383 SkASSERT(0 == offset % sizeof(uint16_t)); |
| 373 *startIndex = static_cast<int>(offset / sizeof(uint16_t)); | 384 *startIndex = static_cast<int>(offset / sizeof(uint16_t)); |
| 374 return ptr; | 385 return ptr; |
| 375 } | 386 } |
| OLD | NEW |