11c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
71c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com */
81c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
101c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com#include "GrBufferAllocPool.h"
11c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrDrawTargetCaps.h"
12c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrGpu.h"
13c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrIndexBuffer.h"
141c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com#include "GrTypes.h"
151c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com#include "GrVertexBuffer.h"
161c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
173512eda332f3a48ab750a047027e2e254ab53a15bsalomon#include "SkTraceEvent.h"
183512eda332f3a48ab750a047027e2e254ab53a15bsalomon
19515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
201c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    #define VALIDATE validate
211c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com#else
22e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.com    static void VALIDATE(bool = false) {}
231c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com#endif
241c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
2525fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com// page size
261c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com#define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 12)
271c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
283512eda332f3a48ab750a047027e2e254ab53a15bsalomon#define UNMAP_BUFFER(block)                                                               \
293512eda332f3a48ab750a047027e2e254ab53a15bsalomondo {                                                                                      \
303512eda332f3a48ab750a047027e2e254ab53a15bsalomon    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"),                           \
313512eda332f3a48ab750a047027e2e254ab53a15bsalomon                         "GrBufferAllocPool Unmapping Buffer",                            \
323512eda332f3a48ab750a047027e2e254ab53a15bsalomon                         TRACE_EVENT_SCOPE_THREAD,                                        \
333512eda332f3a48ab750a047027e2e254ab53a15bsalomon                         "percent_unwritten",                                             \
343512eda332f3a48ab750a047027e2e254ab53a15bsalomon                         (float)((block).fBytesFree) / (block).fBuffer->gpuMemorySize()); \
353512eda332f3a48ab750a047027e2e254ab53a15bsalomon    (block).fBuffer->unmap();                                                             \
363512eda332f3a48ab750a047027e2e254ab53a15bsalomon} while (false)
373512eda332f3a48ab750a047027e2e254ab53a15bsalomon
381c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comGrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu,
391c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                     BufferType bufferType,
401c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                     bool frequentResetHint,
411c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                     size_t blockSize,
421c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                     int preallocBufferCnt) :
43972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        fBlocks(SkTMax(8, 2*preallocBufferCnt)) {
4411f0b519766dabed4ce882f3ee7c07a68d3ccb52bsalomon@google.com
4549f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(gpu);
461c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    fGpu = gpu;
4711f0b519766dabed4ce882f3ee7c07a68d3ccb52bsalomon@google.com    fGpu->ref();
4811f0b519766dabed4ce882f3ee7c07a68d3ccb52bsalomon@google.com    fGpuIsReffed = true;
4911f0b519766dabed4ce882f3ee7c07a68d3ccb52bsalomon@google.com
501c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    fBufferType = bufferType;
511c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    fFrequentResetHint = frequentResetHint;
521c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    fBufferPtr = NULL;
53972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    fMinBlockSize = SkTMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);
541c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
5525fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com    fBytesInUse = 0;
56b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com
571c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    fPreallocBuffersInUse = 0;
58b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com    fPreallocBufferStartIdx = 0;
591c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    for (int i = 0; i < preallocBufferCnt; ++i) {
601c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        GrGeometryBuffer* buffer = this->createBuffer(fMinBlockSize);
6149f085dddff10473b6ebf832a974288300224e60bsalomon        if (buffer) {
621c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com            *fPreallocBuffers.append() = buffer;
631c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        }
641c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
651c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
661c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
671c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comGrBufferAllocPool::~GrBufferAllocPool() {
681c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    VALIDATE();
691c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    if (fBlocks.count()) {
701c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
718341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org        if (buffer->isMapped()) {
723512eda332f3a48ab750a047027e2e254ab53a15bsalomon            UNMAP_BUFFER(fBlocks.back());
731c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        }
741c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
751c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    while (!fBlocks.empty()) {
761c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        destroyBlock();
771c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
7811f0b519766dabed4ce882f3ee7c07a68d3ccb52bsalomon@google.com    fPreallocBuffers.unrefAll();
7911f0b519766dabed4ce882f3ee7c07a68d3ccb52bsalomon@google.com    releaseGpuRef();
8011f0b519766dabed4ce882f3ee7c07a68d3ccb52bsalomon@google.com}
8111f0b519766dabed4ce882f3ee7c07a68d3ccb52bsalomon@google.com
8211f0b519766dabed4ce882f3ee7c07a68d3ccb52bsalomon@google.comvoid GrBufferAllocPool::releaseGpuRef() {
8311f0b519766dabed4ce882f3ee7c07a68d3ccb52bsalomon@google.com    if (fGpuIsReffed) {
8411f0b519766dabed4ce882f3ee7c07a68d3ccb52bsalomon@google.com        fGpu->unref();
8511f0b519766dabed4ce882f3ee7c07a68d3ccb52bsalomon@google.com        fGpuIsReffed = false;
8611f0b519766dabed4ce882f3ee7c07a68d3ccb52bsalomon@google.com    }
871c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
881c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
891c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comvoid GrBufferAllocPool::reset() {
901c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    VALIDATE();
9125fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com    fBytesInUse = 0;
921c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    if (fBlocks.count()) {
931c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
948341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org        if (buffer->isMapped()) {
953512eda332f3a48ab750a047027e2e254ab53a15bsalomon            UNMAP_BUFFER(fBlocks.back());
961c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        }
971c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
98b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com    // fPreallocBuffersInUse will be decremented down to zero in the while loop
99b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com    int preallocBuffersInUse = fPreallocBuffersInUse;
1001c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    while (!fBlocks.empty()) {
101b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com        this->destroyBlock();
1021c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
1031c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    if (fPreallocBuffers.count()) {
1041c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        // must set this after above loop.
105b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com        fPreallocBufferStartIdx = (fPreallocBufferStartIdx +
106b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com                                   preallocBuffersInUse) %
107b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com                                  fPreallocBuffers.count();
1081c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
109987dbc08d88fc264b79d953aa58ba9161d1a0bfdbsalomon@google.com    // we may have created a large cpu mirror of a large VB. Reset the size
110987dbc08d88fc264b79d953aa58ba9161d1a0bfdbsalomon@google.com    // to match our pre-allocated VBs.
111987dbc08d88fc264b79d953aa58ba9161d1a0bfdbsalomon@google.com    fCpuData.reset(fMinBlockSize);
112f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(0 == fPreallocBuffersInUse);
1131c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    VALIDATE();
1141c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
1151c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
1168341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.orgvoid GrBufferAllocPool::unmap() {
1171c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    VALIDATE();
1181c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
11949f085dddff10473b6ebf832a974288300224e60bsalomon    if (fBufferPtr) {
1201c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        BufferBlock& block = fBlocks.back();
1218341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org        if (block.fBuffer->isMapped()) {
1223512eda332f3a48ab750a047027e2e254ab53a15bsalomon            UNMAP_BUFFER(block);
1231c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        } else {
124089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org            size_t flushSize = block.fBuffer->gpuMemorySize() - block.fBytesFree;
1253512eda332f3a48ab750a047027e2e254ab53a15bsalomon            this->flushCpuData(fBlocks.back(), flushSize);
1261c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        }
1271c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        fBufferPtr = NULL;
1281c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
1291c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    VALIDATE();
1301c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
1311c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
132515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
13325fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.comvoid GrBufferAllocPool::validate(bool unusedBlockAllowed) const {
13449f085dddff10473b6ebf832a974288300224e60bsalomon    if (fBufferPtr) {
135f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(!fBlocks.empty());
1368341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org        if (fBlocks.back().fBuffer->isMapped()) {
1371c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com            GrGeometryBuffer* buf = fBlocks.back().fBuffer;
1388341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org            SkASSERT(buf->mapPtr() == fBufferPtr);
1391c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        } else {
140f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org            SkASSERT(fCpuData.get() == fBufferPtr);
1411c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        }
1421c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    } else {
1438341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org        SkASSERT(fBlocks.empty() || !fBlocks.back().fBuffer->isMapped());
1441c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
14525fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com    size_t bytesInUse = 0;
1461c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    for (int i = 0; i < fBlocks.count() - 1; ++i) {
1478341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org        SkASSERT(!fBlocks[i].fBuffer->isMapped());
1481c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
14925fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com    for (int i = 0; i < fBlocks.count(); ++i) {
150089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org        size_t bytes = fBlocks[i].fBuffer->gpuMemorySize() - fBlocks[i].fBytesFree;
15125fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com        bytesInUse += bytes;
152f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(bytes || unusedBlockAllowed);
15325fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com    }
154fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
155f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(bytesInUse == fBytesInUse);
15625fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com    if (unusedBlockAllowed) {
157f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT((fBytesInUse && !fBlocks.empty()) ||
15825fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com                 (!fBytesInUse && (fBlocks.count() < 2)));
15925fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com    } else {
160f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT((0 == fBytesInUse) == fBlocks.empty());
16125fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com    }
1621c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
1631c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com#endif
1641c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
1651c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comvoid* GrBufferAllocPool::makeSpace(size_t size,
1661c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                   size_t alignment,
1671c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                   const GrGeometryBuffer** buffer,
1681c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                   size_t* offset) {
1691c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    VALIDATE();
1701c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
17149f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(buffer);
17249f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(offset);
1731c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
17449f085dddff10473b6ebf832a974288300224e60bsalomon    if (fBufferPtr) {
1751c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        BufferBlock& back = fBlocks.back();
176089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org        size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree;
1771c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        size_t pad = GrSizeAlignUpPad(usedBytes,
1781c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                      alignment);
1791c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        if ((size + pad) <= back.fBytesFree) {
1801c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com            usedBytes += pad;
1811c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com            *offset = usedBytes;
1821c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com            *buffer = back.fBuffer;
1831c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com            back.fBytesFree -= size + pad;
184d51080931700fa989572e5ffe1a5209fe098d2cebsalomon@google.com            fBytesInUse += size + pad;
185d51080931700fa989572e5ffe1a5209fe098d2cebsalomon@google.com            VALIDATE();
1861c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com            return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
1871c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        }
1881c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
1891c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
19096e96dfd1edea2ceaf0311fce71cddae50175086bsalomon@google.com    // We could honor the space request using by a partial update of the current
19196e96dfd1edea2ceaf0311fce71cddae50175086bsalomon@google.com    // VB (if there is room). But we don't currently use draw calls to GL that
19225fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com    // allow the driver to know that previously issued draws won't read from
19396e96dfd1edea2ceaf0311fce71cddae50175086bsalomon@google.com    // the part of the buffer we update. Also, the GL buffer implementation
19496e96dfd1edea2ceaf0311fce71cddae50175086bsalomon@google.com    // may be cheating on the actual buffer size by shrinking the buffer on
19596e96dfd1edea2ceaf0311fce71cddae50175086bsalomon@google.com    // updateData() if the amount of data passed is less than the full buffer
19696e96dfd1edea2ceaf0311fce71cddae50175086bsalomon@google.com    // size.
197fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1981c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    if (!createBlock(size)) {
1991c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        return NULL;
2001c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
20149f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(fBufferPtr);
2021c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
2031c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    *offset = 0;
2041c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    BufferBlock& back = fBlocks.back();
2051c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    *buffer = back.fBuffer;
2061c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    back.fBytesFree -= size;
20725fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com    fBytesInUse += size;
20825fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com    VALIDATE();
2091c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    return fBufferPtr;
2101c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
2111c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
2121c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comint GrBufferAllocPool::currentBufferItems(size_t itemSize) const {
2131c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    VALIDATE();
21449f085dddff10473b6ebf832a974288300224e60bsalomon    if (fBufferPtr) {
2151c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        const BufferBlock& back = fBlocks.back();
216089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org        size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree;
2171c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        size_t pad = GrSizeAlignUpPad(usedBytes, itemSize);
218adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com        return static_cast<int>((back.fBytesFree - pad) / itemSize);
2191c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
220adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com        return static_cast<int>(fMinBlockSize / itemSize);
2211c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
2221c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    return 0;
2231c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
2241c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
2251c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comint GrBufferAllocPool::preallocatedBuffersRemaining() const {
2261c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    return fPreallocBuffers.count() - fPreallocBuffersInUse;
2271c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
2281c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
2291c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comint GrBufferAllocPool::preallocatedBufferCount() const {
2301c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    return fPreallocBuffers.count();
2311c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
2321c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
2331c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comvoid GrBufferAllocPool::putBack(size_t bytes) {
2341c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    VALIDATE();
23525fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com
236b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com    // if the putBack unwinds all the preallocated buffers then we will
237b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com    // advance the starting index. As blocks are destroyed fPreallocBuffersInUse
238b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com    // will be decremented. I will reach zero if all blocks using preallocated
239b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com    // buffers are released.
240b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com    int preallocBuffersInUse = fPreallocBuffersInUse;
241b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com
24225fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com    while (bytes) {
24325fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com        // caller shouldnt try to put back more than they've taken
244f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(!fBlocks.empty());
24525fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com        BufferBlock& block = fBlocks.back();
246089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org        size_t bytesUsed = block.fBuffer->gpuMemorySize() - block.fBytesFree;
2471c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        if (bytes >= bytesUsed) {
2481c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com            bytes -= bytesUsed;
24925fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com            fBytesInUse -= bytesUsed;
2506513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            // if we locked a vb to satisfy the make space and we're releasing
2518341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org            // beyond it, then unmap it.
2528341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org            if (block.fBuffer->isMapped()) {
2533512eda332f3a48ab750a047027e2e254ab53a15bsalomon                UNMAP_BUFFER(block);
2546513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            }
2556513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            this->destroyBlock();
2561c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        } else {
25725fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com            block.fBytesFree += bytes;
25825fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com            fBytesInUse -= bytes;
25925fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com            bytes = 0;
26025fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com            break;
2611c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        }
2621c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
263b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com    if (!fPreallocBuffersInUse && fPreallocBuffers.count()) {
264b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com            fPreallocBufferStartIdx = (fPreallocBufferStartIdx +
265b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com                                       preallocBuffersInUse) %
266b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com                                      fPreallocBuffers.count();
267b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com    }
2681c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    VALIDATE();
2691c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
2701c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
2711c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.combool GrBufferAllocPool::createBlock(size_t requestSize) {
2721c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
273972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    size_t size = SkTMax(requestSize, fMinBlockSize);
274f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);
2751c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
2761c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    VALIDATE();
2771c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
2781c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    BufferBlock& block = fBlocks.push_back();
2791c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
2801c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    if (size == fMinBlockSize &&
2811c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        fPreallocBuffersInUse < fPreallocBuffers.count()) {
2821c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
283b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com        uint32_t nextBuffer = (fPreallocBuffersInUse +
284b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com                               fPreallocBufferStartIdx) %
285b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com                              fPreallocBuffers.count();
2861c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        block.fBuffer = fPreallocBuffers[nextBuffer];
2871c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        block.fBuffer->ref();
2881c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        ++fPreallocBuffersInUse;
2891c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    } else {
2901c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        block.fBuffer = this->createBuffer(size);
2911c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        if (NULL == block.fBuffer) {
2921c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com            fBlocks.pop_back();
2931c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com            return false;
2941c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        }
2951c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
2961c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
2971c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    block.fBytesFree = size;
29849f085dddff10473b6ebf832a974288300224e60bsalomon    if (fBufferPtr) {
299f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(fBlocks.count() > 1);
3001c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        BufferBlock& prev = fBlocks.fromBack(1);
3018341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org        if (prev.fBuffer->isMapped()) {
3023512eda332f3a48ab750a047027e2e254ab53a15bsalomon            UNMAP_BUFFER(prev);
3031c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        } else {
3043512eda332f3a48ab750a047027e2e254ab53a15bsalomon            this->flushCpuData(prev, prev.fBuffer->gpuMemorySize() - prev.fBytesFree);
3051c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        }
3061c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        fBufferPtr = NULL;
3071c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
3081c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
309f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL == fBufferPtr);
3101c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
3118341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org    // If the buffer is CPU-backed we map it because it is free to do so and saves a copy.
3128341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org    // Otherwise when buffer mapping is supported:
3138341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org    //      a) If the frequently reset hint is set we only map when the requested size meets a
314ee3bc3b26771a58a78075f11cde8801e0e79f723bsalomon@google.com    //      threshold (since we don't expect it is likely that we will see more vertex data)
3158341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org    //      b) If the hint is not set we map if the buffer size is greater than the threshold.
3168341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org    bool attemptMap = block.fBuffer->isCPUBacked();
3178341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org    if (!attemptMap && GrDrawTargetCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags()) {
318ee3bc3b26771a58a78075f11cde8801e0e79f723bsalomon@google.com        if (fFrequentResetHint) {
3198341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org            attemptMap = requestSize > GR_GEOM_BUFFER_MAP_THRESHOLD;
320ee3bc3b26771a58a78075f11cde8801e0e79f723bsalomon@google.com        } else {
3218341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org            attemptMap = size > GR_GEOM_BUFFER_MAP_THRESHOLD;
322ee3bc3b26771a58a78075f11cde8801e0e79f723bsalomon@google.com        }
323ee3bc3b26771a58a78075f11cde8801e0e79f723bsalomon@google.com    }
324ee3bc3b26771a58a78075f11cde8801e0e79f723bsalomon@google.com
3258341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org    if (attemptMap) {
3268341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org        fBufferPtr = block.fBuffer->map();
3271c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
3281c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
3291c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    if (NULL == fBufferPtr) {
3307d4679a2e1aaa1953bc20d668135c517ee488c11bsalomon@google.com        fBufferPtr = fCpuData.reset(size);
3311c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
3321c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
33325fb21f5df904c6f111bbf8f07e6a6c339416d09bsalomon@google.com    VALIDATE(true);
3341c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
3351c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    return true;
3361c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
3371c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
3381c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comvoid GrBufferAllocPool::destroyBlock() {
339f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(!fBlocks.empty());
3401c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
3411c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    BufferBlock& block = fBlocks.back();
3421c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    if (fPreallocBuffersInUse > 0) {
3431c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
344b665a6b148826eecb4f425c57e8a0df0ec63f016bsalomon@google.com                                       fPreallocBufferStartIdx +
3451c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                       (fPreallocBuffers.count() - 1)) %
3461c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                      fPreallocBuffers.count();
3471c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        if (block.fBuffer == fPreallocBuffers[prevPreallocBuffer]) {
3481c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com            --fPreallocBuffersInUse;
3491c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        }
3501c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
3518341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org    SkASSERT(!block.fBuffer->isMapped());
3521c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    block.fBuffer->unref();
3531c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    fBlocks.pop_back();
3541c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    fBufferPtr = NULL;
3551c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
3561c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
3573512eda332f3a48ab750a047027e2e254ab53a15bsalomonvoid GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize) {
3583512eda332f3a48ab750a047027e2e254ab53a15bsalomon    GrGeometryBuffer* buffer = block.fBuffer;
35949f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(buffer);
3608341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org    SkASSERT(!buffer->isMapped());
361f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(fCpuData.get() == fBufferPtr);
362089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org    SkASSERT(flushSize <= buffer->gpuMemorySize());
363d51080931700fa989572e5ffe1a5209fe098d2cebsalomon@google.com    VALIDATE(true);
3641c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
365160b478eed1dd4924a86a87fd60c91139e08ff71commit-bot@chromium.org    if (GrDrawTargetCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() &&
3668341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org        flushSize > GR_GEOM_BUFFER_MAP_THRESHOLD) {
3678341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org        void* data = buffer->map();
36849f085dddff10473b6ebf832a974288300224e60bsalomon        if (data) {
3691c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com            memcpy(data, fBufferPtr, flushSize);
3703512eda332f3a48ab750a047027e2e254ab53a15bsalomon            UNMAP_BUFFER(block);
37171bd1ef2807ac2c9d3f82f93f1b958a57a7f612fbsalomon@google.com            return;
3721c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        }
3731c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
3741c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    buffer->updateData(fBufferPtr, flushSize);
375d51080931700fa989572e5ffe1a5209fe098d2cebsalomon@google.com    VALIDATE(true);
3761c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
3771c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
3781c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comGrGeometryBuffer* GrBufferAllocPool::createBuffer(size_t size) {
3791c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    if (kIndex_BufferType == fBufferType) {
3801c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        return fGpu->createIndexBuffer(size, true);
3811c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    } else {
382f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(kVertex_BufferType == fBufferType);
3831c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        return fGpu->createVertexBuffer(size, true);
3841c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
3851c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
3861c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
3871c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
3881c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
3891c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comGrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
3901c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                                 bool frequentResetHint,
3911c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                                 size_t bufferSize,
3921c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                                 int preallocBufferCnt)
3931c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com: GrBufferAllocPool(gpu,
3941c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                    kVertex_BufferType,
3951c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                    frequentResetHint,
3961c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                    bufferSize,
3971c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                    preallocBufferCnt) {
3981c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
3991c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
400a63389843dd18003382d61c2e4610af09ed07d38jvanverth@google.comvoid* GrVertexBufferAllocPool::makeSpace(size_t vertexSize,
4011c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                         int vertexCount,
4021c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                         const GrVertexBuffer** buffer,
4031c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                         int* startVertex) {
4041c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
405f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(vertexCount >= 0);
40649f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(buffer);
40749f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(startVertex);
4081c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
4098b484419e80762ccdecca9ac2c10c1c29368cf2fbsalomon@google.com    size_t offset = 0; // assign to suppress warning
4108b484419e80762ccdecca9ac2c10c1c29368cf2fbsalomon@google.com    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
411a63389843dd18003382d61c2e4610af09ed07d38jvanverth@google.com    void* ptr = INHERITED::makeSpace(vertexSize * vertexCount,
412a63389843dd18003382d61c2e4610af09ed07d38jvanverth@google.com                                     vertexSize,
4131c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                     &geomBuffer,
4141c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                     &offset);
4151c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
4161c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    *buffer = (const GrVertexBuffer*) geomBuffer;
417f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(0 == offset % vertexSize);
418adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    *startVertex = static_cast<int>(offset / vertexSize);
4191c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    return ptr;
4201c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
4211c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
422a63389843dd18003382d61c2e4610af09ed07d38jvanverth@google.combool GrVertexBufferAllocPool::appendVertices(size_t vertexSize,
4231c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                             int vertexCount,
4241c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                             const void* vertices,
4251c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                             const GrVertexBuffer** buffer,
4261c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                             int* startVertex) {
427a63389843dd18003382d61c2e4610af09ed07d38jvanverth@google.com    void* space = makeSpace(vertexSize, vertexCount, buffer, startVertex);
42849f085dddff10473b6ebf832a974288300224e60bsalomon    if (space) {
4291c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        memcpy(space,
4301c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com               vertices,
431a63389843dd18003382d61c2e4610af09ed07d38jvanverth@google.com               vertexSize * vertexCount);
4321c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        return true;
4331c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    } else {
4341c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        return false;
4351c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
4361c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
4371c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
438a63389843dd18003382d61c2e4610af09ed07d38jvanverth@google.comint GrVertexBufferAllocPool::preallocatedBufferVertices(size_t vertexSize) const {
439adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    return static_cast<int>(INHERITED::preallocatedBufferSize() / vertexSize);
4401c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
4411c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
442a63389843dd18003382d61c2e4610af09ed07d38jvanverth@google.comint GrVertexBufferAllocPool::currentBufferVertices(size_t vertexSize) const {
443a63389843dd18003382d61c2e4610af09ed07d38jvanverth@google.com    return currentBufferItems(vertexSize);
4441c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
4451c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
4461c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
4471c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
4481c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comGrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu,
4491c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                               bool frequentResetHint,
4501c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                               size_t bufferSize,
4511c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                               int preallocBufferCnt)
4521c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com: GrBufferAllocPool(gpu,
4531c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                    kIndex_BufferType,
4541c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                    frequentResetHint,
4551c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                    bufferSize,
4561c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                    preallocBufferCnt) {
4571c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
4581c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
4591c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comvoid* GrIndexBufferAllocPool::makeSpace(int indexCount,
4601c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                        const GrIndexBuffer** buffer,
4611c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                        int* startIndex) {
4621c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
463f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(indexCount >= 0);
46449f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(buffer);
46549f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(startIndex);
4661c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
4678b484419e80762ccdecca9ac2c10c1c29368cf2fbsalomon@google.com    size_t offset = 0; // assign to suppress warning
4688b484419e80762ccdecca9ac2c10c1c29368cf2fbsalomon@google.com    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
4691c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t),
4701c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                     sizeof(uint16_t),
4711c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                     &geomBuffer,
4721c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                     &offset);
4731c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
4741c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    *buffer = (const GrIndexBuffer*) geomBuffer;
475f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(0 == offset % sizeof(uint16_t));
476adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    *startIndex = static_cast<int>(offset / sizeof(uint16_t));
4771c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    return ptr;
4781c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
4791c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
4801c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.combool GrIndexBufferAllocPool::appendIndices(int indexCount,
4811c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                           const void* indices,
4821c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                           const GrIndexBuffer** buffer,
4831c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com                                           int* startIndex) {
4841c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    void* space = makeSpace(indexCount, buffer, startIndex);
48549f085dddff10473b6ebf832a974288300224e60bsalomon    if (space) {
4861c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        memcpy(space, indices, sizeof(uint16_t) * indexCount);
4871c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        return true;
4881c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    } else {
4891c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com        return false;
4901c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    }
4911c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
4921c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
4931c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comint GrIndexBufferAllocPool::preallocatedBufferIndices() const {
494adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    return static_cast<int>(INHERITED::preallocatedBufferSize() / sizeof(uint16_t));
4951c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
4961c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com
4971c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.comint GrIndexBufferAllocPool::currentBufferIndices() const {
4981c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com    return currentBufferItems(sizeof(uint16_t));
4991c13c9668a889e56a0c85b51b9f28139c25b76ffbsalomon@google.com}
500