bool GrBufferAllocPool::createBlock(size_t requestSize) { size_t size = GrMax(requestSize, fMinBlockSize); GrAssert(size >= GrBufferAllocPool_MIN_BLOCK_SIZE); VALIDATE(); BufferBlock& block = fBlocks.push_back(); if (size == fMinBlockSize && fPreallocBuffersInUse < fPreallocBuffers.count()) { uint32_t nextBuffer = (fPreallocBuffersInUse + fPreallocBufferStartIdx) % fPreallocBuffers.count(); block.fBuffer = fPreallocBuffers[nextBuffer]; block.fBuffer->ref(); ++fPreallocBuffersInUse; } else { block.fBuffer = this->createBuffer(size); if (NULL == block.fBuffer) { fBlocks.pop_back(); return false; } } block.fBytesFree = size; if (NULL != fBufferPtr) { GrAssert(fBlocks.count() > 1); BufferBlock& prev = fBlocks.fromBack(1); if (prev.fBuffer->isLocked()) { prev.fBuffer->unlock(); } else { flushCpuData(prev.fBuffer, prev.fBuffer->sizeInBytes() - prev.fBytesFree); } fBufferPtr = NULL; } GrAssert(NULL == fBufferPtr); if (fGpu->getCaps().fBufferLockSupport && size > GR_GEOM_BUFFER_LOCK_THRESHOLD && (!fFrequentResetHint || requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD)) { fBufferPtr = block.fBuffer->lock(); } if (NULL == fBufferPtr) { fBufferPtr = fCpuData.reset(size); } VALIDATE(true); return true; }
void GrBufferAllocPool::unlock() { VALIDATE(); if (NULL != fBufferPtr) { BufferBlock& block = fBlocks.back(); if (block.fBuffer->isLocked()) { block.fBuffer->unlock(); } else { size_t flushSize = block.fBuffer->sizeInBytes() - block.fBytesFree; flushCpuData(fBlocks.back().fBuffer, flushSize); } fBufferPtr = NULL; } VALIDATE(); }
bool GrBufferAllocPool::createBlock(size_t requestSize) { size_t size = SkTMax(requestSize, fMinBlockSize); SkASSERT(size >= GrBufferAllocPool_MIN_BLOCK_SIZE); VALIDATE(); BufferBlock& block = fBlocks.push_back(); if (size == fMinBlockSize && fPreallocBuffersInUse < fPreallocBuffers.count()) { uint32_t nextBuffer = (fPreallocBuffersInUse + fPreallocBufferStartIdx) % fPreallocBuffers.count(); block.fBuffer = fPreallocBuffers[nextBuffer]; block.fBuffer->ref(); ++fPreallocBuffersInUse; } else { block.fBuffer = this->createBuffer(size); if (NULL == block.fBuffer) { fBlocks.pop_back(); return false; } } block.fBytesFree = size; if (NULL != fBufferPtr) { SkASSERT(fBlocks.count() > 1); BufferBlock& prev = fBlocks.fromBack(1); if (prev.fBuffer->isLocked()) { prev.fBuffer->unlock(); } else { flushCpuData(prev.fBuffer, prev.fBuffer->sizeInBytes() - prev.fBytesFree); } fBufferPtr = NULL; } SkASSERT(NULL == fBufferPtr); // If the buffer is CPU-backed we lock it because it is free to do so and saves a copy. // Otherwise when buffer locking is supported: // a) If the frequently reset hint is set we only lock when the requested size meets a // threshold (since we don't expect it is likely that we will see more vertex data) // b) If the hint is not set we lock if the buffer size is greater than the threshold. bool attemptLock = block.fBuffer->isCPUBacked(); if (!attemptLock && fGpu->caps()->bufferLockSupport()) { if (fFrequentResetHint) { attemptLock = requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD; } else { attemptLock = size > GR_GEOM_BUFFER_LOCK_THRESHOLD; } } if (attemptLock) { fBufferPtr = block.fBuffer->lock(); } if (NULL == fBufferPtr) { fBufferPtr = fCpuData.reset(size); } VALIDATE(true); return true; }