13f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
23f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com/*
33f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com * Copyright 2010 Google Inc.
43f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com *
53f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
63f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com * found in the LICENSE file.
73f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com */
83f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
93f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
103f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "GrBufferAllocPool.h"
11516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com#include "GrDrawTargetCaps.h"
12516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com#include "GrGpu.h"
13516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com#include "GrIndexBuffer.h"
143f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "GrTypes.h"
153f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "GrVertexBuffer.h"
163f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
173f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#if GR_DEBUG
183f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    #define VALIDATE validate
193f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#else
2085f3b52a22c623fc8846d920660fc0b0a4b7afa7sugoi@google.com    static void VALIDATE(bool = false) {}
213f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#endif
223f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
233f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com// page size
243f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 12)
253f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
263f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comGrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu,
273f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                     BufferType bufferType,
283f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                     bool frequentResetHint,
293f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                     size_t blockSize,
303f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                     int preallocBufferCnt) :
313f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        fBlocks(GrMax(8, 2*preallocBufferCnt)) {
323f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
333f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(NULL != gpu);
343f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fGpu = gpu;
353f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fGpu->ref();
363f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fGpuIsReffed = true;
373f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
383f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fBufferType = bufferType;
393f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fFrequentResetHint = frequentResetHint;
403f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fBufferPtr = NULL;
413f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fMinBlockSize = GrMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);
423f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
433f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fBytesInUse = 0;
440cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com
453f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fPreallocBuffersInUse = 0;
460cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com    fPreallocBufferStartIdx = 0;
473f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    for (int i = 0; i < preallocBufferCnt; ++i) {
483f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrGeometryBuffer* buffer = this->createBuffer(fMinBlockSize);
493f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (NULL != buffer) {
503f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            *fPreallocBuffers.append() = buffer;
513f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
523f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
533f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
543f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
553f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comGrBufferAllocPool::~GrBufferAllocPool() {
563f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    VALIDATE();
573f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (fBlocks.count()) {
583f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
593f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (buffer->isLocked()) {
603f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            buffer->unlock();
613f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
623f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
633f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    while (!fBlocks.empty()) {
643f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        destroyBlock();
653f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
663f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fPreallocBuffers.unrefAll();
673f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    releaseGpuRef();
683f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
693f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
703f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrBufferAllocPool::releaseGpuRef() {
713f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (fGpuIsReffed) {
723f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        fGpu->unref();
733f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        fGpuIsReffed = false;
743f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
753f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
763f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
773f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrBufferAllocPool::reset() {
783f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    VALIDATE();
793f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fBytesInUse = 0;
803f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (fBlocks.count()) {
813f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
823f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (buffer->isLocked()) {
833f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            buffer->unlock();
843f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
853f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
860cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com    // fPreallocBuffersInUse will be decremented down to zero in the while loop
870cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com    int preallocBuffersInUse = fPreallocBuffersInUse;
883f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    while (!fBlocks.empty()) {
890cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com        this->destroyBlock();
903f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
913f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (fPreallocBuffers.count()) {
923f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        // must set this after above loop.
930cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com        fPreallocBufferStartIdx = (fPreallocBufferStartIdx +
940cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com                                   preallocBuffersInUse) %
950cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com                                  fPreallocBuffers.count();
963f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
975b0459ce765d52ff913e277892de83d5a5884fffbsalomon@google.com    // we may have created a large cpu mirror of a large VB. Reset the size
985b0459ce765d52ff913e277892de83d5a5884fffbsalomon@google.com    // to match our pre-allocated VBs.
995b0459ce765d52ff913e277892de83d5a5884fffbsalomon@google.com    fCpuData.reset(fMinBlockSize);
1003f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(0 == fPreallocBuffersInUse);
1013f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    VALIDATE();
1023f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
1033f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1043f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrBufferAllocPool::unlock() {
1053f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    VALIDATE();
1063f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1073f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (NULL != fBufferPtr) {
1083f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        BufferBlock& block = fBlocks.back();
1093f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (block.fBuffer->isLocked()) {
1103f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            block.fBuffer->unlock();
1113f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        } else {
1123f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            size_t flushSize = block.fBuffer->sizeInBytes() - block.fBytesFree;
1133f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            flushCpuData(fBlocks.back().fBuffer, flushSize);
1143f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
1153f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        fBufferPtr = NULL;
1163f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
1173f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    VALIDATE();
1183f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
1193f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1203f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#if GR_DEBUG
1213f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrBufferAllocPool::validate(bool unusedBlockAllowed) const {
1223f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (NULL != fBufferPtr) {
1233f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrAssert(!fBlocks.empty());
1243f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (fBlocks.back().fBuffer->isLocked()) {
1253f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            GrGeometryBuffer* buf = fBlocks.back().fBuffer;
1263f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            GrAssert(buf->lockPtr() == fBufferPtr);
1273f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        } else {
1283f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            GrAssert(fCpuData.get() == fBufferPtr);
1293f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
1303f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else {
1313f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrAssert(fBlocks.empty() || !fBlocks.back().fBuffer->isLocked());
1323f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
1333f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    size_t bytesInUse = 0;
1343f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    for (int i = 0; i < fBlocks.count() - 1; ++i) {
1353f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrAssert(!fBlocks[i].fBuffer->isLocked());
1363f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
1373f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    for (int i = 0; i < fBlocks.count(); ++i) {
138935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com        size_t bytes = fBlocks[i].fBuffer->sizeInBytes() - fBlocks[i].fBytesFree;
1393f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        bytesInUse += bytes;
1403f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrAssert(bytes || unusedBlockAllowed);
1413f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
142935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
1433f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(bytesInUse == fBytesInUse);
1443f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (unusedBlockAllowed) {
1453f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrAssert((fBytesInUse && !fBlocks.empty()) ||
1463f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                 (!fBytesInUse && (fBlocks.count() < 2)));
1473f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else {
1483f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrAssert((0 == fBytesInUse) == fBlocks.empty());
1493f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
1503f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
1513f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#endif
1523f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1533f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid* GrBufferAllocPool::makeSpace(size_t size,
1543f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                   size_t alignment,
1553f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                   const GrGeometryBuffer** buffer,
1563f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                   size_t* offset) {
1573f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    VALIDATE();
1583f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1593f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(NULL != buffer);
1603f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(NULL != offset);
1613f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1623f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (NULL != fBufferPtr) {
1633f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        BufferBlock& back = fBlocks.back();
1643f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        size_t usedBytes = back.fBuffer->sizeInBytes() - back.fBytesFree;
1653f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        size_t pad = GrSizeAlignUpPad(usedBytes,
1663f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                      alignment);
1673f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if ((size + pad) <= back.fBytesFree) {
1683f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            usedBytes += pad;
1693f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            *offset = usedBytes;
1703f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            *buffer = back.fBuffer;
1713f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            back.fBytesFree -= size + pad;
172f1f20f0a36e8b74d95f2bcff2069b49f104a46febsalomon@google.com            fBytesInUse += size + pad;
173f1f20f0a36e8b74d95f2bcff2069b49f104a46febsalomon@google.com            VALIDATE();
1743f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
1753f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
1763f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
1773f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1783f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // We could honor the space request using by a partial update of the current
1793f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // VB (if there is room). But we don't currently use draw calls to GL that
1803f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // allow the driver to know that previously issued draws won't read from
1813f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // the part of the buffer we update. Also, the GL buffer implementation
1823f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // may be cheating on the actual buffer size by shrinking the buffer on
1833f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // updateData() if the amount of data passed is less than the full buffer
1843f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // size.
185935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
1863f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (!createBlock(size)) {
1873f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return NULL;
1883f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
1893f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(NULL != fBufferPtr);
1903f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1913f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    *offset = 0;
1923f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    BufferBlock& back = fBlocks.back();
1933f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    *buffer = back.fBuffer;
1943f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    back.fBytesFree -= size;
1953f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fBytesInUse += size;
1963f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    VALIDATE();
1973f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    return fBufferPtr;
1983f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
1993f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2003f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comint GrBufferAllocPool::currentBufferItems(size_t itemSize) const {
2013f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    VALIDATE();
2023f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (NULL != fBufferPtr) {
2033f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        const BufferBlock& back = fBlocks.back();
2043f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        size_t usedBytes = back.fBuffer->sizeInBytes() - back.fBytesFree;
2053f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        size_t pad = GrSizeAlignUpPad(usedBytes, itemSize);
2063f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return (back.fBytesFree - pad) / itemSize;
2073f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
2083f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return fMinBlockSize / itemSize;
2093f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
2103f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    return 0;
2113f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
2123f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2133f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comint GrBufferAllocPool::preallocatedBuffersRemaining() const {
2143f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    return fPreallocBuffers.count() - fPreallocBuffersInUse;
2153f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
2163f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2173f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comint GrBufferAllocPool::preallocatedBufferCount() const {
2183f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    return fPreallocBuffers.count();
2193f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
2203f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2213f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrBufferAllocPool::putBack(size_t bytes) {
2223f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    VALIDATE();
2233f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2240cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com    // if the putBack unwinds all the preallocated buffers then we will
2250cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com    // advance the starting index. As blocks are destroyed fPreallocBuffersInUse
2260cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com    // will be decremented. I will reach zero if all blocks using preallocated
2270cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com    // buffers are released.
2280cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com    int preallocBuffersInUse = fPreallocBuffersInUse;
2290cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com
2303f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    while (bytes) {
2313f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        // caller shouldnt try to put back more than they've taken
2323f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrAssert(!fBlocks.empty());
2333f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        BufferBlock& block = fBlocks.back();
2343f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        size_t bytesUsed = block.fBuffer->sizeInBytes() - block.fBytesFree;
2353f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (bytes >= bytesUsed) {
2363f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            bytes -= bytesUsed;
2373f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            fBytesInUse -= bytesUsed;
2383f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            // if we locked a vb to satisfy the make space and we're releasing
2393f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            // beyond it, then unlock it.
2403f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            if (block.fBuffer->isLocked()) {
2413f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                block.fBuffer->unlock();
2423f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            }
2433f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            this->destroyBlock();
2443f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        } else {
2453f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            block.fBytesFree += bytes;
2463f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            fBytesInUse -= bytes;
2473f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            bytes = 0;
2483f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            break;
2493f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
2503f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
2510cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com    if (!fPreallocBuffersInUse && fPreallocBuffers.count()) {
2520cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com            fPreallocBufferStartIdx = (fPreallocBufferStartIdx +
2530cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com                                       preallocBuffersInUse) %
2540cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com                                      fPreallocBuffers.count();
2550cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com    }
2563f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    VALIDATE();
2573f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
2583f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2593f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.combool GrBufferAllocPool::createBlock(size_t requestSize) {
2603f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2613f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    size_t size = GrMax(requestSize, fMinBlockSize);
2623f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);
2633f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2643f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    VALIDATE();
2653f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2663f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    BufferBlock& block = fBlocks.push_back();
2673f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2683f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (size == fMinBlockSize &&
2693f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        fPreallocBuffersInUse < fPreallocBuffers.count()) {
2703f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2710cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com        uint32_t nextBuffer = (fPreallocBuffersInUse +
2720cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com                               fPreallocBufferStartIdx) %
2730cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com                              fPreallocBuffers.count();
2743f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        block.fBuffer = fPreallocBuffers[nextBuffer];
2753f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        block.fBuffer->ref();
2763f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        ++fPreallocBuffersInUse;
2773f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else {
2783f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        block.fBuffer = this->createBuffer(size);
2793f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (NULL == block.fBuffer) {
2803f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            fBlocks.pop_back();
2813f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            return false;
2823f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
2833f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
2843f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2853f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    block.fBytesFree = size;
2863f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (NULL != fBufferPtr) {
2873f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrAssert(fBlocks.count() > 1);
2883f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        BufferBlock& prev = fBlocks.fromBack(1);
2893f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (prev.fBuffer->isLocked()) {
2903f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            prev.fBuffer->unlock();
2913f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        } else {
2923f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            flushCpuData(prev.fBuffer,
2933f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                         prev.fBuffer->sizeInBytes() - prev.fBytesFree);
2943f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
2953f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        fBufferPtr = NULL;
2963f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
2973f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2983f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(NULL == fBufferPtr);
2993f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
300407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com    // If the buffer is CPU-backed we lock it because it is free to do so and saves a copy.
301407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com    // Otherwise when buffer locking is supported:
302407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com    //      a) If the frequently reset hint is set we only lock when the requested size meets a
303407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com    //      threshold (since we don't expect it is likely that we will see more vertex data)
304407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com    //      b) If the hint is not set we lock if the buffer size is greater than the threshold.
305407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com    bool attemptLock = block.fBuffer->isCPUBacked();
30659831d70980761e3d9403a122c46e996a5d32543bsalomon@google.com    if (!attemptLock && fGpu->caps()->bufferLockSupport()) {
307407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com        if (fFrequentResetHint) {
308407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com            attemptLock = requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD;
309407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com        } else {
310407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com            attemptLock = size > GR_GEOM_BUFFER_LOCK_THRESHOLD;
311407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com        }
312407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com    }
313407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com
314407c7876a1c8fba9e582a3e48e12ca63e13d99febsalomon@google.com    if (attemptLock) {
3153f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        fBufferPtr = block.fBuffer->lock();
3163f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
3173f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
3183f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (NULL == fBufferPtr) {
3193f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        fBufferPtr = fCpuData.reset(size);
3203f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
3213f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
3223f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    VALIDATE(true);
3233f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
3243f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    return true;
3253f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
3263f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
3273f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrBufferAllocPool::destroyBlock() {
3283f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(!fBlocks.empty());
3293f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
3303f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    BufferBlock& block = fBlocks.back();
3313f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (fPreallocBuffersInUse > 0) {
3323f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
3330cef758dcc01b4422d862f1b30c8010f2927da92bsalomon@google.com                                       fPreallocBufferStartIdx +
3343f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                       (fPreallocBuffers.count() - 1)) %
3353f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                      fPreallocBuffers.count();
3363f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (block.fBuffer == fPreallocBuffers[prevPreallocBuffer]) {
3373f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            --fPreallocBuffersInUse;
3383f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
3393f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
3403f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(!block.fBuffer->isLocked());
3413f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    block.fBuffer->unref();
3423f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fBlocks.pop_back();
3433f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fBufferPtr = NULL;
3443f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
3453f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
3463f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrBufferAllocPool::flushCpuData(GrGeometryBuffer* buffer,
3473f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                     size_t flushSize) {
3483f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(NULL != buffer);
3493f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(!buffer->isLocked());
3503f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(fCpuData.get() == fBufferPtr);
3513f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(flushSize <= buffer->sizeInBytes());
352f1f20f0a36e8b74d95f2bcff2069b49f104a46febsalomon@google.com    VALIDATE(true);
3533f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
35459831d70980761e3d9403a122c46e996a5d32543bsalomon@google.com    if (fGpu->caps()->bufferLockSupport() &&
3553f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
3563f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        void* data = buffer->lock();
3573f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (NULL != data) {
3583f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            memcpy(data, fBufferPtr, flushSize);
3593f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            buffer->unlock();
360028f3a0bf6c7630ab2faf7f8a53108834684648fbsalomon@google.com            return;
3613f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
3623f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
3633f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    buffer->updateData(fBufferPtr, flushSize);
364f1f20f0a36e8b74d95f2bcff2069b49f104a46febsalomon@google.com    VALIDATE(true);
3653f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
3663f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
3673f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comGrGeometryBuffer* GrBufferAllocPool::createBuffer(size_t size) {
3683f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (kIndex_BufferType == fBufferType) {
3693f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return fGpu->createIndexBuffer(size, true);
3703f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else {
3713f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrAssert(kVertex_BufferType == fBufferType);
3723f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return fGpu->createVertexBuffer(size, true);
3733f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
3743f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
3753f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
3763f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
3773f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
3783f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comGrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
3793f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                                 bool frequentResetHint,
3803f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                                 size_t bufferSize,
3813f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                                 int preallocBufferCnt)
3823f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com: GrBufferAllocPool(gpu,
3833f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                    kVertex_BufferType,
3843f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                    frequentResetHint,
3853f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                    bufferSize,
3863f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                    preallocBufferCnt) {
3873f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
3883f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
3894fde2435c57236fbc9d681a1fff7acdcb0fec9bajvanverth@google.comvoid* GrVertexBufferAllocPool::makeSpace(size_t vertexSize,
3903f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                         int vertexCount,
3913f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                         const GrVertexBuffer** buffer,
3923f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                         int* startVertex) {
3933f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
3943f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(vertexCount >= 0);
3953f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(NULL != buffer);
3963f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(NULL != startVertex);
3973f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
3983f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    size_t offset = 0; // assign to suppress warning
3993f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
4004fde2435c57236fbc9d681a1fff7acdcb0fec9bajvanverth@google.com    void* ptr = INHERITED::makeSpace(vertexSize * vertexCount,
4014fde2435c57236fbc9d681a1fff7acdcb0fec9bajvanverth@google.com                                     vertexSize,
4023f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                     &geomBuffer,
4033f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                     &offset);
4043f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4053f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    *buffer = (const GrVertexBuffer*) geomBuffer;
4064fde2435c57236fbc9d681a1fff7acdcb0fec9bajvanverth@google.com    GrAssert(0 == offset % vertexSize);
4074fde2435c57236fbc9d681a1fff7acdcb0fec9bajvanverth@google.com    *startVertex = offset / vertexSize;
4083f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    return ptr;
4093f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
4103f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4114fde2435c57236fbc9d681a1fff7acdcb0fec9bajvanverth@google.combool GrVertexBufferAllocPool::appendVertices(size_t vertexSize,
4123f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                             int vertexCount,
4133f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                             const void* vertices,
4143f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                             const GrVertexBuffer** buffer,
4153f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                             int* startVertex) {
4164fde2435c57236fbc9d681a1fff7acdcb0fec9bajvanverth@google.com    void* space = makeSpace(vertexSize, vertexCount, buffer, startVertex);
4173f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (NULL != space) {
4183f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        memcpy(space,
4193f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com               vertices,
4204fde2435c57236fbc9d681a1fff7acdcb0fec9bajvanverth@google.com               vertexSize * vertexCount);
4213f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return true;
4223f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else {
4233f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return false;
4243f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
4253f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
4263f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4274fde2435c57236fbc9d681a1fff7acdcb0fec9bajvanverth@google.comint GrVertexBufferAllocPool::preallocatedBufferVertices(size_t vertexSize) const {
4284fde2435c57236fbc9d681a1fff7acdcb0fec9bajvanverth@google.com    return INHERITED::preallocatedBufferSize() / vertexSize;
4293f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
4303f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4314fde2435c57236fbc9d681a1fff7acdcb0fec9bajvanverth@google.comint GrVertexBufferAllocPool::currentBufferVertices(size_t vertexSize) const {
4324fde2435c57236fbc9d681a1fff7acdcb0fec9bajvanverth@google.com    return currentBufferItems(vertexSize);
4333f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
4343f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4353f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
4363f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4373f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comGrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu,
4383f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                               bool frequentResetHint,
4393f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                               size_t bufferSize,
4403f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                               int preallocBufferCnt)
4413f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com: GrBufferAllocPool(gpu,
4423f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                    kIndex_BufferType,
4433f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                    frequentResetHint,
4443f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                    bufferSize,
4453f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                    preallocBufferCnt) {
4463f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
4473f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4483f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid* GrIndexBufferAllocPool::makeSpace(int indexCount,
4493f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                        const GrIndexBuffer** buffer,
4503f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                        int* startIndex) {
4513f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4523f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(indexCount >= 0);
4533f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(NULL != buffer);
4543f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(NULL != startIndex);
4553f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4563f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    size_t offset = 0; // assign to suppress warning
4573f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
4583f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t),
4593f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                     sizeof(uint16_t),
4603f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                     &geomBuffer,
4613f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                     &offset);
4623f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4633f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    *buffer = (const GrIndexBuffer*) geomBuffer;
4643f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAssert(0 == offset % sizeof(uint16_t));
4653f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    *startIndex = offset / sizeof(uint16_t);
4663f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    return ptr;
4673f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
4683f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4693f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.combool GrIndexBufferAllocPool::appendIndices(int indexCount,
4703f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                           const void* indices,
4713f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                           const GrIndexBuffer** buffer,
4723f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                           int* startIndex) {
4733f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    void* space = makeSpace(indexCount, buffer, startIndex);
4743f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (NULL != space) {
4753f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        memcpy(space, indices, sizeof(uint16_t) * indexCount);
4763f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return true;
4773f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else {
4783f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return false;
4793f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
4803f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
4813f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4823f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comint GrIndexBufferAllocPool::preallocatedBufferIndices() const {
4833f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    return INHERITED::preallocatedBufferSize() / sizeof(uint16_t);
4843f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
4853f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4863f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comint GrIndexBufferAllocPool::currentBufferIndices() const {
4873f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    return currentBufferItems(sizeof(uint16_t));
4883f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
489