GrGpu.cpp revision a320194e4242ef0e5e758aea896bfd52bcb3dac7
1ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner
2b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell/*
3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell * Copyright 2010 Google Inc.
4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell *
5b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell * Use of this source code is governed by a BSD-style license that can be
6b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell * found in the LICENSE file.
7b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell */
8b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell
9ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner
10ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner#include "GrGpu.h"
11ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner
12ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner#include "GrBufferAllocPool.h"
13ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner#include "GrClipIterator.h"
14ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner#include "GrContext.h"
15ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner#include "GrIndexBuffer.h"
16ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner#include "GrStencilBuffer.h"
17ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner#include "GrVertexBuffer.h"
18ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner
1980a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner// probably makes no sense for this to be less than a page
207152c237b46a920b29d5605af934766b8f9a07a1Chris Lattnerstatic const size_t VERTEX_POOL_VB_SIZE = 1 << 18;
21ca398dc3989d35e8516489fd163e012133bd41cbChris Lattnerstatic const int VERTEX_POOL_VB_COUNT = 4;
2280a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattnerstatic const size_t INDEX_POOL_IB_SIZE = 1 << 16;
2380a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattnerstatic const int INDEX_POOL_IB_COUNT = 4;
2480a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
257152c237b46a920b29d5605af934766b8f9a07a1Chris Lattner////////////////////////////////////////////////////////////////////////////////
26f7703df4968084c18c248c1feea9961c19a32e6aChris Lattner
27ca398dc3989d35e8516489fd163e012133bd41cbChris Lattnerextern void gr_run_unittests();
28f7703df4968084c18c248c1feea9961c19a32e6aChris Lattner
29f7703df4968084c18c248c1feea9961c19a32e6aChris Lattner#define DEBUG_INVAL_BUFFER    0xdeadcafe
3080a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner#define DEBUG_INVAL_START_IDX -1
31ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner
32ca398dc3989d35e8516489fd163e012133bd41cbChris LattnerGrGpu::GrGpu()
33ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    : fClipMaskManager(this)
34ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    , fContext(NULL)
35ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    , fResetTimestamp(kExpiredTimestamp+1)
36ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    , fVertexPool(NULL)
37ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    , fIndexPool(NULL)
38ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    , fVertexPoolUseCnt(0)
39ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    , fIndexPoolUseCnt(0)
40f7703df4968084c18c248c1feea9961c19a32e6aChris Lattner    , fQuadIndexBuffer(NULL)
4180a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    , fUnitSquareVertexBuffer(NULL)
4280a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    , fContextIsDirty(true)
4380a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    , fResourceHead(NULL) {
44ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner
4580a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner#if GR_DEBUG
46ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    //gr_run_unittests();
47ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner#endif
48ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner
49ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    fGeomPoolStateStack.push_back();
5080a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner#if GR_DEBUG
51ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GeometryPoolState& poolState = fGeomPoolStateStack.back();
52ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    poolState.fPoolVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
5380a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    poolState.fPoolStartVertex = DEBUG_INVAL_START_IDX;
5480a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    poolState.fPoolIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
5580a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    poolState.fPoolStartIndex = DEBUG_INVAL_START_IDX;
5680a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner#endif
5780a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
5851d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner    for (int i = 0; i < kGrPixelConfigCount; ++i) {
5980a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner        fConfigRenderSupport[i] = false;
6051d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner    };
6180a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner}
6280a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
63ca398dc3989d35e8516489fd163e012133bd41cbChris LattnerGrGpu::~GrGpu() {
64198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattner    this->releaseResources();
65198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattner}
66198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattner
67198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattnervoid GrGpu::abandonResources() {
68198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattner
69198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattner    fClipMaskManager.releaseResources();
70198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattner
71198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattner    while (NULL != fResourceHead) {
72198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattner        fResourceHead->abandon();
7380a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    }
74f98a08490801b8bc6e2006627d34095f5b8567c8Chris Lattner
75f98a08490801b8bc6e2006627d34095f5b8567c8Chris Lattner    GrAssert(NULL == fQuadIndexBuffer || !fQuadIndexBuffer->isValid());
76f98a08490801b8bc6e2006627d34095f5b8567c8Chris Lattner    GrAssert(NULL == fUnitSquareVertexBuffer ||
77f98a08490801b8bc6e2006627d34095f5b8567c8Chris Lattner             !fUnitSquareVertexBuffer->isValid());
78f98a08490801b8bc6e2006627d34095f5b8567c8Chris Lattner    GrSafeSetNull(fQuadIndexBuffer);
79f98a08490801b8bc6e2006627d34095f5b8567c8Chris Lattner    GrSafeSetNull(fUnitSquareVertexBuffer);
80f98a08490801b8bc6e2006627d34095f5b8567c8Chris Lattner    delete fVertexPool;
8180a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    fVertexPool = NULL;
8280a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    delete fIndexPool;
8380a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    fIndexPool = NULL;
8451d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner}
8580a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
8680a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattnervoid GrGpu::releaseResources() {
8780a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
8880a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    fClipMaskManager.releaseResources();
8980a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
9080a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    while (NULL != fResourceHead) {
9180a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner        fResourceHead->release();
9280a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    }
9380a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
94ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GrAssert(NULL == fQuadIndexBuffer || !fQuadIndexBuffer->isValid());
95ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GrAssert(NULL == fUnitSquareVertexBuffer ||
96ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner             !fUnitSquareVertexBuffer->isValid());
97ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GrSafeSetNull(fQuadIndexBuffer);
98ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GrSafeSetNull(fUnitSquareVertexBuffer);
99ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    delete fVertexPool;
10080a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    fVertexPool = NULL;
101ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    delete fIndexPool;
102ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    fIndexPool = NULL;
103ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner}
10480a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
10580a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattnervoid GrGpu::insertResource(GrResource* resource) {
106ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GrAssert(NULL != resource);
107ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GrAssert(this == resource->getGpu());
108ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GrAssert(NULL == resource->fNext);
109ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GrAssert(NULL == resource->fPrevious);
11080a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
111ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    resource->fNext = fResourceHead;
112ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    if (NULL != fResourceHead) {
113ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        GrAssert(NULL == fResourceHead->fPrevious);
114ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        fResourceHead->fPrevious = resource;
115ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    }
116ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    fResourceHead = resource;
117ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner}
118ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner
119ca398dc3989d35e8516489fd163e012133bd41cbChris Lattnervoid GrGpu::removeResource(GrResource* resource) {
12080a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    GrAssert(NULL != resource);
12180a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    GrAssert(NULL != fResourceHead);
12280a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
123ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    if (fResourceHead == resource) {
12480a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner        GrAssert(NULL == resource->fPrevious);
125ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        fResourceHead = resource->fNext;
12680a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    } else {
12780a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner        GrAssert(NULL != fResourceHead);
128ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        resource->fPrevious->fNext = resource->fNext;
12980a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    }
13080a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    if (NULL != resource->fNext) {
131ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        resource->fNext->fPrevious = resource->fPrevious;
132ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    }
133ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    resource->fNext = NULL;
134ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    resource->fPrevious = NULL;
135ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner}
136ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner
137ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner
138ca398dc3989d35e8516489fd163e012133bd41cbChris Lattnervoid GrGpu::unimpl(const char msg[]) {
139ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner#if GR_DEBUG
140ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg);
141ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner#endif
142ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner}
143ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner
14480a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner////////////////////////////////////////////////////////////////////////////////
14580a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
146ca398dc3989d35e8516489fd163e012133bd41cbChris LattnerGrTexture* GrGpu::createTexture(const GrTextureDesc& desc,
147ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner                                const void* srcData, size_t rowBytes) {
148ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    this->handleDirtyContext();
149ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GrTexture* tex = this->onCreateTexture(desc, srcData, rowBytes);
150ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    if (NULL != tex &&
151ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        (kRenderTarget_GrTextureFlagBit & desc.fFlags) &&
152ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        !(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
153ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        GrAssert(NULL != tex->asRenderTarget());
154ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        // TODO: defer this and attach dynamically
155ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        if (!this->attachStencilBufferToRenderTarget(tex->asRenderTarget())) {
156ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner            tex->unref();
157ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner            return NULL;
158ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        }
159ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    }
160ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    return tex;
161ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner}
162ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner
163ca398dc3989d35e8516489fd163e012133bd41cbChris Lattnerbool GrGpu::attachStencilBufferToRenderTarget(GrRenderTarget* rt) {
164ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GrAssert(NULL == rt->getStencilBuffer());
165ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GrStencilBuffer* sb =
166ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        this->getContext()->findStencilBuffer(rt->width(),
16780a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner                                              rt->height(),
16880a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner                                              rt->numSamples());
169ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    if (NULL != sb) {
170ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        rt->setStencilBuffer(sb);
171ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        bool attached = this->attachStencilBufferToRenderTarget(sb, rt);
172ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        if (!attached) {
173ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner            rt->setStencilBuffer(NULL);
174ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        }
175ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        return attached;
176ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    }
177ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    if (this->createStencilBufferForRenderTarget(rt,
178ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner                                                 rt->width(), rt->height())) {
179ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner        rt->getStencilBuffer()->ref();
18080a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner        rt->getStencilBuffer()->transferToCacheAndLock();
18180a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
18280a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner        // Right now we're clearing the stencil buffer here after it is
18380a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner        // attached to an RT for the first time. When we start matching
18480a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner        // stencil buffers with smaller color targets this will no longer
18580a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner        // be correct because it won't be guaranteed to clear the entire
186f775f95369ba7d88a5cb8b6f1900241699d79351Chris Lattner        // sb.
187f775f95369ba7d88a5cb8b6f1900241699d79351Chris Lattner        // We used to clear down in the GL subclass using a special purpose
188f775f95369ba7d88a5cb8b6f1900241699d79351Chris Lattner        // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported
189f775f95369ba7d88a5cb8b6f1900241699d79351Chris Lattner        // FBO status.
190f775f95369ba7d88a5cb8b6f1900241699d79351Chris Lattner        GrDrawState::AutoRenderTargetRestore artr(this->drawState(), rt);
19180a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner        this->clearStencil();
19280a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner        return true;
19380a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    } else {
19480a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner        return false;
195ee5457cbe88b7f691f774de8515d9a94226d1b00Chris Lattner    }
19651d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner}
197ee5457cbe88b7f691f774de8515d9a94226d1b00Chris Lattner
19880a38d245359cb0a3be8f78f5d7d911232886b9aChris LattnerGrTexture* GrGpu::createPlatformTexture(const GrPlatformTextureDesc& desc) {
19980a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    this->handleDirtyContext();
20080a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    GrTexture* tex = this->onCreatePlatformTexture(desc);
20180a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    if (NULL == tex) {
202e4d90964096c240c9e29ae414792ed1246db4ee8Chris Lattner        return NULL;
203e4d90964096c240c9e29ae414792ed1246db4ee8Chris Lattner    }
204e4d90964096c240c9e29ae414792ed1246db4ee8Chris Lattner    // TODO: defer this and attach dynamically
205e4d90964096c240c9e29ae414792ed1246db4ee8Chris Lattner    GrRenderTarget* tgt = tex->asRenderTarget();
206e4d90964096c240c9e29ae414792ed1246db4ee8Chris Lattner    if (NULL != tgt &&
207e4d90964096c240c9e29ae414792ed1246db4ee8Chris Lattner        !this->attachStencilBufferToRenderTarget(tgt)) {
208e4d90964096c240c9e29ae414792ed1246db4ee8Chris Lattner        tex->unref();
209e07007c2bd0dcb775ff3eecabb4c31ce8dc5fab0Chris Lattner        return NULL;
210e07007c2bd0dcb775ff3eecabb4c31ce8dc5fab0Chris Lattner    } else {
211e07007c2bd0dcb775ff3eecabb4c31ce8dc5fab0Chris Lattner        return tex;
212e07007c2bd0dcb775ff3eecabb4c31ce8dc5fab0Chris Lattner    }
213e07007c2bd0dcb775ff3eecabb4c31ce8dc5fab0Chris Lattner}
214e07007c2bd0dcb775ff3eecabb4c31ce8dc5fab0Chris Lattner
215e07007c2bd0dcb775ff3eecabb4c31ce8dc5fab0Chris LattnerGrRenderTarget* GrGpu::createPlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) {
216e07007c2bd0dcb775ff3eecabb4c31ce8dc5fab0Chris Lattner    this->handleDirtyContext();
217e4d90964096c240c9e29ae414792ed1246db4ee8Chris Lattner    return this->onCreatePlatformRenderTarget(desc);
218e4d90964096c240c9e29ae414792ed1246db4ee8Chris Lattner}
219e4d90964096c240c9e29ae414792ed1246db4ee8Chris Lattner
220e4d90964096c240c9e29ae414792ed1246db4ee8Chris LattnerGrVertexBuffer* GrGpu::createVertexBuffer(uint32_t size, bool dynamic) {
22151d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner    this->handleDirtyContext();
22251d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner    return this->onCreateVertexBuffer(size, dynamic);
22351d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner}
22451d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner
22551d6816089a66c171dc23b50d62989ac6bb5c491Chris LattnerGrIndexBuffer* GrGpu::createIndexBuffer(uint32_t size, bool dynamic) {
22651d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner    this->handleDirtyContext();
22751d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner    return this->onCreateIndexBuffer(size, dynamic);
228e4d90964096c240c9e29ae414792ed1246db4ee8Chris Lattner}
229e4d90964096c240c9e29ae414792ed1246db4ee8Chris Lattner
23080a38d245359cb0a3be8f78f5d7d911232886b9aChris LattnerGrPath* GrGpu::createPath(const SkPath& path) {
23180a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    GrAssert(fCaps.fPathStencilingSupport);
23280a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    this->handleDirtyContext();
23380a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    return this->onCreatePath(path);
234ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner}
235ee5457cbe88b7f691f774de8515d9a94226d1b00Chris Lattner
236ee5457cbe88b7f691f774de8515d9a94226d1b00Chris Lattnervoid GrGpu::clear(const GrIRect* rect, GrColor color) {
237ee5457cbe88b7f691f774de8515d9a94226d1b00Chris Lattner    if (NULL == this->getDrawState().getRenderTarget()) {
238ee5457cbe88b7f691f774de8515d9a94226d1b00Chris Lattner        return;
239ee5457cbe88b7f691f774de8515d9a94226d1b00Chris Lattner    }
240f8485c643412dbff46fe87ea2867445169a5c28eChris Lattner    this->handleDirtyContext();
241ee5457cbe88b7f691f774de8515d9a94226d1b00Chris Lattner    this->onClear(rect, color);
242ee5457cbe88b7f691f774de8515d9a94226d1b00Chris Lattner}
243ee5457cbe88b7f691f774de8515d9a94226d1b00Chris Lattner
244198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattnervoid GrGpu::forceRenderTargetFlush() {
245198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattner    this->handleDirtyContext();
246198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattner    this->onForceRenderTargetFlush();
247198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattner}
248198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattner
249198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattnerbool GrGpu::readPixels(GrRenderTarget* target,
250198f4507e2ff934a8ac3aa0a82526fa6a153b70bChris Lattner                       int left, int top, int width, int height,
251ee5457cbe88b7f691f774de8515d9a94226d1b00Chris Lattner                       GrPixelConfig config, void* buffer,
252ee5457cbe88b7f691f774de8515d9a94226d1b00Chris Lattner                       size_t rowBytes, bool invertY) {
253ee5457cbe88b7f691f774de8515d9a94226d1b00Chris Lattner    GrAssert(GrPixelConfigIsUnpremultiplied(config) ==
25451d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner             GrPixelConfigIsUnpremultiplied(target->config()));
25551d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner    this->handleDirtyContext();
25651d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner    return this->onReadPixels(target, left, top, width, height,
25751d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner                              config, buffer, rowBytes, invertY);
25851d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner}
25951d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner
260dd7036d19a3bfd3dff2531c7fdcd7901b2442de9Chris Lattnervoid GrGpu::writeTexturePixels(GrTexture* texture,
26151d6816089a66c171dc23b50d62989ac6bb5c491Chris Lattner                               int left, int top, int width, int height,
262ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner                               GrPixelConfig config, const void* buffer,
263ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner                               size_t rowBytes) {
264ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    GrAssert(GrPixelConfigIsUnpremultiplied(config) ==
265ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner             GrPixelConfigIsUnpremultiplied(texture->config()));
26680a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner    this->handleDirtyContext();
267ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner    this->onWriteTexturePixels(texture, left, top, width, height,
268ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner                               config, buffer, rowBytes);
2697152c237b46a920b29d5605af934766b8f9a07a1Chris Lattner}
2707152c237b46a920b29d5605af934766b8f9a07a1Chris Lattner
2717152c237b46a920b29d5605af934766b8f9a07a1Chris Lattnervoid GrGpu::resolveRenderTarget(GrRenderTarget* target) {
2727152c237b46a920b29d5605af934766b8f9a07a1Chris Lattner    GrAssert(target);
2737152c237b46a920b29d5605af934766b8f9a07a1Chris Lattner    this->handleDirtyContext();
2747152c237b46a920b29d5605af934766b8f9a07a1Chris Lattner    this->onResolveRenderTarget(target);
2757152c237b46a920b29d5605af934766b8f9a07a1Chris Lattner}
2767152c237b46a920b29d5605af934766b8f9a07a1Chris Lattner
27780a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
27880a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner////////////////////////////////////////////////////////////////////////////////
27980a38d245359cb0a3be8f78f5d7d911232886b9aChris Lattner
280ca398dc3989d35e8516489fd163e012133bd41cbChris Lattnerstatic const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1;
281ca398dc3989d35e8516489fd163e012133bd41cbChris Lattner
282GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535);
283
284static inline void fill_indices(uint16_t* indices, int quadCount) {
285    for (int i = 0; i < quadCount; ++i) {
286        indices[6 * i + 0] = 4 * i + 0;
287        indices[6 * i + 1] = 4 * i + 1;
288        indices[6 * i + 2] = 4 * i + 2;
289        indices[6 * i + 3] = 4 * i + 0;
290        indices[6 * i + 4] = 4 * i + 2;
291        indices[6 * i + 5] = 4 * i + 3;
292    }
293}
294
295const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const {
296    if (NULL == fQuadIndexBuffer) {
297        static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS;
298        GrGpu* me = const_cast<GrGpu*>(this);
299        fQuadIndexBuffer = me->createIndexBuffer(SIZE, false);
300        if (NULL != fQuadIndexBuffer) {
301            uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock();
302            if (NULL != indices) {
303                fill_indices(indices, MAX_QUADS);
304                fQuadIndexBuffer->unlock();
305            } else {
306                indices = (uint16_t*)GrMalloc(SIZE);
307                fill_indices(indices, MAX_QUADS);
308                if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
309                    fQuadIndexBuffer->unref();
310                    fQuadIndexBuffer = NULL;
311                    GrCrash("Can't get indices into buffer!");
312                }
313                GrFree(indices);
314            }
315        }
316    }
317
318    return fQuadIndexBuffer;
319}
320
321const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const {
322    if (NULL == fUnitSquareVertexBuffer) {
323
324        static const GrPoint DATA[] = {
325            { 0,            0 },
326            { GR_Scalar1,   0 },
327            { GR_Scalar1,   GR_Scalar1 },
328            { 0,            GR_Scalar1 }
329#if 0
330            GrPoint(0,         0),
331            GrPoint(GR_Scalar1,0),
332            GrPoint(GR_Scalar1,GR_Scalar1),
333            GrPoint(0,         GR_Scalar1)
334#endif
335        };
336        static const size_t SIZE = sizeof(DATA);
337
338        GrGpu* me = const_cast<GrGpu*>(this);
339        fUnitSquareVertexBuffer = me->createVertexBuffer(SIZE, false);
340        if (NULL != fUnitSquareVertexBuffer) {
341            if (!fUnitSquareVertexBuffer->updateData(DATA, SIZE)) {
342                fUnitSquareVertexBuffer->unref();
343                fUnitSquareVertexBuffer = NULL;
344                GrCrash("Can't get vertices into buffer!");
345            }
346        }
347    }
348
349    return fUnitSquareVertexBuffer;
350}
351
352////////////////////////////////////////////////////////////////////////////////
353
354bool GrGpu::setupClipAndFlushState(DrawType type) {
355
356    if (!fClipMaskManager.setupClipping(fClip)) {
357        return false;
358    }
359
360    if (!this->flushGraphicsState(type)) {
361        return false;
362    }
363
364    return true;
365}
366
367////////////////////////////////////////////////////////////////////////////////
368
369void GrGpu::geometrySourceWillPush() {
370    const GeometrySrcState& geoSrc = this->getGeomSrc();
371    if (kArray_GeometrySrcType == geoSrc.fVertexSrc ||
372        kReserved_GeometrySrcType == geoSrc.fVertexSrc) {
373        this->finalizeReservedVertices();
374    }
375    if (kArray_GeometrySrcType == geoSrc.fIndexSrc ||
376        kReserved_GeometrySrcType == geoSrc.fIndexSrc) {
377        this->finalizeReservedIndices();
378    }
379    GeometryPoolState& newState = fGeomPoolStateStack.push_back();
380#if GR_DEBUG
381    newState.fPoolVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
382    newState.fPoolStartVertex = DEBUG_INVAL_START_IDX;
383    newState.fPoolIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
384    newState.fPoolStartIndex = DEBUG_INVAL_START_IDX;
385#endif
386}
387
388void GrGpu::geometrySourceWillPop(const GeometrySrcState& restoredState) {
389    // if popping last entry then pops are unbalanced with pushes
390    GrAssert(fGeomPoolStateStack.count() > 1);
391    fGeomPoolStateStack.pop_back();
392}
393
394void GrGpu::onDrawIndexed(GrPrimitiveType type,
395                          int startVertex,
396                          int startIndex,
397                          int vertexCount,
398                          int indexCount) {
399
400    this->handleDirtyContext();
401
402    if (!this->setupClipAndFlushState(PrimTypeToDrawType(type))) {
403        return;
404    }
405
406    int sVertex = startVertex;
407    int sIndex = startIndex;
408    setupGeometry(&sVertex, &sIndex, vertexCount, indexCount);
409
410    this->onGpuDrawIndexed(type, sVertex, sIndex,
411                           vertexCount, indexCount);
412}
413
414void GrGpu::onDrawNonIndexed(GrPrimitiveType type,
415                             int startVertex,
416                             int vertexCount) {
417    this->handleDirtyContext();
418
419    if (!this->setupClipAndFlushState(PrimTypeToDrawType(type))) {
420        return;
421    }
422
423    int sVertex = startVertex;
424    setupGeometry(&sVertex, NULL, vertexCount, 0);
425
426    this->onGpuDrawNonIndexed(type, sVertex, vertexCount);
427}
428
429void GrGpu::onStencilPath(const GrPath& path, GrPathFill fill) {
430    this->handleDirtyContext();
431
432    if (!this->setupClipAndFlushState(kStencilPath_DrawType)) {
433        return;
434    }
435
436    this->onGpuStencilPath(path, fill);
437}
438
439void GrGpu::finalizeReservedVertices() {
440    GrAssert(NULL != fVertexPool);
441    fVertexPool->unlock();
442}
443
444void GrGpu::finalizeReservedIndices() {
445    GrAssert(NULL != fIndexPool);
446    fIndexPool->unlock();
447}
448
449void GrGpu::prepareVertexPool() {
450    if (NULL == fVertexPool) {
451        GrAssert(0 == fVertexPoolUseCnt);
452        fVertexPool = new GrVertexBufferAllocPool(this, true,
453                                                  VERTEX_POOL_VB_SIZE,
454                                                  VERTEX_POOL_VB_COUNT);
455        fVertexPool->releaseGpuRef();
456    } else if (!fVertexPoolUseCnt) {
457        // the client doesn't have valid data in the pool
458        fVertexPool->reset();
459    }
460}
461
462void GrGpu::prepareIndexPool() {
463    if (NULL == fIndexPool) {
464        GrAssert(0 == fIndexPoolUseCnt);
465        fIndexPool = new GrIndexBufferAllocPool(this, true,
466                                                INDEX_POOL_IB_SIZE,
467                                                INDEX_POOL_IB_COUNT);
468        fIndexPool->releaseGpuRef();
469    } else if (!fIndexPoolUseCnt) {
470        // the client doesn't have valid data in the pool
471        fIndexPool->reset();
472    }
473}
474
475bool GrGpu::onReserveVertexSpace(GrVertexLayout vertexLayout,
476                                 int vertexCount,
477                                 void** vertices) {
478    GeometryPoolState& geomPoolState = fGeomPoolStateStack.back();
479
480    GrAssert(vertexCount > 0);
481    GrAssert(NULL != vertices);
482
483    this->prepareVertexPool();
484
485    *vertices = fVertexPool->makeSpace(vertexLayout,
486                                       vertexCount,
487                                       &geomPoolState.fPoolVertexBuffer,
488                                       &geomPoolState.fPoolStartVertex);
489    if (NULL == *vertices) {
490        return false;
491    }
492    ++fVertexPoolUseCnt;
493    return true;
494}
495
496bool GrGpu::onReserveIndexSpace(int indexCount, void** indices) {
497    GeometryPoolState& geomPoolState = fGeomPoolStateStack.back();
498
499    GrAssert(indexCount > 0);
500    GrAssert(NULL != indices);
501
502    this->prepareIndexPool();
503
504    *indices = fIndexPool->makeSpace(indexCount,
505                                     &geomPoolState.fPoolIndexBuffer,
506                                     &geomPoolState.fPoolStartIndex);
507    if (NULL == *indices) {
508        return false;
509    }
510    ++fIndexPoolUseCnt;
511    return true;
512}
513
514void GrGpu::releaseReservedVertexSpace() {
515    const GeometrySrcState& geoSrc = this->getGeomSrc();
516    GrAssert(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
517    size_t bytes = geoSrc.fVertexCount * VertexSize(geoSrc.fVertexLayout);
518    fVertexPool->putBack(bytes);
519    --fVertexPoolUseCnt;
520}
521
522void GrGpu::releaseReservedIndexSpace() {
523    const GeometrySrcState& geoSrc = this->getGeomSrc();
524    GrAssert(kReserved_GeometrySrcType == geoSrc.fIndexSrc);
525    size_t bytes = geoSrc.fIndexCount * sizeof(uint16_t);
526    fIndexPool->putBack(bytes);
527    --fIndexPoolUseCnt;
528}
529
530void GrGpu::onSetVertexSourceToArray(const void* vertexArray, int vertexCount) {
531    this->prepareVertexPool();
532    GeometryPoolState& geomPoolState = fGeomPoolStateStack.back();
533#if GR_DEBUG
534    bool success =
535#endif
536    fVertexPool->appendVertices(this->getVertexLayout(),
537                                vertexCount,
538                                vertexArray,
539                                &geomPoolState.fPoolVertexBuffer,
540                                &geomPoolState.fPoolStartVertex);
541    ++fVertexPoolUseCnt;
542    GR_DEBUGASSERT(success);
543}
544
545void GrGpu::onSetIndexSourceToArray(const void* indexArray, int indexCount) {
546    this->prepareIndexPool();
547    GeometryPoolState& geomPoolState = fGeomPoolStateStack.back();
548#if GR_DEBUG
549    bool success =
550#endif
551    fIndexPool->appendIndices(indexCount,
552                              indexArray,
553                              &geomPoolState.fPoolIndexBuffer,
554                              &geomPoolState.fPoolStartIndex);
555    ++fIndexPoolUseCnt;
556    GR_DEBUGASSERT(success);
557}
558
559void GrGpu::releaseVertexArray() {
560    // if vertex source was array, we stowed data in the pool
561    const GeometrySrcState& geoSrc = this->getGeomSrc();
562    GrAssert(kArray_GeometrySrcType == geoSrc.fVertexSrc);
563    size_t bytes = geoSrc.fVertexCount * VertexSize(geoSrc.fVertexLayout);
564    fVertexPool->putBack(bytes);
565    --fVertexPoolUseCnt;
566}
567
568void GrGpu::releaseIndexArray() {
569    // if index source was array, we stowed data in the pool
570    const GeometrySrcState& geoSrc = this->getGeomSrc();
571    GrAssert(kArray_GeometrySrcType == geoSrc.fIndexSrc);
572    size_t bytes = geoSrc.fIndexCount * sizeof(uint16_t);
573    fIndexPool->putBack(bytes);
574    --fIndexPoolUseCnt;
575}
576
577