1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2010 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 9cb93a386Sopenharmony_ci#include "include/gpu/GrTypes.h" 10cb93a386Sopenharmony_ci#include "include/private/SkMacros.h" 11cb93a386Sopenharmony_ci#include "src/core/SkSafeMath.h" 12cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrBufferAllocPool.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#include <memory> 16cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h" 17cb93a386Sopenharmony_ci#include "src/gpu/GrCpuBuffer.h" 18cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 19cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h" 20cb93a386Sopenharmony_ci#include "src/gpu/GrGpuBuffer.h" 21cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h" 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_cisk_sp<GrBufferAllocPool::CpuBufferCache> GrBufferAllocPool::CpuBufferCache::Make( 24cb93a386Sopenharmony_ci int maxBuffersToCache) { 25cb93a386Sopenharmony_ci return sk_sp<CpuBufferCache>(new CpuBufferCache(maxBuffersToCache)); 26cb93a386Sopenharmony_ci} 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ciGrBufferAllocPool::CpuBufferCache::CpuBufferCache(int maxBuffersToCache) 29cb93a386Sopenharmony_ci : fMaxBuffersToCache(maxBuffersToCache) { 30cb93a386Sopenharmony_ci if (fMaxBuffersToCache) { 31cb93a386Sopenharmony_ci fBuffers = std::make_unique<Buffer[]>(fMaxBuffersToCache); 32cb93a386Sopenharmony_ci } 33cb93a386Sopenharmony_ci} 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_cisk_sp<GrCpuBuffer> GrBufferAllocPool::CpuBufferCache::makeBuffer(size_t size, 36cb93a386Sopenharmony_ci bool mustBeInitialized) { 37cb93a386Sopenharmony_ci SkASSERT(size > 0); 38cb93a386Sopenharmony_ci Buffer* result = nullptr; 39cb93a386Sopenharmony_ci if (size == kDefaultBufferSize) { 40cb93a386Sopenharmony_ci int i = 0; 41cb93a386Sopenharmony_ci for (; i < fMaxBuffersToCache && fBuffers[i].fBuffer; ++i) { 42cb93a386Sopenharmony_ci SkASSERT(fBuffers[i].fBuffer->size() == kDefaultBufferSize); 43cb93a386Sopenharmony_ci if (fBuffers[i].fBuffer->unique()) { 44cb93a386Sopenharmony_ci result = &fBuffers[i]; 45cb93a386Sopenharmony_ci } 46cb93a386Sopenharmony_ci } 47cb93a386Sopenharmony_ci if (!result && i < fMaxBuffersToCache) { 48cb93a386Sopenharmony_ci fBuffers[i].fBuffer = GrCpuBuffer::Make(size); 49cb93a386Sopenharmony_ci result = &fBuffers[i]; 50cb93a386Sopenharmony_ci } 51cb93a386Sopenharmony_ci } 52cb93a386Sopenharmony_ci Buffer tempResult; 53cb93a386Sopenharmony_ci if (!result) { 54cb93a386Sopenharmony_ci tempResult.fBuffer = GrCpuBuffer::Make(size); 55cb93a386Sopenharmony_ci result = &tempResult; 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci if (mustBeInitialized && !result->fCleared) { 58cb93a386Sopenharmony_ci result->fCleared = true; 59cb93a386Sopenharmony_ci memset(result->fBuffer->data(), 0, result->fBuffer->size()); 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci return result->fBuffer; 62cb93a386Sopenharmony_ci} 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_civoid GrBufferAllocPool::CpuBufferCache::releaseAll() { 65cb93a386Sopenharmony_ci for (int i = 0; i < fMaxBuffersToCache && fBuffers[i].fBuffer; ++i) { 66cb93a386Sopenharmony_ci fBuffers[i].fBuffer.reset(); 67cb93a386Sopenharmony_ci fBuffers[i].fCleared = false; 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci} 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci#ifdef SK_DEBUG 74cb93a386Sopenharmony_ci #define VALIDATE validate 75cb93a386Sopenharmony_ci#else 76cb93a386Sopenharmony_ci static void VALIDATE(bool = false) {} 77cb93a386Sopenharmony_ci#endif 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ci#define UNMAP_BUFFER(block) \ 80cb93a386Sopenharmony_ci do { \ 81cb93a386Sopenharmony_ci TRACE_EVENT_INSTANT1("skia.gpu", "GrBufferAllocPool Unmapping Buffer", \ 82cb93a386Sopenharmony_ci TRACE_EVENT_SCOPE_THREAD, "percent_unwritten", \ 83cb93a386Sopenharmony_ci (float)((block).fBytesFree) / (block).fBuffer->size()); \ 84cb93a386Sopenharmony_ci SkASSERT(!block.fBuffer->isCpuBuffer()); \ 85cb93a386Sopenharmony_ci static_cast<GrGpuBuffer*>(block.fBuffer.get())->unmap(); \ 86cb93a386Sopenharmony_ci } while (false) 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ciGrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu, GrGpuBufferType bufferType, 89cb93a386Sopenharmony_ci sk_sp<CpuBufferCache> cpuBufferCache) 90cb93a386Sopenharmony_ci : fBlocks(8) 91cb93a386Sopenharmony_ci , fCpuBufferCache(std::move(cpuBufferCache)) 92cb93a386Sopenharmony_ci , fGpu(gpu) 93cb93a386Sopenharmony_ci , fBufferType(bufferType) {} 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_civoid GrBufferAllocPool::deleteBlocks() { 96cb93a386Sopenharmony_ci if (fBlocks.count()) { 97cb93a386Sopenharmony_ci GrBuffer* buffer = fBlocks.back().fBuffer.get(); 98cb93a386Sopenharmony_ci if (!buffer->isCpuBuffer() && static_cast<GrGpuBuffer*>(buffer)->isMapped()) { 99cb93a386Sopenharmony_ci UNMAP_BUFFER(fBlocks.back()); 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci } 102cb93a386Sopenharmony_ci while (!fBlocks.empty()) { 103cb93a386Sopenharmony_ci this->destroyBlock(); 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci SkASSERT(!fBufferPtr); 106cb93a386Sopenharmony_ci} 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ciGrBufferAllocPool::~GrBufferAllocPool() { 109cb93a386Sopenharmony_ci VALIDATE(); 110cb93a386Sopenharmony_ci this->deleteBlocks(); 111cb93a386Sopenharmony_ci} 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_civoid GrBufferAllocPool::reset() { 114cb93a386Sopenharmony_ci VALIDATE(); 115cb93a386Sopenharmony_ci fBytesInUse = 0; 116cb93a386Sopenharmony_ci this->deleteBlocks(); 117cb93a386Sopenharmony_ci this->resetCpuData(0); 118cb93a386Sopenharmony_ci VALIDATE(); 119cb93a386Sopenharmony_ci} 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_civoid GrBufferAllocPool::unmap() { 122cb93a386Sopenharmony_ci VALIDATE(); 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci if (fBufferPtr) { 125cb93a386Sopenharmony_ci BufferBlock& block = fBlocks.back(); 126cb93a386Sopenharmony_ci GrBuffer* buffer = block.fBuffer.get(); 127cb93a386Sopenharmony_ci if (!buffer->isCpuBuffer()) { 128cb93a386Sopenharmony_ci if (static_cast<GrGpuBuffer*>(buffer)->isMapped()) { 129cb93a386Sopenharmony_ci UNMAP_BUFFER(block); 130cb93a386Sopenharmony_ci } else { 131cb93a386Sopenharmony_ci size_t flushSize = block.fBuffer->size() - block.fBytesFree; 132cb93a386Sopenharmony_ci this->flushCpuData(fBlocks.back(), flushSize); 133cb93a386Sopenharmony_ci } 134cb93a386Sopenharmony_ci } 135cb93a386Sopenharmony_ci fBufferPtr = nullptr; 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci VALIDATE(); 138cb93a386Sopenharmony_ci} 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci#ifdef SK_DEBUG 141cb93a386Sopenharmony_civoid GrBufferAllocPool::validate(bool unusedBlockAllowed) const { 142cb93a386Sopenharmony_ci bool wasDestroyed = false; 143cb93a386Sopenharmony_ci if (fBufferPtr) { 144cb93a386Sopenharmony_ci SkASSERT(!fBlocks.empty()); 145cb93a386Sopenharmony_ci const GrBuffer* buffer = fBlocks.back().fBuffer.get(); 146cb93a386Sopenharmony_ci if (!buffer->isCpuBuffer() && !static_cast<const GrGpuBuffer*>(buffer)->isMapped()) { 147cb93a386Sopenharmony_ci SkASSERT(fCpuStagingBuffer && fCpuStagingBuffer->data() == fBufferPtr); 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci } else if (!fBlocks.empty()) { 150cb93a386Sopenharmony_ci const GrBuffer* buffer = fBlocks.back().fBuffer.get(); 151cb93a386Sopenharmony_ci SkASSERT(buffer->isCpuBuffer() || !static_cast<const GrGpuBuffer*>(buffer)->isMapped()); 152cb93a386Sopenharmony_ci } 153cb93a386Sopenharmony_ci size_t bytesInUse = 0; 154cb93a386Sopenharmony_ci for (int i = 0; i < fBlocks.count() - 1; ++i) { 155cb93a386Sopenharmony_ci const GrBuffer* buffer = fBlocks[i].fBuffer.get(); 156cb93a386Sopenharmony_ci SkASSERT(buffer->isCpuBuffer() || !static_cast<const GrGpuBuffer*>(buffer)->isMapped()); 157cb93a386Sopenharmony_ci } 158cb93a386Sopenharmony_ci for (int i = 0; !wasDestroyed && i < fBlocks.count(); ++i) { 159cb93a386Sopenharmony_ci GrBuffer* buffer = fBlocks[i].fBuffer.get(); 160cb93a386Sopenharmony_ci if (!buffer->isCpuBuffer() && static_cast<GrGpuBuffer*>(buffer)->wasDestroyed()) { 161cb93a386Sopenharmony_ci wasDestroyed = true; 162cb93a386Sopenharmony_ci } else { 163cb93a386Sopenharmony_ci size_t bytes = fBlocks[i].fBuffer->size() - fBlocks[i].fBytesFree; 164cb93a386Sopenharmony_ci bytesInUse += bytes; 165cb93a386Sopenharmony_ci SkASSERT(bytes || unusedBlockAllowed); 166cb93a386Sopenharmony_ci } 167cb93a386Sopenharmony_ci } 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_ci if (!wasDestroyed) { 170cb93a386Sopenharmony_ci SkASSERT(bytesInUse == fBytesInUse); 171cb93a386Sopenharmony_ci if (unusedBlockAllowed) { 172cb93a386Sopenharmony_ci SkASSERT((fBytesInUse && !fBlocks.empty()) || 173cb93a386Sopenharmony_ci (!fBytesInUse && (fBlocks.count() < 2))); 174cb93a386Sopenharmony_ci } else { 175cb93a386Sopenharmony_ci SkASSERT((0 == fBytesInUse) == fBlocks.empty()); 176cb93a386Sopenharmony_ci } 177cb93a386Sopenharmony_ci } 178cb93a386Sopenharmony_ci} 179cb93a386Sopenharmony_ci#endif 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_cistatic inline size_t align_up_pad(size_t x, size_t alignment) { 182cb93a386Sopenharmony_ci return (alignment - x % alignment) % alignment; 183cb93a386Sopenharmony_ci} 184cb93a386Sopenharmony_ci 185cb93a386Sopenharmony_cistatic inline size_t align_down(size_t x, uint32_t alignment) { 186cb93a386Sopenharmony_ci return (x / alignment) * alignment; 187cb93a386Sopenharmony_ci} 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_civoid* GrBufferAllocPool::makeSpace(size_t size, 190cb93a386Sopenharmony_ci size_t alignment, 191cb93a386Sopenharmony_ci sk_sp<const GrBuffer>* buffer, 192cb93a386Sopenharmony_ci size_t* offset) { 193cb93a386Sopenharmony_ci VALIDATE(); 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ci SkASSERT(buffer); 196cb93a386Sopenharmony_ci SkASSERT(offset); 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_ci if (fBufferPtr) { 199cb93a386Sopenharmony_ci BufferBlock& back = fBlocks.back(); 200cb93a386Sopenharmony_ci size_t usedBytes = back.fBuffer->size() - back.fBytesFree; 201cb93a386Sopenharmony_ci size_t pad = align_up_pad(usedBytes, alignment); 202cb93a386Sopenharmony_ci SkSafeMath safeMath; 203cb93a386Sopenharmony_ci size_t alignedSize = safeMath.add(pad, size); 204cb93a386Sopenharmony_ci if (!safeMath.ok()) { 205cb93a386Sopenharmony_ci return nullptr; 206cb93a386Sopenharmony_ci } 207cb93a386Sopenharmony_ci if (alignedSize <= back.fBytesFree) { 208cb93a386Sopenharmony_ci memset((void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes), 0, pad); 209cb93a386Sopenharmony_ci usedBytes += pad; 210cb93a386Sopenharmony_ci *offset = usedBytes; 211cb93a386Sopenharmony_ci *buffer = back.fBuffer; 212cb93a386Sopenharmony_ci back.fBytesFree -= alignedSize; 213cb93a386Sopenharmony_ci fBytesInUse += alignedSize; 214cb93a386Sopenharmony_ci VALIDATE(); 215cb93a386Sopenharmony_ci return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes); 216cb93a386Sopenharmony_ci } 217cb93a386Sopenharmony_ci } 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_ci // We could honor the space request using by a partial update of the current 220cb93a386Sopenharmony_ci // VB (if there is room). But we don't currently use draw calls to GL that 221cb93a386Sopenharmony_ci // allow the driver to know that previously issued draws won't read from 222cb93a386Sopenharmony_ci // the part of the buffer we update. Also, the GL buffer implementation 223cb93a386Sopenharmony_ci // may be cheating on the actual buffer size by shrinking the buffer on 224cb93a386Sopenharmony_ci // updateData() if the amount of data passed is less than the full buffer 225cb93a386Sopenharmony_ci // size. 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ci if (!this->createBlock(size)) { 228cb93a386Sopenharmony_ci return nullptr; 229cb93a386Sopenharmony_ci } 230cb93a386Sopenharmony_ci SkASSERT(fBufferPtr); 231cb93a386Sopenharmony_ci 232cb93a386Sopenharmony_ci *offset = 0; 233cb93a386Sopenharmony_ci BufferBlock& back = fBlocks.back(); 234cb93a386Sopenharmony_ci *buffer = back.fBuffer; 235cb93a386Sopenharmony_ci back.fBytesFree -= size; 236cb93a386Sopenharmony_ci fBytesInUse += size; 237cb93a386Sopenharmony_ci VALIDATE(); 238cb93a386Sopenharmony_ci return fBufferPtr; 239cb93a386Sopenharmony_ci} 240cb93a386Sopenharmony_ci 241cb93a386Sopenharmony_civoid* GrBufferAllocPool::makeSpaceAtLeast(size_t minSize, 242cb93a386Sopenharmony_ci size_t fallbackSize, 243cb93a386Sopenharmony_ci size_t alignment, 244cb93a386Sopenharmony_ci sk_sp<const GrBuffer>* buffer, 245cb93a386Sopenharmony_ci size_t* offset, 246cb93a386Sopenharmony_ci size_t* actualSize) { 247cb93a386Sopenharmony_ci VALIDATE(); 248cb93a386Sopenharmony_ci 249cb93a386Sopenharmony_ci SkASSERT(buffer); 250cb93a386Sopenharmony_ci SkASSERT(offset); 251cb93a386Sopenharmony_ci SkASSERT(actualSize); 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_ci size_t usedBytes = (fBlocks.empty()) ? 0 : fBlocks.back().fBuffer->size() - 254cb93a386Sopenharmony_ci fBlocks.back().fBytesFree; 255cb93a386Sopenharmony_ci size_t pad = align_up_pad(usedBytes, alignment); 256cb93a386Sopenharmony_ci if (fBlocks.empty() || (minSize + pad) > fBlocks.back().fBytesFree) { 257cb93a386Sopenharmony_ci // We either don't have a block yet or the current block doesn't have enough free space. 258cb93a386Sopenharmony_ci // Create a new one. 259cb93a386Sopenharmony_ci if (!this->createBlock(fallbackSize)) { 260cb93a386Sopenharmony_ci return nullptr; 261cb93a386Sopenharmony_ci } 262cb93a386Sopenharmony_ci usedBytes = 0; 263cb93a386Sopenharmony_ci pad = 0; 264cb93a386Sopenharmony_ci } 265cb93a386Sopenharmony_ci SkASSERT(fBufferPtr); 266cb93a386Sopenharmony_ci 267cb93a386Sopenharmony_ci // Consume padding first, to make subsequent alignment math easier 268cb93a386Sopenharmony_ci memset(static_cast<char*>(fBufferPtr) + usedBytes, 0, pad); 269cb93a386Sopenharmony_ci usedBytes += pad; 270cb93a386Sopenharmony_ci fBlocks.back().fBytesFree -= pad; 271cb93a386Sopenharmony_ci fBytesInUse += pad; 272cb93a386Sopenharmony_ci 273cb93a386Sopenharmony_ci // Give caller all remaining space in this block (but aligned correctly) 274cb93a386Sopenharmony_ci size_t size = align_down(fBlocks.back().fBytesFree, alignment); 275cb93a386Sopenharmony_ci *offset = usedBytes; 276cb93a386Sopenharmony_ci *buffer = fBlocks.back().fBuffer; 277cb93a386Sopenharmony_ci *actualSize = size; 278cb93a386Sopenharmony_ci fBlocks.back().fBytesFree -= size; 279cb93a386Sopenharmony_ci fBytesInUse += size; 280cb93a386Sopenharmony_ci VALIDATE(); 281cb93a386Sopenharmony_ci return static_cast<char*>(fBufferPtr) + usedBytes; 282cb93a386Sopenharmony_ci} 283cb93a386Sopenharmony_ci 284cb93a386Sopenharmony_civoid GrBufferAllocPool::putBack(size_t bytes) { 285cb93a386Sopenharmony_ci VALIDATE(); 286cb93a386Sopenharmony_ci 287cb93a386Sopenharmony_ci while (bytes) { 288cb93a386Sopenharmony_ci // caller shouldn't try to put back more than they've taken 289cb93a386Sopenharmony_ci SkASSERT(!fBlocks.empty()); 290cb93a386Sopenharmony_ci BufferBlock& block = fBlocks.back(); 291cb93a386Sopenharmony_ci size_t bytesUsed = block.fBuffer->size() - block.fBytesFree; 292cb93a386Sopenharmony_ci if (bytes >= bytesUsed) { 293cb93a386Sopenharmony_ci bytes -= bytesUsed; 294cb93a386Sopenharmony_ci fBytesInUse -= bytesUsed; 295cb93a386Sopenharmony_ci // if we locked a vb to satisfy the make space and we're releasing 296cb93a386Sopenharmony_ci // beyond it, then unmap it. 297cb93a386Sopenharmony_ci GrBuffer* buffer = block.fBuffer.get(); 298cb93a386Sopenharmony_ci if (!buffer->isCpuBuffer() && static_cast<GrGpuBuffer*>(buffer)->isMapped()) { 299cb93a386Sopenharmony_ci UNMAP_BUFFER(block); 300cb93a386Sopenharmony_ci } 301cb93a386Sopenharmony_ci this->destroyBlock(); 302cb93a386Sopenharmony_ci } else { 303cb93a386Sopenharmony_ci block.fBytesFree += bytes; 304cb93a386Sopenharmony_ci fBytesInUse -= bytes; 305cb93a386Sopenharmony_ci bytes = 0; 306cb93a386Sopenharmony_ci break; 307cb93a386Sopenharmony_ci } 308cb93a386Sopenharmony_ci } 309cb93a386Sopenharmony_ci 310cb93a386Sopenharmony_ci VALIDATE(); 311cb93a386Sopenharmony_ci} 312cb93a386Sopenharmony_ci 313cb93a386Sopenharmony_cibool GrBufferAllocPool::createBlock(size_t requestSize) { 314cb93a386Sopenharmony_ci size_t size = std::max(requestSize, kDefaultBufferSize); 315cb93a386Sopenharmony_ci 316cb93a386Sopenharmony_ci VALIDATE(); 317cb93a386Sopenharmony_ci 318cb93a386Sopenharmony_ci BufferBlock& block = fBlocks.push_back(); 319cb93a386Sopenharmony_ci 320cb93a386Sopenharmony_ci block.fBuffer = this->getBuffer(size); 321cb93a386Sopenharmony_ci if (!block.fBuffer) { 322cb93a386Sopenharmony_ci fBlocks.pop_back(); 323cb93a386Sopenharmony_ci return false; 324cb93a386Sopenharmony_ci } 325cb93a386Sopenharmony_ci 326cb93a386Sopenharmony_ci block.fBytesFree = block.fBuffer->size(); 327cb93a386Sopenharmony_ci if (fBufferPtr) { 328cb93a386Sopenharmony_ci SkASSERT(fBlocks.count() > 1); 329cb93a386Sopenharmony_ci BufferBlock& prev = fBlocks.fromBack(1); 330cb93a386Sopenharmony_ci GrBuffer* buffer = prev.fBuffer.get(); 331cb93a386Sopenharmony_ci if (!buffer->isCpuBuffer()) { 332cb93a386Sopenharmony_ci if (static_cast<GrGpuBuffer*>(buffer)->isMapped()) { 333cb93a386Sopenharmony_ci UNMAP_BUFFER(prev); 334cb93a386Sopenharmony_ci } else { 335cb93a386Sopenharmony_ci this->flushCpuData(prev, prev.fBuffer->size() - prev.fBytesFree); 336cb93a386Sopenharmony_ci } 337cb93a386Sopenharmony_ci } 338cb93a386Sopenharmony_ci fBufferPtr = nullptr; 339cb93a386Sopenharmony_ci } 340cb93a386Sopenharmony_ci 341cb93a386Sopenharmony_ci SkASSERT(!fBufferPtr); 342cb93a386Sopenharmony_ci 343cb93a386Sopenharmony_ci // If the buffer is CPU-backed we "map" it because it is free to do so and saves a copy. 344cb93a386Sopenharmony_ci // Otherwise when buffer mapping is supported we map if the buffer size is greater than the 345cb93a386Sopenharmony_ci // threshold. 346cb93a386Sopenharmony_ci if (block.fBuffer->isCpuBuffer()) { 347cb93a386Sopenharmony_ci fBufferPtr = static_cast<GrCpuBuffer*>(block.fBuffer.get())->data(); 348cb93a386Sopenharmony_ci SkASSERT(fBufferPtr); 349cb93a386Sopenharmony_ci } else { 350cb93a386Sopenharmony_ci if (GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() && 351cb93a386Sopenharmony_ci size > fGpu->caps()->bufferMapThreshold()) { 352cb93a386Sopenharmony_ci fBufferPtr = static_cast<GrGpuBuffer*>(block.fBuffer.get())->map(); 353cb93a386Sopenharmony_ci } 354cb93a386Sopenharmony_ci } 355cb93a386Sopenharmony_ci if (!fBufferPtr) { 356cb93a386Sopenharmony_ci this->resetCpuData(block.fBytesFree); 357cb93a386Sopenharmony_ci fBufferPtr = fCpuStagingBuffer->data(); 358cb93a386Sopenharmony_ci } 359cb93a386Sopenharmony_ci 360cb93a386Sopenharmony_ci VALIDATE(true); 361cb93a386Sopenharmony_ci 362cb93a386Sopenharmony_ci return true; 363cb93a386Sopenharmony_ci} 364cb93a386Sopenharmony_ci 365cb93a386Sopenharmony_civoid GrBufferAllocPool::destroyBlock() { 366cb93a386Sopenharmony_ci SkASSERT(!fBlocks.empty()); 367cb93a386Sopenharmony_ci SkASSERT(fBlocks.back().fBuffer->isCpuBuffer() || 368cb93a386Sopenharmony_ci !static_cast<GrGpuBuffer*>(fBlocks.back().fBuffer.get())->isMapped()); 369cb93a386Sopenharmony_ci fBlocks.pop_back(); 370cb93a386Sopenharmony_ci fBufferPtr = nullptr; 371cb93a386Sopenharmony_ci} 372cb93a386Sopenharmony_ci 373cb93a386Sopenharmony_civoid GrBufferAllocPool::resetCpuData(size_t newSize) { 374cb93a386Sopenharmony_ci SkASSERT(newSize >= kDefaultBufferSize || !newSize); 375cb93a386Sopenharmony_ci if (!newSize) { 376cb93a386Sopenharmony_ci fCpuStagingBuffer.reset(); 377cb93a386Sopenharmony_ci return; 378cb93a386Sopenharmony_ci } 379cb93a386Sopenharmony_ci if (fCpuStagingBuffer && newSize <= fCpuStagingBuffer->size()) { 380cb93a386Sopenharmony_ci return; 381cb93a386Sopenharmony_ci } 382cb93a386Sopenharmony_ci bool mustInitialize = fGpu->caps()->mustClearUploadedBufferData(); 383cb93a386Sopenharmony_ci fCpuStagingBuffer = fCpuBufferCache ? fCpuBufferCache->makeBuffer(newSize, mustInitialize) 384cb93a386Sopenharmony_ci : GrCpuBuffer::Make(newSize); 385cb93a386Sopenharmony_ci} 386cb93a386Sopenharmony_ci 387cb93a386Sopenharmony_civoid GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize) { 388cb93a386Sopenharmony_ci SkASSERT(block.fBuffer.get()); 389cb93a386Sopenharmony_ci SkASSERT(!block.fBuffer.get()->isCpuBuffer()); 390cb93a386Sopenharmony_ci GrGpuBuffer* buffer = static_cast<GrGpuBuffer*>(block.fBuffer.get()); 391cb93a386Sopenharmony_ci SkASSERT(!buffer->isMapped()); 392cb93a386Sopenharmony_ci SkASSERT(fCpuStagingBuffer && fCpuStagingBuffer->data() == fBufferPtr); 393cb93a386Sopenharmony_ci SkASSERT(flushSize <= buffer->size()); 394cb93a386Sopenharmony_ci VALIDATE(true); 395cb93a386Sopenharmony_ci 396cb93a386Sopenharmony_ci if (GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() && 397cb93a386Sopenharmony_ci flushSize > fGpu->caps()->bufferMapThreshold()) { 398cb93a386Sopenharmony_ci void* data = buffer->map(); 399cb93a386Sopenharmony_ci if (data) { 400cb93a386Sopenharmony_ci memcpy(data, fBufferPtr, flushSize); 401cb93a386Sopenharmony_ci UNMAP_BUFFER(block); 402cb93a386Sopenharmony_ci return; 403cb93a386Sopenharmony_ci } 404cb93a386Sopenharmony_ci } 405cb93a386Sopenharmony_ci buffer->updateData(fBufferPtr, flushSize); 406cb93a386Sopenharmony_ci VALIDATE(true); 407cb93a386Sopenharmony_ci} 408cb93a386Sopenharmony_ci 409cb93a386Sopenharmony_cisk_sp<GrBuffer> GrBufferAllocPool::getBuffer(size_t size) { 410cb93a386Sopenharmony_ci const GrCaps& caps = *fGpu->caps(); 411cb93a386Sopenharmony_ci auto resourceProvider = fGpu->getContext()->priv().resourceProvider(); 412cb93a386Sopenharmony_ci if (caps.preferClientSideDynamicBuffers() || 413cb93a386Sopenharmony_ci (fBufferType == GrGpuBufferType::kDrawIndirect && caps.useClientSideIndirectBuffers())) { 414cb93a386Sopenharmony_ci // Create a CPU buffer. 415cb93a386Sopenharmony_ci bool mustInitialize = caps.mustClearUploadedBufferData(); 416cb93a386Sopenharmony_ci return fCpuBufferCache ? fCpuBufferCache->makeBuffer(size, mustInitialize) 417cb93a386Sopenharmony_ci : GrCpuBuffer::Make(size); 418cb93a386Sopenharmony_ci } 419cb93a386Sopenharmony_ci return resourceProvider->createBuffer(size, fBufferType, kDynamic_GrAccessPattern); 420cb93a386Sopenharmony_ci} 421cb93a386Sopenharmony_ci 422cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 423cb93a386Sopenharmony_ci 424cb93a386Sopenharmony_ciGrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu, sk_sp<CpuBufferCache> cpuBufferCache) 425cb93a386Sopenharmony_ci : GrBufferAllocPool(gpu, GrGpuBufferType::kVertex, std::move(cpuBufferCache)) {} 426cb93a386Sopenharmony_ci 427cb93a386Sopenharmony_civoid* GrVertexBufferAllocPool::makeSpace(size_t vertexSize, 428cb93a386Sopenharmony_ci int vertexCount, 429cb93a386Sopenharmony_ci sk_sp<const GrBuffer>* buffer, 430cb93a386Sopenharmony_ci int* startVertex) { 431cb93a386Sopenharmony_ci SkASSERT(vertexCount >= 0); 432cb93a386Sopenharmony_ci SkASSERT(buffer); 433cb93a386Sopenharmony_ci SkASSERT(startVertex); 434cb93a386Sopenharmony_ci 435cb93a386Sopenharmony_ci size_t offset SK_INIT_TO_AVOID_WARNING; 436cb93a386Sopenharmony_ci void* ptr = INHERITED::makeSpace(SkSafeMath::Mul(vertexSize, vertexCount), 437cb93a386Sopenharmony_ci vertexSize, 438cb93a386Sopenharmony_ci buffer, 439cb93a386Sopenharmony_ci &offset); 440cb93a386Sopenharmony_ci 441cb93a386Sopenharmony_ci SkASSERT(0 == offset % vertexSize); 442cb93a386Sopenharmony_ci *startVertex = static_cast<int>(offset / vertexSize); 443cb93a386Sopenharmony_ci return ptr; 444cb93a386Sopenharmony_ci} 445cb93a386Sopenharmony_ci 446cb93a386Sopenharmony_civoid* GrVertexBufferAllocPool::makeSpaceAtLeast(size_t vertexSize, int minVertexCount, 447cb93a386Sopenharmony_ci int fallbackVertexCount, 448cb93a386Sopenharmony_ci sk_sp<const GrBuffer>* buffer, int* startVertex, 449cb93a386Sopenharmony_ci int* actualVertexCount) { 450cb93a386Sopenharmony_ci SkASSERT(minVertexCount >= 0); 451cb93a386Sopenharmony_ci SkASSERT(fallbackVertexCount >= minVertexCount); 452cb93a386Sopenharmony_ci SkASSERT(buffer); 453cb93a386Sopenharmony_ci SkASSERT(startVertex); 454cb93a386Sopenharmony_ci SkASSERT(actualVertexCount); 455cb93a386Sopenharmony_ci 456cb93a386Sopenharmony_ci size_t offset SK_INIT_TO_AVOID_WARNING; 457cb93a386Sopenharmony_ci size_t actualSize SK_INIT_TO_AVOID_WARNING; 458cb93a386Sopenharmony_ci void* ptr = INHERITED::makeSpaceAtLeast(SkSafeMath::Mul(vertexSize, minVertexCount), 459cb93a386Sopenharmony_ci SkSafeMath::Mul(vertexSize, fallbackVertexCount), 460cb93a386Sopenharmony_ci vertexSize, 461cb93a386Sopenharmony_ci buffer, 462cb93a386Sopenharmony_ci &offset, 463cb93a386Sopenharmony_ci &actualSize); 464cb93a386Sopenharmony_ci 465cb93a386Sopenharmony_ci SkASSERT(0 == offset % vertexSize); 466cb93a386Sopenharmony_ci *startVertex = static_cast<int>(offset / vertexSize); 467cb93a386Sopenharmony_ci 468cb93a386Sopenharmony_ci SkASSERT(0 == actualSize % vertexSize); 469cb93a386Sopenharmony_ci SkASSERT(actualSize >= vertexSize * minVertexCount); 470cb93a386Sopenharmony_ci *actualVertexCount = static_cast<int>(actualSize / vertexSize); 471cb93a386Sopenharmony_ci 472cb93a386Sopenharmony_ci return ptr; 473cb93a386Sopenharmony_ci} 474cb93a386Sopenharmony_ci 475cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 476cb93a386Sopenharmony_ci 477cb93a386Sopenharmony_ciGrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu, sk_sp<CpuBufferCache> cpuBufferCache) 478cb93a386Sopenharmony_ci : GrBufferAllocPool(gpu, GrGpuBufferType::kIndex, std::move(cpuBufferCache)) {} 479cb93a386Sopenharmony_ci 480cb93a386Sopenharmony_civoid* GrIndexBufferAllocPool::makeSpace(int indexCount, sk_sp<const GrBuffer>* buffer, 481cb93a386Sopenharmony_ci int* startIndex) { 482cb93a386Sopenharmony_ci SkASSERT(indexCount >= 0); 483cb93a386Sopenharmony_ci SkASSERT(buffer); 484cb93a386Sopenharmony_ci SkASSERT(startIndex); 485cb93a386Sopenharmony_ci 486cb93a386Sopenharmony_ci size_t offset SK_INIT_TO_AVOID_WARNING; 487cb93a386Sopenharmony_ci void* ptr = INHERITED::makeSpace(SkSafeMath::Mul(indexCount, sizeof(uint16_t)), 488cb93a386Sopenharmony_ci sizeof(uint16_t), 489cb93a386Sopenharmony_ci buffer, 490cb93a386Sopenharmony_ci &offset); 491cb93a386Sopenharmony_ci 492cb93a386Sopenharmony_ci SkASSERT(0 == offset % sizeof(uint16_t)); 493cb93a386Sopenharmony_ci *startIndex = static_cast<int>(offset / sizeof(uint16_t)); 494cb93a386Sopenharmony_ci return ptr; 495cb93a386Sopenharmony_ci} 496cb93a386Sopenharmony_ci 497cb93a386Sopenharmony_civoid* GrIndexBufferAllocPool::makeSpaceAtLeast(int minIndexCount, int fallbackIndexCount, 498cb93a386Sopenharmony_ci sk_sp<const GrBuffer>* buffer, int* startIndex, 499cb93a386Sopenharmony_ci int* actualIndexCount) { 500cb93a386Sopenharmony_ci SkASSERT(minIndexCount >= 0); 501cb93a386Sopenharmony_ci SkASSERT(fallbackIndexCount >= minIndexCount); 502cb93a386Sopenharmony_ci SkASSERT(buffer); 503cb93a386Sopenharmony_ci SkASSERT(startIndex); 504cb93a386Sopenharmony_ci SkASSERT(actualIndexCount); 505cb93a386Sopenharmony_ci 506cb93a386Sopenharmony_ci size_t offset SK_INIT_TO_AVOID_WARNING; 507cb93a386Sopenharmony_ci size_t actualSize SK_INIT_TO_AVOID_WARNING; 508cb93a386Sopenharmony_ci void* ptr = INHERITED::makeSpaceAtLeast(SkSafeMath::Mul(minIndexCount, sizeof(uint16_t)), 509cb93a386Sopenharmony_ci SkSafeMath::Mul(fallbackIndexCount, sizeof(uint16_t)), 510cb93a386Sopenharmony_ci sizeof(uint16_t), 511cb93a386Sopenharmony_ci buffer, 512cb93a386Sopenharmony_ci &offset, 513cb93a386Sopenharmony_ci &actualSize); 514cb93a386Sopenharmony_ci 515cb93a386Sopenharmony_ci SkASSERT(0 == offset % sizeof(uint16_t)); 516cb93a386Sopenharmony_ci *startIndex = static_cast<int>(offset / sizeof(uint16_t)); 517cb93a386Sopenharmony_ci 518cb93a386Sopenharmony_ci SkASSERT(0 == actualSize % sizeof(uint16_t)); 519cb93a386Sopenharmony_ci SkASSERT(actualSize >= minIndexCount * sizeof(uint16_t)); 520cb93a386Sopenharmony_ci *actualIndexCount = static_cast<int>(actualSize / sizeof(uint16_t)); 521cb93a386Sopenharmony_ci return ptr; 522cb93a386Sopenharmony_ci} 523