GrContext.cpp revision f864ec467dfd518e32f6e4d709fafe57f1b3dbc6
127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 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.
727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com */
827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
101fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com#include "GrContext.h"
111fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com
12278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrBufferAllocPool.h"
13278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrClipIterator.h"
1405ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com#include "GrGpu.h"
1527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrIndexBuffer.h"
1627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrInOrderDrawBuffer.h"
1727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrPathRenderer.h"
18d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com#include "GrPathUtils.h"
1950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com#include "GrResourceCache.h"
20558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com#include "GrStencilBuffer.h"
21278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrTextStrike.h"
228c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com#include "SkTLazy.h"
230c8d93a94099dee2dff8da6000ded9ad59676488tomhudson@google.com#include "SkTrace.h"
2427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
25919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com// Using MSAA seems to be slower for some yet unknown reason.
26919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com#define PREFER_MSAA_OFFSCREEN_AA 0
27919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com#define OFFSCREEN_SSAA_SCALE 4 // super sample at 4x4
2806afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
2927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#define DEFER_TEXT_RENDERING 1
3027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
3127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)
3227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
33d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// When we're using coverage AA but the blend is incompatible (given gpu
34d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// limitations) should we disable AA or draw wrong?
35950d7a8d8def14efc98d12d6947347fde351b737bsalomon@google.com#define DISABLE_COVERAGE_AA_FOR_BLEND 1
36d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
378ccadddfa78adbdbbdfa724247318436465a7378bsalomon@google.comstatic const size_t MAX_TEXTURE_CACHE_COUNT = 256;
388ccadddfa78adbdbbdfa724247318436465a7378bsalomon@google.comstatic const size_t MAX_TEXTURE_CACHE_BYTES = 16 * 1024 * 1024;
3927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
4027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 18;
4127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
4227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
4327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com// We are currently only batching Text and drawRectToRect, both
4427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com// of which use the quad index buffer.
4527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 0;
4627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 0;
4727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
48bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com#define ASSERT_OWNED_RESOURCE(R) GrAssert(!(R) || (R)->getContext() == this)
49bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
5005ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.comGrContext* GrContext::Create(GrEngine engine,
5105ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com                             GrPlatform3DContext context3D) {
5227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrContext* ctx = NULL;
5327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrGpu* fGpu = GrGpu::Create(engine, context3D);
5427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != fGpu) {
5527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        ctx = new GrContext(fGpu);
5627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fGpu->unref();
5727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
5827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return ctx;
5927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
6027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
6127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrContext::~GrContext() {
628fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
6327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fTextureCache;
6427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fFontCache;
6527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBuffer;
6627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBufferVBAllocPool;
67de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    delete fDrawBufferIBAllocPool;
683008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
69205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrSafeUnref(fAAFillRectIndexBuffer);
70205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrSafeUnref(fAAStrokeRectIndexBuffer);
71205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->unref();
723008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeUnref(fPathRendererChain);
7327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
7427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
758fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::contextLost() {
7653a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    contextDestroyed();
7753a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    this->setupDrawBuffer();
7853a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com}
7953a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com
8053a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.comvoid GrContext::contextDestroyed() {
81205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // abandon first to so destructors
82205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // don't try to free the resources in the API.
83205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->abandonResources();
84205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
853008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources that
863008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // are now unusable
873008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeSetNull(fPathRendererChain);
883008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
898fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBuffer;
908fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
91205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
928fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferVBAllocPool;
938fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
94205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
958fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferIBAllocPool;
968fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
978fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
98205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrSafeSetNull(fAAFillRectIndexBuffer);
99205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrSafeSetNull(fAAStrokeRectIndexBuffer);
100205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1018fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fTextureCache->removeAll();
1028fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
1038fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
1048fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
1058fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1068fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::resetContext() {
1078fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
1088fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
1098fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1108fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::freeGpuResources() {
1118fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
1128fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fTextureCache->removeAll();
1138fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
1143008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources
1153008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeSetNull(fPathRendererChain);
11627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
11727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
118fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
119fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
12026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.comint GrContext::PaintStageVertexLayoutBits(
12126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                            const GrPaint& paint,
12226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                            const bool hasTexCoords[GrPaint::kTotalStages]) {
12326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int stageMask = paint.getActiveStageMask();
12426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int layout = 0;
12526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kTotalStages; ++i) {
12626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        if ((1 << i) & stageMask) {
12726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            if (NULL != hasTexCoords && hasTexCoords[i]) {
12826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(i, i);
12926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            } else {
13026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(i);
13126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            }
13226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        }
13326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
13426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    return layout;
13526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com}
13626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
13726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
13826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
13926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
140fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.comenum {
141558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    // flags for textures
142558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kNPOTBit            = 0x1,
143558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kFilterBit          = 0x2,
144558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kScratchBit         = 0x4,
145558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
146558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    // resource type
147558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kTextureBit         = 0x8,
148558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kStencilBufferBit   = 0x10
149fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com};
150fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
15150398bf7f1953e640e5529616e710cf540799731bsalomon@google.comGrTexture* GrContext::TextureCacheEntry::texture() const {
15250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (NULL == fEntry) {
15350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        return NULL;
15450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    } else {
15550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        return (GrTexture*) fEntry->resource();
15650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    }
15750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com}
15850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
15950398bf7f1953e640e5529616e710cf540799731bsalomon@google.comnamespace {
16050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com// returns true if this is a "special" texture because of gpu NPOT limitations
16150398bf7f1953e640e5529616e710cf540799731bsalomon@google.combool gen_texture_key_values(const GrGpu* gpu,
1621fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                            const GrSamplerState* sampler,
16350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            GrContext::TextureKey clientKey,
16450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            int width,
16550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            int height,
16650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            bool scratch,
16750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            uint32_t v[4]) {
16850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GR_STATIC_ASSERT(sizeof(GrContext::TextureKey) == sizeof(uint64_t));
16950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // we assume we only need 16 bits of width and height
17050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // assert that texture creation will fail anyway if this assumption
17150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // would cause key collisions.
17218c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    GrAssert(gpu->getCaps().fMaxTextureSize <= SK_MaxU16);
17350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    v[0] = clientKey & 0xffffffffUL;
17450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    v[1] = (clientKey >> 32) & 0xffffffffUL;
17550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    v[2] = width | (height << 16);
17650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
17750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    v[3] = 0;
17818c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    if (!gpu->getCaps().fNPOTTextureTileSupport) {
179fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
180fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
1811fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        bool tiled = NULL != sampler &&
1821fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                     ((sampler->getWrapX() != GrSamplerState::kClamp_WrapMode) ||
1831fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                      (sampler->getWrapY() != GrSamplerState::kClamp_WrapMode));
184fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
185fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        if (tiled && !isPow2) {
18650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            v[3] |= kNPOTBit;
1871fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com            if (GrSamplerState::kNearest_Filter != sampler->getFilter()) {
18850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                v[3] |= kFilterBit;
189fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com            }
190fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        }
191fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
192fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
19350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (scratch) {
19450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        v[3] |= kScratchBit;
195fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
19650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
197558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[3] |= kTextureBit;
198558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
19950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    return v[3] & kNPOTBit;
20050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com}
201558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
202558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com// we should never have more than one stencil buffer with same combo of
203558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com// (width,height,samplecount)
204558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid gen_stencil_key_values(int width, int height,
205558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                            int sampleCnt, uint32_t v[4]) {
206558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[0] = width;
207558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[1] = height;
208558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[2] = sampleCnt;
209558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[3] = kStencilBufferBit;
210558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
211558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
212558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid gen_stencil_key_values(const GrStencilBuffer* sb,
213558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                            uint32_t v[4]) {
214558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(sb->width(), sb->height(),
215558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                           sb->numSamples(), v);
216558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
21782c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com
21882c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com// This should be subsumed by a future version of GrDrawState
21982c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com// It does not reset stage textures/samplers or per-vertex-edge-aa state since
22082c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com// they aren't used unless the vertex layout references them.
22182c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com// It also doesn't set the render target.
2226b67e21b6549598254c1ffa4243bf32615d90fb6bsalomon@google.comvoid reset_draw_state(GrDrawState* drawState){
2238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
2248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setViewMatrix(GrMatrix::I());
2258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setColorFilter(0, SkXfermode::kDst_Mode);
2266b67e21b6549598254c1ffa4243bf32615d90fb6bsalomon@google.com        drawState->resetStateFlags();
2278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setEdgeAAData(NULL, 0);
2288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->disableStencil();
2298f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setAlpha(0xFF);
2306b67e21b6549598254c1ffa4243bf32615d90fb6bsalomon@google.com        drawState->setBlendFunc(kOne_BlendCoeff,
2313d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com                           kZero_BlendCoeff);
2328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setFirstCoverageStage(GrDrawState::kNumStages);
2338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setDrawFace(GrDrawState::kBoth_DrawFace);
23482c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com}
235fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com}
236fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
2371fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.comGrContext::TextureCacheEntry GrContext::findAndLockTexture(
2381fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        TextureKey key,
2391fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        int width,
2401fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        int height,
2411fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrSamplerState* sampler) {
24250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    uint32_t v[4];
24350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    gen_texture_key_values(fGpu, sampler, key, width, height, false, v);
24450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrResourceKey resourceKey(v);
245558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    return TextureCacheEntry(fTextureCache->findAndLock(resourceKey,
246558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                            GrResourceCache::kNested_LockType));
247558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
248558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
249fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.combool GrContext::isTextureInCache(TextureKey key,
250fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com                                 int width,
251fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com                                 int height,
2521fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                 const GrSamplerState* sampler) const {
253fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    uint32_t v[4];
254fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    gen_texture_key_values(fGpu, sampler, key, width, height, false, v);
255fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    GrResourceKey resourceKey(v);
256fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    return fTextureCache->hasKey(resourceKey);
257fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com}
258fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com
259558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comGrResourceEntry* GrContext::addAndLockStencilBuffer(GrStencilBuffer* sb) {
260bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(sb);
261558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    uint32_t v[4];
262558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(sb, v);
263558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceKey resourceKey(v);
264558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    return fTextureCache->createAndLock(resourceKey, sb);
265558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
266558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
267558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comGrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
268558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                              int sampleCnt) {
269558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    uint32_t v[4];
270558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(width, height, sampleCnt, v);
271558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceKey resourceKey(v);
272558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceEntry* entry = fTextureCache->findAndLock(resourceKey,
273558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                            GrResourceCache::kSingle_LockType);
274558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    if (NULL != entry) {
275558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        GrStencilBuffer* sb = (GrStencilBuffer*) entry->resource();
276558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        return sb;
277558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    } else {
278558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        return NULL;
279558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    }
280558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
281558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
282558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid GrContext::unlockStencilBuffer(GrResourceEntry* sbEntry) {
283bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(sbEntry->resource());
284558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    fTextureCache->unlock(sbEntry);
28527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
28627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
28727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic void stretchImage(void* dst,
28827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstW,
28927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstH,
29027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         void* src,
29127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcW,
29227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcH,
29327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int bpp) {
29427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dx = (srcW << 16) / dstW;
29527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dy = (srcH << 16) / dstH;
29627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
29727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed y = dy >> 1;
29827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
29927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    int dstXLimit = dstW*bpp;
30027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    for (int j = 0; j < dstH; ++j) {
30127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrFixed x = dx >> 1;
30227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
30327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* dstRow = (uint8_t*)dst + j*dstW*bpp;
30427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < dstXLimit; i += bpp) {
30527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            memcpy((uint8_t*) dstRow + i,
30627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   (uint8_t*) srcRow + (x>>16)*bpp,
30727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   bpp);
30827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            x += dx;
30927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
31027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        y += dy;
31127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
31227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
31327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
3141fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.comGrContext::TextureCacheEntry GrContext::createAndLockTexture(
3151fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        TextureKey key,
3161fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrSamplerState* sampler,
3171fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrTextureDesc& desc,
3181fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        void* srcData,
3191fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        size_t rowBytes) {
320278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::createAndLockTexture");
32127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
32227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_DUMP_TEXTURE_UPLOAD
32327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
32427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
32527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
32650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    TextureCacheEntry entry;
32750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    uint32_t v[4];
32850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    bool special = gen_texture_key_values(fGpu, sampler, key,
32950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                          desc.fWidth, desc.fHeight, false, v);
33050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrResourceKey resourceKey(v);
33150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
33227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (special) {
3331fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        GrAssert(NULL != sampler);
3341fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        TextureCacheEntry clampEntry = this->findAndLockTexture(key,
3351fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                                desc.fWidth,
3361fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                                desc.fHeight,
3371fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                                NULL);
33827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
33950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        if (NULL == clampEntry.texture()) {
3401fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com            clampEntry = this->createAndLockTexture(key, NULL, desc,
3411fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                    srcData, rowBytes);
34250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            GrAssert(NULL != clampEntry.texture());
34350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            if (NULL == clampEntry.texture()) {
34450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                return entry;
34527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
34627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
347fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        GrTextureDesc rtDesc = desc;
348fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        rtDesc.fFlags =  rtDesc.fFlags |
349fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com                         kRenderTarget_GrTextureFlagBit |
350fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com                         kNoStencil_GrTextureFlagBit;
3519962108c400dadcae913614e8a5ab781780981d8bsalomon@google.com        rtDesc.fWidth  = GrNextPow2(GrMax(desc.fWidth, 64));
3529962108c400dadcae913614e8a5ab781780981d8bsalomon@google.com        rtDesc.fHeight = GrNextPow2(GrMax(desc.fHeight, 64));
35327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
35427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
35527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
35627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != texture) {
35727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrDrawTarget::AutoStateRestore asr(fGpu);
3588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = fGpu->drawState();
3596b67e21b6549598254c1ffa4243bf32615d90fb6bsalomon@google.com            reset_draw_state(drawState);
3608f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->setRenderTarget(texture->asRenderTarget());
3618f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->setTexture(0, clampEntry.texture());
36282c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com
3636aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            GrSamplerState::Filter filter;
3646aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // if filtering is not desired then we want to ensure all
3656aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // texels in the resampled image are copies of texels from
3666aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // the original.
3671fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com            if (GrSamplerState::kNearest_Filter == sampler->getFilter()) {
3686aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com                filter = GrSamplerState::kNearest_Filter;
3696aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            } else {
3706aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com                filter = GrSamplerState::kBilinear_Filter;
3716aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            }
3721e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com            drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
3731e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                         filter);
37427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
37527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            static const GrVertexLayout layout =
37627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
37727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
37827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
37927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (arg.succeeded()) {
38027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                GrPoint* verts = (GrPoint*) arg.vertices();
38127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                verts[0].setIRectFan(0, 0,
38227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     texture->width(),
38327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     texture->height(),
38427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     2*sizeof(GrPoint));
38527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
38627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,
38727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     0, 4);
38850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                entry.set(fTextureCache->createAndLock(resourceKey, texture));
38927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
3901da0746fa155cdca982ae8deb68cc64f540c92dfbsalomon@google.com            texture->releaseRenderTarget();
39127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        } else {
39227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // TODO: Our CPU stretch doesn't filter. But we create separate
39327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // stretched textures when the sampler state is either filtered or
39427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // not. Either implement filtered stretch blit on CPU or just create
39527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // one when FBO case fails.
39627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
397fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com            rtDesc.fFlags = kNone_GrTextureFlags;
39827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // no longer need to clamp at min RT size.
39927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            rtDesc.fWidth  = GrNextPow2(desc.fWidth);
40027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            rtDesc.fHeight = GrNextPow2(desc.fHeight);
40164c4fe4113424bcfab8b3e0c7049887fda5ab4ffbsalomon@google.com            int bpp = GrBytesPerPixel(desc.fConfig);
4023582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com            SkAutoSMalloc<128*128*4> stretchedPixels(bpp *
40327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     rtDesc.fWidth *
40427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     rtDesc.fHeight);
40527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
40627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         srcData, desc.fWidth, desc.fHeight, bpp);
40727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
40827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            size_t stretchedRowBytes = rtDesc.fWidth * bpp;
40927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
41027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrTexture* texture = fGpu->createTexture(rtDesc,
41127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     stretchedPixels.get(),
41227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     stretchedRowBytes);
41327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrAssert(NULL != texture);
41450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            entry.set(fTextureCache->createAndLock(resourceKey, texture));
41527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
41650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->unlock(clampEntry.cacheEntry());
41727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
41827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
41927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
42027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != texture) {
42150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            entry.set(fTextureCache->createAndLock(resourceKey, texture));
42227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
42327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
42427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return entry;
42527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
42627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
42750398bf7f1953e640e5529616e710cf540799731bsalomon@google.comnamespace {
42850398bf7f1953e640e5529616e710cf540799731bsalomon@google.cominline void gen_scratch_tex_key_values(const GrGpu* gpu,
42950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                       const GrTextureDesc& desc,
43050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                       uint32_t v[4]) {
43150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // Instead of a client-provided key of the texture contents
43250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // we create a key of from the descriptor.
43350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrContext::TextureKey descKey = desc.fAALevel |
43450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                    (desc.fFlags << 8) |
43564c4fe4113424bcfab8b3e0c7049887fda5ab4ffbsalomon@google.com                                    ((uint64_t) desc.fConfig << 32);
43650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // this code path isn't friendly to tiling with NPOT restricitons
43750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // We just pass ClampNoFilter()
4381fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com    gen_texture_key_values(gpu, NULL, descKey, desc.fWidth,
4391fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                           desc.fHeight, true, v);
44050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com}
44127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
44227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
44350398bf7f1953e640e5529616e710cf540799731bsalomon@google.comGrContext::TextureCacheEntry GrContext::lockScratchTexture(
44450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                                const GrTextureDesc& inDesc,
44550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                                ScratchTexMatch match) {
44650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
447b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    GrTextureDesc desc = inDesc;
44850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (kExact_ScratchTexMatch != match) {
44950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        // bin by pow2 with a reasonable min
45050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        static const int MIN_SIZE = 256;
45150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fWidth  = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
45250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
45350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    }
454b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
45564c4fe4113424bcfab8b3e0c7049887fda5ab4ffbsalomon@google.com    uint32_t p0 = desc.fConfig;
456b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    uint32_t p1 = (desc.fAALevel << 16) | desc.fFlags;
457b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
45850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrResourceEntry* entry;
459b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origWidth = desc.fWidth;
460b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origHeight = desc.fHeight;
461b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    bool doubledW = false;
462b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    bool doubledH = false;
463b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
464b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    do {
46550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        uint32_t v[4];
46650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        gen_scratch_tex_key_values(fGpu, desc, v);
46750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        GrResourceKey key(v);
468558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        entry = fTextureCache->findAndLock(key,
469558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                           GrResourceCache::kNested_LockType);
470b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        // if we miss, relax the fit of the flags...
471b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        // then try doubling width... then height.
47250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        if (NULL != entry || kExact_ScratchTexMatch == match) {
473b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
474b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
475b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        if (!(desc.fFlags & kRenderTarget_GrTextureFlagBit)) {
476b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = desc.fFlags | kRenderTarget_GrTextureFlagBit;
477b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (desc.fFlags & kNoStencil_GrTextureFlagBit) {
478b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit;
479b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (!doubledW) {
480b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = inDesc.fFlags;
481b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fWidth *= 2;
482b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            doubledW = true;
483b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (!doubledH) {
484b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = inDesc.fFlags;
485b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fWidth = origWidth;
486b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fHeight *= 2;
487b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            doubledH = true;
488b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else {
489b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
490b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
491b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
492b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    } while (true);
493b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
494b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    if (NULL == entry) {
495b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fFlags = inDesc.fFlags;
496b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fWidth = origWidth;
497b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fHeight = origHeight;
498b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
499b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        if (NULL != texture) {
50050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            uint32_t v[4];
50150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            gen_scratch_tex_key_values(fGpu, desc, v);
50250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            GrResourceKey key(v);
503b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            entry = fTextureCache->createAndLock(key, texture);
504b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
505b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
506b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
507b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // If the caller gives us the same desc/sampler twice we don't want
508b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // to return the same texture the second time (unless it was previously
509b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // released). So we detach the entry from the cache and reattach at release.
510b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    if (NULL != entry) {
511b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        fTextureCache->detach(entry);
512b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
51350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    return TextureCacheEntry(entry);
514b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com}
515b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
51650398bf7f1953e640e5529616e710cf540799731bsalomon@google.comvoid GrContext::unlockTexture(TextureCacheEntry entry) {
517bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(entry.texture());
51850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // If this is a scratch texture we detached it from the cache
51950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // while it was locked (to avoid two callers simultaneously getting
52050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // the same texture).
52150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (kScratchBit & entry.cacheEntry()->key().getValue32(3)) {
52250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->reattachAndUnlock(entry.cacheEntry());
523fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    } else {
52450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->unlock(entry.cacheEntry());
525fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
52627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
52727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
528fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.comGrTexture* GrContext::createUncachedTexture(const GrTextureDesc& desc,
52927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            void* srcData,
53027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            size_t rowBytes) {
53127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return fGpu->createTexture(desc, srcData, rowBytes);
53227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
53327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
53427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::getTextureCacheLimits(int* maxTextures,
53527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                      size_t* maxTextureBytes) const {
53627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fTextureCache->getLimits(maxTextures, maxTextureBytes);
53727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
53827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
53927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
54027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fTextureCache->setLimits(maxTextures, maxTextureBytes);
54127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
54227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
543919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxTextureSize() const {
54418c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    return fGpu->getCaps().fMaxTextureSize;
545919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com}
546919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
547919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxRenderTargetSize() const {
54818c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    return fGpu->getCaps().fMaxRenderTargetSize;
54927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
55027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
55127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com///////////////////////////////////////////////////////////////////////////////
55227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
553e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrTexture* GrContext::createPlatformTexture(const GrPlatformTextureDesc& desc) {
554e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com    return fGpu->createPlatformTexture(desc);
555e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
556e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
557e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrRenderTarget* GrContext::createPlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) {
558e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com    return fGpu->createPlatformRenderTarget(desc);
559e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
560e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
5615877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.comGrResource* GrContext::createPlatformSurface(const GrPlatformSurfaceDesc& desc) {
5625877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com    // validate flags here so that GrGpu subclasses don't have to check
5635877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com    if (kTexture_GrPlatformSurfaceType == desc.fSurfaceType &&
5645877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com        0 != desc.fRenderTargetFlags) {
5655877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com        return NULL;
5665877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com    }
5675bfc21761e0ce41206acac4c5008fc0f24debd44bsalomon@google.com    if (desc.fSampleCnt &&
5685bfc21761e0ce41206acac4c5008fc0f24debd44bsalomon@google.com        (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
569973b879dfd994fdb2d5d487edc2012ee3a81f326bsalomon@google.com        return NULL;
5705bfc21761e0ce41206acac4c5008fc0f24debd44bsalomon@google.com    }
5715bfc21761e0ce41206acac4c5008fc0f24debd44bsalomon@google.com    if (kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType &&
5725bfc21761e0ce41206acac4c5008fc0f24debd44bsalomon@google.com        desc.fSampleCnt &&
5735bfc21761e0ce41206acac4c5008fc0f24debd44bsalomon@google.com        !(kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
5745bfc21761e0ce41206acac4c5008fc0f24debd44bsalomon@google.com        return NULL;
5755bfc21761e0ce41206acac4c5008fc0f24debd44bsalomon@google.com    }
5765877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com    return fGpu->createPlatformSurface(desc);
57727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
57827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
5795877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
5805877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com
5811fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.combool GrContext::supportsIndex8PixelConfig(const GrSamplerState* sampler,
5821f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com                                          int width, int height) const {
58318c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    const GrDrawTarget::Caps& caps = fGpu->getCaps();
58418c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    if (!caps.f8BitPaletteSupport) {
58527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return false;
58627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
58727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
58827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
58927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
59027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (!isPow2) {
5911fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        bool tiled = NULL != sampler &&
5921fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                     (sampler->getWrapX() != GrSamplerState::kClamp_WrapMode ||
5931fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                      sampler->getWrapY() != GrSamplerState::kClamp_WrapMode);
59418c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com        if (tiled && !caps.fNPOTTextureTileSupport) {
59527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return false;
59627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
59727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
59827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return true;
59927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
60027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
60127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
60227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
60305ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.comconst GrClip& GrContext::getClip() const { return fGpu->getClip(); }
60405ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com
60527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setClip(const GrClip& clip) {
60627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->setClip(clip);
6078f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    fGpu->drawState()->enableState(GrDrawState::kClip_StateBit);
60827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
60927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
61027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setClip(const GrIRect& rect) {
61127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrClip clip;
612d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    clip.setFromIRect(rect);
61327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->setClip(clip);
61427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
61527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
61627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
61727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
6186aa25c3f555dc2a6711365d14279db3ec909e064bsalomon@google.comvoid GrContext::clear(const GrIRect* rect, const GrColor color) {
619398109cc3e56b8122ad21c4d43a74a83be5b42a8bsalomon@google.com    this->flush();
6206aa25c3f555dc2a6711365d14279db3ec909e064bsalomon@google.com    fGpu->clear(rect, color);
62127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
62227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
62327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawPaint(const GrPaint& paint) {
62427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // set rect to be big enough to fill the space, but not super-huge, so we
62527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // don't overflow fixed-point implementations
626d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    GrRect r;
627d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    r.setLTRB(0, 0,
628d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com              GrIntToScalar(getRenderTarget()->width()),
629d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com              GrIntToScalar(getRenderTarget()->height()));
63027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix inverse;
6318c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    SkTLazy<GrPaint> tmpPaint;
6328c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    const GrPaint* p = &paint;
6338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
6348f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrAutoMatrix am;
6358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6364f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // We attempt to map r by the inverse matrix and draw that. mapRect will
6374f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // map the four corners and bound them with a new rect. This will not
6384f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // produce a correct result for some perspective matrices.
6398c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    if (!this->getMatrix().hasPerspective()) {
6408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        if (!drawState->getViewInverse(&inverse)) {
6418c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            GrPrintf("Could not invert matrix");
6428c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            return;
6438c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
64427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        inverse.mapRect(&r);
64527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
6468c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        if (paint.getActiveMaskStageMask() || paint.getActiveStageMask()) {
6478f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            if (!drawState->getViewInverse(&inverse)) {
6488c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com                GrPrintf("Could not invert matrix");
6498c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com                return;
6508c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            }
6518c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.set(paint);
6528c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.get()->preConcatActiveSamplerMatrices(inverse);
6538c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            p = tmpPaint.get();
6548c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
6554f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com        am.set(this, GrMatrix::I());
65627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
6574f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // by definition this fills the entire clip, no need for AA
6584f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    if (paint.fAntiAlias) {
6598c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        if (!tmpPaint.isValid()) {
6608c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.set(paint);
6618c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            p = tmpPaint.get();
6628c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
6638c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        GrAssert(p == tmpPaint.get());
6648c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        tmpPaint.get()->fAntiAlias = false;
6654f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    }
6664f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    this->drawRect(*p, r);
66727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
66827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
669205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
670205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
671d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.comnamespace {
672d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.cominline bool disable_coverage_aa_for_blend(GrDrawTarget* target) {
673d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage();
674d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com}
675d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com}
676d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
677919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comstruct GrContext::OffscreenRecord {
678919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    enum Downsample {
679919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        k4x4TwoPass_Downsample,
680919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        k4x4SinglePass_Downsample,
681919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        kFSAA_Downsample
682919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    }                              fDownsample;
683b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int                            fTileSizeX;
684b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int                            fTileSizeY;
685919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    int                            fTileCountX;
686919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    int                            fTileCountY;
687919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    int                            fScale;
68850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrAutoScratchTexture           fOffscreen0;
68950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrAutoScratchTexture           fOffscreen1;
690919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    GrDrawTarget::SavedDrawState   fSavedState;
691237a461ec96918eef9bd9f61d4d63fc43968b3e8tomhudson@google.com    GrClip                         fClip;
692919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com};
693919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
694471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.combool GrContext::doOffscreenAA(GrDrawTarget* target,
695471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com                              bool isHairLines) const {
696919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com#if !GR_USE_OFFSCREEN_AA
6978295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    return false;
6988295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com#else
6991f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com    // Line primitves are always rasterized as 1 pixel wide.
7001f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com    // Super-sampling would make them too thin but MSAA would be OK.
7011f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com    if (isHairLines &&
70218c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com        (!PREFER_MSAA_OFFSCREEN_AA || !fGpu->getCaps().fFSAASupport)) {
7038295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        return false;
7048295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
7058f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (target->getDrawState().getRenderTarget()->isMultisampled()) {
7068295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        return false;
7078295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
708d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (disable_coverage_aa_for_blend(target)) {
7091983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
710979432ba2621b617f5e85a9ff48c6b6cd1504a0dbsalomon@google.com        //GrPrintf("Turning off AA to correctly apply blend.\n");
7111983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
7128295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        return false;
7138295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
7148295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    return true;
7158295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com#endif
7168295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com}
7178295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
718919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.combool GrContext::prepareForOffscreenAA(GrDrawTarget* target,
71906afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com                                      bool requireStencil,
7208295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com                                      const GrIRect& boundRect,
721d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com                                      GrPathRenderer* pr,
72206afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com                                      OffscreenRecord* record) {
723919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
724919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    GrAssert(GR_USE_OFFSCREEN_AA);
72506afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
72650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrAssert(NULL == record->fOffscreen0.texture());
72750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrAssert(NULL == record->fOffscreen1.texture());
728919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    GrAssert(!boundRect.isEmpty());
72906afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
7308295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    int boundW = boundRect.width();
7318295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    int boundH = boundRect.height();
732919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
733b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    GrTextureDesc desc;
734919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
735b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    desc.fWidth  = GrMin(fMaxOffscreenAASize, boundW);
736b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    desc.fHeight = GrMin(fMaxOffscreenAASize, boundH);
73706afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
73806afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com    if (requireStencil) {
73906afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com        desc.fFlags = kRenderTarget_GrTextureFlagBit;
74006afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com    } else {
74106afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com        desc.fFlags = kRenderTarget_GrTextureFlagBit |
74206afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com                      kNoStencil_GrTextureFlagBit;
74306afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com    }
74406afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
745c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    desc.fConfig = kRGBA_8888_PM_GrPixelConfig;
74606afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
74718c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    if (PREFER_MSAA_OFFSCREEN_AA && fGpu->getCaps().fFSAASupport) {
7486aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com        record->fDownsample = OffscreenRecord::kFSAA_Downsample;
749d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com        record->fScale = 1;
7508295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        desc.fAALevel = kMed_GrAALevel;
7518295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    } else {
75218c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com        record->fDownsample = fGpu->getCaps().fShaderSupport ?
7536aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com                                OffscreenRecord::k4x4SinglePass_Downsample :
7546aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com                                OffscreenRecord::k4x4TwoPass_Downsample;
755919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        record->fScale = OFFSCREEN_SSAA_SCALE;
756919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        // both downsample paths assume this
757919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        GR_STATIC_ASSERT(4 == OFFSCREEN_SSAA_SCALE);
7588295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        desc.fAALevel = kNone_GrAALevel;
7598295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
760d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com
761b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    desc.fWidth *= record->fScale;
762b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    desc.fHeight *= record->fScale;
76350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    record->fOffscreen0.set(this, desc);
76450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (NULL == record->fOffscreen0.texture()) {
76506afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com        return false;
76606afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com    }
767b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // the approximate lookup might have given us some slop space, might as well
768b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // use it when computing the tiles size.
769b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // these are scale values, will adjust after considering
770b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // the possible second offscreen.
77150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    record->fTileSizeX = record->fOffscreen0.texture()->width();
77250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    record->fTileSizeY = record->fOffscreen0.texture()->height();
7738295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
7746aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com    if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) {
7758295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        desc.fWidth /= 2;
7768295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        desc.fHeight /= 2;
77750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        record->fOffscreen1.set(this, desc);
77850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        if (NULL == record->fOffscreen1.texture()) {
7798295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com            return false;
7808295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        }
781b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        record->fTileSizeX = GrMin(record->fTileSizeX,
78250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                   2 * record->fOffscreen0.texture()->width());
783b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        record->fTileSizeY = GrMin(record->fTileSizeY,
78450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                   2 * record->fOffscreen0.texture()->height());
7858295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
786b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    record->fTileSizeX /= record->fScale;
787b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    record->fTileSizeY /= record->fScale;
788b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
789b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    record->fTileCountX = GrIDivRoundUp(boundW, record->fTileSizeX);
790b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    record->fTileCountY = GrIDivRoundUp(boundH, record->fTileSizeY);
791b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
792237a461ec96918eef9bd9f61d4d63fc43968b3e8tomhudson@google.com    record->fClip = target->getClip();
793237a461ec96918eef9bd9f61d4d63fc43968b3e8tomhudson@google.com
794919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    target->saveCurrentDrawState(&record->fSavedState);
795919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    return true;
796919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com}
797919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
798919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comvoid GrContext::setupOffscreenAAPass1(GrDrawTarget* target,
799919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com                                      const GrIRect& boundRect,
800919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com                                      int tileX, int tileY,
801919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com                                      OffscreenRecord* record) {
8028295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
80350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrRenderTarget* offRT0 = record->fOffscreen0.texture()->asRenderTarget();
8048295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    GrAssert(NULL != offRT0);
80506afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
80606afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com    GrPaint tempPaint;
80706afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com    tempPaint.reset();
808bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    this->setPaint(tempPaint, target);
8098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = target->drawState();
8108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(offRT0);
811289533ada623f2238a83771eec977f204f75994fbsalomon@google.com#if PREFER_MSAA_OFFSCREEN_AA
8128f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    target->enableState(GrDrawState::kHWAntialias_StateBit);
813289533ada623f2238a83771eec977f204f75994fbsalomon@google.com#endif
81406afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
8153d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    GrMatrix transM;
816b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int left = boundRect.fLeft + tileX * record->fTileSizeX;
817b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int top =  boundRect.fTop  + tileY * record->fTileSizeY;
8183d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    transM.setTranslate(-left * GR_Scalar1, -top * GR_Scalar1);
8198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->viewMatrix()->postConcat(transM);
8203d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    GrMatrix scaleM;
8213d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    scaleM.setScale(record->fScale * GR_Scalar1, record->fScale * GR_Scalar1);
8228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->viewMatrix()->postConcat(scaleM);
82306afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
824919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    int w = (tileX == record->fTileCountX-1) ? boundRect.fRight - left :
825b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com                                               record->fTileSizeX;
826919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    int h = (tileY == record->fTileCountY-1) ? boundRect.fBottom - top :
827b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com                                               record->fTileSizeY;
828919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    GrIRect clear = SkIRect::MakeWH(record->fScale * w,
829919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com                                    record->fScale * h);
830237a461ec96918eef9bd9f61d4d63fc43968b3e8tomhudson@google.com    target->setClip(GrClip(clear));
831919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com#if 0
832919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // visualize tile boundaries by setting edges of offscreen to white
833919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // and interior to tranparent. black.
834919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    target->clear(&clear, 0xffffffff);
835919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
836919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    static const int gOffset = 2;
837919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    GrIRect clear2 = SkIRect::MakeLTRB(gOffset, gOffset,
838919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com                                       record->fScale * w - gOffset,
839919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com                                       record->fScale * h - gOffset);
840919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    target->clear(&clear2, 0x0);
841919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com#else
8428295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    target->clear(&clear, 0x0);
843919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com#endif
84406afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com}
84506afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
846919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comvoid GrContext::doOffscreenAAPass2(GrDrawTarget* target,
8478295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com                                 const GrPaint& paint,
8488295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com                                 const GrIRect& boundRect,
849919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com                                 int tileX, int tileY,
8508295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com                                 OffscreenRecord* record) {
851278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::doOffscreenAAPass2");
85250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrAssert(NULL != record->fOffscreen0.texture());
853ee435122d7dcb9cd4be4524004b0de282c42848bbsalomon@google.com    GrDrawTarget::AutoGeometryPush agp(target);
854919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    GrIRect tileRect;
855b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    tileRect.fLeft = boundRect.fLeft + tileX * record->fTileSizeX;
856b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    tileRect.fTop  = boundRect.fTop  + tileY * record->fTileSizeY,
857919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    tileRect.fRight = (tileX == record->fTileCountX-1) ?
858919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com                        boundRect.fRight :
859b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com                        tileRect.fLeft + record->fTileSizeX;
860919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    tileRect.fBottom = (tileY == record->fTileCountY-1) ?
861919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com                        boundRect.fBottom :
862b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com                        tileRect.fTop + record->fTileSizeY;
86306afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
8646aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com    GrSamplerState::Filter filter;
8656aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com    if (OffscreenRecord::k4x4SinglePass_Downsample == record->fDownsample) {
8666aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com        filter = GrSamplerState::k4x4Downsample_Filter;
8676aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com    } else {
8686aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com        filter = GrSamplerState::kBilinear_Filter;
8696aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com    }
8706aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com
87150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrTexture* src = record->fOffscreen0.texture();
8728295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    int scale;
8738295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
87426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    enum {
87526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        kOffscreenStage = GrPaint::kTotalStages,
87626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    };
87726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
8788f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = target->drawState();
8798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
8806aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com    if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) {
88150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        GrAssert(NULL != record->fOffscreen1.texture());
8828295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        scale = 2;
88350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        GrRenderTarget* dst = record->fOffscreen1.texture()->asRenderTarget();
8848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
8858295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        // Do 2x2 downsample from first to second
8868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setTexture(kOffscreenStage, src);
8878f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setRenderTarget(dst);
8888f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setViewMatrix(GrMatrix::I());
8891e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com        GrSamplerState* sampler = drawState->sampler(kOffscreenStage);
8901e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com        sampler->reset(GrSamplerState::kClamp_WrapMode, filter);
891aa814fe4a148b05f9160a5f77cb4e630406ea62dbsalomon@google.com        sampler->matrix()->setScale(scale * GR_Scalar1 / src->width(),
892aa814fe4a148b05f9160a5f77cb4e630406ea62dbsalomon@google.com                                    scale * GR_Scalar1 / src->height());
8939d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com        GrRect rect = SkRect::MakeWH(SkIntToScalar(scale * tileRect.width()),
8949d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com                                     SkIntToScalar(scale * tileRect.height()));
8958295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawSimpleRect(rect, NULL, 1 << kOffscreenStage);
8968295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
89750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        src = record->fOffscreen1.texture();
8986aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com    } else if (OffscreenRecord::kFSAA_Downsample == record->fDownsample) {
8998295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        scale = 1;
900919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        GrIRect rect = SkIRect::MakeWH(tileRect.width(), tileRect.height());
9018295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        src->asRenderTarget()->overrideResolveRect(rect);
9026aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com    } else {
9036aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com        GrAssert(OffscreenRecord::k4x4SinglePass_Downsample ==
9046aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com                 record->fDownsample);
9056aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com        scale = 4;
9068295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
9078295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
908919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // setup for draw back to main RT, we use the original
909919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // draw state setup by the caller plus an additional coverage
910919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // stage to handle the AA resolve. Also, we use an identity
911919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // view matrix and so pre-concat sampler matrices with view inv.
91226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int stageMask = paint.getActiveStageMask();
91326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
9148295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    target->restoreDrawState(record->fSavedState);
915237a461ec96918eef9bd9f61d4d63fc43968b3e8tomhudson@google.com    target->setClip(record->fClip);
91626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
91726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    if (stageMask) {
9188295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        GrMatrix invVM;
9198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        if (drawState->getViewInverse(&invVM)) {
9208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatSamplerMatrices(stageMask, invVM);
9218295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        }
9228295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
923919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // This is important when tiling, otherwise second tile's
924919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // pass 1 view matrix will be incorrect.
9258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState::AutoViewMatrixRestore avmr(drawState, GrMatrix::I());
9268295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
9278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setTexture(kOffscreenStage, src);
9281e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    GrSamplerState* sampler = drawState->sampler(kOffscreenStage);
9291e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    sampler->reset(GrSamplerState::kClamp_WrapMode, filter);
930aa814fe4a148b05f9160a5f77cb4e630406ea62dbsalomon@google.com    sampler->matrix()->setScale(scale * GR_Scalar1 / src->width(),
931aa814fe4a148b05f9160a5f77cb4e630406ea62dbsalomon@google.com                                scale * GR_Scalar1 / src->height());
932aa814fe4a148b05f9160a5f77cb4e630406ea62dbsalomon@google.com    sampler->matrix()->preTranslate(SkIntToScalar(-tileRect.fLeft),
933aa814fe4a148b05f9160a5f77cb4e630406ea62dbsalomon@google.com                                    SkIntToScalar(-tileRect.fTop));
93406afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
93520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    GrRect dstRect;
93626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int stages = (1 << kOffscreenStage) | stageMask;
937919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    dstRect.set(tileRect);
9388295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    target->drawSimpleRect(dstRect, NULL, stages);
939919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com}
94006afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
941d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.comvoid GrContext::cleanupOffscreenAA(GrDrawTarget* target,
942d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com                                   GrPathRenderer* pr,
943d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com                                   OffscreenRecord* record) {
9448295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    target->restoreDrawState(record->fSavedState);
94506afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com}
94606afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
94706afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
94806afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
94927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com/*  create a triangle strip that strokes the specified triangle. There are 8
95027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com unique vertices, but we repreat the last 2 to close up. Alternatively we
95127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com could use an indices array, and then only send 8 verts, but not sure that
95227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com would be faster.
95327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com */
954205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
95527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               GrScalar width) {
95627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    const GrScalar rad = GrScalarHalf(width);
957205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    rect.sort();
95827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
95927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[0].set(rect.fLeft + rad, rect.fTop + rad);
96027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[1].set(rect.fLeft - rad, rect.fTop - rad);
96127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[2].set(rect.fRight - rad, rect.fTop + rad);
96227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[3].set(rect.fRight + rad, rect.fTop - rad);
96327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[4].set(rect.fRight - rad, rect.fBottom - rad);
96427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[5].set(rect.fRight + rad, rect.fBottom + rad);
96527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
96627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
96727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[8] = verts[0];
96827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[9] = verts[1];
96927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
97027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
971205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic void setInsetFan(GrPoint* pts, size_t stride,
972205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        const GrRect& r, GrScalar dx, GrScalar dy) {
973205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    pts->setRectFan(r.fLeft + dx, r.fTop + dy, r.fRight - dx, r.fBottom - dy, stride);
974205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
975205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
976205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic const uint16_t gFillAARectIdx[] = {
977205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    0, 1, 5, 5, 4, 0,
978205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    1, 2, 6, 6, 5, 1,
979205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    2, 3, 7, 7, 6, 2,
980205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    3, 0, 4, 4, 7, 3,
981205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    4, 5, 6, 6, 7, 4,
982205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com};
983205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
984205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comint GrContext::aaFillRectIndexCount() const {
985205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    return GR_ARRAY_COUNT(gFillAARectIdx);
986205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
987205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
988205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comGrIndexBuffer* GrContext::aaFillRectIndexBuffer() {
989205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL == fAAFillRectIndexBuffer) {
990205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        fAAFillRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gFillAARectIdx),
991205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                                                         false);
9929b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        if (NULL != fAAFillRectIndexBuffer) {
9939b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    #if GR_DEBUG
9949b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            bool updated =
9959b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    #endif
9969b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            fAAFillRectIndexBuffer->updateData(gFillAARectIdx,
9979b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com                                               sizeof(gFillAARectIdx));
9989b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            GR_DEBUGASSERT(updated);
9999b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        }
1000205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1001205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    return fAAFillRectIndexBuffer;
1002205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
1003205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1004205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic const uint16_t gStrokeAARectIdx[] = {
1005205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
1006205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
1007205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
1008205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
1009205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1010205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
1011205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
1012205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
1013205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
1014205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1015205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
1016205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
1017205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
1018205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
1019205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com};
1020205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1021205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comint GrContext::aaStrokeRectIndexCount() const {
1022205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    return GR_ARRAY_COUNT(gStrokeAARectIdx);
1023205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
1024205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1025205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comGrIndexBuffer* GrContext::aaStrokeRectIndexBuffer() {
1026205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL == fAAStrokeRectIndexBuffer) {
1027205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        fAAStrokeRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gStrokeAARectIdx),
1028205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                                                           false);
10299b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        if (NULL != fAAStrokeRectIndexBuffer) {
10309b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    #if GR_DEBUG
10319b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            bool updated =
10329b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    #endif
10339b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx,
10349b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com                                                 sizeof(gStrokeAARectIdx));
10359b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            GR_DEBUGASSERT(updated);
10369b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        }
1037205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1038205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    return fAAStrokeRectIndexBuffer;
1039205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
1040205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1041a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.comstatic GrVertexLayout aa_rect_layout(const GrDrawTarget* target,
1042a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                     bool useCoverage) {
1043a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrVertexLayout layout = 0;
10449381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
10458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        if (NULL != target->getDrawState().getTexture(s)) {
1046a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
1047a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        }
1048a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    }
1049a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    if (useCoverage) {
1050a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        layout |= GrDrawTarget::kCoverage_VertexLayoutBit;
1051a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    } else {
1052a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        layout |= GrDrawTarget::kColor_VertexLayoutBit;
1053a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    }
1054a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    return layout;
1055a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com}
1056a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com
1057205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comvoid GrContext::fillAARect(GrDrawTarget* target,
1058a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                           const GrRect& devRect,
1059a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                           bool useVertexCoverage) {
1060a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage);
1061205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1062205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    size_t vsize = GrDrawTarget::VertexSize(layout);
1063205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1064205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(target, layout, 8, 0);
10656513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    if (!geo.succeeded()) {
10666513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
10676513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        return;
10686513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    }
10699b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer();
10709b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    if (NULL == indexBuffer) {
10719b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        GrPrintf("Failed to create index buffer!\n");
10729b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        return;
10739b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    }
1074205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1075205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
1076205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1077205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
1078205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
1079205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1080205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan0Pos, vsize, devRect, -GR_ScalarHalf, -GR_ScalarHalf);
1081205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan1Pos, vsize, devRect,  GR_ScalarHalf,  GR_ScalarHalf);
1082205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1083205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += sizeof(GrPoint);
1084205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 4; ++i) {
1085205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
1086205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1087205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1088a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrColor innerColor;
1089a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    if (useVertexCoverage) {
1090e10f6fdf76fa9b627cbb8471b58b13c457af83e8bsalomon@google.com        innerColor = 0xffffffff;
1091a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    } else {
10928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        innerColor = target->getDrawState().getColor();
1093a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    }
1094a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com
1095205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += 4 * vsize;
1096205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 4; ++i) {
1097205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
1098205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1099205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
11009b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    target->setIndexSourceToBuffer(indexBuffer);
1101205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1102205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    target->drawIndexed(kTriangles_PrimitiveType, 0,
1103205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                         0, 8, this->aaFillRectIndexCount());
1104205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
1105205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1106a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.comvoid GrContext::strokeAARect(GrDrawTarget* target,
1107a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             const GrRect& devRect,
1108a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             const GrVec& devStrokeSize,
1109a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             bool useVertexCoverage) {
1110205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    const GrScalar& dx = devStrokeSize.fX;
1111205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    const GrScalar& dy = devStrokeSize.fY;
1112205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    const GrScalar rx = GrMul(dx, GR_ScalarHalf);
1113205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    const GrScalar ry = GrMul(dy, GR_ScalarHalf);
1114205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1115205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrScalar spare;
1116205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    {
1117205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrScalar w = devRect.width() - dx;
1118205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrScalar h = devRect.height() - dy;
1119205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        spare = GrMin(w, h);
1120205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1121205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1122205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (spare <= 0) {
1123205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrRect r(devRect);
1124205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        r.inset(-rx, -ry);
1125a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        fillAARect(target, r, useVertexCoverage);
1126205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return;
1127205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1128a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage);
1129205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    size_t vsize = GrDrawTarget::VertexSize(layout);
1130205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1131205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(target, layout, 16, 0);
11326513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    if (!geo.succeeded()) {
11336513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
11346513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        return;
11356513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    }
11369b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer();
11379b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    if (NULL == indexBuffer) {
11389b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        GrPrintf("Failed to create index buffer!\n");
11399b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        return;
11409b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    }
1141205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1142205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
1143205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1144205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
1145205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
1146205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize);
1147205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize);
1148205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1149205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan0Pos, vsize, devRect, -rx - GR_ScalarHalf, -ry - GR_ScalarHalf);
1150205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan1Pos, vsize, devRect, -rx + GR_ScalarHalf, -ry + GR_ScalarHalf);
1151205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan2Pos, vsize, devRect,  rx - GR_ScalarHalf,  ry - GR_ScalarHalf);
1152205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan3Pos, vsize, devRect,  rx + GR_ScalarHalf,  ry + GR_ScalarHalf);
1153205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1154205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += sizeof(GrPoint);
1155205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 4; ++i) {
1156205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
1157205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1158205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1159a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrColor innerColor;
1160a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    if (useVertexCoverage) {
1161e10f6fdf76fa9b627cbb8471b58b13c457af83e8bsalomon@google.com        innerColor = 0xffffffff;
1162a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    } else {
11638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        innerColor = target->getDrawState().getColor();
1164a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    }
1165205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += 4 * vsize;
1166205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 8; ++i) {
1167205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
1168205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1169205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1170205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += 8 * vsize;
1171205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 8; ++i) {
1172205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
1173205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1174205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
11759b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    target->setIndexSourceToBuffer(indexBuffer);
1176205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    target->drawIndexed(kTriangles_PrimitiveType,
1177205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0, 0, 16, aaStrokeRectIndexCount());
1178205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
1179205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
118020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com/**
118120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com * Returns true if the rects edges are integer-aligned.
118220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com */
118320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.comstatic bool isIRect(const GrRect& r) {
118420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    return GrScalarIsInt(r.fLeft) && GrScalarIsInt(r.fTop) &&
118520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com           GrScalarIsInt(r.fRight) && GrScalarIsInt(r.fBottom);
118620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com}
118720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
1188205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic bool apply_aa_to_rect(GrDrawTarget* target,
1189205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             const GrRect& rect,
1190205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             GrScalar width,
1191205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             const GrMatrix* matrix,
1192205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             GrMatrix* combinedMatrix,
1193a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             GrRect* devRect,
1194a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             bool* useVertexCoverage) {
1195205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // we use a simple alpha ramp to do aa on axis-aligned rects
1196205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // do AA with alpha ramp if the caller requested AA, the rect
1197289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    // will be axis-aligned, and the rect won't land on integer coords.
1198d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
1199a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // we are keeping around the "tweak the alpha" trick because
1200a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // it is our only hope for the fixed-pipe implementation.
1201a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // In a shader implementation we can give a separate coverage input
1202289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    // TODO: remove this ugliness when we drop the fixed-pipe impl
1203a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    *useVertexCoverage = false;
1204d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (!target->canTweakAlphaForCoverage()) {
1205a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        if (target->getCaps().fSupportPerVertexCoverage) {
1206a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            if (disable_coverage_aa_for_blend(target)) {
12071983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
1208979432ba2621b617f5e85a9ff48c6b6cd1504a0dbsalomon@google.com                //GrPrintf("Turning off AA to correctly apply blend.\n");
12091983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
1210a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                return false;
1211a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            } else {
1212a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                *useVertexCoverage = true;
1213a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            }
1214a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        } else {
1215a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            GrPrintf("Rect AA dropped because no support for coverage.\n");
1216a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            return false;
1217a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        }
1218205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
12198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    const GrDrawState& drawState = target->getDrawState();
12208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (drawState.getRenderTarget()->isMultisampled()) {
1221205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
1222205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1223205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1224471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com    if (0 == width && target->willUseHWAALines()) {
1225205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
1226205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1227205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
12288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (!drawState.getViewMatrix().preservesAxisAlignment()) {
1229205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
1230205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1231205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1232205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL != matrix &&
1233205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        !matrix->preservesAxisAlignment()) {
1234205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
1235205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1236205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
12378f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    *combinedMatrix = drawState.getViewMatrix();
1238205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL != matrix) {
1239205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        combinedMatrix->preConcat(*matrix);
1240205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrAssert(combinedMatrix->preservesAxisAlignment());
1241205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1242205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1243205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    combinedMatrix->mapRect(devRect, rect);
1244205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    devRect->sort();
1245205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1246205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (width < 0) {
124720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        return !isIRect(*devRect);
1248205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    } else {
1249205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return true;
1250205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1251205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
1252205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
125327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRect(const GrPaint& paint,
125427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         const GrRect& rect,
125527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         GrScalar width,
125627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         const GrMatrix* matrix) {
1257278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRect");
125827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
125927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
126026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int stageMask = paint.getActiveStageMask();
126127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1262205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrRect devRect = rect;
1263205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrMatrix combinedMatrix;
1264a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    bool useVertexCoverage;
1265289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool needAA = paint.fAntiAlias &&
1266289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                  !this->getRenderTarget()->isMultisampled();
1267289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix,
1268289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &combinedMatrix, &devRect,
1269289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &useVertexCoverage);
1270205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1271205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (doAA) {
12728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
1273205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        if (width >= 0) {
1274205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            GrVec strokeSize;;
1275205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            if (width > 0) {
1276205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.set(width, width);
1277cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com                combinedMatrix.mapVectors(&strokeSize, 1);
1278205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.setAbs(strokeSize);
1279205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            } else {
1280205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.set(GR_Scalar1, GR_Scalar1);
1281205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            }
1282a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            strokeAARect(target, devRect, strokeSize, useVertexCoverage);
1283205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        } else {
1284a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            fillAARect(target, devRect, useVertexCoverage);
1285205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        }
1286205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return;
1287205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1288205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
128927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (width >= 0) {
129027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // TODO: consider making static vertex buffers for these cases.
129127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // Hairline could be done by just adding closing vertex to
129227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // unitSquareVertexBuffer()
129326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        GrVertexLayout layout =  PaintStageVertexLayoutBits(paint, NULL);
129426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
129527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        static const int worstCaseVertCount = 10;
129627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
129727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
129827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.succeeded()) {
12996513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
130027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
130127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
130227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
130327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPrimitiveType primType;
130427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int vertCount;
130527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPoint* vertex = geo.positions();
130627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
130727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (width > 0) {
130827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 10;
130927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            primType = kTriangleStrip_PrimitiveType;
131027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            setStrokeRectStrip(vertex, rect, width);
131127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        } else {
131227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // hairline
131327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 5;
131427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            primType = kLineStrip_PrimitiveType;
131527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[0].set(rect.fLeft, rect.fTop);
131627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[1].set(rect.fRight, rect.fTop);
131727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[2].set(rect.fRight, rect.fBottom);
131827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[3].set(rect.fLeft, rect.fBottom);
131927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[4].set(rect.fLeft, rect.fTop);
132027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
132127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
13228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState::AutoViewMatrixRestore avmr;
132327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != matrix) {
13248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
13258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            avmr.set(drawState);
13268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatViewMatrix(*matrix);
13278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatSamplerMatrices(stageMask, *matrix);
132827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
132927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
133027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->drawNonIndexed(primType, 0, vertCount);
133127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
13328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#if GR_STATIC_RECT_VB
133326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
13346513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
13356513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            if (NULL == sqVB) {
13366513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com                GrPrintf("Failed to create static rect vb.\n");
13376513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com                return;
13386513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            }
13396513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            target->setVertexSourceToBuffer(layout, sqVB);
13408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
13418f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState::AutoViewMatrixRestore avmr(drawState);
134227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrMatrix m;
13438295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com            m.setAll(rect.width(),    0,             rect.fLeft,
1344205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0,            rect.height(), rect.fTop,
1345205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0,            0,             GrMatrix::I()[8]);
134627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
134727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (NULL != matrix) {
134827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                m.postConcat(*matrix);
134927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
13508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatViewMatrix(m);
13518f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatSamplerMatrices(stageMask, m);
135226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
135327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
13548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#else
135526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            target->drawSimpleRect(rect, matrix, stageMask);
13568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#endif
135727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
135827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
135927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
136027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRectToRect(const GrPaint& paint,
136127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrRect& dstRect,
136227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrRect& srcRect,
136327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrMatrix* dstMatrix,
136427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrMatrix* srcMatrix) {
1365278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRectToRect");
136627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
136726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    // srcRect refers to paint's first texture
136826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    if (NULL == paint.getTexture(0)) {
136927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        drawRect(paint, dstRect, -1, dstMatrix);
137027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
137127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
1372de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com
137327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB);
137427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
137527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_STATIC_RECT_VB
137627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
13778f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = target->drawState();
137826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
13798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState::AutoViewMatrixRestore avmr(drawState);
138027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
138127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix m;
138227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
138327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    m.setAll(dstRect.width(), 0,                dstRect.fLeft,
138427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               dstRect.height(), dstRect.fTop,
138527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               0,                GrMatrix::I()[8]);
138627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != dstMatrix) {
138727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        m.postConcat(*dstMatrix);
138827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
13898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->preConcatViewMatrix(m);
139027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
139126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    // srcRect refers to first stage
139226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int otherStageMask = paint.getActiveStageMask() &
139326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                         (~(1 << GrPaint::kFirstTextureStage));
139426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    if (otherStageMask) {
13958f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->preConcatSamplerMatrices(otherStageMask, m);
139626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
139726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
139827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    m.setAll(srcRect.width(), 0,                srcRect.fLeft,
139927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               srcRect.height(), srcRect.fTop,
140027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               0,                GrMatrix::I()[8]);
140127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != srcMatrix) {
140227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        m.postConcat(*srcMatrix);
140327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
14048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->sampler(GrPaint::kFirstTextureStage)->preConcatMatrix(m);
140527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
14066513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
14076513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    if (NULL == sqVB) {
14086513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to create static rect vb.\n");
14096513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        return;
14106513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    }
14116513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    target->setVertexSourceToBuffer(layout, sqVB);
141227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
141327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
141427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
141527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target;
1416de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com#if BATCH_RECT_TO_RECT
141727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = this->prepareToDraw(paint, kBuffered_DrawCategory);
1418de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com#else
141927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
142027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
142127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
14229381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
14239381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    const GrMatrix* srcMatrices[GrDrawState::kNumStages] = {NULL};
142427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    srcRects[0] = &srcRect;
142527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    srcMatrices[0] = srcMatrix;
142627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
142727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices);
142827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
142927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
143027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
143127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawVertices(const GrPaint& paint,
143227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             GrPrimitiveType primitiveType,
143327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int vertexCount,
143427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint positions[],
143527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint texCoords[],
143627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrColor colors[],
143727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const uint16_t indices[],
143827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int indexCount) {
1439278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawVertices");
144027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
144127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo;
144227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
144327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
144427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
144526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    bool hasTexCoords[GrPaint::kTotalStages] = {
144626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        NULL != texCoords,   // texCoordSrc provides explicit stage 0 coords
144726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        0                    // remaining stages use positions
144826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    };
144926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
145026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, hasTexCoords);
145127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
145227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != colors) {
145327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        layout |= GrDrawTarget::kColor_VertexLayoutBit;
145427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
145526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int vertexSize = GrDrawTarget::VertexSize(layout);
145627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
145727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (sizeof(GrPoint) != vertexSize) {
145827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.set(target, layout, vertexCount, 0)) {
14596513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
146027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
146127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
14629381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        int texOffsets[GrDrawState::kMaxTexCoords];
146327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int colorOffset;
146426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
146526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                                                texOffsets,
1466aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com                                                &colorOffset,
1467a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                                NULL,
1468a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                                NULL);
146927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* curVertex = geo.vertices();
147027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
147127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < vertexCount; ++i) {
147227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            *((GrPoint*)curVertex) = positions[i];
147327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
147427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (texOffsets[0] > 0) {
147527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
147627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
147727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (colorOffset > 0) {
147827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
147927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
148026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            curVertex = (void*)((intptr_t)curVertex + vertexSize);
148127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
148227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
148327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->setVertexSourceToArray(layout, positions, vertexCount);
148427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
148527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1486919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // we don't currently apply offscreen AA to this path. Need improved
1487919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // management of GrDrawTarget's geometry to avoid copying points per-tile.
1488a47a48dca5045d71cbc5de343404045209a13e15bsalomon@google.com
14898295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    if (NULL != indices) {
1490919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        target->setIndexSourceToArray(indices, indexCount);
14918295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
149227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
14938295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawNonIndexed(primitiveType, 0, vertexCount);
14948295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
149527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
149627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
149706afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
149827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
149907f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.comvoid GrContext::drawPath(const GrPaint& paint, const GrPath& path,
150007f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.com                         GrPathFill fill, const GrPoint* translate) {
150127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1502fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (path.isEmpty()) {
1503fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com#if GR_DEBUG
1504fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       GrPrintf("Empty path should have been caught by canvas.\n");
1505fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com#endif
1506fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       if (GrIsFillInverted(fill)) {
1507fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com           this->drawPaint(paint);
1508fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       }
1509fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       return;
1510fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
1511fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
151227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
1513d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
1514289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool prAA = paint.fAntiAlias && !this->getRenderTarget()->isMultisampled();
1515289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
1516d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // An Assumption here is that path renderer would use some form of tweaking
1517d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // the src color (either the input alpha or in the frag shader) to implement
1518d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // aa. If we have some future driver-mojo path AA that can do the right
1519d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // thing WRT to the blend then we'll need some query on the PR.
1520d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (disable_coverage_aa_for_blend(target)) {
15211983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
1522979432ba2621b617f5e85a9ff48c6b6cd1504a0dbsalomon@google.com        //GrPrintf("Turning off AA to correctly apply blend.\n");
15231983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
1524289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        prAA = false;
1525d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    }
1526289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
1527289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool doOSAA = false;
1528289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    GrPathRenderer* pr = NULL;
1529289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    if (prAA) {
1530289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        pr = this->getPathRenderer(path, fill, true);
1531289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        if (NULL == pr) {
1532289533ada623f2238a83771eec977f204f75994fbsalomon@google.com            prAA = false;
1533289533ada623f2238a83771eec977f204f75994fbsalomon@google.com            doOSAA = this->doOffscreenAA(target, kHairLine_PathFill == fill);
1534289533ada623f2238a83771eec977f204f75994fbsalomon@google.com            pr = this->getPathRenderer(path, fill, false);
1535289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        }
1536289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    } else {
1537289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        pr = this->getPathRenderer(path, fill, false);
1538289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    }
1539289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
15403008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == pr) {
15411983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
15423008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        GrPrintf("Unable to find path renderer compatible with path.\n");
15431983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
15443008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        return;
15453008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
15463008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
1547289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    GrPathRenderer::AutoClearPath arp(pr, target, &path, fill, prAA, translate);
154839ee0ffa72fbd5df6d3ec6db4fdad0c1bc3946fdbsalomon@google.com    GrDrawState::StageMask stageMask = paint.getActiveStageMask();
154906afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
1550289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    if (doOSAA) {
15518295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        bool needsStencil = pr->requiresStencilPass(target, path, fill);
15528f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
15538295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        // compute bounds as intersection of rt size, clip, and path
15548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrIRect bound = SkIRect::MakeWH(rt->width(), rt->height());
15557ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com        GrIRect clipIBounds;
15568295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        if (target->getClip().hasConservativeBounds()) {
15578295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com            target->getClip().getConservativeBounds().roundOut(&clipIBounds);
155820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com            if (!bound.intersect(clipIBounds)) {
15598295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com                return;
15608295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com            }
15618295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        }
156207f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.com        GrRect pathBounds = path.getBounds();
156307f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.com        if (!pathBounds.isEmpty()) {
15647ca72f33556e9d6c827b8c9493eb9531da5e347bbsalomon@google.com            if (NULL != translate) {
15657ca72f33556e9d6c827b8c9493eb9531da5e347bbsalomon@google.com                pathBounds.offset(*translate);
15667ca72f33556e9d6c827b8c9493eb9531da5e347bbsalomon@google.com            }
15678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            target->getDrawState().getViewMatrix().mapRect(&pathBounds,
15688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                                                           pathBounds);
1569919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com            GrIRect pathIBounds;
15708295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com            pathBounds.roundOut(&pathIBounds);
157120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com            if (!bound.intersect(pathIBounds)) {
15728295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com                return;
15738295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com            }
15748295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        }
1575919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        OffscreenRecord record;
1576d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com        if (this->prepareForOffscreenAA(target, needsStencil, bound,
1577d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com                                        pr, &record)) {
1578919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com            for (int tx = 0; tx < record.fTileCountX; ++tx) {
1579919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com                for (int ty = 0; ty < record.fTileCountY; ++ty) {
1580919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com                    this->setupOffscreenAAPass1(target, bound, tx, ty, &record);
1581ee435122d7dcb9cd4be4524004b0de282c42848bbsalomon@google.com                    pr->drawPath(0);
1582919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com                    this->doOffscreenAAPass2(target, paint, bound, tx, ty, &record);
1583919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com                }
1584919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com            }
1585d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com            this->cleanupOffscreenAA(target, pr, &record);
1586fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            if (GrIsFillInverted(fill) && bound != clipIBounds) {
15877ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
15887ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                GrRect rect;
15897ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                if (clipIBounds.fTop < bound.fTop) {
15909d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com                    rect.iset(clipIBounds.fLeft, clipIBounds.fTop,
15919d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com                              clipIBounds.fRight, bound.fTop);
15927ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                    target->drawSimpleRect(rect, NULL, stageMask);
15937ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                }
15947ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                if (clipIBounds.fLeft < bound.fLeft) {
15959d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com                    rect.iset(clipIBounds.fLeft, bound.fTop,
15969d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com                              bound.fLeft, bound.fBottom);
15977ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                    target->drawSimpleRect(rect, NULL, stageMask);
15987ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                }
15997ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                if (clipIBounds.fRight > bound.fRight) {
16009d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com                    rect.iset(bound.fRight, bound.fTop,
16019d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com                              clipIBounds.fRight, bound.fBottom);
16027ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                    target->drawSimpleRect(rect, NULL, stageMask);
16037ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                }
16047ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                if (clipIBounds.fBottom > bound.fBottom) {
16059d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com                    rect.iset(clipIBounds.fLeft, bound.fBottom,
16069d12f5c11b56ef51ba2c95db721ae7e5bab27023bsalomon@google.com                              clipIBounds.fRight, clipIBounds.fBottom);
16077ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                    target->drawSimpleRect(rect, NULL, stageMask);
16087ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com                }
16097ac249bdc7a86bc44610e02abeeaa0c14ba8163absalomon@google.com            }
16108295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com            return;
16118295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        }
1612ee435122d7dcb9cd4be4524004b0de282c42848bbsalomon@google.com    }
1613ee435122d7dcb9cd4be4524004b0de282c42848bbsalomon@google.com    pr->drawPath(stageMask);
161427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
16158295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
161627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
161727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
16181f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.combool GrContext::supportsShaders() const {
161918c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    return fGpu->getCaps().fShaderSupport;
16201f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com}
16211f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com
1622a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.comvoid GrContext::flush(int flagsBitfield) {
1623a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kDiscard_FlushBit & flagsBitfield) {
1624a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com        fDrawBuffer->reset();
1625a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    } else {
1626c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        this->flushDrawBuffer();
1627a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    }
1628a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) {
162927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fGpu->forceRenderTargetFlush();
163027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
163127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
163227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
163327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::flushText() {
163427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (kText_DrawCategory == fLastDrawCategory) {
163527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        flushDrawBuffer();
163627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
163727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
163827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
163927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::flushDrawBuffer() {
164027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING
164153a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    if (fDrawBuffer) {
164253a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com        fDrawBuffer->playback(fGpu);
164353a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com        fDrawBuffer->reset();
164453a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    }
164527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
164627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
164727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
16486f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.comvoid GrContext::internalWriteTexturePixels(GrTexture* texture,
16496f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           int left, int top,
16506f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           int width, int height,
16516f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           GrPixelConfig config,
16526f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           const void* buffer,
16536f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           size_t rowBytes,
16546f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           uint32_t flags) {
16556f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeTexturePixels");
1656bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1657bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
16586f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
16596f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        this->flush();
16606f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
16616f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    // TODO: use scratch texture to perform conversion
16626f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (GrPixelConfigIsUnpremultiplied(texture->config()) !=
16636f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config)) {
16646f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        return;
16656f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
16666f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
16676f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    fGpu->writeTexturePixels(texture, left, top, width, height,
16686f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                             config, buffer, rowBytes);
16696f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com}
16706f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
16716f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.combool GrContext::internalReadTexturePixels(GrTexture* texture,
16726f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          int left, int top,
16736f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          int width, int height,
16746f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          GrPixelConfig config,
16756f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          void* buffer,
16766f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          size_t rowBytes,
16776f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          uint32_t flags) {
1678278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readTexturePixels");
1679bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1680669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1681a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // TODO: code read pixels for textures that aren't also rendertargets
1682669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    GrRenderTarget* target = texture->asRenderTarget();
1683669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    if (NULL != target) {
16846f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        return this->internalReadRenderTargetPixels(target,
16856f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    left, top, width, height,
16866f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    config, buffer, rowBytes,
16876f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    flags);
1688669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    } else {
1689669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com        return false;
1690669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    }
1691669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com}
1692669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
16936f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.combool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target,
16946f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               int left, int top,
16956f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               int width, int height,
16966f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               GrPixelConfig config,
16976f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               void* buffer,
16986f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               size_t rowBytes,
16996f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               uint32_t flags) {
1700278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
1701bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
1702bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
1703669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    if (NULL == target) {
17048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        target = fGpu->drawState()->getRenderTarget();
1705c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (NULL == target) {
1706c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            return false;
1707c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1708c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1709c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1710c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    // PM <-> UPM conversion requires a draw. Currently we only support drawing
1711c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    // into a UPM target, not reading from a UPM texture. Thus, UPM->PM is not
1712c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    // not supported at this time.
1713c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    if (GrPixelConfigIsUnpremultiplied(target->config()) &&
1714c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        !GrPixelConfigIsUnpremultiplied(config)) {
1715c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        return false;
1716669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    }
1717669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
17186f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
17196f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        this->flush();
17206f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
1721c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1722c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    GrTexture* src = target->asTexture();
17230a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    bool swapRAndB = NULL != src &&
17240a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                     fGpu->preferredReadPixelsConfig(config) ==
17250a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                     GrPixelConfigSwapRAndB(config);
1726c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1727c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    bool flipY = NULL != src &&
1728c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                 fGpu->readPixelsWillPayForYFlip(target, left, top,
1729c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 width, height, config,
1730c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 rowBytes);
17310a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    bool alphaConversion = (!GrPixelConfigIsUnpremultiplied(target->config()) &&
17320a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                             GrPixelConfigIsUnpremultiplied(config));
1733c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
17340a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    if (NULL == src && alphaConversion) {
17350a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // we should fallback to cpu conversion here. This could happen when
17360a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // we were given an external render target by the client that is not
17370a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // also a texture (e.g. FBO 0 in GL)
17380a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        return false;
17390a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    }
17400a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    // we draw to a scratch texture if any of these conversion are applied
1741c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com    GrAutoScratchTexture ast;
17420a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    if (flipY || swapRAndB || alphaConversion) {
17430a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        GrAssert(NULL != src);
17440a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        if (swapRAndB) {
17450a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com            config = GrPixelConfigSwapRAndB(config);
17460a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com            GrAssert(kUnknown_GrPixelConfig != config);
1747c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1748c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        // Make the scratch a render target because we don't have a robust
1749c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        // readTexturePixels as of yet (it calls this function).
1750c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        const GrTextureDesc desc = {
1751c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            kRenderTarget_GrTextureFlagBit,
1752c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            kNone_GrAALevel,
1753c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            width, height,
17545bc34f04fe70cdde702ac3bff1fea0ccb275d4a5bsalomon@google.com            config
1755c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        };
1756c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com
175756d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // When a full readback is faster than a partial we could always make
175856d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // the scratch exactly match the passed rect. However, if we see many
175956d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // different size rectangles we will trash our texture cache and pay the
176056d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // cost of creating and destroying many textures. So, we only request
176156d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // an exact match when the caller is reading an entire RT.
176256d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ScratchTexMatch match = kApprox_ScratchTexMatch;
176356d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        if (0 == left &&
176456d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            0 == top &&
176556d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->width() == width &&
176656d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->height() == height &&
176756d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            fGpu->fullReadPixelsIsFasterThanPartial()) {
176856d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            match = kExact_ScratchTexMatch;
176956d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        }
177056d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ast.set(this, desc, match);
1771c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrTexture* texture = ast.texture();
1772c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (!texture) {
1773c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            return false;
1774c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1775c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        target = texture->asRenderTarget();
1776c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrAssert(NULL != target);
1777c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1778c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrDrawTarget::AutoStateRestore asr(fGpu);
17798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState* drawState = fGpu->drawState();
17806b67e21b6549598254c1ffa4243bf32615d90fb6bsalomon@google.com        reset_draw_state(drawState);
17818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setRenderTarget(target);
1782c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1783c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrMatrix matrix;
1784c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (flipY) {
1785c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.setTranslate(SK_Scalar1 * left,
1786c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                SK_Scalar1 * (top + height));
1787c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.set(GrMatrix::kMScaleY, -GR_Scalar1);
1788c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        } else {
1789c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
1790c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1791c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        matrix.postIDiv(src->width(), src->height());
17921e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com        drawState->sampler(0)->reset(matrix);
17931e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com        drawState->sampler(0)->setRAndBSwap(swapRAndB);
17948f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setTexture(0, src);
1795c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrRect rect;
1796c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        rect.setXYWH(0, 0, SK_Scalar1 * width, SK_Scalar1 * height);
1797c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        fGpu->drawSimpleRect(rect, NULL, 0x1);
1798c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        left = 0;
1799c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        top = 0;
1800c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1801669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    return fGpu->readPixels(target,
1802c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                            left, top, width, height,
1803c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                            config, buffer, rowBytes, flipY);
180427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
180527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1806ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.orgvoid GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst) {
1807ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    if (NULL == src || NULL == dst) {
1808ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        return;
1809ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
1810ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(src);
1811ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
1812ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    GrDrawTarget::AutoStateRestore asr(fGpu);
18138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
18146b67e21b6549598254c1ffa4243bf32615d90fb6bsalomon@google.com    reset_draw_state(drawState);
18158f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(dst);
1816ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    GrMatrix sampleM;
1817ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    sampleM.setIDiv(src->width(), src->height());
18188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setTexture(0, src);
18191e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->reset(sampleM);
1820ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    SkRect rect = SkRect::MakeXYWH(0, 0, src->width(), src->height());
1821ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    fGpu->drawSimpleRect(rect, NULL, 1 << 0);
1822ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org}
1823ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
18246f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.comvoid GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target,
18256f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                int left, int top,
18266f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                int width, int height,
18276f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                GrPixelConfig config,
18286f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                const void* buffer,
18296f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                size_t rowBytes,
18306f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                uint32_t flags) {
18316f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
1832bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
18336f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
18346f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (NULL == target) {
18358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        target = fGpu->drawState()->getRenderTarget();
18366f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        if (NULL == target) {
18376f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com            return;
18386f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        }
18396f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
184027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
184127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // TODO: when underlying api has a direct way to do this we should use it
184227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // (e.g. glDrawPixels on desktop GL).
184327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1844a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // If the RT is also a texture and we don't have to do PM/UPM conversion
1845a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // then take the texture path, which we expect to be at least as fast or
1846a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // faster since it doesn't use an intermediate texture as we do below.
1847a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1848a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#if !GR_MAC_BUILD
1849a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // At least some drivers on the Mac get confused when glTexImage2D is called
1850a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // on a texture attached to an FBO. The FBO still sees the old image. TODO:
1851a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // determine what OS versions and/or HW is affected.
1852a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    if (NULL != target->asTexture() &&
1853a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        GrPixelConfigIsUnpremultiplied(target->config()) ==
1854a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config)) {
1855a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1856a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        this->internalWriteTexturePixels(target->asTexture(),
1857a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                                         left, top, width, height,
1858a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                                         config, buffer, rowBytes, flags);
1859a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        return;
1860a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1861a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#endif
1862a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1863a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    bool swapRAndB = fGpu->preferredReadPixelsConfig(config) ==
1864a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                     GrPixelConfigSwapRAndB(config);
1865a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    if (swapRAndB) {
1866a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        config = GrPixelConfigSwapRAndB(config);
1867a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1868a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1869fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    const GrTextureDesc desc = {
18705bc34f04fe70cdde702ac3bff1fea0ccb275d4a5bsalomon@google.com        kNone_GrTextureFlags, kNone_GrAALevel, width, height, config
187127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    };
187250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrAutoScratchTexture ast(this, desc);
187350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrTexture* texture = ast.texture();
187427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL == texture) {
187527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
187627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
18776f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    this->internalWriteTexturePixels(texture, 0, 0, width, height,
18786f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                     config, buffer, rowBytes, flags);
187927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
188027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoStateRestore  asr(fGpu);
18818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
18826b67e21b6549598254c1ffa4243bf32615d90fb6bsalomon@google.com    reset_draw_state(drawState);
188327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
188427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix matrix;
188527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
18868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setViewMatrix(matrix);
18878f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(target);
18888f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setTexture(0, texture);
188927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
18905c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com    matrix.setIDiv(texture->width(), texture->height());
18911e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
18921e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                 GrSamplerState::kNearest_Filter,
18931e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                 matrix);
18941e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->setRAndBSwap(swapRAndB);
189527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
189627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
189727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    static const int VCOUNT = 4;
18986513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    // TODO: Use GrGpu::drawRect here
189927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
190027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (!geo.succeeded()) {
19016513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
190227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
190327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
190427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
190527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT);
190627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
190727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
190827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1909bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.comvoid GrContext::setPaint(const GrPaint& paint, GrDrawTarget* target) {
19108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = target->drawState();
191126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
191226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kMaxTextures; ++i) {
191326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        int s = i + GrPaint::kFirstTextureStage;
19148f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setTexture(s, paint.getTexture(i));
1915bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com        ASSERT_OWNED_RESOURCE(paint.getTexture(i));
1916f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        if (paint.getTexture(i)) {
1917f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com            *drawState->sampler(s) = paint.getTextureSampler(i);
1918f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        }
191926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
192026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
19218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setFirstCoverageStage(GrPaint::kFirstMaskStage);
192226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
192326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kMaxMasks; ++i) {
192426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        int s = i + GrPaint::kFirstMaskStage;
19258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setTexture(s, paint.getMask(i));
1926bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com        ASSERT_OWNED_RESOURCE(paint.getMask(i));
1927f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        if (paint.getMask(i)) {
1928f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com            *drawState->sampler(s) = paint.getMaskSampler(i);
1929f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        }
193026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
193126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
19328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setColor(paint.fColor);
193327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
193427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (paint.fDither) {
19358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->enableState(GrDrawState::kDither_StateBit);
193627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
19378f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->disableState(GrDrawState::kDither_StateBit);
193827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
193927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (paint.fAntiAlias) {
19408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->enableState(GrDrawState::kHWAntialias_StateBit);
194127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
19428f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->disableState(GrDrawState::kHWAntialias_StateBit);
194327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
19446b67e21b6549598254c1ffa4243bf32615d90fb6bsalomon@google.com    drawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
19458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
1946d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
1947d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (paint.getActiveMaskStageMask() && !target->canApplyCoverage()) {
1948d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com        GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
1949d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    }
195027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
195127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1952de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.comGrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
195327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                       DrawCategory category) {
195427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (category != fLastDrawCategory) {
195527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        flushDrawBuffer();
195627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fLastDrawCategory = category;
195727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
1958bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    this->setPaint(paint, fGpu);
195927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = fGpu;
196027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    switch (category) {
196127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    case kText_DrawCategory:
196227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if DEFER_TEXT_RENDERING
196327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target = fDrawBuffer;
196427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fDrawBuffer->initializeDrawStateAndClip(*fGpu);
196527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
196627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target = fGpu;
196727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
196827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        break;
196927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    case kUnbuffered_DrawCategory:
197027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target = fGpu;
197127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        break;
197227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    case kBuffered_DrawCategory:
197327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target = fDrawBuffer;
197427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fDrawBuffer->initializeDrawStateAndClip(*fGpu);
197527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        break;
197627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
197727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return target;
197827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
197927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1980289533ada623f2238a83771eec977f204f75994fbsalomon@google.comGrPathRenderer* GrContext::getPathRenderer(const GrPath& path,
1981289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           GrPathFill fill,
1982289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           bool antiAlias) {
19833008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == fPathRendererChain) {
19843008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        fPathRendererChain =
19853008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com            new GrPathRendererChain(this, GrPathRendererChain::kNone_UsageFlag);
19863008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
1987289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    return fPathRendererChain->getPathRenderer(fGpu->getCaps(), path,
1988289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                               fill, antiAlias);
19893008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com}
19903008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
199127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
199227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
199327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setRenderTarget(GrRenderTarget* target) {
1994bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
19958fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush(false);
19968f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    fGpu->drawState()->setRenderTarget(target);
199727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
199827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
199927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrRenderTarget* GrContext::getRenderTarget() {
20008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    return fGpu->drawState()->getRenderTarget();
200127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
200227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
200327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrRenderTarget* GrContext::getRenderTarget() const {
20048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    return fGpu->getDrawState().getRenderTarget();
200527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
200627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
200727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrMatrix& GrContext::getMatrix() const {
20088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    return fGpu->getDrawState().getViewMatrix();
200927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
201027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
201127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setMatrix(const GrMatrix& m) {
20128f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    fGpu->drawState()->setViewMatrix(m);
201327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
201427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
201527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::concatMatrix(const GrMatrix& m) const {
20168f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    fGpu->drawState()->preConcatViewMatrix(m);
201727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
201827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
201927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
202027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    intptr_t mask = 1 << shift;
202127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (pred) {
202227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        bits |= mask;
202327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
202427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        bits &= ~mask;
202527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
202627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return bits;
202727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
202827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
202927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::resetStats() {
203027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->resetStats();
203127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
203227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
203305ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.comconst GrGpuStats& GrContext::getStats() const {
203427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return fGpu->getStats();
203527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
203627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
203727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::printStats() const {
203827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->printStats();
203927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
204027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
2041583a1e38503ebd57ba9bd39a3fabe89bead8e76cbsalomon@google.comGrContext::GrContext(GrGpu* gpu) {
204227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu = gpu;
204327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->ref();
2044669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    fGpu->setContext(this);
20458fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
20463008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    fPathRendererChain = NULL;
2047dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com
204850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    fTextureCache = new GrResourceCache(MAX_TEXTURE_CACHE_COUNT,
204950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                        MAX_TEXTURE_CACHE_BYTES);
205027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fFontCache = new GrFontCache(fGpu);
205127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
205227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fLastDrawCategory = kUnbuffered_DrawCategory;
205327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
20548fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
20558fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
20568fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
20578fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
2058205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fAAFillRectIndexBuffer = NULL;
2059205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fAAStrokeRectIndexBuffer = NULL;
2060919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
206118c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    int gpuMaxOffscreen = gpu->getCaps().fMaxRenderTargetSize;
206218c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    if (!PREFER_MSAA_OFFSCREEN_AA || !gpu->getCaps().fFSAASupport) {
2063919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        gpuMaxOffscreen /= OFFSCREEN_SSAA_SCALE;
2064919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    }
2065919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    fMaxOffscreenAASize = GrMin(GR_MAX_OFFSCREEN_AA_SIZE, gpuMaxOffscreen);
2066205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
20678fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->setupDrawBuffer();
20688fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
20698fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
20708fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::setupDrawBuffer() {
20718fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
20728fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBuffer);
20738fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBufferVBAllocPool);
20748fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBufferIBAllocPool);
20758fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
207627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT
2077de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferVBAllocPool =
20788fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com        new GrVertexBufferAllocPool(fGpu, false,
207927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                    DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
208027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                    DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS);
2081de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferIBAllocPool =
20828fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com        new GrIndexBufferAllocPool(fGpu, false,
2083de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com                                   DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
208427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                   DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS);
208527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
2086471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com    fDrawBuffer = new GrInOrderDrawBuffer(fGpu,
2087471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com                                          fDrawBufferVBAllocPool,
208827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                          fDrawBufferIBAllocPool);
208927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
209027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
209127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if BATCH_RECT_TO_RECT
209227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
209327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
209427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
209527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
209627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
209727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target;
209827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if DEFER_TEXT_RENDERING
209927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = prepareToDraw(paint, kText_DrawCategory);
210027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
210127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = prepareToDraw(paint, kUnbuffered_DrawCategory);
210227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
2103bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    this->setPaint(paint, target);
210427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return target;
210527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
210627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
210727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
210827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return fGpu->getQuadIndexBuffer();
210927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
2110dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com
2111aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.orgvoid GrContext::convolveInX(GrTexture* texture,
2112aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org                            const SkRect& rect,
2113aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org                            const float* kernel,
2114aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org                            int kernelWidth) {
2115bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
2116bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
21179962108c400dadcae913614e8a5ab781780981d8bsalomon@google.com    float imageIncrement[2] = {1.0f / texture->width(), 0.0f};
2118aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org    convolve(texture, rect, imageIncrement, kernel, kernelWidth);
2119aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org}
2120aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org
2121aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.orgvoid GrContext::convolveInY(GrTexture* texture,
2122aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org                            const SkRect& rect,
2123aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org                            const float* kernel,
2124aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org                            int kernelWidth) {
2125bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
2126bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
21279962108c400dadcae913614e8a5ab781780981d8bsalomon@google.com    float imageIncrement[2] = {0.0f, 1.0f / texture->height()};
2128aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org    convolve(texture, rect, imageIncrement, kernel, kernelWidth);
2129aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org}
2130aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org
2131aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.orgvoid GrContext::convolve(GrTexture* texture,
2132aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org                         const SkRect& rect,
2133aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org                         float imageIncrement[2],
2134aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org                         const float* kernel,
2135aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org                         int kernelWidth) {
2136bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
2137bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
2138027de5f922e8ad1acc5402829f716b8c513fdd8dsenorblanco@chromium.org    GrDrawTarget::AutoStateRestore asr(fGpu);
21391e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
2140027de5f922e8ad1acc5402829f716b8c513fdd8dsenorblanco@chromium.org    GrMatrix sampleM;
214160014ca38710d3fc265f4376b05c0fefd0e044cfsenorblanco@chromium.org    sampleM.setIDiv(texture->width(), texture->height());
21421e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
21431e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                 GrSamplerState::kConvolution_Filter,
21441e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                 sampleM);
21451e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->setConvolutionParams(kernelWidth,
21461e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                                kernel,
21471e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                                imageIncrement);
21481e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com
21498f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setViewMatrix(GrMatrix::I());
21508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setTexture(0, texture);
21518f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setAlpha(0xFF);
21526b67e21b6549598254c1ffa4243bf32615d90fb6bsalomon@google.com    drawState->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);
2153027de5f922e8ad1acc5402829f716b8c513fdd8dsenorblanco@chromium.org    fGpu->drawSimpleRect(rect, NULL, 1 << 0);
2154027de5f922e8ad1acc5402829f716b8c513fdd8dsenorblanco@chromium.org}
2155c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
2156c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
2157