GrContext.cpp revision 95cd7bdf2b4dee54739f0a375fe99a02f86178b0
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
2527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#define DEFER_TEXT_RENDERING 1
2627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
27fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com#define DEFER_PATHS 1
28fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com
2927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)
3027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
313b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org#define MAX_BLUR_SIGMA 4.0f
323b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
33fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com
34d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// When we're using coverage AA but the blend is incompatible (given gpu
35d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// limitations) should we disable AA or draw wrong?
36950d7a8d8def14efc98d12d6947347fde351b737bsalomon@google.com#define DISABLE_COVERAGE_AA_FOR_BLEND 1
37d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
388ccadddfa78adbdbbdfa724247318436465a7378bsalomon@google.comstatic const size_t MAX_TEXTURE_CACHE_COUNT = 256;
398ccadddfa78adbdbbdfa724247318436465a7378bsalomon@google.comstatic const size_t MAX_TEXTURE_CACHE_BYTES = 16 * 1024 * 1024;
4027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
4160361493548d5259d0a8afae84274c2a3c31dcacbsalomon@google.comstatic const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 15;
4227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
4327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
44fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com// path rendering is the only thing we defer today that uses non-static indices
45fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.comstatic const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = DEFER_PATHS ? 1 << 11 : 0;
46fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.comstatic const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = DEFER_PATHS ? 4 : 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);
73a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    fDrawState->unref();
7427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
7527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
768fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::contextLost() {
7753a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    contextDestroyed();
7853a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    this->setupDrawBuffer();
7953a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com}
8053a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com
8153a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.comvoid GrContext::contextDestroyed() {
82205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // abandon first to so destructors
83205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // don't try to free the resources in the API.
84205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->abandonResources();
85205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
863008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources that
873008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // are now unusable
883008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeSetNull(fPathRendererChain);
893008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
908fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBuffer;
918fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
92205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
938fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferVBAllocPool;
948fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
95205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
968fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferIBAllocPool;
978fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
988fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
99205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrSafeSetNull(fAAFillRectIndexBuffer);
100205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrSafeSetNull(fAAStrokeRectIndexBuffer);
101205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1028fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fTextureCache->removeAll();
1038fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
1048fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
1058fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
1068fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1078fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::resetContext() {
1088fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
1098fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
1108fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1118fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::freeGpuResources() {
1128fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
1138fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fTextureCache->removeAll();
1148fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
1153008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources
1163008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeSetNull(fPathRendererChain);
11727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
11827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
11905e70247c31ae927074ef27ea9893634a8dda543twiz@google.comsize_t GrContext::getGpuTextureCacheBytes() const {
12005e70247c31ae927074ef27ea9893634a8dda543twiz@google.com  return fTextureCache->getCachedResourceBytes();
12105e70247c31ae927074ef27ea9893634a8dda543twiz@google.com}
12205e70247c31ae927074ef27ea9893634a8dda543twiz@google.com
123fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
124fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
12526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.comint GrContext::PaintStageVertexLayoutBits(
12626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                            const GrPaint& paint,
12726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                            const bool hasTexCoords[GrPaint::kTotalStages]) {
12826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int stageMask = paint.getActiveStageMask();
12926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int layout = 0;
13026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kTotalStages; ++i) {
13126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        if ((1 << i) & stageMask) {
13226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            if (NULL != hasTexCoords && hasTexCoords[i]) {
13326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(i, i);
13426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            } else {
13526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(i);
13626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            }
13726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        }
13826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
13926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    return layout;
14026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com}
14126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
14226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
14326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
14426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
145fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.comenum {
146558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    // flags for textures
147558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kNPOTBit            = 0x1,
148558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kFilterBit          = 0x2,
149558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kScratchBit         = 0x4,
150558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
151558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    // resource type
152558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kTextureBit         = 0x8,
153558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kStencilBufferBit   = 0x10
154fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com};
155fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
15650398bf7f1953e640e5529616e710cf540799731bsalomon@google.comGrTexture* GrContext::TextureCacheEntry::texture() const {
15750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (NULL == fEntry) {
15850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        return NULL;
15950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    } else {
16050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        return (GrTexture*) fEntry->resource();
16150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    }
16250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com}
16350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
16450398bf7f1953e640e5529616e710cf540799731bsalomon@google.comnamespace {
16550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com// returns true if this is a "special" texture because of gpu NPOT limitations
16650398bf7f1953e640e5529616e710cf540799731bsalomon@google.combool gen_texture_key_values(const GrGpu* gpu,
1671fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                            const GrSamplerState* sampler,
16850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            GrContext::TextureKey clientKey,
16950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            int width,
17050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            int height,
17178d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com                            int sampleCnt,
17250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            bool scratch,
17350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            uint32_t v[4]) {
17450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GR_STATIC_ASSERT(sizeof(GrContext::TextureKey) == sizeof(uint64_t));
17550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // we assume we only need 16 bits of width and height
17650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // assert that texture creation will fail anyway if this assumption
17750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // would cause key collisions.
17818c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    GrAssert(gpu->getCaps().fMaxTextureSize <= SK_MaxU16);
17950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    v[0] = clientKey & 0xffffffffUL;
18050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    v[1] = (clientKey >> 32) & 0xffffffffUL;
18150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    v[2] = width | (height << 16);
18250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
18378d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com    v[3] = (sampleCnt << 24);
18478d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com    GrAssert(sampleCnt >= 0 && sampleCnt < 256);
18578d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com
18618c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    if (!gpu->getCaps().fNPOTTextureTileSupport) {
187fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
188fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
1891fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        bool tiled = NULL != sampler &&
1901fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                     ((sampler->getWrapX() != GrSamplerState::kClamp_WrapMode) ||
1911fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                      (sampler->getWrapY() != GrSamplerState::kClamp_WrapMode));
192fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
193fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        if (tiled && !isPow2) {
19450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            v[3] |= kNPOTBit;
1951fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com            if (GrSamplerState::kNearest_Filter != sampler->getFilter()) {
19650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                v[3] |= kFilterBit;
197fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com            }
198fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        }
199fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
200fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
20150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (scratch) {
20250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        v[3] |= kScratchBit;
203fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
20450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
205558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[3] |= kTextureBit;
206558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
20750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    return v[3] & kNPOTBit;
20850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com}
209558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
210558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com// we should never have more than one stencil buffer with same combo of
211558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com// (width,height,samplecount)
212558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid gen_stencil_key_values(int width, int height,
213558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                            int sampleCnt, uint32_t v[4]) {
214558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[0] = width;
215558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[1] = height;
216558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[2] = sampleCnt;
217558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[3] = kStencilBufferBit;
218558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
219558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
220558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid gen_stencil_key_values(const GrStencilBuffer* sb,
221558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                            uint32_t v[4]) {
222558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(sb->width(), sb->height(),
223558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                           sb->numSamples(), v);
224558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
22582c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com
2263b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgvoid build_kernel(float sigma, float* kernel, int kernelWidth) {
2273b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    int halfWidth = (kernelWidth - 1) / 2;
2283b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    float sum = 0.0f;
2293b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    float denom = 1.0f / (2.0f * sigma * sigma);
2303b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    for (int i = 0; i < kernelWidth; ++i) {
2313b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        float x = static_cast<float>(i - halfWidth);
2323b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian
2333b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // is dropped here, since we renormalize the kernel below.
2343b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        kernel[i] = sk_float_exp(- x * x * denom);
2353b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        sum += kernel[i];
2363b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
2373b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    // Normalize the kernel
2383b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    float scale = 1.0f / sum;
2393b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    for (int i = 0; i < kernelWidth; ++i)
2403b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        kernel[i] *= scale;
2413b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
2423b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
2433b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgvoid scale_rect(SkRect* rect, float xScale, float yScale) {
2443b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    rect->fLeft *= xScale;
2453b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    rect->fTop *= yScale;
2463b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    rect->fRight *= xScale;
2473b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    rect->fBottom *= yScale;
2483b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
2493b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
2503b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgfloat adjust_sigma(float sigma, int *scaleFactor, int *halfWidth,
2513b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                          int *kernelWidth) {
2523b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    *scaleFactor = 1;
2533b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    while (sigma > MAX_BLUR_SIGMA) {
2543b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        *scaleFactor *= 2;
2553b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        sigma *= 0.5f;
2563b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
2573b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    *halfWidth = static_cast<int>(ceilf(sigma * 3.0f));
2583b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    *kernelWidth = *halfWidth * 2 + 1;
2593b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    return sigma;
2603b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
2613b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
2623b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgvoid apply_morphology(GrGpu* gpu,
2633b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                      GrTexture* texture,
2643b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                      const SkRect& rect,
2653b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                      int radius,
2663b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                      GrSamplerState::Filter filter,
2673b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                      GrSamplerState::FilterDirection direction) {
2683b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrAssert(filter == GrSamplerState::kErode_Filter ||
2693b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org             filter == GrSamplerState::kDilate_Filter);
2703b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
2713b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrDrawTarget::AutoStateRestore asr(gpu);
2723b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrDrawState* drawState = gpu->drawState();
2733b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrRenderTarget* target = drawState->getRenderTarget();
2743b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->reset();
2753b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->setRenderTarget(target);
2763b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrMatrix sampleM;
2773b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    sampleM.setIDiv(texture->width(), texture->height());
2783b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode, filter,
2793b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                 sampleM);
2803b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->sampler(0)->setMorphologyRadius(radius);
2813b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->sampler(0)->setFilterDirection(direction);
2823b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->setTexture(0, texture);
2833b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    gpu->drawSimpleRect(rect, NULL, 1 << 0);
2843b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
2853b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
2863b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgvoid convolve(GrGpu* gpu,
2873b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org              GrTexture* texture,
2883b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org              const SkRect& rect,
2893b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org              const float* kernel,
2903b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org              int kernelWidth,
2913b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org              GrSamplerState::FilterDirection direction) {
2923b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrDrawTarget::AutoStateRestore asr(gpu);
2933b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrDrawState* drawState = gpu->drawState();
2943b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrRenderTarget* target = drawState->getRenderTarget();
2953b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->reset();
2963b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->setRenderTarget(target);
2973b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrMatrix sampleM;
2983b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    sampleM.setIDiv(texture->width(), texture->height());
2993b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
3003b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                 GrSamplerState::kConvolution_Filter,
3013b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                 sampleM);
3023b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->sampler(0)->setConvolutionParams(kernelWidth, kernel);
3033b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->sampler(0)->setFilterDirection(direction);
3043b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->setTexture(0, texture);
3053b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    gpu->drawSimpleRect(rect, NULL, 1 << 0);
3063b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
3073b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
308fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com}
309fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
3101fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.comGrContext::TextureCacheEntry GrContext::findAndLockTexture(
3111fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        TextureKey key,
3121fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        int width,
3131fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        int height,
3141fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrSamplerState* sampler) {
31550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    uint32_t v[4];
31678d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com    gen_texture_key_values(fGpu, sampler, key, width, height, 0, false, v);
31750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrResourceKey resourceKey(v);
318558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    return TextureCacheEntry(fTextureCache->findAndLock(resourceKey,
319558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                            GrResourceCache::kNested_LockType));
320558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
321558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
322fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.combool GrContext::isTextureInCache(TextureKey key,
323fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com                                 int width,
324fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com                                 int height,
3251fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                 const GrSamplerState* sampler) const {
326fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    uint32_t v[4];
32778d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com    gen_texture_key_values(fGpu, sampler, key, width, height, 0, false, v);
328fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    GrResourceKey resourceKey(v);
329fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    return fTextureCache->hasKey(resourceKey);
330fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com}
331fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com
332558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comGrResourceEntry* GrContext::addAndLockStencilBuffer(GrStencilBuffer* sb) {
333bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(sb);
334558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    uint32_t v[4];
335558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(sb, v);
336558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceKey resourceKey(v);
337558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    return fTextureCache->createAndLock(resourceKey, sb);
338558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
339558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
340558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comGrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
341558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                              int sampleCnt) {
342558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    uint32_t v[4];
343558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(width, height, sampleCnt, v);
344558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceKey resourceKey(v);
345558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceEntry* entry = fTextureCache->findAndLock(resourceKey,
346558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                            GrResourceCache::kSingle_LockType);
347558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    if (NULL != entry) {
348558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        GrStencilBuffer* sb = (GrStencilBuffer*) entry->resource();
349558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        return sb;
350558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    } else {
351558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        return NULL;
352558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    }
353558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
354558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
355558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid GrContext::unlockStencilBuffer(GrResourceEntry* sbEntry) {
356bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(sbEntry->resource());
357558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    fTextureCache->unlock(sbEntry);
35827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
35927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
36027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic void stretchImage(void* dst,
36127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstW,
36227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstH,
36327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         void* src,
36427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcW,
36527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcH,
36627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int bpp) {
36727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dx = (srcW << 16) / dstW;
36827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dy = (srcH << 16) / dstH;
36927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
37027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed y = dy >> 1;
37127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
37227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    int dstXLimit = dstW*bpp;
37327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    for (int j = 0; j < dstH; ++j) {
37427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrFixed x = dx >> 1;
37527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
37627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* dstRow = (uint8_t*)dst + j*dstW*bpp;
37727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < dstXLimit; i += bpp) {
37827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            memcpy((uint8_t*) dstRow + i,
37927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   (uint8_t*) srcRow + (x>>16)*bpp,
38027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   bpp);
38127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            x += dx;
38227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
38327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        y += dy;
38427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
38527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
38627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
3871fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.comGrContext::TextureCacheEntry GrContext::createAndLockTexture(
3881fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        TextureKey key,
3891fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrSamplerState* sampler,
3901fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrTextureDesc& desc,
3911fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        void* srcData,
3921fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        size_t rowBytes) {
393278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::createAndLockTexture");
39427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
39527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_DUMP_TEXTURE_UPLOAD
39627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
39727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
39827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
39950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    TextureCacheEntry entry;
40050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    uint32_t v[4];
40150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    bool special = gen_texture_key_values(fGpu, sampler, key,
40278d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com                                          desc.fWidth, desc.fHeight,
40378d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com                                          desc.fSampleCnt, false, v);
40450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrResourceKey resourceKey(v);
40550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
40627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (special) {
4071fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        GrAssert(NULL != sampler);
4081fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        TextureCacheEntry clampEntry = this->findAndLockTexture(key,
4091fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                                desc.fWidth,
4101fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                                desc.fHeight,
4111fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                                NULL);
41227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
41350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        if (NULL == clampEntry.texture()) {
4141fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com            clampEntry = this->createAndLockTexture(key, NULL, desc,
4151fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                    srcData, rowBytes);
41650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            GrAssert(NULL != clampEntry.texture());
41750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            if (NULL == clampEntry.texture()) {
41850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                return entry;
41927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
42027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
421fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        GrTextureDesc rtDesc = desc;
422fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        rtDesc.fFlags =  rtDesc.fFlags |
423fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com                         kRenderTarget_GrTextureFlagBit |
424fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com                         kNoStencil_GrTextureFlagBit;
4259962108c400dadcae913614e8a5ab781780981d8bsalomon@google.com        rtDesc.fWidth  = GrNextPow2(GrMax(desc.fWidth, 64));
4269962108c400dadcae913614e8a5ab781780981d8bsalomon@google.com        rtDesc.fHeight = GrNextPow2(GrMax(desc.fHeight, 64));
42727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
42827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
42927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
43027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != texture) {
43127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrDrawTarget::AutoStateRestore asr(fGpu);
4328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = fGpu->drawState();
43352a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com            drawState->reset();
4348f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->setRenderTarget(texture->asRenderTarget());
4358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->setTexture(0, clampEntry.texture());
43682c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com
4376aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            GrSamplerState::Filter filter;
4386aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // if filtering is not desired then we want to ensure all
4396aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // texels in the resampled image are copies of texels from
4406aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // the original.
4411fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com            if (GrSamplerState::kNearest_Filter == sampler->getFilter()) {
4426aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com                filter = GrSamplerState::kNearest_Filter;
4436aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            } else {
4446aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com                filter = GrSamplerState::kBilinear_Filter;
4456aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            }
4461e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com            drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
4471e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                         filter);
44827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
44927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            static const GrVertexLayout layout =
45027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
45127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
45227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
45327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (arg.succeeded()) {
45427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                GrPoint* verts = (GrPoint*) arg.vertices();
45527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                verts[0].setIRectFan(0, 0,
45627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     texture->width(),
45727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     texture->height(),
45827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     2*sizeof(GrPoint));
45927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
46027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,
46127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     0, 4);
46250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                entry.set(fTextureCache->createAndLock(resourceKey, texture));
46327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
4641da0746fa155cdca982ae8deb68cc64f540c92dfbsalomon@google.com            texture->releaseRenderTarget();
46527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        } else {
46627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // TODO: Our CPU stretch doesn't filter. But we create separate
46727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // stretched textures when the sampler state is either filtered or
46827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // not. Either implement filtered stretch blit on CPU or just create
46927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // one when FBO case fails.
47027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
471fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com            rtDesc.fFlags = kNone_GrTextureFlags;
47227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // no longer need to clamp at min RT size.
47327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            rtDesc.fWidth  = GrNextPow2(desc.fWidth);
47427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            rtDesc.fHeight = GrNextPow2(desc.fHeight);
47564c4fe4113424bcfab8b3e0c7049887fda5ab4ffbsalomon@google.com            int bpp = GrBytesPerPixel(desc.fConfig);
4763582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com            SkAutoSMalloc<128*128*4> stretchedPixels(bpp *
47727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     rtDesc.fWidth *
47827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     rtDesc.fHeight);
47927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
48027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         srcData, desc.fWidth, desc.fHeight, bpp);
48127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
48227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            size_t stretchedRowBytes = rtDesc.fWidth * bpp;
48327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
48427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrTexture* texture = fGpu->createTexture(rtDesc,
48527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     stretchedPixels.get(),
48627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     stretchedRowBytes);
48727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrAssert(NULL != texture);
48850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            entry.set(fTextureCache->createAndLock(resourceKey, texture));
48927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
49050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->unlock(clampEntry.cacheEntry());
49127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
49227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
49327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
49427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != texture) {
49550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            entry.set(fTextureCache->createAndLock(resourceKey, texture));
49627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
49727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
49827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return entry;
49927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
50027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
50150398bf7f1953e640e5529616e710cf540799731bsalomon@google.comnamespace {
50250398bf7f1953e640e5529616e710cf540799731bsalomon@google.cominline void gen_scratch_tex_key_values(const GrGpu* gpu,
50350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                       const GrTextureDesc& desc,
50450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                       uint32_t v[4]) {
50550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // Instead of a client-provided key of the texture contents
50650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // we create a key of from the descriptor.
50778d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com    GrContext::TextureKey descKey = (desc.fFlags << 8) |
50864c4fe4113424bcfab8b3e0c7049887fda5ab4ffbsalomon@google.com                                    ((uint64_t) desc.fConfig << 32);
50950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // this code path isn't friendly to tiling with NPOT restricitons
51050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // We just pass ClampNoFilter()
5111fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com    gen_texture_key_values(gpu, NULL, descKey, desc.fWidth,
51278d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com                           desc.fHeight, desc.fSampleCnt, true, v);
51350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com}
51427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
51527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
51650398bf7f1953e640e5529616e710cf540799731bsalomon@google.comGrContext::TextureCacheEntry GrContext::lockScratchTexture(
51750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                                const GrTextureDesc& inDesc,
51850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                                ScratchTexMatch match) {
51950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
520b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    GrTextureDesc desc = inDesc;
52150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (kExact_ScratchTexMatch != match) {
52250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        // bin by pow2 with a reasonable min
52350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        static const int MIN_SIZE = 256;
52450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fWidth  = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
52550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
52650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    }
527b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
52850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrResourceEntry* entry;
529b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origWidth = desc.fWidth;
530b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origHeight = desc.fHeight;
531b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    bool doubledW = false;
532b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    bool doubledH = false;
533b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
534b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    do {
53550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        uint32_t v[4];
53650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        gen_scratch_tex_key_values(fGpu, desc, v);
53750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        GrResourceKey key(v);
538558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        entry = fTextureCache->findAndLock(key,
539558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                           GrResourceCache::kNested_LockType);
540b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        // if we miss, relax the fit of the flags...
541b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        // then try doubling width... then height.
54250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        if (NULL != entry || kExact_ScratchTexMatch == match) {
543b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
544b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
545b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        if (!(desc.fFlags & kRenderTarget_GrTextureFlagBit)) {
546b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = desc.fFlags | kRenderTarget_GrTextureFlagBit;
547b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (desc.fFlags & kNoStencil_GrTextureFlagBit) {
548b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit;
549b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (!doubledW) {
550b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = inDesc.fFlags;
551b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fWidth *= 2;
552b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            doubledW = true;
553b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (!doubledH) {
554b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = inDesc.fFlags;
555b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fWidth = origWidth;
556b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fHeight *= 2;
557b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            doubledH = true;
558b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else {
559b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
560b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
561b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
562b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    } while (true);
563b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
564b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    if (NULL == entry) {
565b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fFlags = inDesc.fFlags;
566b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fWidth = origWidth;
567b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fHeight = origHeight;
568b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
569b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        if (NULL != texture) {
57050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            uint32_t v[4];
57150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            gen_scratch_tex_key_values(fGpu, desc, v);
57250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            GrResourceKey key(v);
573b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            entry = fTextureCache->createAndLock(key, texture);
574b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
575b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
576b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
577b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // If the caller gives us the same desc/sampler twice we don't want
578b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // to return the same texture the second time (unless it was previously
579b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // released). So we detach the entry from the cache and reattach at release.
580b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    if (NULL != entry) {
581b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        fTextureCache->detach(entry);
582b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
58350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    return TextureCacheEntry(entry);
584b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com}
585b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
58650398bf7f1953e640e5529616e710cf540799731bsalomon@google.comvoid GrContext::unlockTexture(TextureCacheEntry entry) {
587bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(entry.texture());
58850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // If this is a scratch texture we detached it from the cache
58950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // while it was locked (to avoid two callers simultaneously getting
59050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // the same texture).
59150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (kScratchBit & entry.cacheEntry()->key().getValue32(3)) {
59250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->reattachAndUnlock(entry.cacheEntry());
593fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    } else {
59450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->unlock(entry.cacheEntry());
595fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
59627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
59727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
598fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.comGrTexture* GrContext::createUncachedTexture(const GrTextureDesc& desc,
59927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            void* srcData,
60027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            size_t rowBytes) {
60127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return fGpu->createTexture(desc, srcData, rowBytes);
60227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
60327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
60427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::getTextureCacheLimits(int* maxTextures,
60527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                      size_t* maxTextureBytes) const {
60627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fTextureCache->getLimits(maxTextures, maxTextureBytes);
60727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
60827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
60927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
61027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fTextureCache->setLimits(maxTextures, maxTextureBytes);
61127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
61227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
613919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxTextureSize() const {
61418c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    return fGpu->getCaps().fMaxTextureSize;
615919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com}
616919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
617919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxRenderTargetSize() const {
61818c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    return fGpu->getCaps().fMaxRenderTargetSize;
61927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
62027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
62127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com///////////////////////////////////////////////////////////////////////////////
62227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
623e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrTexture* GrContext::createPlatformTexture(const GrPlatformTextureDesc& desc) {
624e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com    return fGpu->createPlatformTexture(desc);
625e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
626e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
627e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrRenderTarget* GrContext::createPlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) {
628e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com    return fGpu->createPlatformRenderTarget(desc);
629e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
630e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
6315877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
6325877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com
6331fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.combool GrContext::supportsIndex8PixelConfig(const GrSamplerState* sampler,
6341f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com                                          int width, int height) const {
63518c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    const GrDrawTarget::Caps& caps = fGpu->getCaps();
63618c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    if (!caps.f8BitPaletteSupport) {
63727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return false;
63827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
63927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
64027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
64127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
64227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (!isPow2) {
6431fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        bool tiled = NULL != sampler &&
6441fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                     (sampler->getWrapX() != GrSamplerState::kClamp_WrapMode ||
6451fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                      sampler->getWrapY() != GrSamplerState::kClamp_WrapMode);
64618c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com        if (tiled && !caps.fNPOTTextureTileSupport) {
64727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return false;
64827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
64927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
65027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return true;
65127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
65227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
65327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
65427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
65505ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.comconst GrClip& GrContext::getClip() const { return fGpu->getClip(); }
65605ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com
65727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setClip(const GrClip& clip) {
65827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->setClip(clip);
659a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    fDrawState->enableState(GrDrawState::kClip_StateBit);
66027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
66127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
66227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setClip(const GrIRect& rect) {
66327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrClip clip;
664d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    clip.setFromIRect(rect);
66527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->setClip(clip);
66627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
66727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
66827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
66927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
6706aa25c3f555dc2a6711365d14279db3ec909e064bsalomon@google.comvoid GrContext::clear(const GrIRect* rect, const GrColor color) {
671398109cc3e56b8122ad21c4d43a74a83be5b42a8bsalomon@google.com    this->flush();
6726aa25c3f555dc2a6711365d14279db3ec909e064bsalomon@google.com    fGpu->clear(rect, color);
67327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
67427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
67527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawPaint(const GrPaint& paint) {
67627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // set rect to be big enough to fill the space, but not super-huge, so we
67727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // don't overflow fixed-point implementations
678d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    GrRect r;
679d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    r.setLTRB(0, 0,
680d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com              GrIntToScalar(getRenderTarget()->width()),
681d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com              GrIntToScalar(getRenderTarget()->height()));
68227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix inverse;
6838c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    SkTLazy<GrPaint> tmpPaint;
6848c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    const GrPaint* p = &paint;
6858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrAutoMatrix am;
6868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6874f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // We attempt to map r by the inverse matrix and draw that. mapRect will
6884f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // map the four corners and bound them with a new rect. This will not
6894f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // produce a correct result for some perspective matrices.
6908c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    if (!this->getMatrix().hasPerspective()) {
691a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        if (!fDrawState->getViewInverse(&inverse)) {
6928c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            GrPrintf("Could not invert matrix");
6938c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            return;
6948c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
69527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        inverse.mapRect(&r);
69627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
6978c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        if (paint.getActiveMaskStageMask() || paint.getActiveStageMask()) {
698a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com            if (!fDrawState->getViewInverse(&inverse)) {
6998c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com                GrPrintf("Could not invert matrix");
7008c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com                return;
7018c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            }
7028c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.set(paint);
7038c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.get()->preConcatActiveSamplerMatrices(inverse);
7048c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            p = tmpPaint.get();
7058c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
7064f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com        am.set(this, GrMatrix::I());
70727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
7084f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // by definition this fills the entire clip, no need for AA
7094f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    if (paint.fAntiAlias) {
7108c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        if (!tmpPaint.isValid()) {
7118c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.set(paint);
7128c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            p = tmpPaint.get();
7138c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
7148c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        GrAssert(p == tmpPaint.get());
7158c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        tmpPaint.get()->fAntiAlias = false;
7164f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    }
7174f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    this->drawRect(*p, r);
71827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
71927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
720205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
721205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
722d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.comnamespace {
723d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.cominline bool disable_coverage_aa_for_blend(GrDrawTarget* target) {
724d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage();
725d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com}
726d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com}
727d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
72806afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
72906afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
73027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com/*  create a triangle strip that strokes the specified triangle. There are 8
73127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com unique vertices, but we repreat the last 2 to close up. Alternatively we
73227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com could use an indices array, and then only send 8 verts, but not sure that
73327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com would be faster.
73427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com */
735205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
73627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               GrScalar width) {
73727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    const GrScalar rad = GrScalarHalf(width);
738205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    rect.sort();
73927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
74027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[0].set(rect.fLeft + rad, rect.fTop + rad);
74127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[1].set(rect.fLeft - rad, rect.fTop - rad);
74227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[2].set(rect.fRight - rad, rect.fTop + rad);
74327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[3].set(rect.fRight + rad, rect.fTop - rad);
74427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[4].set(rect.fRight - rad, rect.fBottom - rad);
74527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[5].set(rect.fRight + rad, rect.fBottom + rad);
74627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
74727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
74827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[8] = verts[0];
74927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[9] = verts[1];
75027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
75127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
752205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic void setInsetFan(GrPoint* pts, size_t stride,
753205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        const GrRect& r, GrScalar dx, GrScalar dy) {
754205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    pts->setRectFan(r.fLeft + dx, r.fTop + dy, r.fRight - dx, r.fBottom - dy, stride);
755205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
756205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
757205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic const uint16_t gFillAARectIdx[] = {
758205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    0, 1, 5, 5, 4, 0,
759205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    1, 2, 6, 6, 5, 1,
760205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    2, 3, 7, 7, 6, 2,
761205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    3, 0, 4, 4, 7, 3,
762205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    4, 5, 6, 6, 7, 4,
763205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com};
764205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
765205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comint GrContext::aaFillRectIndexCount() const {
766205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    return GR_ARRAY_COUNT(gFillAARectIdx);
767205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
768205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
769205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comGrIndexBuffer* GrContext::aaFillRectIndexBuffer() {
770205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL == fAAFillRectIndexBuffer) {
771205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        fAAFillRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gFillAARectIdx),
772205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                                                         false);
7739b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        if (NULL != fAAFillRectIndexBuffer) {
7749b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    #if GR_DEBUG
7759b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            bool updated =
7769b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    #endif
7779b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            fAAFillRectIndexBuffer->updateData(gFillAARectIdx,
7789b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com                                               sizeof(gFillAARectIdx));
7799b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            GR_DEBUGASSERT(updated);
7809b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        }
781205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
782205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    return fAAFillRectIndexBuffer;
783205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
784205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
785205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic const uint16_t gStrokeAARectIdx[] = {
786205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
787205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
788205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
789205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
790205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
791205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
792205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
793205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
794205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
795205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
796205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
797205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
798205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
799205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
800205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com};
801205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
802205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comint GrContext::aaStrokeRectIndexCount() const {
803205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    return GR_ARRAY_COUNT(gStrokeAARectIdx);
804205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
805205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
806205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comGrIndexBuffer* GrContext::aaStrokeRectIndexBuffer() {
807205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL == fAAStrokeRectIndexBuffer) {
808205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        fAAStrokeRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gStrokeAARectIdx),
809205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                                                           false);
8109b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        if (NULL != fAAStrokeRectIndexBuffer) {
8119b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    #if GR_DEBUG
8129b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            bool updated =
8139b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    #endif
8149b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx,
8159b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com                                                 sizeof(gStrokeAARectIdx));
8169b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            GR_DEBUGASSERT(updated);
8179b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        }
818205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
819205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    return fAAStrokeRectIndexBuffer;
820205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
821205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
822a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.comstatic GrVertexLayout aa_rect_layout(const GrDrawTarget* target,
823a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                     bool useCoverage) {
824a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrVertexLayout layout = 0;
8259381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
8268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        if (NULL != target->getDrawState().getTexture(s)) {
827a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
828a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        }
829a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    }
830a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    if (useCoverage) {
831a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        layout |= GrDrawTarget::kCoverage_VertexLayoutBit;
832a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    } else {
833a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        layout |= GrDrawTarget::kColor_VertexLayoutBit;
834a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    }
835a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    return layout;
836a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com}
837a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com
838205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comvoid GrContext::fillAARect(GrDrawTarget* target,
839a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                           const GrRect& devRect,
840a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                           bool useVertexCoverage) {
841a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage);
842205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
843205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    size_t vsize = GrDrawTarget::VertexSize(layout);
844205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
845205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(target, layout, 8, 0);
8466513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    if (!geo.succeeded()) {
8476513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
8486513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        return;
8496513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    }
8509b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer();
8519b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    if (NULL == indexBuffer) {
8529b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        GrPrintf("Failed to create index buffer!\n");
8539b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        return;
8549b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    }
855205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
856205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
857205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
858205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
859205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
860205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
861205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan0Pos, vsize, devRect, -GR_ScalarHalf, -GR_ScalarHalf);
862205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan1Pos, vsize, devRect,  GR_ScalarHalf,  GR_ScalarHalf);
863205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
864205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += sizeof(GrPoint);
865205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 4; ++i) {
866205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
867205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
868205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
869a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrColor innerColor;
870a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    if (useVertexCoverage) {
871e10f6fdf76fa9b627cbb8471b58b13c457af83e8bsalomon@google.com        innerColor = 0xffffffff;
872a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    } else {
8738f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        innerColor = target->getDrawState().getColor();
874a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    }
875a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com
876205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += 4 * vsize;
877205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 4; ++i) {
878205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
879205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
880205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
8819b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    target->setIndexSourceToBuffer(indexBuffer);
882205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
883205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    target->drawIndexed(kTriangles_PrimitiveType, 0,
884205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                         0, 8, this->aaFillRectIndexCount());
885205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
886205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
887a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.comvoid GrContext::strokeAARect(GrDrawTarget* target,
888a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             const GrRect& devRect,
889a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             const GrVec& devStrokeSize,
890a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             bool useVertexCoverage) {
891205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    const GrScalar& dx = devStrokeSize.fX;
892205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    const GrScalar& dy = devStrokeSize.fY;
893205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    const GrScalar rx = GrMul(dx, GR_ScalarHalf);
894205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    const GrScalar ry = GrMul(dy, GR_ScalarHalf);
895205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
896205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrScalar spare;
897205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    {
898205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrScalar w = devRect.width() - dx;
899205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrScalar h = devRect.height() - dy;
900205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        spare = GrMin(w, h);
901205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
902205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
903205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (spare <= 0) {
904205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrRect r(devRect);
905205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        r.inset(-rx, -ry);
906a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        fillAARect(target, r, useVertexCoverage);
907205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return;
908205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
909a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage);
910205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    size_t vsize = GrDrawTarget::VertexSize(layout);
911205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
912205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(target, layout, 16, 0);
9136513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    if (!geo.succeeded()) {
9146513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
9156513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        return;
9166513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    }
9179b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer();
9189b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    if (NULL == indexBuffer) {
9199b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        GrPrintf("Failed to create index buffer!\n");
9209b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        return;
9219b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    }
922205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
923205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
924205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
925205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
926205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
927205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize);
928205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize);
929205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
930205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan0Pos, vsize, devRect, -rx - GR_ScalarHalf, -ry - GR_ScalarHalf);
931205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan1Pos, vsize, devRect, -rx + GR_ScalarHalf, -ry + GR_ScalarHalf);
932205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan2Pos, vsize, devRect,  rx - GR_ScalarHalf,  ry - GR_ScalarHalf);
933205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan3Pos, vsize, devRect,  rx + GR_ScalarHalf,  ry + GR_ScalarHalf);
934205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
935205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += sizeof(GrPoint);
936205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 4; ++i) {
937205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
938205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
939205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
940a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrColor innerColor;
941a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    if (useVertexCoverage) {
942e10f6fdf76fa9b627cbb8471b58b13c457af83e8bsalomon@google.com        innerColor = 0xffffffff;
943a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    } else {
9448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        innerColor = target->getDrawState().getColor();
945a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    }
946205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += 4 * vsize;
947205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 8; ++i) {
948205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
949205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
950205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
951205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += 8 * vsize;
952205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 8; ++i) {
953205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
954205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
955205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
9569b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    target->setIndexSourceToBuffer(indexBuffer);
957205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    target->drawIndexed(kTriangles_PrimitiveType,
958205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0, 0, 16, aaStrokeRectIndexCount());
959205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
960205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
96120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com/**
96220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com * Returns true if the rects edges are integer-aligned.
96320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com */
96420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.comstatic bool isIRect(const GrRect& r) {
96520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    return GrScalarIsInt(r.fLeft) && GrScalarIsInt(r.fTop) &&
96620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com           GrScalarIsInt(r.fRight) && GrScalarIsInt(r.fBottom);
96720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com}
96820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
969205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic bool apply_aa_to_rect(GrDrawTarget* target,
970205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             const GrRect& rect,
971205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             GrScalar width,
972205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             const GrMatrix* matrix,
973205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             GrMatrix* combinedMatrix,
974a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             GrRect* devRect,
975a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             bool* useVertexCoverage) {
9762eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // we use a simple coverage ramp to do aa on axis-aligned rects
9772eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // we check if the rect will be axis-aligned, and the rect won't land on
9782eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // integer coords.
979d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
980a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // we are keeping around the "tweak the alpha" trick because
981a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // it is our only hope for the fixed-pipe implementation.
982a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // In a shader implementation we can give a separate coverage input
983289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    // TODO: remove this ugliness when we drop the fixed-pipe impl
984a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    *useVertexCoverage = false;
985d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (!target->canTweakAlphaForCoverage()) {
9862eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com        if (disable_coverage_aa_for_blend(target)) {
9871983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
9882eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            //GrPrintf("Turning off AA to correctly apply blend.\n");
9891983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
990a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            return false;
9912eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com        } else {
9922eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            *useVertexCoverage = true;
993a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        }
994205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
9958f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    const GrDrawState& drawState = target->getDrawState();
9968f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (drawState.getRenderTarget()->isMultisampled()) {
997205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
998205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
999205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1000471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com    if (0 == width && target->willUseHWAALines()) {
1001205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
1002205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1003205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
10048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (!drawState.getViewMatrix().preservesAxisAlignment()) {
1005205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
1006205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1007205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1008205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL != matrix &&
1009205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        !matrix->preservesAxisAlignment()) {
1010205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
1011205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1012205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
10138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    *combinedMatrix = drawState.getViewMatrix();
1014205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL != matrix) {
1015205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        combinedMatrix->preConcat(*matrix);
1016205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrAssert(combinedMatrix->preservesAxisAlignment());
1017205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1018205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1019205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    combinedMatrix->mapRect(devRect, rect);
1020205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    devRect->sort();
1021205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1022205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (width < 0) {
102320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        return !isIRect(*devRect);
1024205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    } else {
1025205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return true;
1026205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1027205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
1028205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
102927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRect(const GrPaint& paint,
103027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         const GrRect& rect,
103127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         GrScalar width,
103227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         const GrMatrix* matrix) {
1033278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRect");
103427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
103527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
103626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int stageMask = paint.getActiveStageMask();
103727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1038205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrRect devRect = rect;
1039205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrMatrix combinedMatrix;
1040a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    bool useVertexCoverage;
1041289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool needAA = paint.fAntiAlias &&
1042289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                  !this->getRenderTarget()->isMultisampled();
1043289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix,
1044289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &combinedMatrix, &devRect,
1045289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &useVertexCoverage);
1046205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1047205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (doAA) {
10488f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
1049205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        if (width >= 0) {
1050205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            GrVec strokeSize;;
1051205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            if (width > 0) {
1052205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.set(width, width);
1053cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com                combinedMatrix.mapVectors(&strokeSize, 1);
1054205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.setAbs(strokeSize);
1055205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            } else {
1056205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.set(GR_Scalar1, GR_Scalar1);
1057205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            }
1058a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            strokeAARect(target, devRect, strokeSize, useVertexCoverage);
1059205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        } else {
1060a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            fillAARect(target, devRect, useVertexCoverage);
1061205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        }
1062205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return;
1063205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
1064205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
106527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (width >= 0) {
106627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // TODO: consider making static vertex buffers for these cases.
106727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // Hairline could be done by just adding closing vertex to
106827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // unitSquareVertexBuffer()
106926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        GrVertexLayout layout =  PaintStageVertexLayoutBits(paint, NULL);
107026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
107127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        static const int worstCaseVertCount = 10;
107227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
107327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
107427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.succeeded()) {
10756513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
107627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
107727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
107827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
107927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPrimitiveType primType;
108027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int vertCount;
108127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPoint* vertex = geo.positions();
108227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
108327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (width > 0) {
108427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 10;
108527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            primType = kTriangleStrip_PrimitiveType;
108627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            setStrokeRectStrip(vertex, rect, width);
108727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        } else {
108827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // hairline
108927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 5;
109027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            primType = kLineStrip_PrimitiveType;
109127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[0].set(rect.fLeft, rect.fTop);
109227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[1].set(rect.fRight, rect.fTop);
109327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[2].set(rect.fRight, rect.fBottom);
109427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[3].set(rect.fLeft, rect.fBottom);
109527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[4].set(rect.fLeft, rect.fTop);
109627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
109727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
10988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState::AutoViewMatrixRestore avmr;
109927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != matrix) {
11008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
11018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            avmr.set(drawState);
11028f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatViewMatrix(*matrix);
11038f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatSamplerMatrices(stageMask, *matrix);
110427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
110527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
110627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->drawNonIndexed(primType, 0, vertCount);
110727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
11088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#if GR_STATIC_RECT_VB
110926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
11106513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
11116513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            if (NULL == sqVB) {
11126513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com                GrPrintf("Failed to create static rect vb.\n");
11136513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com                return;
11146513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            }
11156513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            target->setVertexSourceToBuffer(layout, sqVB);
11168f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
11178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState::AutoViewMatrixRestore avmr(drawState);
111827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrMatrix m;
11198295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com            m.setAll(rect.width(),    0,             rect.fLeft,
1120205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0,            rect.height(), rect.fTop,
1121205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0,            0,             GrMatrix::I()[8]);
112227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
112327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (NULL != matrix) {
112427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                m.postConcat(*matrix);
112527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
11268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatViewMatrix(m);
11278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatSamplerMatrices(stageMask, m);
112826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
112927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
11308f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#else
113126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            target->drawSimpleRect(rect, matrix, stageMask);
11328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#endif
113327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
113427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
113527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
113627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRectToRect(const GrPaint& paint,
113727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrRect& dstRect,
113827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrRect& srcRect,
113927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrMatrix* dstMatrix,
114027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrMatrix* srcMatrix) {
1141278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRectToRect");
114227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
114326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    // srcRect refers to paint's first texture
114426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    if (NULL == paint.getTexture(0)) {
114527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        drawRect(paint, dstRect, -1, dstMatrix);
114627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
114727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
1148de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com
114927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB);
115027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
115127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_STATIC_RECT_VB
115227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
11538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = target->drawState();
115426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
11558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState::AutoViewMatrixRestore avmr(drawState);
115627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
115727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix m;
115827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
115927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    m.setAll(dstRect.width(), 0,                dstRect.fLeft,
116027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               dstRect.height(), dstRect.fTop,
116127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               0,                GrMatrix::I()[8]);
116227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != dstMatrix) {
116327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        m.postConcat(*dstMatrix);
116427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
11658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->preConcatViewMatrix(m);
116627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
116726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    // srcRect refers to first stage
116826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int otherStageMask = paint.getActiveStageMask() &
116926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                         (~(1 << GrPaint::kFirstTextureStage));
117026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    if (otherStageMask) {
11718f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->preConcatSamplerMatrices(otherStageMask, m);
117226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
117326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
117427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    m.setAll(srcRect.width(), 0,                srcRect.fLeft,
117527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               srcRect.height(), srcRect.fTop,
117627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               0,                GrMatrix::I()[8]);
117727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != srcMatrix) {
117827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        m.postConcat(*srcMatrix);
117927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
11808f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->sampler(GrPaint::kFirstTextureStage)->preConcatMatrix(m);
118127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
11826513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
11836513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    if (NULL == sqVB) {
11846513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to create static rect vb.\n");
11856513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        return;
11866513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    }
11876513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    target->setVertexSourceToBuffer(layout, sqVB);
118827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
118927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
119027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
119127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target;
1192de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com#if BATCH_RECT_TO_RECT
119327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = this->prepareToDraw(paint, kBuffered_DrawCategory);
1194de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com#else
119527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
119627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
119727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
11989381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
11999381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    const GrMatrix* srcMatrices[GrDrawState::kNumStages] = {NULL};
120027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    srcRects[0] = &srcRect;
120127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    srcMatrices[0] = srcMatrix;
120227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
120327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices);
120427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
120527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
120627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
120727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawVertices(const GrPaint& paint,
120827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             GrPrimitiveType primitiveType,
120927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int vertexCount,
121027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint positions[],
121127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint texCoords[],
121227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrColor colors[],
121327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const uint16_t indices[],
121427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int indexCount) {
1215278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawVertices");
121627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
121727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo;
121827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
121927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
122027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
122126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    bool hasTexCoords[GrPaint::kTotalStages] = {
122226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        NULL != texCoords,   // texCoordSrc provides explicit stage 0 coords
122326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        0                    // remaining stages use positions
122426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    };
122526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
122626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, hasTexCoords);
122727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
122827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != colors) {
122927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        layout |= GrDrawTarget::kColor_VertexLayoutBit;
123027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
123126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int vertexSize = GrDrawTarget::VertexSize(layout);
123227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
123327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (sizeof(GrPoint) != vertexSize) {
123427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.set(target, layout, vertexCount, 0)) {
12356513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
123627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
123727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
12389381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        int texOffsets[GrDrawState::kMaxTexCoords];
123927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int colorOffset;
124026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
124126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                                                texOffsets,
1242aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com                                                &colorOffset,
1243a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                                NULL,
1244a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                                NULL);
124527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* curVertex = geo.vertices();
124627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
124727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < vertexCount; ++i) {
124827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            *((GrPoint*)curVertex) = positions[i];
124927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
125027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (texOffsets[0] > 0) {
125127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
125227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
125327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (colorOffset > 0) {
125427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
125527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
125626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            curVertex = (void*)((intptr_t)curVertex + vertexSize);
125727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
125827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
125927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->setVertexSourceToArray(layout, positions, vertexCount);
126027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
126127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1262919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // we don't currently apply offscreen AA to this path. Need improved
1263919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // management of GrDrawTarget's geometry to avoid copying points per-tile.
1264a47a48dca5045d71cbc5de343404045209a13e15bsalomon@google.com
12658295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    if (NULL != indices) {
1266919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        target->setIndexSourceToArray(indices, indexCount);
12678295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
126827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
12698295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawNonIndexed(primitiveType, 0, vertexCount);
12708295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
127127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
127227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
127306afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
1274150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com#include "SkDraw.h"
1275150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com#include "SkRasterClip.h"
1276150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1277150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.comnamespace {
1278150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1279150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.comSkPath::FillType gr_fill_to_sk_fill(GrPathFill fill) {
1280150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    switch (fill) {
1281150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        case kWinding_PathFill:
1282150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return SkPath::kWinding_FillType;
1283150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        case kEvenOdd_PathFill:
1284150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return SkPath::kEvenOdd_FillType;
1285150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        case kInverseWinding_PathFill:
1286150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return SkPath::kInverseWinding_FillType;
1287150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        case kInverseEvenOdd_PathFill:
1288150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return SkPath::kInverseEvenOdd_FillType;
1289150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        default:
1290150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            GrCrash("Unexpected fill.");
1291150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return SkPath::kWinding_FillType;
1292150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1293150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
1294150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1295150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com// gets device coord bounds of path (not considering the fill) and clip. The
1296150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com// path bounds will be a subset of the clip bounds. returns false if path bounds
1297150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com// would be empty.
1298150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.combool get_path_and_clip_bounds(const GrDrawTarget* target,
1299150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                              const GrPath& path,
1300150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                              const GrVec* translate,
1301150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                              GrIRect* pathBounds,
1302150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                              GrIRect* clipBounds) {
1303150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    // compute bounds as intersection of rt size, clip, and path
1304150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
1305150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (NULL == rt) {
1306150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        return false;
1307150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1308150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    *pathBounds = GrIRect::MakeWH(rt->width(), rt->height());
1309150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    const GrClip& clip = target->getClip();
1310150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (clip.hasConservativeBounds()) {
1311150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        clip.getConservativeBounds().roundOut(clipBounds);
1312150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        if (!pathBounds->intersect(*clipBounds)) {
1313150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return false;
1314150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        }
1315150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    } else {
1316150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        // pathBounds is currently the rt extent, set clip bounds to that rect.
1317150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        *clipBounds = *pathBounds;
1318150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1319150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrRect pathSBounds = path.getBounds();
1320150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (!pathSBounds.isEmpty()) {
1321150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        if (NULL != translate) {
1322150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            pathSBounds.offset(*translate);
1323150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        }
1324150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        target->getDrawState().getViewMatrix().mapRect(&pathSBounds,
1325150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                                        pathSBounds);
1326150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        GrIRect pathIBounds;
1327150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        pathSBounds.roundOut(&pathIBounds);
1328150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        if (!pathBounds->intersect(pathIBounds)) {
1329150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return false;
1330150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        }
1331150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    } else {
1332150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        return false;
1333150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1334150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    return true;
1335150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
1336150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1337150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com/**
1338150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com * sw rasterizes path to A8 mask using the context's matrix and uploads to a
1339150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com * scratch texture.
1340150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com */
1341150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1342150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.combool sw_draw_path_to_mask_texture(const GrPath& clientPath,
1343150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                  const GrIRect& pathDevBounds,
1344150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                  GrPathFill fill,
1345150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                  GrContext* context,
1346150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                  const GrPoint* translate,
1347150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                  GrAutoScratchTexture* tex) {
1348150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    SkPaint paint;
1349150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    SkPath tmpPath;
1350150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    const SkPath* pathToDraw = &clientPath;
1351150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (kHairLine_PathFill == fill) {
1352150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        paint.setStyle(SkPaint::kStroke_Style);
1353150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        paint.setStrokeWidth(SK_Scalar1);
1354150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    } else {
1355150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        paint.setStyle(SkPaint::kFill_Style);
1356150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        SkPath::FillType skfill = gr_fill_to_sk_fill(fill);
1357150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        if (skfill != pathToDraw->getFillType()) {
1358150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            tmpPath = *pathToDraw;
1359150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            tmpPath.setFillType(skfill);
1360150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            pathToDraw = &tmpPath;
1361150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        }
1362150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1363150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    paint.setAntiAlias(true);
1364150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    paint.setColor(SK_ColorWHITE);
1365150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1366150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrMatrix matrix = context->getMatrix();
1367150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (NULL != translate) {
1368150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        matrix.postTranslate(translate->fX, translate->fY);
1369150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1370150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1371150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    matrix.postTranslate(-pathDevBounds.fLeft * SK_Scalar1,
1372150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                         -pathDevBounds.fTop * SK_Scalar1);
1373150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrIRect bounds = GrIRect::MakeWH(pathDevBounds.width(),
1374150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                     pathDevBounds.height());
1375150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1376150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    SkBitmap bm;
1377150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    bm.setConfig(SkBitmap::kA8_Config, bounds.fRight, bounds.fBottom);
1378150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (!bm.allocPixels()) {
1379150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        return false;
1380150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1381150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    sk_bzero(bm.getPixels(), bm.getSafeSize());
1382150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1383150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    SkDraw  draw;
1384150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    sk_bzero(&draw, sizeof(draw));
1385150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    SkRasterClip rc(bounds);
1386150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    draw.fRC    = &rc;
1387150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    draw.fClip  = &rc.bwRgn();
1388150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    draw.fMatrix = &matrix;
1389150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    draw.fBitmap = &bm;
1390150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    draw.drawPath(*pathToDraw, paint);
1391150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1392150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    const GrTextureDesc desc = {
1393150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        kNone_GrTextureFlags,
1394150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        bounds.fRight,
1395150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        bounds.fBottom,
139678d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com        kAlpha_8_GrPixelConfig,
139778d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com        {0} // samples
1398150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    };
1399150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1400150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    tex->set(context, desc);
1401150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrTexture* texture = tex->texture();
1402150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1403150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (NULL == texture) {
1404150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        return false;
1405150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1406150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    SkAutoLockPixels alp(bm);
1407150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
1408150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                         bm.getPixels(), bm.rowBytes());
1409150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    return true;
1410150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
1411150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1412150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.comvoid draw_around_inv_path(GrDrawTarget* target,
1413150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                          GrDrawState::StageMask stageMask,
1414150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                          const GrIRect& clipBounds,
1415150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                          const GrIRect& pathBounds) {
1416150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
1417150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrRect rect;
1418150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (clipBounds.fTop < pathBounds.fTop) {
1419150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        rect.iset(clipBounds.fLeft, clipBounds.fTop,
1420150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                    clipBounds.fRight, pathBounds.fTop);
1421150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        target->drawSimpleRect(rect, NULL, stageMask);
1422150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1423150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (clipBounds.fLeft < pathBounds.fLeft) {
1424150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        rect.iset(clipBounds.fLeft, pathBounds.fTop,
1425150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                    pathBounds.fLeft, pathBounds.fBottom);
1426150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        target->drawSimpleRect(rect, NULL, stageMask);
1427150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1428150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (clipBounds.fRight > pathBounds.fRight) {
1429150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        rect.iset(pathBounds.fRight, pathBounds.fTop,
1430150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                    clipBounds.fRight, pathBounds.fBottom);
1431150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        target->drawSimpleRect(rect, NULL, stageMask);
1432150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1433150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (clipBounds.fBottom > pathBounds.fBottom) {
1434150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        rect.iset(clipBounds.fLeft, pathBounds.fBottom,
1435150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                    clipBounds.fRight, clipBounds.fBottom);
1436150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        target->drawSimpleRect(rect, NULL, stageMask);
1437150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1438150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
1439150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1440150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
144127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
144207f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.comvoid GrContext::drawPath(const GrPaint& paint, const GrPath& path,
144307f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.com                         GrPathFill fill, const GrPoint* translate) {
144427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1445fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (path.isEmpty()) {
1446fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       if (GrIsFillInverted(fill)) {
1447fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com           this->drawPaint(paint);
1448fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       }
1449fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       return;
1450fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
1451fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1452fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // Note that below we may sw-rasterize the path into a scratch texture.
1453fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // Scratch textures can be recycled after they are returned to the texture
1454fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // cache. This presents a potential hazard for buffered drawing. However,
1455fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // the writePixels that uploads to the scratch will perform a flush so we're
1456fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // OK.
1457fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    DrawCategory category = (DEFER_PATHS) ? kBuffered_DrawCategory :
1458fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com                                            kUnbuffered_DrawCategory;
1459fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, category);
1460150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrDrawState::StageMask stageMask = paint.getActiveStageMask();
1461d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
1462289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool prAA = paint.fAntiAlias && !this->getRenderTarget()->isMultisampled();
1463289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
1464d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // An Assumption here is that path renderer would use some form of tweaking
1465d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // the src color (either the input alpha or in the frag shader) to implement
1466d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // aa. If we have some future driver-mojo path AA that can do the right
1467d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // thing WRT to the blend then we'll need some query on the PR.
1468d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (disable_coverage_aa_for_blend(target)) {
14691983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
1470979432ba2621b617f5e85a9ff48c6b6cd1504a0dbsalomon@google.com        //GrPrintf("Turning off AA to correctly apply blend.\n");
14711983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
1472289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        prAA = false;
1473d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    }
1474289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
1475289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    GrPathRenderer* pr = NULL;
1476289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    if (prAA) {
1477c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com        pr = this->getPathRenderer(path, fill, target, true);
1478289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        if (NULL == pr) {
1479150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            GrAutoScratchTexture ast;
1480150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            GrIRect pathBounds, clipBounds;
1481150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            if (!get_path_and_clip_bounds(target, path, translate,
1482150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                          &pathBounds, &clipBounds)) {
1483150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                return;
1484150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            }
1485150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            if (NULL == pr && sw_draw_path_to_mask_texture(path, pathBounds,
1486150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                                           fill, this,
1487150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                                           translate, &ast)) {
1488150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                GrTexture* texture = ast.texture();
1489150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                GrAssert(NULL != texture);
1490150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
1491150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                enum {
1492150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                    kPathMaskStage = GrPaint::kTotalStages,
1493150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                };
1494150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                target->drawState()->setTexture(kPathMaskStage, texture);
1495150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                target->drawState()->sampler(kPathMaskStage)->reset();
1496150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                GrScalar w = GrIntToScalar(pathBounds.width());
1497150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                GrScalar h = GrIntToScalar(pathBounds.height());
1498150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                GrRect maskRect = GrRect::MakeWH(w / texture->width(),
1499150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                                 h / texture->height());
1500150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
1501150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                srcRects[kPathMaskStage] = &maskRect;
1502150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                stageMask |= 1 << kPathMaskStage;
15035db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                GrRect dstRect = GrRect::MakeLTRB(
15045db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                    SK_Scalar1* pathBounds.fLeft,
15055db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                    SK_Scalar1* pathBounds.fTop,
15065db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                    SK_Scalar1* pathBounds.fRight,
15075db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                    SK_Scalar1* pathBounds.fBottom);
1508150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                target->drawRect(dstRect, NULL, stageMask, srcRects, NULL);
1509150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                target->drawState()->setTexture(kPathMaskStage, NULL);
1510150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                if (GrIsFillInverted(fill)) {
1511150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                    draw_around_inv_path(target, stageMask,
1512150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                         clipBounds, pathBounds);
1513150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                }
1514150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                return;
1515150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            }
1516289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        }
1517289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    } else {
1518c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com        pr = this->getPathRenderer(path, fill, target, false);
1519289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    }
1520289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
15213008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == pr) {
15221983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
15233008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        GrPrintf("Unable to find path renderer compatible with path.\n");
15241983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
15253008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        return;
15263008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
15273008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
1528c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com    pr->drawPath(path, fill, translate, target, stageMask, prAA);
152927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
15308295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
153127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
153227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1533a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.comvoid GrContext::flush(int flagsBitfield) {
1534a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kDiscard_FlushBit & flagsBitfield) {
1535a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com        fDrawBuffer->reset();
1536a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    } else {
1537c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        this->flushDrawBuffer();
1538a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    }
1539a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) {
154027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fGpu->forceRenderTargetFlush();
154127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
154227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
154327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
154427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::flushText() {
154527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (kText_DrawCategory == fLastDrawCategory) {
154627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        flushDrawBuffer();
154727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
154827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
154927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
155027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::flushDrawBuffer() {
155127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING
155253a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    if (fDrawBuffer) {
155397805382d89b717de3355312a79a957ea4a864c9bsalomon@google.com        fDrawBuffer->flushTo(fGpu);
155453a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    }
155527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
155627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
155727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
15586f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.comvoid GrContext::internalWriteTexturePixels(GrTexture* texture,
15596f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           int left, int top,
15606f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           int width, int height,
15616f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           GrPixelConfig config,
15626f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           const void* buffer,
15636f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           size_t rowBytes,
15646f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           uint32_t flags) {
15656f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeTexturePixels");
1566bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1567bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
15686f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
15696f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        this->flush();
15706f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
15716f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    // TODO: use scratch texture to perform conversion
15726f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (GrPixelConfigIsUnpremultiplied(texture->config()) !=
15736f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config)) {
15746f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        return;
15756f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
15766f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
15776f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    fGpu->writeTexturePixels(texture, left, top, width, height,
15786f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                             config, buffer, rowBytes);
15796f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com}
15806f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
15816f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.combool GrContext::internalReadTexturePixels(GrTexture* texture,
15826f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          int left, int top,
15836f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          int width, int height,
15846f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          GrPixelConfig config,
15856f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          void* buffer,
15866f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          size_t rowBytes,
15876f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          uint32_t flags) {
1588278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readTexturePixels");
1589bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1590669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1591a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // TODO: code read pixels for textures that aren't also rendertargets
1592669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    GrRenderTarget* target = texture->asRenderTarget();
1593669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    if (NULL != target) {
15946f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        return this->internalReadRenderTargetPixels(target,
15956f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    left, top, width, height,
15966f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    config, buffer, rowBytes,
15976f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    flags);
1598669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    } else {
1599669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com        return false;
1600669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    }
1601669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com}
1602669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1603a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com#include "SkConfig8888.h"
1604a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
1605a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.comnamespace {
1606a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com/**
1607a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * Converts a GrPixelConfig to a SkCanvas::Config8888. Only byte-per-channel
1608a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * formats are representable as Config8888 and so the function returns false
1609a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * if the GrPixelConfig has no equivalent Config8888.
1610a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com */
1611a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.combool grconfig_to_config8888(GrPixelConfig config,
1612a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                            SkCanvas::Config8888* config8888) {
1613a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    switch (config) {
1614a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kRGBA_8888_PM_GrPixelConfig:
1615a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kRGBA_Premul_Config8888;
1616a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1617a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kRGBA_8888_UPM_GrPixelConfig:
1618a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
1619a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1620a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kBGRA_8888_PM_GrPixelConfig:
1621a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kBGRA_Premul_Config8888;
1622a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1623a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kBGRA_8888_UPM_GrPixelConfig:
1624a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kBGRA_Unpremul_Config8888;
1625a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1626a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        default:
1627a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return false;
1628a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1629a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
1630a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
1631a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
16326f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.combool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target,
16336f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               int left, int top,
16346f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               int width, int height,
16356f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               GrPixelConfig config,
16366f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               void* buffer,
16376f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               size_t rowBytes,
16386f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               uint32_t flags) {
1639278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
1640bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
1641bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
1642669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    if (NULL == target) {
1643a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        target = fDrawState->getRenderTarget();
1644c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (NULL == target) {
1645c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            return false;
1646c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1647c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1648669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
16496f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
16506f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        this->flush();
16516f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
1652c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1653a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    if (!GrPixelConfigIsUnpremultiplied(target->config()) &&
1654a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config) &&
1655a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        !fGpu->canPreserveReadWriteUnpremulPixels()) {
1656a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkCanvas::Config8888 srcConfig8888, dstConfig8888;
1657a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        if (!grconfig_to_config8888(target->config(), &srcConfig8888) ||
1658a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            !grconfig_to_config8888(config, &dstConfig8888)) {
1659a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return false;
1660a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        }
1661a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // do read back using target's own config
1662a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        this->internalReadRenderTargetPixels(target,
1663a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             left, top,
1664a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             width, height,
1665a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             target->config(),
1666a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             buffer, rowBytes,
1667a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             kDontFlush_PixelOpsFlag);
1668a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // sw convert the pixels to unpremul config
1669a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        uint32_t* pixels = reinterpret_cast<uint32_t*>(buffer);
1670a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkConvertConfig8888Pixels(pixels, rowBytes, dstConfig8888,
1671a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  pixels, rowBytes, srcConfig8888,
1672a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  width, height);
1673a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        return true;
1674a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1675a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
1676c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    GrTexture* src = target->asTexture();
16770a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    bool swapRAndB = NULL != src &&
16780a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                     fGpu->preferredReadPixelsConfig(config) ==
16790a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                     GrPixelConfigSwapRAndB(config);
1680c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1681c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    bool flipY = NULL != src &&
1682c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                 fGpu->readPixelsWillPayForYFlip(target, left, top,
1683c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 width, height, config,
1684c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 rowBytes);
16850a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    bool alphaConversion = (!GrPixelConfigIsUnpremultiplied(target->config()) &&
16860a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                             GrPixelConfigIsUnpremultiplied(config));
1687c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
16880a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    if (NULL == src && alphaConversion) {
16890a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // we should fallback to cpu conversion here. This could happen when
16900a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // we were given an external render target by the client that is not
16910a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // also a texture (e.g. FBO 0 in GL)
16920a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        return false;
16930a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    }
16940a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    // we draw to a scratch texture if any of these conversion are applied
1695c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com    GrAutoScratchTexture ast;
16960a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    if (flipY || swapRAndB || alphaConversion) {
16970a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        GrAssert(NULL != src);
16980a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        if (swapRAndB) {
16990a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com            config = GrPixelConfigSwapRAndB(config);
17000a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com            GrAssert(kUnknown_GrPixelConfig != config);
1701c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1702c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        // Make the scratch a render target because we don't have a robust
1703c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        // readTexturePixels as of yet (it calls this function).
1704c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        const GrTextureDesc desc = {
1705c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            kRenderTarget_GrTextureFlagBit,
1706c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            width, height,
170778d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com            config,
170878d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com            {0}, // samples
1709c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        };
1710c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com
171156d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // When a full readback is faster than a partial we could always make
171256d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // the scratch exactly match the passed rect. However, if we see many
171356d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // different size rectangles we will trash our texture cache and pay the
171456d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // cost of creating and destroying many textures. So, we only request
171556d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // an exact match when the caller is reading an entire RT.
171656d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ScratchTexMatch match = kApprox_ScratchTexMatch;
171756d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        if (0 == left &&
171856d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            0 == top &&
171956d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->width() == width &&
172056d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->height() == height &&
172156d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            fGpu->fullReadPixelsIsFasterThanPartial()) {
172256d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            match = kExact_ScratchTexMatch;
172356d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        }
172456d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ast.set(this, desc, match);
1725c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrTexture* texture = ast.texture();
1726c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (!texture) {
1727c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            return false;
1728c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1729c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        target = texture->asRenderTarget();
1730c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrAssert(NULL != target);
1731c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1732c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrDrawTarget::AutoStateRestore asr(fGpu);
17338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState* drawState = fGpu->drawState();
173452a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com        drawState->reset();
17358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setRenderTarget(target);
1736c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1737c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrMatrix matrix;
1738c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (flipY) {
1739c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.setTranslate(SK_Scalar1 * left,
1740c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                SK_Scalar1 * (top + height));
1741c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.set(GrMatrix::kMScaleY, -GR_Scalar1);
1742c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        } else {
1743c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
1744c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1745c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        matrix.postIDiv(src->width(), src->height());
17461e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com        drawState->sampler(0)->reset(matrix);
17471e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com        drawState->sampler(0)->setRAndBSwap(swapRAndB);
17488f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setTexture(0, src);
1749c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrRect rect;
1750c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        rect.setXYWH(0, 0, SK_Scalar1 * width, SK_Scalar1 * height);
1751c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        fGpu->drawSimpleRect(rect, NULL, 0x1);
1752c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        left = 0;
1753c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        top = 0;
1754c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1755669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    return fGpu->readPixels(target,
1756c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                            left, top, width, height,
1757c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                            config, buffer, rowBytes, flipY);
175827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
175927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
176075f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.comvoid GrContext::resolveRenderTarget(GrRenderTarget* target) {
176175f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    GrAssert(target);
176275f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
176375f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // In the future we may track whether there are any pending draws to this
176475f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // target. We don't today so we always perform a flush. We don't promise
176575f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // this to our clients, though.
176675f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    this->flush();
176775f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    fGpu->resolveRenderTarget(target);
176875f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com}
176975f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com
1770ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.orgvoid GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst) {
1771ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    if (NULL == src || NULL == dst) {
1772ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        return;
1773ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
1774ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(src);
1775ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
1776ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    GrDrawTarget::AutoStateRestore asr(fGpu);
17778f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
177852a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com    drawState->reset();
17798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(dst);
1780ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    GrMatrix sampleM;
1781ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    sampleM.setIDiv(src->width(), src->height());
17828f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setTexture(0, src);
17831e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->reset(sampleM);
17845db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com    SkRect rect = SkRect::MakeXYWH(0, 0,
17855db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                                   SK_Scalar1 * src->width(),
17865db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                                   SK_Scalar1 * src->height());
1787ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    fGpu->drawSimpleRect(rect, NULL, 1 << 0);
1788ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org}
1789ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
17906f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.comvoid GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target,
17916f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                int left, int top,
17926f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                int width, int height,
17936f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                GrPixelConfig config,
17946f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                const void* buffer,
17956f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                size_t rowBytes,
17966f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                uint32_t flags) {
17976f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
1798bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
17996f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
18006f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (NULL == target) {
18018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        target = fGpu->drawState()->getRenderTarget();
18026f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        if (NULL == target) {
18036f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com            return;
18046f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        }
18056f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
180627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
180727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // TODO: when underlying api has a direct way to do this we should use it
180827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // (e.g. glDrawPixels on desktop GL).
180927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1810a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // If the RT is also a texture and we don't have to do PM/UPM conversion
1811a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // then take the texture path, which we expect to be at least as fast or
1812a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // faster since it doesn't use an intermediate texture as we do below.
1813a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1814a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#if !GR_MAC_BUILD
1815a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // At least some drivers on the Mac get confused when glTexImage2D is called
1816a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // on a texture attached to an FBO. The FBO still sees the old image. TODO:
1817a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // determine what OS versions and/or HW is affected.
1818a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    if (NULL != target->asTexture() &&
1819a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        GrPixelConfigIsUnpremultiplied(target->config()) ==
1820a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config)) {
1821a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1822a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        this->internalWriteTexturePixels(target->asTexture(),
1823a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                                         left, top, width, height,
1824a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                                         config, buffer, rowBytes, flags);
1825a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        return;
1826a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1827a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#endif
1828a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    if (!GrPixelConfigIsUnpremultiplied(target->config()) &&
1829a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config) &&
1830a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        !fGpu->canPreserveReadWriteUnpremulPixels()) {
1831a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkCanvas::Config8888 srcConfig8888, dstConfig8888;
1832a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        if (!grconfig_to_config8888(config, &srcConfig8888) ||
1833a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            !grconfig_to_config8888(target->config(), &dstConfig8888)) {
1834a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return;
1835a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        }
1836a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // allocate a tmp buffer and sw convert the pixels to premul
1837a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(width * height);
1838a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        const uint32_t* src = reinterpret_cast<const uint32_t*>(buffer);
1839a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkConvertConfig8888Pixels(tmpPixels.get(), 4 * width, dstConfig8888,
1840a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  src, rowBytes, srcConfig8888,
1841a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  width, height);
1842a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // upload the already premul pixels
1843a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        this->internalWriteRenderTargetPixels(target,
1844a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             left, top,
1845a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             width, height,
1846a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             target->config(),
1847a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             tmpPixels, 4 * width, flags);
1848a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        return;
1849a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1850a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1851a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    bool swapRAndB = fGpu->preferredReadPixelsConfig(config) ==
1852a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                     GrPixelConfigSwapRAndB(config);
1853a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    if (swapRAndB) {
1854a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        config = GrPixelConfigSwapRAndB(config);
1855a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1856a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1857fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    const GrTextureDesc desc = {
185878d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com        kNone_GrTextureFlags, width, height, config, {0}
185927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    };
186050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrAutoScratchTexture ast(this, desc);
186150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrTexture* texture = ast.texture();
186227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL == texture) {
186327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
186427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
18656f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    this->internalWriteTexturePixels(texture, 0, 0, width, height,
18666f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                     config, buffer, rowBytes, flags);
186727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
186827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoStateRestore  asr(fGpu);
18698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
187052a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com    drawState->reset();
187127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
187227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix matrix;
187327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
18748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setViewMatrix(matrix);
18758f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(target);
18768f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setTexture(0, texture);
187727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
18785c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com    matrix.setIDiv(texture->width(), texture->height());
18791e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
18801e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                 GrSamplerState::kNearest_Filter,
18811e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                 matrix);
18821e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->setRAndBSwap(swapRAndB);
188327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
188427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
188527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    static const int VCOUNT = 4;
18866513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    // TODO: Use GrGpu::drawRect here
188727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
188827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (!geo.succeeded()) {
18896513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
189027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
189127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
189227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
189327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT);
189427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
189527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
189627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1897a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.comvoid GrContext::setPaint(const GrPaint& paint) {
189826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
189926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kMaxTextures; ++i) {
190026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        int s = i + GrPaint::kFirstTextureStage;
1901a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        fDrawState->setTexture(s, paint.getTexture(i));
1902bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com        ASSERT_OWNED_RESOURCE(paint.getTexture(i));
1903f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        if (paint.getTexture(i)) {
1904a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com            *fDrawState->sampler(s) = paint.getTextureSampler(i);
1905f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        }
190626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
190726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
1908a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    fDrawState->setFirstCoverageStage(GrPaint::kFirstMaskStage);
190926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
191026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kMaxMasks; ++i) {
191126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        int s = i + GrPaint::kFirstMaskStage;
1912a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        fDrawState->setTexture(s, paint.getMask(i));
1913bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com        ASSERT_OWNED_RESOURCE(paint.getMask(i));
1914f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        if (paint.getMask(i)) {
1915a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com            *fDrawState->sampler(s) = paint.getMaskSampler(i);
1916f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        }
191726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
191826936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com
191926936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com    // disable all stages not accessible via the paint
192026936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com    for (int s = GrPaint::kTotalStages; s < GrDrawState::kNumStages; ++s) {
1921a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        fDrawState->setTexture(s, NULL);
192226936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com    }
192326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
1924a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    fDrawState->setColor(paint.fColor);
192527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
192627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (paint.fDither) {
1927a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        fDrawState->enableState(GrDrawState::kDither_StateBit);
192827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
1929a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        fDrawState->disableState(GrDrawState::kDither_StateBit);
193027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
193127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (paint.fAntiAlias) {
1932a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        fDrawState->enableState(GrDrawState::kHWAntialias_StateBit);
193327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
1934a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        fDrawState->disableState(GrDrawState::kHWAntialias_StateBit);
193527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
193650bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    if (paint.fColorMatrixEnabled) {
1937a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        fDrawState->enableState(GrDrawState::kColorMatrix_StateBit);
1938a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        fDrawState->setColorMatrix(paint.fColorMatrix);
193950bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    } else {
1940a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        fDrawState->disableState(GrDrawState::kColorMatrix_StateBit);
194150bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    }
1942a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    fDrawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
1943a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    fDrawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
1944a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    fDrawState->setCoverage(paint.fCoverage);
1945d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
194695cd7bdf2b4dee54739f0a375fe99a02f86178b0bsalomon@google.com#if GR_DEBUG
1947a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    if ((paint.getActiveMaskStageMask() || 0xffffffff != paint.fCoverage) &&
1948a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        !fGpu->canApplyCoverage()) {
1949d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com        GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
1950d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    }
195195cd7bdf2b4dee54739f0a375fe99a02f86178b0bsalomon@google.com#endif
195227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
195327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1954de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.comGrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
195527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                       DrawCategory category) {
195627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (category != fLastDrawCategory) {
1957fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com        this->flushDrawBuffer();
195827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fLastDrawCategory = category;
195927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
1960a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    this->setPaint(paint);
196127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = fGpu;
196227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    switch (category) {
196327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    case kText_DrawCategory:
196427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if DEFER_TEXT_RENDERING
196527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target = fDrawBuffer;
1966a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        fDrawBuffer->setClip(fGpu->getClip());
196727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
196827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target = fGpu;
196927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
197027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        break;
197127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    case kUnbuffered_DrawCategory:
197227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target = fGpu;
197327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        break;
197427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    case kBuffered_DrawCategory:
197527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target = fDrawBuffer;
1976a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        fDrawBuffer->setClip(fGpu->getClip());
197727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        break;
197827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
197927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return target;
198027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
198127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1982289533ada623f2238a83771eec977f204f75994fbsalomon@google.comGrPathRenderer* GrContext::getPathRenderer(const GrPath& path,
1983289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           GrPathFill fill,
1984c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com                                           const GrDrawTarget* target,
1985289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           bool antiAlias) {
19863008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == fPathRendererChain) {
19873008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        fPathRendererChain =
19883008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com            new GrPathRendererChain(this, GrPathRendererChain::kNone_UsageFlag);
19893008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
1990c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com    return fPathRendererChain->getPathRenderer(path, fill, target, antiAlias);
19913008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com}
19923008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
199327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
199427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
199527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setRenderTarget(GrRenderTarget* target) {
1996bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
1997a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    if (fDrawState->getRenderTarget() != target) {
1998fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com        this->flush(false);
1999a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com        fDrawState->setRenderTarget(target);
2000fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    }
200127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
200227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
200327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrRenderTarget* GrContext::getRenderTarget() {
2004a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    return fDrawState->getRenderTarget();
200527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
200627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
200727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrRenderTarget* GrContext::getRenderTarget() const {
2008a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    return fDrawState->getRenderTarget();
200927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
201027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
201127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrMatrix& GrContext::getMatrix() const {
2012a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    return fDrawState->getViewMatrix();
201327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
201427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
201527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setMatrix(const GrMatrix& m) {
2016a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    fDrawState->setViewMatrix(m);
201727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
201827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
201927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::concatMatrix(const GrMatrix& m) const {
2020a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    fDrawState->preConcatViewMatrix(m);
202127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
202227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
202327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
202427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    intptr_t mask = 1 << shift;
202527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (pred) {
202627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        bits |= mask;
202727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
202827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        bits &= ~mask;
202927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
203027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return bits;
203127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
203227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
203327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::resetStats() {
203427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->resetStats();
203527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
203627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
203705ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.comconst GrGpuStats& GrContext::getStats() const {
203827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return fGpu->getStats();
203927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
204027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
204127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::printStats() const {
204227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->printStats();
204327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
204427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
2045583a1e38503ebd57ba9bd39a3fabe89bead8e76cbsalomon@google.comGrContext::GrContext(GrGpu* gpu) {
204627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu = gpu;
204727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->ref();
2048669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    fGpu->setContext(this);
20498fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
2050a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    fDrawState = new GrDrawState();
2051a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    fGpu->setDrawState(fDrawState);
2052a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com
20533008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    fPathRendererChain = NULL;
2054dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com
205550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    fTextureCache = new GrResourceCache(MAX_TEXTURE_CACHE_COUNT,
205650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                        MAX_TEXTURE_CACHE_BYTES);
205727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fFontCache = new GrFontCache(fGpu);
205827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
205927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fLastDrawCategory = kUnbuffered_DrawCategory;
206027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
20618fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
20628fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
20638fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
20648fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
2065205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fAAFillRectIndexBuffer = NULL;
2066205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fAAStrokeRectIndexBuffer = NULL;
2067a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com
20688fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->setupDrawBuffer();
20698fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
20708fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
20718fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::setupDrawBuffer() {
20728fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
20738fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBuffer);
20748fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBufferVBAllocPool);
20758fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBufferIBAllocPool);
20768fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
207727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT
2078de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferVBAllocPool =
20798fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com        new GrVertexBufferAllocPool(fGpu, false,
208027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                    DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
208127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                    DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS);
2082de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferIBAllocPool =
20838fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com        new GrIndexBufferAllocPool(fGpu, false,
2084de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com                                   DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
208527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                   DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS);
208627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
2087471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com    fDrawBuffer = new GrInOrderDrawBuffer(fGpu,
2088471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com                                          fDrawBufferVBAllocPool,
208927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                          fDrawBufferIBAllocPool);
209027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
209127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
209227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if BATCH_RECT_TO_RECT
209327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
209427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
2095fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    fDrawBuffer->setAutoFlushTarget(fGpu);
2096a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    fDrawBuffer->setDrawState(fDrawState);
209727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
209827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
209927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
210027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if DEFER_TEXT_RENDERING
2101a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    return prepareToDraw(paint, kText_DrawCategory);
210227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
2103a5d2203f58c28db033aad47f95470a2cb36efe29bsalomon@google.com    return prepareToDraw(paint, kUnbuffered_DrawCategory);
210427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
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
21113b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgGrTexture* GrContext::gaussianBlur(GrTexture* srcTexture,
21123b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                   GrAutoScratchTexture* temp1,
21133b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                   GrAutoScratchTexture* temp2,
21143b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                   const SkRect& rect,
21153b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                   float sigmaX, float sigmaY) {
2116ceb441476e1712861e87a9bb428f119349ef6bb5senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(srcTexture);
21173b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrRenderTarget* oldRenderTarget = this->getRenderTarget();
21183b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrClip oldClip = this->getClip();
21193b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrTexture* origTexture = srcTexture;
21203b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrAutoMatrix avm(this, GrMatrix::I());
21213b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    SkIRect clearRect;
21223b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    int scaleFactorX, halfWidthX, kernelWidthX;
21233b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    int scaleFactorY, halfWidthY, kernelWidthY;
21243b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &halfWidthX, &kernelWidthX);
21253b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &halfWidthY, &kernelWidthY);
21263b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
21273b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    SkRect srcRect(rect);
21283b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
21293b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    srcRect.roundOut();
21303b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    scale_rect(&srcRect, scaleFactorX, scaleFactorY);
21313b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setClip(srcRect);
2132bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
21333b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    const GrTextureDesc desc = {
21343b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit,
2135f8aa18c08d97cdc98a85a0422d3415822a73949cbungeman@google.com        SkScalarFloorToInt(srcRect.width()),
2136f8aa18c08d97cdc98a85a0422d3415822a73949cbungeman@google.com        SkScalarFloorToInt(srcRect.height()),
21373b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        kRGBA_8888_GrPixelConfig,
21383b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        {0} // samples
21393b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    };
21401e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com
21413b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    temp1->set(this, desc);
21423b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (temp2) temp2->set(this, desc);
21433b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
21443b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrTexture* dstTexture = temp1->texture();
21453b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrPaint paint;
21463b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    paint.reset();
21473b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    paint.textureSampler(0)->setFilter(GrSamplerState::kBilinear_Filter);
21483b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
21493b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
21503b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(),
21513b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                                   srcTexture->height());
21523b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
21533b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkRect dstRect(srcRect);
21543b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
21553b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                            i < scaleFactorY ? 0.5f : 1.0f);
21563b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.setTexture(0, srcTexture);
21573b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->drawRectToRect(paint, dstRect, srcRect);
21583b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        srcRect = dstRect;
21593b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkTSwap(srcTexture, dstTexture);
21603b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // If temp2 is non-NULL, don't render back to origTexture
21613b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        if (temp2 && dstTexture == origTexture) dstTexture = temp2->texture();
21623b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
21633b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
21643b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (sigmaX > 0.0f) {
21653b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkAutoTMalloc<float> kernelStorageX(kernelWidthX);
21663b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        float* kernelX = kernelStorageX.get();
21673b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        build_kernel(sigmaX, kernelX, kernelWidthX);
21683b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
21693b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        if (scaleFactorX > 1) {
21703b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            // Clear out a halfWidth to the right of the srcRect to prevent the
21713b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            // X convolution from reading garbage.
21723b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            clearRect = SkIRect::MakeXYWH(
21733b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                srcRect.fRight, srcRect.fTop, halfWidthX, srcRect.height());
21743b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            this->clear(&clearRect, 0x0);
21753b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        }
217605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
21773b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
21783b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        convolve(fGpu, srcTexture, srcRect, kernelX, kernelWidthX,
21793b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                 GrSamplerState::kX_FilterDirection);
21803b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkTSwap(srcTexture, dstTexture);
21813b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        if (temp2 && dstTexture == origTexture) dstTexture = temp2->texture();
21823b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
21833b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
21843b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (sigmaY > 0.0f) {
21853b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkAutoTMalloc<float> kernelStorageY(kernelWidthY);
21863b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        float* kernelY = kernelStorageY.get();
21873b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        build_kernel(sigmaY, kernelY, kernelWidthY);
21883b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
21893b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        if (scaleFactorY > 1 || sigmaX > 0.0f) {
21903b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            // Clear out a halfWidth below the srcRect to prevent the Y
21913b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            // convolution from reading garbage.
21923b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            clearRect = SkIRect::MakeXYWH(
21933b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                srcRect.fLeft, srcRect.fBottom, srcRect.width(), halfWidthY);
21943b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            this->clear(&clearRect, 0x0);
21953b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        }
21963b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
21973b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
21983b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        convolve(fGpu, srcTexture, srcRect, kernelY, kernelWidthY,
21993b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                 GrSamplerState::kY_FilterDirection);
22003b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkTSwap(srcTexture, dstTexture);
22013b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        if (temp2 && dstTexture == origTexture) dstTexture = temp2->texture();
22023b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
22033b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
22043b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (scaleFactorX > 1 || scaleFactorY > 1) {
22053b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // Clear one pixel to the right and below, to accommodate bilinear
22063b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // upsampling.
22073b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        clearRect = SkIRect::MakeXYWH(
22083b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            srcRect.fLeft, srcRect.fBottom, srcRect.width() + 1, 1);
22093b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->clear(&clearRect, 0x0);
22103b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        clearRect = SkIRect::MakeXYWH(
22113b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            srcRect.fRight, srcRect.fTop, 1, srcRect.height());
22123b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->clear(&clearRect, 0x0);
22133b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // FIXME:  This should be mitchell, not bilinear.
22143b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.textureSampler(0)->setFilter(GrSamplerState::kBilinear_Filter);
22153b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(),
22163b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                                   srcTexture->height());
22173b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
22183b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.setTexture(0, srcTexture);
22193b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkRect dstRect(srcRect);
22203b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        scale_rect(&dstRect, scaleFactorX, scaleFactorY);
22213b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->drawRectToRect(paint, dstRect, srcRect);
22223b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        srcRect = dstRect;
22233b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkTSwap(srcTexture, dstTexture);
22243b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
22253b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setRenderTarget(oldRenderTarget);
22263b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setClip(oldClip);
22273b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    return srcTexture;
22283b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
22293b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
22303b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgGrTexture* GrContext::applyMorphology(GrTexture* srcTexture,
22313b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                      const GrRect& rect,
22323b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                      GrTexture* temp1, GrTexture* temp2,
22333b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                      GrSamplerState::Filter filter,
22343b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                      SkISize radius) {
2235ceb441476e1712861e87a9bb428f119349ef6bb5senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(srcTexture);
22363b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrRenderTarget* oldRenderTarget = this->getRenderTarget();
22373b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrAutoMatrix avm(this, GrMatrix::I());
22383b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrClip oldClip = this->getClip();
22393b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setClip(GrRect::MakeWH(srcTexture->width(), srcTexture->height()));
22403b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (radius.fWidth > 0) {
22413b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(temp1->asRenderTarget());
22423b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        apply_morphology(fGpu, srcTexture, rect, radius.fWidth, filter,
22433b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                         GrSamplerState::kX_FilterDirection);
22443b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkIRect clearRect = SkIRect::MakeXYWH(rect.fLeft, rect.fBottom,
22453b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                              rect.width(), radius.fHeight);
22463b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->clear(&clearRect, 0x0);
22473b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        srcTexture = temp1;
22483b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
22493b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (radius.fHeight > 0) {
22503b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(temp2->asRenderTarget());
22513b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        apply_morphology(fGpu, srcTexture, rect, radius.fHeight, filter,
22523b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                         GrSamplerState::kY_FilterDirection);
22533b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        srcTexture = temp2;
22543b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
22553b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setRenderTarget(oldRenderTarget);
22563b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setClip(oldClip);
22573b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    return srcTexture;
2258027de5f922e8ad1acc5402829f716b8c513fdd8dsenorblanco@chromium.org}
2259c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
2260c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
2261