GrContext.cpp revision 05054f1a78a697b507580d0025db6c90423e033f
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
2727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)
2827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
29d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// When we're using coverage AA but the blend is incompatible (given gpu
30d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// limitations) should we disable AA or draw wrong?
31950d7a8d8def14efc98d12d6947347fde351b737bsalomon@google.com#define DISABLE_COVERAGE_AA_FOR_BLEND 1
32d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
338ccadddfa78adbdbbdfa724247318436465a7378bsalomon@google.comstatic const size_t MAX_TEXTURE_CACHE_COUNT = 256;
348ccadddfa78adbdbbdfa724247318436465a7378bsalomon@google.comstatic const size_t MAX_TEXTURE_CACHE_BYTES = 16 * 1024 * 1024;
3527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
3627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 18;
3727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
3827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
3927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com// We are currently only batching Text and drawRectToRect, both
4027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com// of which use the quad index buffer.
4127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 0;
4227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 0;
4327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
44bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com#define ASSERT_OWNED_RESOURCE(R) GrAssert(!(R) || (R)->getContext() == this)
45bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
4605ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.comGrContext* GrContext::Create(GrEngine engine,
4705ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com                             GrPlatform3DContext context3D) {
4827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrContext* ctx = NULL;
4927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrGpu* fGpu = GrGpu::Create(engine, context3D);
5027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != fGpu) {
5127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        ctx = new GrContext(fGpu);
5227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fGpu->unref();
5327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
5427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return ctx;
5527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
5627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
5727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrContext::~GrContext() {
588fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
5927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fTextureCache;
6027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fFontCache;
6127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBuffer;
6227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBufferVBAllocPool;
63de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    delete fDrawBufferIBAllocPool;
643008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
65205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrSafeUnref(fAAFillRectIndexBuffer);
66205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrSafeUnref(fAAStrokeRectIndexBuffer);
67205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->unref();
683008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeUnref(fPathRendererChain);
6927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
7027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
718fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::contextLost() {
7253a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    contextDestroyed();
7353a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    this->setupDrawBuffer();
7453a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com}
7553a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com
7653a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.comvoid GrContext::contextDestroyed() {
77205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // abandon first to so destructors
78205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // don't try to free the resources in the API.
79205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->abandonResources();
80205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
813008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources that
823008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // are now unusable
833008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeSetNull(fPathRendererChain);
843008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
858fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBuffer;
868fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
87205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
888fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferVBAllocPool;
898fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
90205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
918fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferIBAllocPool;
928fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
938fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
94205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrSafeSetNull(fAAFillRectIndexBuffer);
95205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrSafeSetNull(fAAStrokeRectIndexBuffer);
96205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
978fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fTextureCache->removeAll();
988fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
998fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
1008fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
1018fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1028fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::resetContext() {
1038fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
1048fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
1058fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1068fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::freeGpuResources() {
1078fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
1088fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fTextureCache->removeAll();
1098fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
1103008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources
1113008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeSetNull(fPathRendererChain);
11227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
11327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
11405e70247c31ae927074ef27ea9893634a8dda543twiz@google.comsize_t GrContext::getGpuTextureCacheBytes() const {
11505e70247c31ae927074ef27ea9893634a8dda543twiz@google.com  return fTextureCache->getCachedResourceBytes();
11605e70247c31ae927074ef27ea9893634a8dda543twiz@google.com}
11705e70247c31ae927074ef27ea9893634a8dda543twiz@google.com
118fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
119fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
12026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.comint GrContext::PaintStageVertexLayoutBits(
12126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                            const GrPaint& paint,
12226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                            const bool hasTexCoords[GrPaint::kTotalStages]) {
12326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int stageMask = paint.getActiveStageMask();
12426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int layout = 0;
12526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kTotalStages; ++i) {
12626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        if ((1 << i) & stageMask) {
12726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            if (NULL != hasTexCoords && hasTexCoords[i]) {
12826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(i, i);
12926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            } else {
13026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(i);
13126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            }
13226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        }
13326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
13426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    return layout;
13526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com}
13626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
13726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
13826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
13926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
140fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.comenum {
141558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    // flags for textures
142558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kNPOTBit            = 0x1,
143558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kFilterBit          = 0x2,
144558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kScratchBit         = 0x4,
145558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
146558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    // resource type
147558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kTextureBit         = 0x8,
148558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    kStencilBufferBit   = 0x10
149fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com};
150fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
15150398bf7f1953e640e5529616e710cf540799731bsalomon@google.comGrTexture* GrContext::TextureCacheEntry::texture() const {
15250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (NULL == fEntry) {
15350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        return NULL;
15450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    } else {
15550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        return (GrTexture*) fEntry->resource();
15650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    }
15750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com}
15850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
15950398bf7f1953e640e5529616e710cf540799731bsalomon@google.comnamespace {
16050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com// returns true if this is a "special" texture because of gpu NPOT limitations
16150398bf7f1953e640e5529616e710cf540799731bsalomon@google.combool gen_texture_key_values(const GrGpu* gpu,
1621fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                            const GrSamplerState* sampler,
16350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            GrContext::TextureKey clientKey,
16450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            int width,
16550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            int height,
16678d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com                            int sampleCnt,
16750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            bool scratch,
16850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                            uint32_t v[4]) {
16950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GR_STATIC_ASSERT(sizeof(GrContext::TextureKey) == sizeof(uint64_t));
17050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // we assume we only need 16 bits of width and height
17150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // assert that texture creation will fail anyway if this assumption
17250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // would cause key collisions.
17318c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    GrAssert(gpu->getCaps().fMaxTextureSize <= SK_MaxU16);
17450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    v[0] = clientKey & 0xffffffffUL;
17550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    v[1] = (clientKey >> 32) & 0xffffffffUL;
17650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    v[2] = width | (height << 16);
17750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
17878d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com    v[3] = (sampleCnt << 24);
17978d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com    GrAssert(sampleCnt >= 0 && sampleCnt < 256);
18078d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com
18118c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    if (!gpu->getCaps().fNPOTTextureTileSupport) {
182fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
183fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
1841fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        bool tiled = NULL != sampler &&
1851fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                     ((sampler->getWrapX() != GrSamplerState::kClamp_WrapMode) ||
1861fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                      (sampler->getWrapY() != GrSamplerState::kClamp_WrapMode));
187fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
188fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        if (tiled && !isPow2) {
18950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            v[3] |= kNPOTBit;
1901fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com            if (GrSamplerState::kNearest_Filter != sampler->getFilter()) {
19150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                v[3] |= kFilterBit;
192fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com            }
193fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        }
194fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
195fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
19650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (scratch) {
19750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        v[3] |= kScratchBit;
198fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
19950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
200558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[3] |= kTextureBit;
201558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
20250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    return v[3] & kNPOTBit;
20350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com}
204558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
205558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com// we should never have more than one stencil buffer with same combo of
206558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com// (width,height,samplecount)
207558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid gen_stencil_key_values(int width, int height,
208558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                            int sampleCnt, uint32_t v[4]) {
209558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[0] = width;
210558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[1] = height;
211558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[2] = sampleCnt;
212558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[3] = kStencilBufferBit;
213558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
214558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
215558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid gen_stencil_key_values(const GrStencilBuffer* sb,
216558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                            uint32_t v[4]) {
217558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(sb->width(), sb->height(),
218558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                           sb->numSamples(), v);
219558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
22082c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com
221fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com}
222fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
2231fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.comGrContext::TextureCacheEntry GrContext::findAndLockTexture(
2241fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        TextureKey key,
2251fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        int width,
2261fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        int height,
2271fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrSamplerState* sampler) {
22850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    uint32_t v[4];
22978d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com    gen_texture_key_values(fGpu, sampler, key, width, height, 0, false, v);
23050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrResourceKey resourceKey(v);
231558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    return TextureCacheEntry(fTextureCache->findAndLock(resourceKey,
232558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                            GrResourceCache::kNested_LockType));
233558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
234558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
235fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.combool GrContext::isTextureInCache(TextureKey key,
236fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com                                 int width,
237fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com                                 int height,
2381fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                 const GrSamplerState* sampler) const {
239fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    uint32_t v[4];
24078d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com    gen_texture_key_values(fGpu, sampler, key, width, height, 0, false, v);
241fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    GrResourceKey resourceKey(v);
242fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    return fTextureCache->hasKey(resourceKey);
243fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com}
244fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com
245558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comGrResourceEntry* GrContext::addAndLockStencilBuffer(GrStencilBuffer* sb) {
246bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(sb);
247558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    uint32_t v[4];
248558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(sb, v);
249558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceKey resourceKey(v);
250558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    return fTextureCache->createAndLock(resourceKey, sb);
251558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
252558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
253558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comGrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
254558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                              int sampleCnt) {
255558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    uint32_t v[4];
256558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(width, height, sampleCnt, v);
257558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceKey resourceKey(v);
258558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceEntry* entry = fTextureCache->findAndLock(resourceKey,
259558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                            GrResourceCache::kSingle_LockType);
260558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    if (NULL != entry) {
261558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        GrStencilBuffer* sb = (GrStencilBuffer*) entry->resource();
262558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        return sb;
263558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    } else {
264558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        return NULL;
265558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    }
266558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
267558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
268558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid GrContext::unlockStencilBuffer(GrResourceEntry* sbEntry) {
269bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(sbEntry->resource());
270558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    fTextureCache->unlock(sbEntry);
27127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
27227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
27327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic void stretchImage(void* dst,
27427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstW,
27527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstH,
27627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         void* src,
27727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcW,
27827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcH,
27927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int bpp) {
28027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dx = (srcW << 16) / dstW;
28127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dy = (srcH << 16) / dstH;
28227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
28327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed y = dy >> 1;
28427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
28527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    int dstXLimit = dstW*bpp;
28627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    for (int j = 0; j < dstH; ++j) {
28727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrFixed x = dx >> 1;
28827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
28927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* dstRow = (uint8_t*)dst + j*dstW*bpp;
29027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < dstXLimit; i += bpp) {
29127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            memcpy((uint8_t*) dstRow + i,
29227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   (uint8_t*) srcRow + (x>>16)*bpp,
29327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   bpp);
29427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            x += dx;
29527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
29627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        y += dy;
29727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
29827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
29927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
3001fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.comGrContext::TextureCacheEntry GrContext::createAndLockTexture(
3011fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        TextureKey key,
3021fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrSamplerState* sampler,
3031fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrTextureDesc& desc,
3041fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        void* srcData,
3051fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        size_t rowBytes) {
306278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::createAndLockTexture");
30727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
30827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_DUMP_TEXTURE_UPLOAD
30927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
31027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
31127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
31250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    TextureCacheEntry entry;
31350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    uint32_t v[4];
31450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    bool special = gen_texture_key_values(fGpu, sampler, key,
31578d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com                                          desc.fWidth, desc.fHeight,
31678d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com                                          desc.fSampleCnt, false, v);
31750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrResourceKey resourceKey(v);
31850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
31927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (special) {
3201fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        GrAssert(NULL != sampler);
3211fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        TextureCacheEntry clampEntry = this->findAndLockTexture(key,
3221fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                                desc.fWidth,
3231fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                                desc.fHeight,
3241fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                                NULL);
32527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
32650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        if (NULL == clampEntry.texture()) {
3271fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com            clampEntry = this->createAndLockTexture(key, NULL, desc,
3281fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                    srcData, rowBytes);
32950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            GrAssert(NULL != clampEntry.texture());
33050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            if (NULL == clampEntry.texture()) {
33150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                return entry;
33227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
33327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
334fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        GrTextureDesc rtDesc = desc;
335fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        rtDesc.fFlags =  rtDesc.fFlags |
336fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com                         kRenderTarget_GrTextureFlagBit |
337fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com                         kNoStencil_GrTextureFlagBit;
3389962108c400dadcae913614e8a5ab781780981d8bsalomon@google.com        rtDesc.fWidth  = GrNextPow2(GrMax(desc.fWidth, 64));
3399962108c400dadcae913614e8a5ab781780981d8bsalomon@google.com        rtDesc.fHeight = GrNextPow2(GrMax(desc.fHeight, 64));
34027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
34127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
34227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
34327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != texture) {
34427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrDrawTarget::AutoStateRestore asr(fGpu);
3458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = fGpu->drawState();
34652a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com            drawState->reset();
3478f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->setRenderTarget(texture->asRenderTarget());
3488f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->setTexture(0, clampEntry.texture());
34982c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com
3506aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            GrSamplerState::Filter filter;
3516aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // if filtering is not desired then we want to ensure all
3526aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // texels in the resampled image are copies of texels from
3536aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // the original.
3541fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com            if (GrSamplerState::kNearest_Filter == sampler->getFilter()) {
3556aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com                filter = GrSamplerState::kNearest_Filter;
3566aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            } else {
3576aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com                filter = GrSamplerState::kBilinear_Filter;
3586aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            }
3591e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com            drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
3601e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                         filter);
36127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
36227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            static const GrVertexLayout layout =
36327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
36427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
36527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
36627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (arg.succeeded()) {
36727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                GrPoint* verts = (GrPoint*) arg.vertices();
36827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                verts[0].setIRectFan(0, 0,
36927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     texture->width(),
37027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     texture->height(),
37127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     2*sizeof(GrPoint));
37227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
37327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,
37427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     0, 4);
37550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                entry.set(fTextureCache->createAndLock(resourceKey, texture));
37627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
3771da0746fa155cdca982ae8deb68cc64f540c92dfbsalomon@google.com            texture->releaseRenderTarget();
37827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        } else {
37927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // TODO: Our CPU stretch doesn't filter. But we create separate
38027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // stretched textures when the sampler state is either filtered or
38127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // not. Either implement filtered stretch blit on CPU or just create
38227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // one when FBO case fails.
38327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
384fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com            rtDesc.fFlags = kNone_GrTextureFlags;
38527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // no longer need to clamp at min RT size.
38627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            rtDesc.fWidth  = GrNextPow2(desc.fWidth);
38727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            rtDesc.fHeight = GrNextPow2(desc.fHeight);
38864c4fe4113424bcfab8b3e0c7049887fda5ab4ffbsalomon@google.com            int bpp = GrBytesPerPixel(desc.fConfig);
3893582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com            SkAutoSMalloc<128*128*4> stretchedPixels(bpp *
39027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     rtDesc.fWidth *
39127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     rtDesc.fHeight);
39227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
39327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         srcData, desc.fWidth, desc.fHeight, bpp);
39427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
39527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            size_t stretchedRowBytes = rtDesc.fWidth * bpp;
39627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
39727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrTexture* texture = fGpu->createTexture(rtDesc,
39827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     stretchedPixels.get(),
39927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     stretchedRowBytes);
40027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrAssert(NULL != texture);
40150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            entry.set(fTextureCache->createAndLock(resourceKey, texture));
40227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
40350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->unlock(clampEntry.cacheEntry());
40427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
40527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
40627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
40727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != texture) {
40850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            entry.set(fTextureCache->createAndLock(resourceKey, texture));
40927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
41027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
41127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return entry;
41227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
41327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
41450398bf7f1953e640e5529616e710cf540799731bsalomon@google.comnamespace {
41550398bf7f1953e640e5529616e710cf540799731bsalomon@google.cominline void gen_scratch_tex_key_values(const GrGpu* gpu,
41650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                       const GrTextureDesc& desc,
41750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                       uint32_t v[4]) {
41850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // Instead of a client-provided key of the texture contents
41950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // we create a key of from the descriptor.
42078d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com    GrContext::TextureKey descKey = (desc.fFlags << 8) |
42164c4fe4113424bcfab8b3e0c7049887fda5ab4ffbsalomon@google.com                                    ((uint64_t) desc.fConfig << 32);
42250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // this code path isn't friendly to tiling with NPOT restricitons
42350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // We just pass ClampNoFilter()
4241fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com    gen_texture_key_values(gpu, NULL, descKey, desc.fWidth,
42578d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com                           desc.fHeight, desc.fSampleCnt, true, v);
42650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com}
42727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
42827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
42950398bf7f1953e640e5529616e710cf540799731bsalomon@google.comGrContext::TextureCacheEntry GrContext::lockScratchTexture(
43050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                                const GrTextureDesc& inDesc,
43150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                                ScratchTexMatch match) {
43250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
433b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    GrTextureDesc desc = inDesc;
43450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (kExact_ScratchTexMatch != match) {
43550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        // bin by pow2 with a reasonable min
43650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        static const int MIN_SIZE = 256;
43750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fWidth  = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
43850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
43950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    }
440b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
44150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrResourceEntry* entry;
442b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origWidth = desc.fWidth;
443b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origHeight = desc.fHeight;
444b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    bool doubledW = false;
445b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    bool doubledH = false;
446b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
447b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    do {
44850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        uint32_t v[4];
44950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        gen_scratch_tex_key_values(fGpu, desc, v);
45050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        GrResourceKey key(v);
451558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        entry = fTextureCache->findAndLock(key,
452558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                           GrResourceCache::kNested_LockType);
453b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        // if we miss, relax the fit of the flags...
454b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        // then try doubling width... then height.
45550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        if (NULL != entry || kExact_ScratchTexMatch == match) {
456b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
457b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
458b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        if (!(desc.fFlags & kRenderTarget_GrTextureFlagBit)) {
459b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = desc.fFlags | kRenderTarget_GrTextureFlagBit;
460b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (desc.fFlags & kNoStencil_GrTextureFlagBit) {
461b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit;
462b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (!doubledW) {
463b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = inDesc.fFlags;
464b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fWidth *= 2;
465b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            doubledW = true;
466b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (!doubledH) {
467b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = inDesc.fFlags;
468b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fWidth = origWidth;
469b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fHeight *= 2;
470b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            doubledH = true;
471b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else {
472b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
473b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
474b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
475b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    } while (true);
476b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
477b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    if (NULL == entry) {
478b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fFlags = inDesc.fFlags;
479b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fWidth = origWidth;
480b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fHeight = origHeight;
481b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
482b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        if (NULL != texture) {
48350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            uint32_t v[4];
48450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            gen_scratch_tex_key_values(fGpu, desc, v);
48550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            GrResourceKey key(v);
486b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            entry = fTextureCache->createAndLock(key, texture);
487b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
488b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
489b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
490b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // If the caller gives us the same desc/sampler twice we don't want
491b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // to return the same texture the second time (unless it was previously
492b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // released). So we detach the entry from the cache and reattach at release.
493b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    if (NULL != entry) {
494b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        fTextureCache->detach(entry);
495b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
49650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    return TextureCacheEntry(entry);
497b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com}
498b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
49950398bf7f1953e640e5529616e710cf540799731bsalomon@google.comvoid GrContext::unlockTexture(TextureCacheEntry entry) {
500bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(entry.texture());
50150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // If this is a scratch texture we detached it from the cache
50250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // while it was locked (to avoid two callers simultaneously getting
50350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // the same texture).
50450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (kScratchBit & entry.cacheEntry()->key().getValue32(3)) {
50550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->reattachAndUnlock(entry.cacheEntry());
506fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    } else {
50750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->unlock(entry.cacheEntry());
508fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
50927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
51027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
511fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.comGrTexture* GrContext::createUncachedTexture(const GrTextureDesc& desc,
51227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            void* srcData,
51327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            size_t rowBytes) {
51427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return fGpu->createTexture(desc, srcData, rowBytes);
51527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
51627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
51727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::getTextureCacheLimits(int* maxTextures,
51827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                      size_t* maxTextureBytes) const {
51927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fTextureCache->getLimits(maxTextures, maxTextureBytes);
52027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
52127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
52227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
52327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fTextureCache->setLimits(maxTextures, maxTextureBytes);
52427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
52527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
526919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxTextureSize() const {
52718c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    return fGpu->getCaps().fMaxTextureSize;
528919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com}
529919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
530919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxRenderTargetSize() const {
53118c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    return fGpu->getCaps().fMaxRenderTargetSize;
53227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
53327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
53427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com///////////////////////////////////////////////////////////////////////////////
53527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
536e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrTexture* GrContext::createPlatformTexture(const GrPlatformTextureDesc& desc) {
537e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com    return fGpu->createPlatformTexture(desc);
538e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
539e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
540e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrRenderTarget* GrContext::createPlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) {
541e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com    return fGpu->createPlatformRenderTarget(desc);
542e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
543e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
5445877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
5455877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com
5461fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.combool GrContext::supportsIndex8PixelConfig(const GrSamplerState* sampler,
5471f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com                                          int width, int height) const {
54818c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    const GrDrawTarget::Caps& caps = fGpu->getCaps();
54918c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    if (!caps.f8BitPaletteSupport) {
55027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return false;
55127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
55227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
55327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
55427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
55527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (!isPow2) {
5561fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        bool tiled = NULL != sampler &&
5571fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                     (sampler->getWrapX() != GrSamplerState::kClamp_WrapMode ||
5581fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                      sampler->getWrapY() != GrSamplerState::kClamp_WrapMode);
55918c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com        if (tiled && !caps.fNPOTTextureTileSupport) {
56027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return false;
56127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
56227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
56327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return true;
56427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
56527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
56627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
56727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
56805ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.comconst GrClip& GrContext::getClip() const { return fGpu->getClip(); }
56905ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com
57027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setClip(const GrClip& clip) {
57127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->setClip(clip);
5728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    fGpu->drawState()->enableState(GrDrawState::kClip_StateBit);
57327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
57427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
57527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setClip(const GrIRect& rect) {
57627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrClip clip;
577d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    clip.setFromIRect(rect);
57827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->setClip(clip);
57927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
58027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
58127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
58227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
5836aa25c3f555dc2a6711365d14279db3ec909e064bsalomon@google.comvoid GrContext::clear(const GrIRect* rect, const GrColor color) {
584398109cc3e56b8122ad21c4d43a74a83be5b42a8bsalomon@google.com    this->flush();
5856aa25c3f555dc2a6711365d14279db3ec909e064bsalomon@google.com    fGpu->clear(rect, color);
58627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
58727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
58827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawPaint(const GrPaint& paint) {
58927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // set rect to be big enough to fill the space, but not super-huge, so we
59027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // don't overflow fixed-point implementations
591d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    GrRect r;
592d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    r.setLTRB(0, 0,
593d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com              GrIntToScalar(getRenderTarget()->width()),
594d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com              GrIntToScalar(getRenderTarget()->height()));
59527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix inverse;
5968c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    SkTLazy<GrPaint> tmpPaint;
5978c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    const GrPaint* p = &paint;
5988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
5998f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrAutoMatrix am;
6008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6014f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // We attempt to map r by the inverse matrix and draw that. mapRect will
6024f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // map the four corners and bound them with a new rect. This will not
6034f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // produce a correct result for some perspective matrices.
6048c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    if (!this->getMatrix().hasPerspective()) {
6058f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        if (!drawState->getViewInverse(&inverse)) {
6068c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            GrPrintf("Could not invert matrix");
6078c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            return;
6088c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
60927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        inverse.mapRect(&r);
61027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
6118c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        if (paint.getActiveMaskStageMask() || paint.getActiveStageMask()) {
6128f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            if (!drawState->getViewInverse(&inverse)) {
6138c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com                GrPrintf("Could not invert matrix");
6148c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com                return;
6158c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            }
6168c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.set(paint);
6178c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.get()->preConcatActiveSamplerMatrices(inverse);
6188c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            p = tmpPaint.get();
6198c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
6204f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com        am.set(this, GrMatrix::I());
62127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
6224f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // by definition this fills the entire clip, no need for AA
6234f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    if (paint.fAntiAlias) {
6248c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        if (!tmpPaint.isValid()) {
6258c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.set(paint);
6268c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            p = tmpPaint.get();
6278c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
6288c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        GrAssert(p == tmpPaint.get());
6298c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        tmpPaint.get()->fAntiAlias = false;
6304f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    }
6314f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    this->drawRect(*p, r);
63227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
63327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
634205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
635205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
636d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.comnamespace {
637d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.cominline bool disable_coverage_aa_for_blend(GrDrawTarget* target) {
638d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage();
639d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com}
640d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com}
641d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
64206afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
64306afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
64427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com/*  create a triangle strip that strokes the specified triangle. There are 8
64527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com unique vertices, but we repreat the last 2 to close up. Alternatively we
64627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com could use an indices array, and then only send 8 verts, but not sure that
64727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com would be faster.
64827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com */
649205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
65027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               GrScalar width) {
65127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    const GrScalar rad = GrScalarHalf(width);
652205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    rect.sort();
65327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
65427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[0].set(rect.fLeft + rad, rect.fTop + rad);
65527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[1].set(rect.fLeft - rad, rect.fTop - rad);
65627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[2].set(rect.fRight - rad, rect.fTop + rad);
65727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[3].set(rect.fRight + rad, rect.fTop - rad);
65827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[4].set(rect.fRight - rad, rect.fBottom - rad);
65927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[5].set(rect.fRight + rad, rect.fBottom + rad);
66027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
66127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
66227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[8] = verts[0];
66327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[9] = verts[1];
66427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
66527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
666205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic void setInsetFan(GrPoint* pts, size_t stride,
667205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        const GrRect& r, GrScalar dx, GrScalar dy) {
668205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    pts->setRectFan(r.fLeft + dx, r.fTop + dy, r.fRight - dx, r.fBottom - dy, stride);
669205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
670205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
671205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic const uint16_t gFillAARectIdx[] = {
672205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    0, 1, 5, 5, 4, 0,
673205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    1, 2, 6, 6, 5, 1,
674205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    2, 3, 7, 7, 6, 2,
675205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    3, 0, 4, 4, 7, 3,
676205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    4, 5, 6, 6, 7, 4,
677205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com};
678205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
679205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comint GrContext::aaFillRectIndexCount() const {
680205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    return GR_ARRAY_COUNT(gFillAARectIdx);
681205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
682205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
683205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comGrIndexBuffer* GrContext::aaFillRectIndexBuffer() {
684205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL == fAAFillRectIndexBuffer) {
685205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        fAAFillRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gFillAARectIdx),
686205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                                                         false);
6879b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        if (NULL != fAAFillRectIndexBuffer) {
6889b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    #if GR_DEBUG
6899b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            bool updated =
6909b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    #endif
6919b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            fAAFillRectIndexBuffer->updateData(gFillAARectIdx,
6929b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com                                               sizeof(gFillAARectIdx));
6939b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            GR_DEBUGASSERT(updated);
6949b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        }
695205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
696205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    return fAAFillRectIndexBuffer;
697205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
698205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
699205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic const uint16_t gStrokeAARectIdx[] = {
700205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
701205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
702205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
703205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
704205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
705205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
706205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
707205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
708205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
709205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
710205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
711205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
712205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
713205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
714205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com};
715205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
716205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comint GrContext::aaStrokeRectIndexCount() const {
717205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    return GR_ARRAY_COUNT(gStrokeAARectIdx);
718205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
719205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
720205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comGrIndexBuffer* GrContext::aaStrokeRectIndexBuffer() {
721205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL == fAAStrokeRectIndexBuffer) {
722205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        fAAStrokeRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gStrokeAARectIdx),
723205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                                                           false);
7249b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        if (NULL != fAAStrokeRectIndexBuffer) {
7259b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    #if GR_DEBUG
7269b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            bool updated =
7279b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    #endif
7289b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx,
7299b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com                                                 sizeof(gStrokeAARectIdx));
7309b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com            GR_DEBUGASSERT(updated);
7319b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        }
732205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
733205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    return fAAStrokeRectIndexBuffer;
734205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
735205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
736a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.comstatic GrVertexLayout aa_rect_layout(const GrDrawTarget* target,
737a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                     bool useCoverage) {
738a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrVertexLayout layout = 0;
7399381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
7408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        if (NULL != target->getDrawState().getTexture(s)) {
741a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
742a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        }
743a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    }
744a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    if (useCoverage) {
745a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        layout |= GrDrawTarget::kCoverage_VertexLayoutBit;
746a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    } else {
747a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        layout |= GrDrawTarget::kColor_VertexLayoutBit;
748a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    }
749a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    return layout;
750a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com}
751a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com
752205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comvoid GrContext::fillAARect(GrDrawTarget* target,
753a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                           const GrRect& devRect,
754a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                           bool useVertexCoverage) {
755a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage);
756205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
757205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    size_t vsize = GrDrawTarget::VertexSize(layout);
758205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
759205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(target, layout, 8, 0);
7606513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    if (!geo.succeeded()) {
7616513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
7626513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        return;
7636513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    }
7649b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer();
7659b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    if (NULL == indexBuffer) {
7669b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        GrPrintf("Failed to create index buffer!\n");
7679b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        return;
7689b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    }
769205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
770205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
771205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
772205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
773205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
774205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
775205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan0Pos, vsize, devRect, -GR_ScalarHalf, -GR_ScalarHalf);
776205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan1Pos, vsize, devRect,  GR_ScalarHalf,  GR_ScalarHalf);
777205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
778205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += sizeof(GrPoint);
779205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 4; ++i) {
780205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
781205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
782205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
783a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrColor innerColor;
784a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    if (useVertexCoverage) {
785e10f6fdf76fa9b627cbb8471b58b13c457af83e8bsalomon@google.com        innerColor = 0xffffffff;
786a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    } else {
7878f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        innerColor = target->getDrawState().getColor();
788a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    }
789a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com
790205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += 4 * vsize;
791205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 4; ++i) {
792205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
793205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
794205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
7959b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    target->setIndexSourceToBuffer(indexBuffer);
796205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
797205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    target->drawIndexed(kTriangles_PrimitiveType, 0,
798205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                         0, 8, this->aaFillRectIndexCount());
799205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
800205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
801a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.comvoid GrContext::strokeAARect(GrDrawTarget* target,
802a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             const GrRect& devRect,
803a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             const GrVec& devStrokeSize,
804a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             bool useVertexCoverage) {
805205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    const GrScalar& dx = devStrokeSize.fX;
806205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    const GrScalar& dy = devStrokeSize.fY;
807205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    const GrScalar rx = GrMul(dx, GR_ScalarHalf);
808205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    const GrScalar ry = GrMul(dy, GR_ScalarHalf);
809205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
810205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrScalar spare;
811205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    {
812205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrScalar w = devRect.width() - dx;
813205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrScalar h = devRect.height() - dy;
814205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        spare = GrMin(w, h);
815205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
816205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
817205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (spare <= 0) {
818205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrRect r(devRect);
819205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        r.inset(-rx, -ry);
820a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        fillAARect(target, r, useVertexCoverage);
821205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return;
822205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
823a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage);
824205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    size_t vsize = GrDrawTarget::VertexSize(layout);
825205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
826205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(target, layout, 16, 0);
8276513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    if (!geo.succeeded()) {
8286513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
8296513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        return;
8306513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    }
8319b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer();
8329b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    if (NULL == indexBuffer) {
8339b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        GrPrintf("Failed to create index buffer!\n");
8349b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com        return;
8359b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    }
836205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
837205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
838205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
839205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
840205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
841205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize);
842205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize);
843205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
844205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan0Pos, vsize, devRect, -rx - GR_ScalarHalf, -ry - GR_ScalarHalf);
845205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan1Pos, vsize, devRect, -rx + GR_ScalarHalf, -ry + GR_ScalarHalf);
846205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan2Pos, vsize, devRect,  rx - GR_ScalarHalf,  ry - GR_ScalarHalf);
847205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    setInsetFan(fan3Pos, vsize, devRect,  rx + GR_ScalarHalf,  ry + GR_ScalarHalf);
848205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
849205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += sizeof(GrPoint);
850205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 4; ++i) {
851205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
852205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
853205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
854a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    GrColor innerColor;
855a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    if (useVertexCoverage) {
856e10f6fdf76fa9b627cbb8471b58b13c457af83e8bsalomon@google.com        innerColor = 0xffffffff;
857a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    } else {
8588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        innerColor = target->getDrawState().getColor();
859a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    }
860205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += 4 * vsize;
861205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 8; ++i) {
862205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
863205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
864205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
865205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    verts += 8 * vsize;
866205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    for (int i = 0; i < 8; ++i) {
867205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
868205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
869205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
8709b09c9e91c2863d526cb05e67288c230f5ff33debsalomon@google.com    target->setIndexSourceToBuffer(indexBuffer);
871205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    target->drawIndexed(kTriangles_PrimitiveType,
872205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0, 0, 16, aaStrokeRectIndexCount());
873205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
874205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
87520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com/**
87620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com * Returns true if the rects edges are integer-aligned.
87720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com */
87820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.comstatic bool isIRect(const GrRect& r) {
87920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    return GrScalarIsInt(r.fLeft) && GrScalarIsInt(r.fTop) &&
88020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com           GrScalarIsInt(r.fRight) && GrScalarIsInt(r.fBottom);
88120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com}
88220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
883205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic bool apply_aa_to_rect(GrDrawTarget* target,
884205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             const GrRect& rect,
885205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             GrScalar width,
886205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             const GrMatrix* matrix,
887205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             GrMatrix* combinedMatrix,
888a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             GrRect* devRect,
889a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             bool* useVertexCoverage) {
8902eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // we use a simple coverage ramp to do aa on axis-aligned rects
8912eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // we check if the rect will be axis-aligned, and the rect won't land on
8922eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // integer coords.
893d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
894a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // we are keeping around the "tweak the alpha" trick because
895a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // it is our only hope for the fixed-pipe implementation.
896a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // In a shader implementation we can give a separate coverage input
897289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    // TODO: remove this ugliness when we drop the fixed-pipe impl
898a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    *useVertexCoverage = false;
899d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (!target->canTweakAlphaForCoverage()) {
9002eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com        if (disable_coverage_aa_for_blend(target)) {
9011983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
9022eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            //GrPrintf("Turning off AA to correctly apply blend.\n");
9031983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
904a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            return false;
9052eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com        } else {
9062eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            *useVertexCoverage = true;
907a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        }
908205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
9098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    const GrDrawState& drawState = target->getDrawState();
9108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (drawState.getRenderTarget()->isMultisampled()) {
911205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
912205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
913205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
914471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com    if (0 == width && target->willUseHWAALines()) {
915205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
916205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
917205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
9188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (!drawState.getViewMatrix().preservesAxisAlignment()) {
919205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
920205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
921205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
922205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL != matrix &&
923205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        !matrix->preservesAxisAlignment()) {
924205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
925205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
926205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
9278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    *combinedMatrix = drawState.getViewMatrix();
928205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL != matrix) {
929205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        combinedMatrix->preConcat(*matrix);
930205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrAssert(combinedMatrix->preservesAxisAlignment());
931205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
932205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
933205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    combinedMatrix->mapRect(devRect, rect);
934205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    devRect->sort();
935205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
936205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (width < 0) {
93720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        return !isIRect(*devRect);
938205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    } else {
939205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return true;
940205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
941205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
942205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
94327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRect(const GrPaint& paint,
94427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         const GrRect& rect,
94527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         GrScalar width,
94627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         const GrMatrix* matrix) {
947278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRect");
94827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
94927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
95026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int stageMask = paint.getActiveStageMask();
95127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
952205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrRect devRect = rect;
953205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrMatrix combinedMatrix;
954a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    bool useVertexCoverage;
955289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool needAA = paint.fAntiAlias &&
956289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                  !this->getRenderTarget()->isMultisampled();
957289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix,
958289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &combinedMatrix, &devRect,
959289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &useVertexCoverage);
960205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
961205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (doAA) {
9628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
963205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        if (width >= 0) {
964205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            GrVec strokeSize;;
965205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            if (width > 0) {
966205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.set(width, width);
967cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com                combinedMatrix.mapVectors(&strokeSize, 1);
968205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.setAbs(strokeSize);
969205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            } else {
970205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.set(GR_Scalar1, GR_Scalar1);
971205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            }
972a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            strokeAARect(target, devRect, strokeSize, useVertexCoverage);
973205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        } else {
974a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            fillAARect(target, devRect, useVertexCoverage);
975205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        }
976205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return;
977205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
978205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
97927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (width >= 0) {
98027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // TODO: consider making static vertex buffers for these cases.
98127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // Hairline could be done by just adding closing vertex to
98227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // unitSquareVertexBuffer()
98326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        GrVertexLayout layout =  PaintStageVertexLayoutBits(paint, NULL);
98426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
98527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        static const int worstCaseVertCount = 10;
98627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
98727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
98827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.succeeded()) {
9896513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
99027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
99127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
99227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
99327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPrimitiveType primType;
99427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int vertCount;
99527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPoint* vertex = geo.positions();
99627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
99727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (width > 0) {
99827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 10;
99927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            primType = kTriangleStrip_PrimitiveType;
100027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            setStrokeRectStrip(vertex, rect, width);
100127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        } else {
100227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // hairline
100327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 5;
100427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            primType = kLineStrip_PrimitiveType;
100527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[0].set(rect.fLeft, rect.fTop);
100627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[1].set(rect.fRight, rect.fTop);
100727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[2].set(rect.fRight, rect.fBottom);
100827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[3].set(rect.fLeft, rect.fBottom);
100927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[4].set(rect.fLeft, rect.fTop);
101027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
101127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
10128f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState::AutoViewMatrixRestore avmr;
101327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != matrix) {
10148f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
10158f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            avmr.set(drawState);
10168f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatViewMatrix(*matrix);
10178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatSamplerMatrices(stageMask, *matrix);
101827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
101927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
102027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->drawNonIndexed(primType, 0, vertCount);
102127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
10228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#if GR_STATIC_RECT_VB
102326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
10246513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
10256513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            if (NULL == sqVB) {
10266513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com                GrPrintf("Failed to create static rect vb.\n");
10276513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com                return;
10286513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            }
10296513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            target->setVertexSourceToBuffer(layout, sqVB);
10308f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
10318f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState::AutoViewMatrixRestore avmr(drawState);
103227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrMatrix m;
10338295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com            m.setAll(rect.width(),    0,             rect.fLeft,
1034205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0,            rect.height(), rect.fTop,
1035205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0,            0,             GrMatrix::I()[8]);
103627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
103727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (NULL != matrix) {
103827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                m.postConcat(*matrix);
103927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
10408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatViewMatrix(m);
10418f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatSamplerMatrices(stageMask, m);
104226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
104327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
10448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#else
104526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            target->drawSimpleRect(rect, matrix, stageMask);
10468f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#endif
104727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
104827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
104927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
105027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRectToRect(const GrPaint& paint,
105127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrRect& dstRect,
105227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrRect& srcRect,
105327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrMatrix* dstMatrix,
105427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrMatrix* srcMatrix) {
1055278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRectToRect");
105627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
105726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    // srcRect refers to paint's first texture
105826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    if (NULL == paint.getTexture(0)) {
105927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        drawRect(paint, dstRect, -1, dstMatrix);
106027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
106127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
1062de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com
106327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB);
106427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
106527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_STATIC_RECT_VB
106627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
10678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = target->drawState();
106826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
10698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState::AutoViewMatrixRestore avmr(drawState);
107027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
107127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix m;
107227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
107327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    m.setAll(dstRect.width(), 0,                dstRect.fLeft,
107427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               dstRect.height(), dstRect.fTop,
107527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               0,                GrMatrix::I()[8]);
107627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != dstMatrix) {
107727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        m.postConcat(*dstMatrix);
107827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
10798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->preConcatViewMatrix(m);
108027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
108126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    // srcRect refers to first stage
108226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int otherStageMask = paint.getActiveStageMask() &
108326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                         (~(1 << GrPaint::kFirstTextureStage));
108426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    if (otherStageMask) {
10858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->preConcatSamplerMatrices(otherStageMask, m);
108626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
108726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
108827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    m.setAll(srcRect.width(), 0,                srcRect.fLeft,
108927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               srcRect.height(), srcRect.fTop,
109027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               0,                GrMatrix::I()[8]);
109127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != srcMatrix) {
109227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        m.postConcat(*srcMatrix);
109327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
10948f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->sampler(GrPaint::kFirstTextureStage)->preConcatMatrix(m);
109527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
10966513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
10976513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    if (NULL == sqVB) {
10986513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to create static rect vb.\n");
10996513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        return;
11006513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    }
11016513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    target->setVertexSourceToBuffer(layout, sqVB);
110227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
110327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
110427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
110527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target;
1106de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com#if BATCH_RECT_TO_RECT
110727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = this->prepareToDraw(paint, kBuffered_DrawCategory);
1108de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com#else
110927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
111027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
111127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
11129381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
11139381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    const GrMatrix* srcMatrices[GrDrawState::kNumStages] = {NULL};
111427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    srcRects[0] = &srcRect;
111527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    srcMatrices[0] = srcMatrix;
111627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
111727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices);
111827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
111927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
112027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
112127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawVertices(const GrPaint& paint,
112227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             GrPrimitiveType primitiveType,
112327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int vertexCount,
112427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint positions[],
112527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint texCoords[],
112627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrColor colors[],
112727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const uint16_t indices[],
112827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int indexCount) {
1129278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawVertices");
113027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
113127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo;
113227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
113327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
113427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
113526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    bool hasTexCoords[GrPaint::kTotalStages] = {
113626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        NULL != texCoords,   // texCoordSrc provides explicit stage 0 coords
113726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        0                    // remaining stages use positions
113826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    };
113926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
114026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, hasTexCoords);
114127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
114227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != colors) {
114327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        layout |= GrDrawTarget::kColor_VertexLayoutBit;
114427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
114526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int vertexSize = GrDrawTarget::VertexSize(layout);
114627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
114727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (sizeof(GrPoint) != vertexSize) {
114827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.set(target, layout, vertexCount, 0)) {
11496513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
115027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
115127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
11529381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        int texOffsets[GrDrawState::kMaxTexCoords];
115327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int colorOffset;
115426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
115526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                                                texOffsets,
1156aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com                                                &colorOffset,
1157a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                                NULL,
1158a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                                NULL);
115927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* curVertex = geo.vertices();
116027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
116127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < vertexCount; ++i) {
116227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            *((GrPoint*)curVertex) = positions[i];
116327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
116427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (texOffsets[0] > 0) {
116527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
116627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
116727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (colorOffset > 0) {
116827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
116927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
117026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            curVertex = (void*)((intptr_t)curVertex + vertexSize);
117127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
117227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
117327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->setVertexSourceToArray(layout, positions, vertexCount);
117427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
117527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1176919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // we don't currently apply offscreen AA to this path. Need improved
1177919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // management of GrDrawTarget's geometry to avoid copying points per-tile.
1178a47a48dca5045d71cbc5de343404045209a13e15bsalomon@google.com
11798295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    if (NULL != indices) {
1180919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        target->setIndexSourceToArray(indices, indexCount);
11818295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
118227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
11838295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawNonIndexed(primitiveType, 0, vertexCount);
11848295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
118527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
118627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
118706afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
1188150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com#include "SkDraw.h"
1189150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com#include "SkRasterClip.h"
1190150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1191150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.comnamespace {
1192150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1193150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.comSkPath::FillType gr_fill_to_sk_fill(GrPathFill fill) {
1194150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    switch (fill) {
1195150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        case kWinding_PathFill:
1196150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return SkPath::kWinding_FillType;
1197150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        case kEvenOdd_PathFill:
1198150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return SkPath::kEvenOdd_FillType;
1199150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        case kInverseWinding_PathFill:
1200150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return SkPath::kInverseWinding_FillType;
1201150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        case kInverseEvenOdd_PathFill:
1202150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return SkPath::kInverseEvenOdd_FillType;
1203150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        default:
1204150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            GrCrash("Unexpected fill.");
1205150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return SkPath::kWinding_FillType;
1206150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1207150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
1208150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1209150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com// gets device coord bounds of path (not considering the fill) and clip. The
1210150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com// path bounds will be a subset of the clip bounds. returns false if path bounds
1211150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com// would be empty.
1212150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.combool get_path_and_clip_bounds(const GrDrawTarget* target,
1213150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                              const GrPath& path,
1214150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                              const GrVec* translate,
1215150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                              GrIRect* pathBounds,
1216150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                              GrIRect* clipBounds) {
1217150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    // compute bounds as intersection of rt size, clip, and path
1218150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
1219150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (NULL == rt) {
1220150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        return false;
1221150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1222150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    *pathBounds = GrIRect::MakeWH(rt->width(), rt->height());
1223150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    const GrClip& clip = target->getClip();
1224150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (clip.hasConservativeBounds()) {
1225150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        clip.getConservativeBounds().roundOut(clipBounds);
1226150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        if (!pathBounds->intersect(*clipBounds)) {
1227150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return false;
1228150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        }
1229150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    } else {
1230150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        // pathBounds is currently the rt extent, set clip bounds to that rect.
1231150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        *clipBounds = *pathBounds;
1232150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1233150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrRect pathSBounds = path.getBounds();
1234150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (!pathSBounds.isEmpty()) {
1235150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        if (NULL != translate) {
1236150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            pathSBounds.offset(*translate);
1237150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        }
1238150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        target->getDrawState().getViewMatrix().mapRect(&pathSBounds,
1239150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                                        pathSBounds);
1240150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        GrIRect pathIBounds;
1241150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        pathSBounds.roundOut(&pathIBounds);
1242150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        if (!pathBounds->intersect(pathIBounds)) {
1243150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            return false;
1244150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        }
1245150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    } else {
1246150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        return false;
1247150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1248150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    return true;
1249150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
1250150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1251150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com/**
1252150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com * sw rasterizes path to A8 mask using the context's matrix and uploads to a
1253150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com * scratch texture.
1254150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com */
1255150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1256150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.combool sw_draw_path_to_mask_texture(const GrPath& clientPath,
1257150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                  const GrIRect& pathDevBounds,
1258150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                  GrPathFill fill,
1259150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                  GrContext* context,
1260150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                  const GrPoint* translate,
1261150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                  GrAutoScratchTexture* tex) {
1262150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    SkPaint paint;
1263150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    SkPath tmpPath;
1264150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    const SkPath* pathToDraw = &clientPath;
1265150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (kHairLine_PathFill == fill) {
1266150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        paint.setStyle(SkPaint::kStroke_Style);
1267150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        paint.setStrokeWidth(SK_Scalar1);
1268150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    } else {
1269150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        paint.setStyle(SkPaint::kFill_Style);
1270150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        SkPath::FillType skfill = gr_fill_to_sk_fill(fill);
1271150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        if (skfill != pathToDraw->getFillType()) {
1272150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            tmpPath = *pathToDraw;
1273150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            tmpPath.setFillType(skfill);
1274150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            pathToDraw = &tmpPath;
1275150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        }
1276150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1277150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    paint.setAntiAlias(true);
1278150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    paint.setColor(SK_ColorWHITE);
1279150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1280150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrMatrix matrix = context->getMatrix();
1281150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (NULL != translate) {
1282150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        matrix.postTranslate(translate->fX, translate->fY);
1283150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1284150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1285150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    matrix.postTranslate(-pathDevBounds.fLeft * SK_Scalar1,
1286150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                         -pathDevBounds.fTop * SK_Scalar1);
1287150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrIRect bounds = GrIRect::MakeWH(pathDevBounds.width(),
1288150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                     pathDevBounds.height());
1289150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1290150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    SkBitmap bm;
1291150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    bm.setConfig(SkBitmap::kA8_Config, bounds.fRight, bounds.fBottom);
1292150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (!bm.allocPixels()) {
1293150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        return false;
1294150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1295150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    sk_bzero(bm.getPixels(), bm.getSafeSize());
1296150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1297150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    SkDraw  draw;
1298150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    sk_bzero(&draw, sizeof(draw));
1299150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    SkRasterClip rc(bounds);
1300150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    draw.fRC    = &rc;
1301150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    draw.fClip  = &rc.bwRgn();
1302150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    draw.fMatrix = &matrix;
1303150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    draw.fBitmap = &bm;
1304150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    draw.drawPath(*pathToDraw, paint);
1305150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1306150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    const GrTextureDesc desc = {
1307150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        kNone_GrTextureFlags,
1308150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        bounds.fRight,
1309150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        bounds.fBottom,
131078d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com        kAlpha_8_GrPixelConfig,
131178d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com        {0} // samples
1312150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    };
1313150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1314150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    tex->set(context, desc);
1315150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrTexture* texture = tex->texture();
1316150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1317150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (NULL == texture) {
1318150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        return false;
1319150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1320150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    SkAutoLockPixels alp(bm);
1321150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
1322150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                         bm.getPixels(), bm.rowBytes());
1323150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    return true;
1324150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
1325150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1326150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.comvoid draw_around_inv_path(GrDrawTarget* target,
1327150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                          GrDrawState::StageMask stageMask,
1328150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                          const GrIRect& clipBounds,
1329150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                          const GrIRect& pathBounds) {
1330150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
1331150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrRect rect;
1332150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (clipBounds.fTop < pathBounds.fTop) {
1333150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        rect.iset(clipBounds.fLeft, clipBounds.fTop,
1334150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                    clipBounds.fRight, pathBounds.fTop);
1335150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        target->drawSimpleRect(rect, NULL, stageMask);
1336150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1337150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (clipBounds.fLeft < pathBounds.fLeft) {
1338150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        rect.iset(clipBounds.fLeft, pathBounds.fTop,
1339150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                    pathBounds.fLeft, pathBounds.fBottom);
1340150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        target->drawSimpleRect(rect, NULL, stageMask);
1341150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1342150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (clipBounds.fRight > pathBounds.fRight) {
1343150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        rect.iset(pathBounds.fRight, pathBounds.fTop,
1344150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                    clipBounds.fRight, pathBounds.fBottom);
1345150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        target->drawSimpleRect(rect, NULL, stageMask);
1346150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1347150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    if (clipBounds.fBottom > pathBounds.fBottom) {
1348150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        rect.iset(clipBounds.fLeft, pathBounds.fBottom,
1349150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                    clipBounds.fRight, clipBounds.fBottom);
1350150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com        target->drawSimpleRect(rect, NULL, stageMask);
1351150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    }
1352150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
1353150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
1354150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
135527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
135607f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.comvoid GrContext::drawPath(const GrPaint& paint, const GrPath& path,
135707f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.com                         GrPathFill fill, const GrPoint* translate) {
135827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1359fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (path.isEmpty()) {
1360fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       if (GrIsFillInverted(fill)) {
1361fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com           this->drawPaint(paint);
1362fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       }
1363fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       return;
1364fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
1365fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
136627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
1367150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrDrawState::StageMask stageMask = paint.getActiveStageMask();
1368d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
1369289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool prAA = paint.fAntiAlias && !this->getRenderTarget()->isMultisampled();
1370289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
1371d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // An Assumption here is that path renderer would use some form of tweaking
1372d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // the src color (either the input alpha or in the frag shader) to implement
1373d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // aa. If we have some future driver-mojo path AA that can do the right
1374d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // thing WRT to the blend then we'll need some query on the PR.
1375d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (disable_coverage_aa_for_blend(target)) {
13761983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
1377979432ba2621b617f5e85a9ff48c6b6cd1504a0dbsalomon@google.com        //GrPrintf("Turning off AA to correctly apply blend.\n");
13781983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
1379289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        prAA = false;
1380d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    }
1381289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
1382289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    GrPathRenderer* pr = NULL;
1383289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    if (prAA) {
1384289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        pr = this->getPathRenderer(path, fill, true);
1385289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        if (NULL == pr) {
1386150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            GrAutoScratchTexture ast;
1387150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            GrIRect pathBounds, clipBounds;
1388150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            if (!get_path_and_clip_bounds(target, path, translate,
1389150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                          &pathBounds, &clipBounds)) {
1390150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                return;
1391150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            }
1392150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            if (NULL == pr && sw_draw_path_to_mask_texture(path, pathBounds,
1393150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                                           fill, this,
1394150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                                           translate, &ast)) {
1395150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                GrTexture* texture = ast.texture();
1396150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                GrAssert(NULL != texture);
1397150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
1398150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                enum {
1399150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                    kPathMaskStage = GrPaint::kTotalStages,
1400150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                };
1401150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                target->drawState()->setTexture(kPathMaskStage, texture);
1402150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                target->drawState()->sampler(kPathMaskStage)->reset();
1403150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                GrScalar w = GrIntToScalar(pathBounds.width());
1404150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                GrScalar h = GrIntToScalar(pathBounds.height());
1405150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                GrRect maskRect = GrRect::MakeWH(w / texture->width(),
1406150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                                 h / texture->height());
1407150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
1408150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                srcRects[kPathMaskStage] = &maskRect;
1409150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                stageMask |= 1 << kPathMaskStage;
14105db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                GrRect dstRect = GrRect::MakeLTRB(
14115db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                    SK_Scalar1* pathBounds.fLeft,
14125db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                    SK_Scalar1* pathBounds.fTop,
14135db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                    SK_Scalar1* pathBounds.fRight,
14145db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                    SK_Scalar1* pathBounds.fBottom);
1415150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                target->drawRect(dstRect, NULL, stageMask, srcRects, NULL);
1416150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                target->drawState()->setTexture(kPathMaskStage, NULL);
1417150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                if (GrIsFillInverted(fill)) {
1418150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                    draw_around_inv_path(target, stageMask,
1419150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                                         clipBounds, pathBounds);
1420150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                }
1421150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com                return;
1422150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com            }
1423289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        }
1424289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    } else {
1425289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        pr = this->getPathRenderer(path, fill, false);
1426289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    }
1427289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
14283008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == pr) {
14291983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
14303008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        GrPrintf("Unable to find path renderer compatible with path.\n");
14311983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
14323008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        return;
14333008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
14343008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
1435289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    GrPathRenderer::AutoClearPath arp(pr, target, &path, fill, prAA, translate);
143606afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
1437ee435122d7dcb9cd4be4524004b0de282c42848bbsalomon@google.com    pr->drawPath(stageMask);
143827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
14398295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
144027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
144127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1442a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.comvoid GrContext::flush(int flagsBitfield) {
1443a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kDiscard_FlushBit & flagsBitfield) {
1444a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com        fDrawBuffer->reset();
1445a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    } else {
1446c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        this->flushDrawBuffer();
1447a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    }
1448a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) {
144927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fGpu->forceRenderTargetFlush();
145027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
145127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
145227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
145327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::flushText() {
145427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (kText_DrawCategory == fLastDrawCategory) {
145527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        flushDrawBuffer();
145627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
145727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
145827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
145927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::flushDrawBuffer() {
146027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING
146153a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    if (fDrawBuffer) {
146253a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com        fDrawBuffer->playback(fGpu);
146353a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com        fDrawBuffer->reset();
146453a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    }
146527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
146627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
146727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
14686f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.comvoid GrContext::internalWriteTexturePixels(GrTexture* texture,
14696f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           int left, int top,
14706f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           int width, int height,
14716f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           GrPixelConfig config,
14726f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           const void* buffer,
14736f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           size_t rowBytes,
14746f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           uint32_t flags) {
14756f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeTexturePixels");
1476bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1477bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
14786f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
14796f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        this->flush();
14806f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
14816f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    // TODO: use scratch texture to perform conversion
14826f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (GrPixelConfigIsUnpremultiplied(texture->config()) !=
14836f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config)) {
14846f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        return;
14856f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
14866f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
14876f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    fGpu->writeTexturePixels(texture, left, top, width, height,
14886f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                             config, buffer, rowBytes);
14896f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com}
14906f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
14916f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.combool GrContext::internalReadTexturePixels(GrTexture* texture,
14926f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          int left, int top,
14936f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          int width, int height,
14946f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          GrPixelConfig config,
14956f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          void* buffer,
14966f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          size_t rowBytes,
14976f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          uint32_t flags) {
1498278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readTexturePixels");
1499bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1500669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1501a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // TODO: code read pixels for textures that aren't also rendertargets
1502669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    GrRenderTarget* target = texture->asRenderTarget();
1503669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    if (NULL != target) {
15046f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        return this->internalReadRenderTargetPixels(target,
15056f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    left, top, width, height,
15066f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    config, buffer, rowBytes,
15076f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    flags);
1508669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    } else {
1509669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com        return false;
1510669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    }
1511669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com}
1512669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1513a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com#include "SkConfig8888.h"
1514a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
1515a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.comnamespace {
1516a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com/**
1517a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * Converts a GrPixelConfig to a SkCanvas::Config8888. Only byte-per-channel
1518a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * formats are representable as Config8888 and so the function returns false
1519a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * if the GrPixelConfig has no equivalent Config8888.
1520a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com */
1521a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.combool grconfig_to_config8888(GrPixelConfig config,
1522a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                            SkCanvas::Config8888* config8888) {
1523a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    switch (config) {
1524a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kRGBA_8888_PM_GrPixelConfig:
1525a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kRGBA_Premul_Config8888;
1526a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1527a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kRGBA_8888_UPM_GrPixelConfig:
1528a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
1529a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1530a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kBGRA_8888_PM_GrPixelConfig:
1531a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kBGRA_Premul_Config8888;
1532a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1533a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kBGRA_8888_UPM_GrPixelConfig:
1534a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kBGRA_Unpremul_Config8888;
1535a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1536a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        default:
1537a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return false;
1538a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1539a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
1540a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
1541a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
15426f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.combool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target,
15436f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               int left, int top,
15446f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               int width, int height,
15456f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               GrPixelConfig config,
15466f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               void* buffer,
15476f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               size_t rowBytes,
15486f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               uint32_t flags) {
1549278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
1550bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
1551bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
1552669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    if (NULL == target) {
15538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        target = fGpu->drawState()->getRenderTarget();
1554c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (NULL == target) {
1555c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            return false;
1556c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1557c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1558669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
15596f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
15606f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        this->flush();
15616f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
1562c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1563a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    if (!GrPixelConfigIsUnpremultiplied(target->config()) &&
1564a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config) &&
1565a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        !fGpu->canPreserveReadWriteUnpremulPixels()) {
1566a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkCanvas::Config8888 srcConfig8888, dstConfig8888;
1567a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        if (!grconfig_to_config8888(target->config(), &srcConfig8888) ||
1568a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            !grconfig_to_config8888(config, &dstConfig8888)) {
1569a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return false;
1570a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        }
1571a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // do read back using target's own config
1572a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        this->internalReadRenderTargetPixels(target,
1573a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             left, top,
1574a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             width, height,
1575a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             target->config(),
1576a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             buffer, rowBytes,
1577a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             kDontFlush_PixelOpsFlag);
1578a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // sw convert the pixels to unpremul config
1579a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        uint32_t* pixels = reinterpret_cast<uint32_t*>(buffer);
1580a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkConvertConfig8888Pixels(pixels, rowBytes, dstConfig8888,
1581a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  pixels, rowBytes, srcConfig8888,
1582a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  width, height);
1583a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        return true;
1584a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1585a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
1586c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    GrTexture* src = target->asTexture();
15870a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    bool swapRAndB = NULL != src &&
15880a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                     fGpu->preferredReadPixelsConfig(config) ==
15890a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                     GrPixelConfigSwapRAndB(config);
1590c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1591c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    bool flipY = NULL != src &&
1592c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                 fGpu->readPixelsWillPayForYFlip(target, left, top,
1593c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 width, height, config,
1594c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 rowBytes);
15950a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    bool alphaConversion = (!GrPixelConfigIsUnpremultiplied(target->config()) &&
15960a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                             GrPixelConfigIsUnpremultiplied(config));
1597c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
15980a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    if (NULL == src && alphaConversion) {
15990a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // we should fallback to cpu conversion here. This could happen when
16000a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // we were given an external render target by the client that is not
16010a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // also a texture (e.g. FBO 0 in GL)
16020a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        return false;
16030a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    }
16040a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    // we draw to a scratch texture if any of these conversion are applied
1605c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com    GrAutoScratchTexture ast;
16060a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    if (flipY || swapRAndB || alphaConversion) {
16070a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        GrAssert(NULL != src);
16080a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        if (swapRAndB) {
16090a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com            config = GrPixelConfigSwapRAndB(config);
16100a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com            GrAssert(kUnknown_GrPixelConfig != config);
1611c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1612c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        // Make the scratch a render target because we don't have a robust
1613c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        // readTexturePixels as of yet (it calls this function).
1614c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        const GrTextureDesc desc = {
1615c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            kRenderTarget_GrTextureFlagBit,
1616c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            width, height,
161778d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com            config,
161878d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com            {0}, // samples
1619c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        };
1620c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com
162156d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // When a full readback is faster than a partial we could always make
162256d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // the scratch exactly match the passed rect. However, if we see many
162356d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // different size rectangles we will trash our texture cache and pay the
162456d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // cost of creating and destroying many textures. So, we only request
162556d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // an exact match when the caller is reading an entire RT.
162656d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ScratchTexMatch match = kApprox_ScratchTexMatch;
162756d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        if (0 == left &&
162856d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            0 == top &&
162956d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->width() == width &&
163056d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->height() == height &&
163156d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            fGpu->fullReadPixelsIsFasterThanPartial()) {
163256d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            match = kExact_ScratchTexMatch;
163356d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        }
163456d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ast.set(this, desc, match);
1635c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrTexture* texture = ast.texture();
1636c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (!texture) {
1637c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            return false;
1638c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1639c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        target = texture->asRenderTarget();
1640c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrAssert(NULL != target);
1641c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1642c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrDrawTarget::AutoStateRestore asr(fGpu);
16438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState* drawState = fGpu->drawState();
164452a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com        drawState->reset();
16458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setRenderTarget(target);
1646c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1647c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrMatrix matrix;
1648c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (flipY) {
1649c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.setTranslate(SK_Scalar1 * left,
1650c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                SK_Scalar1 * (top + height));
1651c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.set(GrMatrix::kMScaleY, -GR_Scalar1);
1652c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        } else {
1653c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
1654c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1655c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        matrix.postIDiv(src->width(), src->height());
16561e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com        drawState->sampler(0)->reset(matrix);
16571e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com        drawState->sampler(0)->setRAndBSwap(swapRAndB);
16588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setTexture(0, src);
1659c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrRect rect;
1660c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        rect.setXYWH(0, 0, SK_Scalar1 * width, SK_Scalar1 * height);
1661c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        fGpu->drawSimpleRect(rect, NULL, 0x1);
1662c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        left = 0;
1663c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        top = 0;
1664c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1665669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    return fGpu->readPixels(target,
1666c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                            left, top, width, height,
1667c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                            config, buffer, rowBytes, flipY);
166827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
166927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
167075f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.comvoid GrContext::resolveRenderTarget(GrRenderTarget* target) {
167175f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    GrAssert(target);
167275f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
167375f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // In the future we may track whether there are any pending draws to this
167475f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // target. We don't today so we always perform a flush. We don't promise
167575f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // this to our clients, though.
167675f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    this->flush();
167775f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    fGpu->resolveRenderTarget(target);
167875f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com}
167975f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com
1680ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.orgvoid GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst) {
1681ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    if (NULL == src || NULL == dst) {
1682ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        return;
1683ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
1684ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(src);
1685ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
1686ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    GrDrawTarget::AutoStateRestore asr(fGpu);
16878f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
168852a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com    drawState->reset();
16898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(dst);
1690ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    GrMatrix sampleM;
1691ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    sampleM.setIDiv(src->width(), src->height());
16928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setTexture(0, src);
16931e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->reset(sampleM);
16945db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com    SkRect rect = SkRect::MakeXYWH(0, 0,
16955db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                                   SK_Scalar1 * src->width(),
16965db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                                   SK_Scalar1 * src->height());
1697ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    fGpu->drawSimpleRect(rect, NULL, 1 << 0);
1698ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org}
1699ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
17006f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.comvoid GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target,
17016f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                int left, int top,
17026f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                int width, int height,
17036f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                GrPixelConfig config,
17046f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                const void* buffer,
17056f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                size_t rowBytes,
17066f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                uint32_t flags) {
17076f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
1708bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
17096f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
17106f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (NULL == target) {
17118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        target = fGpu->drawState()->getRenderTarget();
17126f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        if (NULL == target) {
17136f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com            return;
17146f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        }
17156f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
171627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
171727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // TODO: when underlying api has a direct way to do this we should use it
171827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // (e.g. glDrawPixels on desktop GL).
171927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1720a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // If the RT is also a texture and we don't have to do PM/UPM conversion
1721a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // then take the texture path, which we expect to be at least as fast or
1722a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // faster since it doesn't use an intermediate texture as we do below.
1723a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1724a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#if !GR_MAC_BUILD
1725a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // At least some drivers on the Mac get confused when glTexImage2D is called
1726a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // on a texture attached to an FBO. The FBO still sees the old image. TODO:
1727a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // determine what OS versions and/or HW is affected.
1728a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    if (NULL != target->asTexture() &&
1729a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        GrPixelConfigIsUnpremultiplied(target->config()) ==
1730a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config)) {
1731a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1732a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        this->internalWriteTexturePixels(target->asTexture(),
1733a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                                         left, top, width, height,
1734a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                                         config, buffer, rowBytes, flags);
1735a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        return;
1736a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1737a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#endif
1738a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    if (!GrPixelConfigIsUnpremultiplied(target->config()) &&
1739a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config) &&
1740a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        !fGpu->canPreserveReadWriteUnpremulPixels()) {
1741a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkCanvas::Config8888 srcConfig8888, dstConfig8888;
1742a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        if (!grconfig_to_config8888(config, &srcConfig8888) ||
1743a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            !grconfig_to_config8888(target->config(), &dstConfig8888)) {
1744a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return;
1745a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        }
1746a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // allocate a tmp buffer and sw convert the pixels to premul
1747a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(width * height);
1748a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        const uint32_t* src = reinterpret_cast<const uint32_t*>(buffer);
1749a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkConvertConfig8888Pixels(tmpPixels.get(), 4 * width, dstConfig8888,
1750a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  src, rowBytes, srcConfig8888,
1751a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  width, height);
1752a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // upload the already premul pixels
1753a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        this->internalWriteRenderTargetPixels(target,
1754a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             left, top,
1755a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             width, height,
1756a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             target->config(),
1757a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             tmpPixels, 4 * width, flags);
1758a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        return;
1759a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1760a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1761a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    bool swapRAndB = fGpu->preferredReadPixelsConfig(config) ==
1762a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                     GrPixelConfigSwapRAndB(config);
1763a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    if (swapRAndB) {
1764a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        config = GrPixelConfigSwapRAndB(config);
1765a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1766a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1767fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    const GrTextureDesc desc = {
176878d6cf9f434d3351b19de14f1eab424c23f0ab6dbsalomon@google.com        kNone_GrTextureFlags, width, height, config, {0}
176927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    };
177050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrAutoScratchTexture ast(this, desc);
177150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrTexture* texture = ast.texture();
177227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL == texture) {
177327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
177427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
17756f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    this->internalWriteTexturePixels(texture, 0, 0, width, height,
17766f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                     config, buffer, rowBytes, flags);
177727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
177827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoStateRestore  asr(fGpu);
17798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
178052a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com    drawState->reset();
178127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
178227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix matrix;
178327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
17848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setViewMatrix(matrix);
17858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(target);
17868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setTexture(0, texture);
178727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
17885c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com    matrix.setIDiv(texture->width(), texture->height());
17891e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
17901e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                 GrSamplerState::kNearest_Filter,
17911e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                 matrix);
17921e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->setRAndBSwap(swapRAndB);
179327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
179427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
179527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    static const int VCOUNT = 4;
17966513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    // TODO: Use GrGpu::drawRect here
179727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
179827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (!geo.succeeded()) {
17996513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
180027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
180127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
180227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
180327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT);
180427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
180527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
180627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1807bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.comvoid GrContext::setPaint(const GrPaint& paint, GrDrawTarget* target) {
18088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = target->drawState();
180926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
181026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kMaxTextures; ++i) {
181126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        int s = i + GrPaint::kFirstTextureStage;
18128f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setTexture(s, paint.getTexture(i));
1813bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com        ASSERT_OWNED_RESOURCE(paint.getTexture(i));
1814f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        if (paint.getTexture(i)) {
1815f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com            *drawState->sampler(s) = paint.getTextureSampler(i);
1816f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        }
181726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
181826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
18198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setFirstCoverageStage(GrPaint::kFirstMaskStage);
182026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
182126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kMaxMasks; ++i) {
182226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        int s = i + GrPaint::kFirstMaskStage;
18238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setTexture(s, paint.getMask(i));
1824bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com        ASSERT_OWNED_RESOURCE(paint.getMask(i));
1825f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        if (paint.getMask(i)) {
1826f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com            *drawState->sampler(s) = paint.getMaskSampler(i);
1827f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        }
182826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
182926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
18308f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setColor(paint.fColor);
183127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
183227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (paint.fDither) {
18338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->enableState(GrDrawState::kDither_StateBit);
183427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
18358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->disableState(GrDrawState::kDither_StateBit);
183627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
183727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (paint.fAntiAlias) {
18388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->enableState(GrDrawState::kHWAntialias_StateBit);
183927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
18408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->disableState(GrDrawState::kHWAntialias_StateBit);
184127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
184250bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    if (paint.fColorMatrixEnabled) {
184350bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org        drawState->enableState(GrDrawState::kColorMatrix_StateBit);
184450bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    } else {
184550bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org        drawState->disableState(GrDrawState::kColorMatrix_StateBit);
184650bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    }
18476b67e21b6549598254c1ffa4243bf32615d90fb6bsalomon@google.com    drawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
18488f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
184950bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    drawState->setColorMatrix(paint.fColorMatrix);
1850dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com    drawState->setCoverage(paint.fCoverage);
1851d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
1852d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (paint.getActiveMaskStageMask() && !target->canApplyCoverage()) {
1853d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com        GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
1854d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    }
185527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
185627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1857de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.comGrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
185827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                       DrawCategory category) {
185927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (category != fLastDrawCategory) {
186027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        flushDrawBuffer();
186127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fLastDrawCategory = category;
186227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
1863bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    this->setPaint(paint, fGpu);
186427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = fGpu;
186527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    switch (category) {
186627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    case kText_DrawCategory:
186727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if DEFER_TEXT_RENDERING
186827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target = fDrawBuffer;
186927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fDrawBuffer->initializeDrawStateAndClip(*fGpu);
187027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
187127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target = fGpu;
187227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
187327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        break;
187427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    case kUnbuffered_DrawCategory:
187527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target = fGpu;
187627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        break;
187727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    case kBuffered_DrawCategory:
187827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target = fDrawBuffer;
187927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fDrawBuffer->initializeDrawStateAndClip(*fGpu);
188027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        break;
188127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
188227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return target;
188327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
188427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1885289533ada623f2238a83771eec977f204f75994fbsalomon@google.comGrPathRenderer* GrContext::getPathRenderer(const GrPath& path,
1886289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           GrPathFill fill,
1887289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           bool antiAlias) {
18883008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == fPathRendererChain) {
18893008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        fPathRendererChain =
18903008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com            new GrPathRendererChain(this, GrPathRendererChain::kNone_UsageFlag);
18913008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
1892289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    return fPathRendererChain->getPathRenderer(fGpu->getCaps(), path,
1893289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                               fill, antiAlias);
18943008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com}
18953008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
189627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
189727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
189827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setRenderTarget(GrRenderTarget* target) {
1899bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
19008fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush(false);
19018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    fGpu->drawState()->setRenderTarget(target);
190227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
190327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
190427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrRenderTarget* GrContext::getRenderTarget() {
19058f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    return fGpu->drawState()->getRenderTarget();
190627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
190727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
190827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrRenderTarget* GrContext::getRenderTarget() const {
19098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    return fGpu->getDrawState().getRenderTarget();
191027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
191127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
191227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrMatrix& GrContext::getMatrix() const {
19138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    return fGpu->getDrawState().getViewMatrix();
191427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
191527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
191627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setMatrix(const GrMatrix& m) {
19178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    fGpu->drawState()->setViewMatrix(m);
191827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
191927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
192027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::concatMatrix(const GrMatrix& m) const {
19218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    fGpu->drawState()->preConcatViewMatrix(m);
192227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
192327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
192427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
192527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    intptr_t mask = 1 << shift;
192627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (pred) {
192727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        bits |= mask;
192827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
192927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        bits &= ~mask;
193027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
193127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return bits;
193227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
193327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
193427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::resetStats() {
193527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->resetStats();
193627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
193727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
193805ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.comconst GrGpuStats& GrContext::getStats() const {
193927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return fGpu->getStats();
194027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
194127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
194227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::printStats() const {
194327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->printStats();
194427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
194527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1946583a1e38503ebd57ba9bd39a3fabe89bead8e76cbsalomon@google.comGrContext::GrContext(GrGpu* gpu) {
194727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu = gpu;
194827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->ref();
1949669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    fGpu->setContext(this);
19508fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
19513008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    fPathRendererChain = NULL;
1952dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com
195350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    fTextureCache = new GrResourceCache(MAX_TEXTURE_CACHE_COUNT,
195450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                        MAX_TEXTURE_CACHE_BYTES);
195527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fFontCache = new GrFontCache(fGpu);
195627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
195727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fLastDrawCategory = kUnbuffered_DrawCategory;
195827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
19598fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
19608fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
19618fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
19628fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1963205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fAAFillRectIndexBuffer = NULL;
1964205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fAAStrokeRectIndexBuffer = NULL;
1965919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
19668fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->setupDrawBuffer();
19678fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
19688fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
19698fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::setupDrawBuffer() {
19708fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
19718fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBuffer);
19728fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBufferVBAllocPool);
19738fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBufferIBAllocPool);
19748fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
197527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT
1976de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferVBAllocPool =
19778fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com        new GrVertexBufferAllocPool(fGpu, false,
197827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                    DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
197927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                    DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS);
1980de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferIBAllocPool =
19818fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com        new GrIndexBufferAllocPool(fGpu, false,
1982de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com                                   DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
198327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                   DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS);
198427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1985471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com    fDrawBuffer = new GrInOrderDrawBuffer(fGpu,
1986471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com                                          fDrawBufferVBAllocPool,
198727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                          fDrawBufferIBAllocPool);
198827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
198927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
199027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if BATCH_RECT_TO_RECT
199127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
199227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
199327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
199427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
199527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
199627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target;
199727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if DEFER_TEXT_RENDERING
199827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = prepareToDraw(paint, kText_DrawCategory);
199927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
200027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = prepareToDraw(paint, kUnbuffered_DrawCategory);
200127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
2002bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    this->setPaint(paint, target);
200327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return target;
200427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
200527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
200627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
200727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return fGpu->getQuadIndexBuffer();
200827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
2009dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com
2010aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.orgvoid GrContext::convolve(GrTexture* texture,
2011aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org                         const SkRect& rect,
2012aadd9f8b193aa70e3dc30cbe5c4e1bc5c1d047basenorblanco@chromium.org                         const float* kernel,
201305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                         int kernelWidth,
201405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                         GrSamplerState::FilterDirection direction) {
2015bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
2016bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
2017027de5f922e8ad1acc5402829f716b8c513fdd8dsenorblanco@chromium.org    GrDrawTarget::AutoStateRestore asr(fGpu);
20181e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
2019dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com    GrRenderTarget* target = drawState->getRenderTarget();
2020dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com    drawState->reset();
2021dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com    drawState->setRenderTarget(target);
2022027de5f922e8ad1acc5402829f716b8c513fdd8dsenorblanco@chromium.org    GrMatrix sampleM;
202360014ca38710d3fc265f4376b05c0fefd0e044cfsenorblanco@chromium.org    sampleM.setIDiv(texture->width(), texture->height());
20241e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
20251e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                 GrSamplerState::kConvolution_Filter,
20261e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                 sampleM);
202705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    drawState->sampler(0)->setConvolutionParams(kernelWidth, kernel);
202805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    drawState->sampler(0)->setFilterDirection(direction);
202905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    drawState->setTexture(0, texture);
203005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    fGpu->drawSimpleRect(rect, NULL, 1 << 0);
203105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org}
20321e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com
203305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.orgvoid GrContext::applyMorphology(GrTexture* texture,
203405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                                const SkRect& rect,
203505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                                int radius,
203605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                                GrSamplerState::Filter filter,
203705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                                GrSamplerState::FilterDirection direction) {
203805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    ASSERT_OWNED_RESOURCE(texture);
203905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    GrAssert(filter == GrSamplerState::kErode_Filter ||
204005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org             filter == GrSamplerState::kDilate_Filter);
204105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
204205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    GrDrawTarget::AutoStateRestore asr(fGpu);
204305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    GrDrawState* drawState = fGpu->drawState();
204405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    GrRenderTarget* target = drawState->getRenderTarget();
204505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    drawState->reset();
204605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    drawState->setRenderTarget(target);
204705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    GrMatrix sampleM;
204805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    sampleM.setIDiv(texture->width(), texture->height());
204905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
205005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                                 filter,
205105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                                 sampleM);
205205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    drawState->sampler(0)->setMorphologyRadius(radius);
205305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    drawState->sampler(0)->setFilterDirection(direction);
20548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setTexture(0, texture);
2055027de5f922e8ad1acc5402829f716b8c513fdd8dsenorblanco@chromium.org    fGpu->drawSimpleRect(rect, NULL, 1 << 0);
2056027de5f922e8ad1acc5402829f716b8c513fdd8dsenorblanco@chromium.org}
2057c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
2058c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
2059