GrContext.cpp revision a0a66c118392fdc6f84f18ac634473468e31becb
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
12b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com#include "effects/GrMorphologyEffect.h"
13b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com#include "effects/GrConvolutionEffect.h"
14b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com
15278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrBufferAllocPool.h"
16278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrClipIterator.h"
1705ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com#include "GrGpu.h"
1827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrIndexBuffer.h"
1927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrInOrderDrawBuffer.h"
2027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrPathRenderer.h"
21d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com#include "GrPathUtils.h"
2250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com#include "GrResourceCache.h"
2372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com#include "GrSoftwarePathRenderer.h"
24558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com#include "GrStencilBuffer.h"
25278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrTextStrike.h"
268c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com#include "SkTLazy.h"
27c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com#include "SkTLS.h"
280c8d93a94099dee2dff8da6000ded9ad59676488tomhudson@google.com#include "SkTrace.h"
2927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
303c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com#define DEFER_TEXT_RENDERING 1
3127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
323c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com#define DEFER_PATHS 1
33fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com
343c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com#define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)
3527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
363b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org#define MAX_BLUR_SIGMA 4.0f
373b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
38d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// When we're using coverage AA but the blend is incompatible (given gpu
39d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// limitations) should we disable AA or draw wrong?
40950d7a8d8def14efc98d12d6947347fde351b737bsalomon@google.com#define DISABLE_COVERAGE_AA_FOR_BLEND 1
41d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
424b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#if GR_DEBUG
434b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    // change this to a 1 to see notifications when partial coverage fails
444b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
454b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#else
464b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
474b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#endif
484b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com
498f7e1dac5c92bf1f53feb603a9bd249d53afa81absalomon@google.comstatic const size_t kDefaultTextureCacheBudget = 16 * 1024 * 1024;
5027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
5160361493548d5259d0a8afae84274c2a3c31dcacbsalomon@google.comstatic const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 15;
5227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
5327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
54fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com// path rendering is the only thing we defer today that uses non-static indices
55fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.comstatic const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = DEFER_PATHS ? 1 << 11 : 0;
56fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.comstatic const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = DEFER_PATHS ? 4 : 0;
5727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
58bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com#define ASSERT_OWNED_RESOURCE(R) GrAssert(!(R) || (R)->getContext() == this)
59bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
6005ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.comGrContext* GrContext::Create(GrEngine engine,
6105ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com                             GrPlatform3DContext context3D) {
6227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrContext* ctx = NULL;
6327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrGpu* fGpu = GrGpu::Create(engine, context3D);
6427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != fGpu) {
6527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        ctx = new GrContext(fGpu);
6627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fGpu->unref();
6727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
6827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return ctx;
6927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
7027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
71c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comnamespace {
72c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comvoid* CreateThreadInstanceCount() {
73c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    return new int(0);
74c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
75c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comvoid DeleteThreadInstanceCount(void* v) {
76c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    delete reinterpret_cast<int*>(v);
77c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
78c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com#define THREAD_INSTANCE_COUNT                                               \
79c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    (*reinterpret_cast<int*>(SkTLS::Get(CreateThreadInstanceCount,          \
80c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com                                        DeleteThreadInstanceCount)))
81c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
82c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
83c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
84c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comint GrContext::GetThreadInstanceCount() {
85c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    return THREAD_INSTANCE_COUNT;
86c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
87c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
8827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrContext::~GrContext() {
898fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
905acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com
915acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // Since the gpu can hold scratch textures, give it a chance to let go
925acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // of them before freeing the texture cache
935acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    fGpu->purgeResources();
945acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com
9527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fTextureCache;
9627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fFontCache;
9727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBuffer;
9827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBufferVBAllocPool;
99de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    delete fDrawBufferIBAllocPool;
1003008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
101f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->unref();
102f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com
103205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->unref();
1043008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeUnref(fPathRendererChain);
10572176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrSafeUnref(fSoftwarePathRenderer);
10610e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->unref();
107c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
108c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    --THREAD_INSTANCE_COUNT;
10927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
11027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1118fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::contextLost() {
11253a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    contextDestroyed();
11353a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    this->setupDrawBuffer();
11453a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com}
11553a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com
11653a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.comvoid GrContext::contextDestroyed() {
117205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // abandon first to so destructors
118205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // don't try to free the resources in the API.
119205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->abandonResources();
120205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1213008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources that
1223008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // are now unusable
1233008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeSetNull(fPathRendererChain);
12472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrSafeSetNull(fSoftwarePathRenderer);
1253008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
1268fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBuffer;
1278fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
128205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1298fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferVBAllocPool;
1308fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
131205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1328fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferIBAllocPool;
1338fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
1348fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
135f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->reset();
136205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1378fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fTextureCache->removeAll();
1388fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
1398fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
1408fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
1418fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1428fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::resetContext() {
1438fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
1448fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
1458fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1468fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::freeGpuResources() {
1478fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
148ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com
149ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com    fGpu->purgeResources();
150ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com
151f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->reset();
152f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com
1538fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fTextureCache->removeAll();
1548fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
1553008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources
1563008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeSetNull(fPathRendererChain);
15772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrSafeSetNull(fSoftwarePathRenderer);
15827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
15927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
16005e70247c31ae927074ef27ea9893634a8dda543twiz@google.comsize_t GrContext::getGpuTextureCacheBytes() const {
16105e70247c31ae927074ef27ea9893634a8dda543twiz@google.com  return fTextureCache->getCachedResourceBytes();
16205e70247c31ae927074ef27ea9893634a8dda543twiz@google.com}
16305e70247c31ae927074ef27ea9893634a8dda543twiz@google.com
164fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
165fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
16626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.comint GrContext::PaintStageVertexLayoutBits(
16726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                            const GrPaint& paint,
16826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                            const bool hasTexCoords[GrPaint::kTotalStages]) {
16926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int stageMask = paint.getActiveStageMask();
17026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int layout = 0;
17126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kTotalStages; ++i) {
17226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        if ((1 << i) & stageMask) {
17326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            if (NULL != hasTexCoords && hasTexCoords[i]) {
17426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(i, i);
17526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            } else {
17626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(i);
17726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            }
17826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        }
17926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
18026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    return layout;
18126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com}
18226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
18326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
18426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
18526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
18650398bf7f1953e640e5529616e710cf540799731bsalomon@google.comGrTexture* GrContext::TextureCacheEntry::texture() const {
18750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (NULL == fEntry) {
18850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        return NULL;
18950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    } else {
19050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        return (GrTexture*) fEntry->resource();
19150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    }
19250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com}
19350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
19450398bf7f1953e640e5529616e710cf540799731bsalomon@google.comnamespace {
195558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
196558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com// we should never have more than one stencil buffer with same combo of
197558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com// (width,height,samplecount)
198558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid gen_stencil_key_values(int width, int height,
199558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                            int sampleCnt, uint32_t v[4]) {
200558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[0] = width;
201558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[1] = height;
202558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[2] = sampleCnt;
203a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    v[3] = GrResourceKey::kStencilBuffer_TypeBit;
204558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
205558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
206558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid gen_stencil_key_values(const GrStencilBuffer* sb,
207558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                            uint32_t v[4]) {
208558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(sb->width(), sb->height(),
209558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                           sb->numSamples(), v);
210558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
21182c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com
2123b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgvoid scale_rect(SkRect* rect, float xScale, float yScale) {
2135af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com    rect->fLeft = SkScalarMul(rect->fLeft, SkFloatToScalar(xScale));
2145af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com    rect->fTop = SkScalarMul(rect->fTop, SkFloatToScalar(yScale));
2155af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com    rect->fRight = SkScalarMul(rect->fRight, SkFloatToScalar(xScale));
2165af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com    rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale));
2173b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
2183b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
219b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.comfloat adjust_sigma(float sigma, int *scaleFactor, int *radius) {
2203b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    *scaleFactor = 1;
2213b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    while (sigma > MAX_BLUR_SIGMA) {
2223b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        *scaleFactor *= 2;
2233b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        sigma *= 0.5f;
2243b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
225b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    *radius = static_cast<int>(ceilf(sigma * 3.0f));
226b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius);
2273b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    return sigma;
2283b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
2293b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
2303b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgvoid apply_morphology(GrGpu* gpu,
2313b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                      GrTexture* texture,
2323b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                      const SkRect& rect,
2333b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                      int radius,
234b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                      GrContext::MorphologyType morphType,
235b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                      Gr1DKernelEffect::Direction direction) {
2363b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
237873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrRenderTarget* target = gpu->drawState()->getRenderTarget();
238873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit);
2393b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrDrawState* drawState = gpu->drawState();
2403b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->setRenderTarget(target);
2413b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrMatrix sampleM;
2423b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    sampleM.setIDiv(texture->width(), texture->height());
243b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    drawState->sampler(0)->reset(sampleM);
244b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    SkAutoTUnref<GrCustomStage> morph(
245b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        new GrMorphologyEffect(direction, radius, morphType));
246b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    drawState->sampler(0)->setCustomStage(morph);
2473b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->setTexture(0, texture);
2483b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    gpu->drawSimpleRect(rect, NULL, 1 << 0);
2493b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
2503b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
251b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.comvoid convolve_gaussian(GrGpu* gpu,
252b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       GrTexture* texture,
253b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       const SkRect& rect,
254b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       float sigma,
255b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       int radius,
256b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       Gr1DKernelEffect::Direction direction) {
257873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrRenderTarget* target = gpu->drawState()->getRenderTarget();
258873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit);
2593b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrDrawState* drawState = gpu->drawState();
2603b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->setRenderTarget(target);
2613b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrMatrix sampleM;
2623b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    sampleM.setIDiv(texture->width(), texture->height());
263b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    drawState->sampler(0)->reset(sampleM);
264b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    SkAutoTUnref<GrConvolutionEffect> conv(new
265b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        GrConvolutionEffect(direction, radius));
266b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    conv->setGaussianKernel(sigma);
267b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    drawState->sampler(0)->setCustomStage(conv);
2683b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->setTexture(0, texture);
2693b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    gpu->drawSimpleRect(rect, NULL, 1 << 0);
2703b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
2713b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
272fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com}
273fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
2741fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.comGrContext::TextureCacheEntry GrContext::findAndLockTexture(
275a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        const GrTextureDesc& desc,
2761fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrSamplerState* sampler) {
27775b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, sampler, desc, false);
278558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    return TextureCacheEntry(fTextureCache->findAndLock(resourceKey,
279558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                            GrResourceCache::kNested_LockType));
280558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
281558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
28275b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.combool GrContext::isTextureInCache(const GrTextureDesc& desc,
2831fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                 const GrSamplerState* sampler) const {
28475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, sampler, desc, false);
285fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    return fTextureCache->hasKey(resourceKey);
286fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com}
287fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com
288558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comGrResourceEntry* GrContext::addAndLockStencilBuffer(GrStencilBuffer* sb) {
289bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(sb);
290558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    uint32_t v[4];
291558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(sb, v);
292558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceKey resourceKey(v);
293558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    return fTextureCache->createAndLock(resourceKey, sb);
294558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
295558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
296558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comGrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
297558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                              int sampleCnt) {
298558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    uint32_t v[4];
299558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(width, height, sampleCnt, v);
300558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceKey resourceKey(v);
301558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceEntry* entry = fTextureCache->findAndLock(resourceKey,
302558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                            GrResourceCache::kSingle_LockType);
303558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    if (NULL != entry) {
304558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        GrStencilBuffer* sb = (GrStencilBuffer*) entry->resource();
305558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        return sb;
306558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    } else {
307558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        return NULL;
308558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    }
309558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
310558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
311558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid GrContext::unlockStencilBuffer(GrResourceEntry* sbEntry) {
312bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(sbEntry->resource());
313558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    fTextureCache->unlock(sbEntry);
31427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
31527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
31627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic void stretchImage(void* dst,
31727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstW,
31827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstH,
31927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         void* src,
32027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcW,
32127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcH,
32227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int bpp) {
32327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dx = (srcW << 16) / dstW;
32427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dy = (srcH << 16) / dstH;
32527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
32627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed y = dy >> 1;
32727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
32827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    int dstXLimit = dstW*bpp;
32927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    for (int j = 0; j < dstH; ++j) {
33027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrFixed x = dx >> 1;
33127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
33227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* dstRow = (uint8_t*)dst + j*dstW*bpp;
33327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < dstXLimit; i += bpp) {
33427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            memcpy((uint8_t*) dstRow + i,
33527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   (uint8_t*) srcRow + (x>>16)*bpp,
33627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   bpp);
33727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            x += dx;
33827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
33927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        y += dy;
34027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
34127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
34227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
3431fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.comGrContext::TextureCacheEntry GrContext::createAndLockTexture(
3441fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrSamplerState* sampler,
3451fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrTextureDesc& desc,
3461fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        void* srcData,
3471fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        size_t rowBytes) {
348278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::createAndLockTexture");
34927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
35027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_DUMP_TEXTURE_UPLOAD
35127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
35227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
35327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
35450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    TextureCacheEntry entry;
35550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
35675b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, sampler,
357a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                                                      desc, false);
358a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
359a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    if (GrTexture::NeedsResizing(resourceKey)) {
360a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        // The desired texture is NPOT and tiled but that isn't supported by
361a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        // the current hardware. Resize the texture to be a POT
3621fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        GrAssert(NULL != sampler);
36375b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        TextureCacheEntry clampEntry = this->findAndLockTexture(desc,
3641fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                                NULL);
36527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
36650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        if (NULL == clampEntry.texture()) {
36775b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com            clampEntry = this->createAndLockTexture(NULL, desc,
3681fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                                                    srcData, rowBytes);
36950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            GrAssert(NULL != clampEntry.texture());
37050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            if (NULL == clampEntry.texture()) {
37150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                return entry;
37227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
37327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
374fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        GrTextureDesc rtDesc = desc;
375fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        rtDesc.fFlags =  rtDesc.fFlags |
376fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com                         kRenderTarget_GrTextureFlagBit |
377fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com                         kNoStencil_GrTextureFlagBit;
3789962108c400dadcae913614e8a5ab781780981d8bsalomon@google.com        rtDesc.fWidth  = GrNextPow2(GrMax(desc.fWidth, 64));
3799962108c400dadcae913614e8a5ab781780981d8bsalomon@google.com        rtDesc.fHeight = GrNextPow2(GrMax(desc.fHeight, 64));
38027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
38127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
38227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
38327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != texture) {
384873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com            GrDrawTarget::AutoStateRestore asr(fGpu,
385873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com                                               GrDrawTarget::kReset_ASRInit);
3868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = fGpu->drawState();
3878f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->setRenderTarget(texture->asRenderTarget());
3888f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->setTexture(0, clampEntry.texture());
38982c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com
3906aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            GrSamplerState::Filter filter;
3916aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // if filtering is not desired then we want to ensure all
3926aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // texels in the resampled image are copies of texels from
3936aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // the original.
394a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com            if (GrTexture::NeedsFiltering(resourceKey)) {
3956aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com                filter = GrSamplerState::kBilinear_Filter;
396a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com            } else {
397a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                filter = GrSamplerState::kNearest_Filter;
3986aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            }
3991e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com            drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
4001e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                         filter);
40127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
40227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            static const GrVertexLayout layout =
40327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
40427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
40527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
40627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (arg.succeeded()) {
40727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                GrPoint* verts = (GrPoint*) arg.vertices();
40827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                verts[0].setIRectFan(0, 0,
40927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     texture->width(),
41027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     texture->height(),
41127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     2*sizeof(GrPoint));
41227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
41347059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com                fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType,
41427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     0, 4);
41550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                entry.set(fTextureCache->createAndLock(resourceKey, texture));
41627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
4171da0746fa155cdca982ae8deb68cc64f540c92dfbsalomon@google.com            texture->releaseRenderTarget();
41827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        } else {
41927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // TODO: Our CPU stretch doesn't filter. But we create separate
42027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // stretched textures when the sampler state is either filtered or
42127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // not. Either implement filtered stretch blit on CPU or just create
42227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // one when FBO case fails.
42327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
424fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com            rtDesc.fFlags = kNone_GrTextureFlags;
42527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // no longer need to clamp at min RT size.
42627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            rtDesc.fWidth  = GrNextPow2(desc.fWidth);
42727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            rtDesc.fHeight = GrNextPow2(desc.fHeight);
42864c4fe4113424bcfab8b3e0c7049887fda5ab4ffbsalomon@google.com            int bpp = GrBytesPerPixel(desc.fConfig);
4293582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com            SkAutoSMalloc<128*128*4> stretchedPixels(bpp *
43027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     rtDesc.fWidth *
43127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     rtDesc.fHeight);
43227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
43327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         srcData, desc.fWidth, desc.fHeight, bpp);
43427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
43527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            size_t stretchedRowBytes = rtDesc.fWidth * bpp;
43627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
43727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrTexture* texture = fGpu->createTexture(rtDesc,
43827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     stretchedPixels.get(),
43927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     stretchedRowBytes);
44027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrAssert(NULL != texture);
44150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            entry.set(fTextureCache->createAndLock(resourceKey, texture));
44227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
44350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->unlock(clampEntry.cacheEntry());
44427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
44527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
44627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
44727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != texture) {
44850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            entry.set(fTextureCache->createAndLock(resourceKey, texture));
44927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
45027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
45127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return entry;
45227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
45327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
45450398bf7f1953e640e5529616e710cf540799731bsalomon@google.comGrContext::TextureCacheEntry GrContext::lockScratchTexture(
45550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                                const GrTextureDesc& inDesc,
45650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                                ScratchTexMatch match) {
457b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    GrTextureDesc desc = inDesc;
45875b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fClientCacheID = kScratch_CacheID;
45975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com
46050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (kExact_ScratchTexMatch != match) {
46150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        // bin by pow2 with a reasonable min
46250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        static const int MIN_SIZE = 256;
46350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fWidth  = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
46450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
46550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    }
466b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
46750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrResourceEntry* entry;
468b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origWidth = desc.fWidth;
469b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origHeight = desc.fHeight;
470b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    bool doubledW = false;
471b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    bool doubledH = false;
472b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
473b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    do {
47475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL, desc, true);
475558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        entry = fTextureCache->findAndLock(key,
476558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                           GrResourceCache::kNested_LockType);
477b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        // if we miss, relax the fit of the flags...
478b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        // then try doubling width... then height.
47950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        if (NULL != entry || kExact_ScratchTexMatch == match) {
480b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
481b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
482b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        if (!(desc.fFlags & kRenderTarget_GrTextureFlagBit)) {
483b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = desc.fFlags | kRenderTarget_GrTextureFlagBit;
484b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (desc.fFlags & kNoStencil_GrTextureFlagBit) {
485b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit;
486b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (!doubledW) {
487b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = inDesc.fFlags;
488b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fWidth *= 2;
489b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            doubledW = true;
490b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (!doubledH) {
491b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = inDesc.fFlags;
492b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fWidth = origWidth;
493b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fHeight *= 2;
494b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            doubledH = true;
495b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else {
496b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
497b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
498b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
499b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    } while (true);
500b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
501b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    if (NULL == entry) {
502b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fFlags = inDesc.fFlags;
503b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fWidth = origWidth;
504b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fHeight = origHeight;
505b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
506b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        if (NULL != texture) {
50775b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com            GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL,
508a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                                                      texture->desc(),
509a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                                                      true);
510b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            entry = fTextureCache->createAndLock(key, texture);
511b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
512b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
513b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
514b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // If the caller gives us the same desc/sampler twice we don't want
515b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // to return the same texture the second time (unless it was previously
516b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // released). So we detach the entry from the cache and reattach at release.
517b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    if (NULL != entry) {
518b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        fTextureCache->detach(entry);
519b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
52050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    return TextureCacheEntry(entry);
521b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com}
522b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
52315c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.comvoid GrContext::addExistingTextureToCache(GrTexture* texture) {
52415c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
52515c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    if (NULL == texture) {
52615c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com        return;
52715c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    }
52815c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
52915c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL,
53015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com                                              texture->desc(),
53115c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com                                              true);
53215c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    fTextureCache->attach(key, texture);
53315c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com}
53415c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
53550398bf7f1953e640e5529616e710cf540799731bsalomon@google.comvoid GrContext::unlockTexture(TextureCacheEntry entry) {
536bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(entry.texture());
53750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // If this is a scratch texture we detached it from the cache
53850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // while it was locked (to avoid two callers simultaneously getting
53950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // the same texture).
540a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    if (GrTexture::IsScratchTexture(entry.cacheEntry()->key())) {
54150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->reattachAndUnlock(entry.cacheEntry());
542fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    } else {
54350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->unlock(entry.cacheEntry());
544fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
54527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
54627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
54715c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.comvoid GrContext::freeEntry(TextureCacheEntry entry) {
54815c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    ASSERT_OWNED_RESOURCE(entry.texture());
54915c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
55015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    fTextureCache->freeEntry(entry.cacheEntry());
55115c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com}
55215c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
55375b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.comGrTexture* GrContext::createUncachedTexture(const GrTextureDesc& descIn,
55427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            void* srcData,
55527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            size_t rowBytes) {
55675b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc descCopy = descIn;
55775b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    descCopy.fClientCacheID = kUncached_CacheID;
55875b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    return fGpu->createTexture(descCopy, srcData, rowBytes);
55927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
56027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
5618f7e1dac5c92bf1f53feb603a9bd249d53afa81absalomon@google.comsize_t GrContext::getTextureCacheBudget() const {
5628f7e1dac5c92bf1f53feb603a9bd249d53afa81absalomon@google.com    return fTextureCache->getBudget();
56327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
56427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
5658f7e1dac5c92bf1f53feb603a9bd249d53afa81absalomon@google.comvoid GrContext::setTextureCacheBudget(size_t maxTextureBytes) {
5668f7e1dac5c92bf1f53feb603a9bd249d53afa81absalomon@google.com    fTextureCache->setBudget(maxTextureBytes);
56727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
56827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
569919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxTextureSize() const {
57018c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    return fGpu->getCaps().fMaxTextureSize;
571919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com}
572919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
573919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxRenderTargetSize() const {
57418c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    return fGpu->getCaps().fMaxRenderTargetSize;
57527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
57627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
57727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com///////////////////////////////////////////////////////////////////////////////
57827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
579e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrTexture* GrContext::createPlatformTexture(const GrPlatformTextureDesc& desc) {
580e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com    return fGpu->createPlatformTexture(desc);
581e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
582e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
583e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrRenderTarget* GrContext::createPlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) {
584e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com    return fGpu->createPlatformRenderTarget(desc);
585e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
586e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
5875877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
5885877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com
5891fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.combool GrContext::supportsIndex8PixelConfig(const GrSamplerState* sampler,
5901f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com                                          int width, int height) const {
59118c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    const GrDrawTarget::Caps& caps = fGpu->getCaps();
59218c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    if (!caps.f8BitPaletteSupport) {
59327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return false;
59427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
59527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
59627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
59727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
59827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (!isPow2) {
5991fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        bool tiled = NULL != sampler &&
6001fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                     (sampler->getWrapX() != GrSamplerState::kClamp_WrapMode ||
6011fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com                      sampler->getWrapY() != GrSamplerState::kClamp_WrapMode);
60218c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com        if (tiled && !caps.fNPOTTextureTileSupport) {
60327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return false;
60427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
60527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
60627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return true;
60727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
60827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
60927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
61027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
61105ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.comconst GrClip& GrContext::getClip() const { return fGpu->getClip(); }
61205ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com
61327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setClip(const GrClip& clip) {
61427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->setClip(clip);
61510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->enableState(GrDrawState::kClip_StateBit);
61627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
61727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
61827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setClip(const GrIRect& rect) {
61927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrClip clip;
620d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    clip.setFromIRect(rect);
62127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->setClip(clip);
62227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
62327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
62427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
62527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
626c82a8b7aa4ec19fba508c394920a9e88d3e5bd12robertphillips@google.comvoid GrContext::clear(const GrIRect* rect,
627c82a8b7aa4ec19fba508c394920a9e88d3e5bd12robertphillips@google.com                      const GrColor color,
628c82a8b7aa4ec19fba508c394920a9e88d3e5bd12robertphillips@google.com                      GrRenderTarget* target) {
629398109cc3e56b8122ad21c4d43a74a83be5b42a8bsalomon@google.com    this->flush();
630c82a8b7aa4ec19fba508c394920a9e88d3e5bd12robertphillips@google.com    fGpu->clear(rect, color, target);
63127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
63227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
63327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawPaint(const GrPaint& paint) {
63427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // set rect to be big enough to fill the space, but not super-huge, so we
63527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // don't overflow fixed-point implementations
636d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    GrRect r;
637d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    r.setLTRB(0, 0,
638d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com              GrIntToScalar(getRenderTarget()->width()),
639d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com              GrIntToScalar(getRenderTarget()->height()));
64027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix inverse;
6418c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    SkTLazy<GrPaint> tmpPaint;
6428c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    const GrPaint* p = &paint;
6438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrAutoMatrix am;
6448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6454f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // We attempt to map r by the inverse matrix and draw that. mapRect will
6464f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // map the four corners and bound them with a new rect. This will not
6474f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // produce a correct result for some perspective matrices.
6488c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    if (!this->getMatrix().hasPerspective()) {
64910e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        if (!fDrawState->getViewInverse(&inverse)) {
6508c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            GrPrintf("Could not invert matrix");
6518c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            return;
6528c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
65327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        inverse.mapRect(&r);
65427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
6558c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        if (paint.getActiveMaskStageMask() || paint.getActiveStageMask()) {
65610e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com            if (!fDrawState->getViewInverse(&inverse)) {
6578c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com                GrPrintf("Could not invert matrix");
6588c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com                return;
6598c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            }
6608c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.set(paint);
6618c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.get()->preConcatActiveSamplerMatrices(inverse);
6628c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            p = tmpPaint.get();
6638c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
6644f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com        am.set(this, GrMatrix::I());
66527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
6664f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // by definition this fills the entire clip, no need for AA
6674f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    if (paint.fAntiAlias) {
6688c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        if (!tmpPaint.isValid()) {
6698c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.set(paint);
6708c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            p = tmpPaint.get();
6718c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
6728c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        GrAssert(p == tmpPaint.get());
6738c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        tmpPaint.get()->fAntiAlias = false;
6744f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    }
6754f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    this->drawRect(*p, r);
67627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
67727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
678205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
679205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
680d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.comnamespace {
681d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.cominline bool disable_coverage_aa_for_blend(GrDrawTarget* target) {
682d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage();
683d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com}
684d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com}
685d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
68606afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
68706afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
68827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com/*  create a triangle strip that strokes the specified triangle. There are 8
68927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com unique vertices, but we repreat the last 2 to close up. Alternatively we
69027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com could use an indices array, and then only send 8 verts, but not sure that
69127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com would be faster.
69227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com */
693205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
69427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               GrScalar width) {
69527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    const GrScalar rad = GrScalarHalf(width);
696205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    rect.sort();
69727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
69827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[0].set(rect.fLeft + rad, rect.fTop + rad);
69927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[1].set(rect.fLeft - rad, rect.fTop - rad);
70027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[2].set(rect.fRight - rad, rect.fTop + rad);
70127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[3].set(rect.fRight + rad, rect.fTop - rad);
70227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[4].set(rect.fRight - rad, rect.fBottom - rad);
70327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[5].set(rect.fRight + rad, rect.fBottom + rad);
70427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
70527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
70627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[8] = verts[0];
70727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[9] = verts[1];
70827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
70927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
71020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com/**
71120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com * Returns true if the rects edges are integer-aligned.
71220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com */
71320efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.comstatic bool isIRect(const GrRect& r) {
71420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    return GrScalarIsInt(r.fLeft) && GrScalarIsInt(r.fTop) &&
71520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com           GrScalarIsInt(r.fRight) && GrScalarIsInt(r.fBottom);
71620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com}
71720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
718205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic bool apply_aa_to_rect(GrDrawTarget* target,
719205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             const GrRect& rect,
720205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             GrScalar width,
721205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             const GrMatrix* matrix,
722205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             GrMatrix* combinedMatrix,
723a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             GrRect* devRect,
724a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             bool* useVertexCoverage) {
7252eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // we use a simple coverage ramp to do aa on axis-aligned rects
7262eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // we check if the rect will be axis-aligned, and the rect won't land on
7272eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // integer coords.
728d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
729a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // we are keeping around the "tweak the alpha" trick because
730a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // it is our only hope for the fixed-pipe implementation.
731a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // In a shader implementation we can give a separate coverage input
732289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    // TODO: remove this ugliness when we drop the fixed-pipe impl
733a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    *useVertexCoverage = false;
734d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (!target->canTweakAlphaForCoverage()) {
7352eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com        if (disable_coverage_aa_for_blend(target)) {
7361983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
7372eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            //GrPrintf("Turning off AA to correctly apply blend.\n");
7381983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
739a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            return false;
7402eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com        } else {
7412eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            *useVertexCoverage = true;
742a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        }
743205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
7448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    const GrDrawState& drawState = target->getDrawState();
7458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (drawState.getRenderTarget()->isMultisampled()) {
746205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
747205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
748205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
749471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com    if (0 == width && target->willUseHWAALines()) {
750205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
751205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
752205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
7538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (!drawState.getViewMatrix().preservesAxisAlignment()) {
754205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
755205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
756205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
757205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL != matrix &&
758205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        !matrix->preservesAxisAlignment()) {
759205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
760205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
761205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
7628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    *combinedMatrix = drawState.getViewMatrix();
763205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL != matrix) {
764205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        combinedMatrix->preConcat(*matrix);
765205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrAssert(combinedMatrix->preservesAxisAlignment());
766205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
767205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
768205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    combinedMatrix->mapRect(devRect, rect);
769205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    devRect->sort();
770205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
771205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (width < 0) {
77220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        return !isIRect(*devRect);
773205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    } else {
774205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return true;
775205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
776205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
777205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
77827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRect(const GrPaint& paint,
77927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         const GrRect& rect,
78027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         GrScalar width,
78127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         const GrMatrix* matrix) {
782278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRect");
78327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
78427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
785972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    GrDrawState::AutoTextureRelease atr(fDrawState);
78626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int stageMask = paint.getActiveStageMask();
78727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
788205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrRect devRect = rect;
789205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrMatrix combinedMatrix;
790a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    bool useVertexCoverage;
791289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool needAA = paint.fAntiAlias &&
792289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                  !this->getRenderTarget()->isMultisampled();
793289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix,
794289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &combinedMatrix, &devRect,
795289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &useVertexCoverage);
796205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
797205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (doAA) {
7988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
799205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        if (width >= 0) {
800205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            GrVec strokeSize;;
801205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            if (width > 0) {
802205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.set(width, width);
803cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com                combinedMatrix.mapVectors(&strokeSize, 1);
804205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.setAbs(strokeSize);
805205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            } else {
806205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.set(GR_Scalar1, GR_Scalar1);
807205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            }
808f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com            fAARectRenderer->strokeAARect(this->getGpu(), target, devRect,
809f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com                                         strokeSize, useVertexCoverage);
810205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        } else {
811f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com            fAARectRenderer->fillAARect(this->getGpu(), target,
812f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com                                       devRect, useVertexCoverage);
813205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        }
814205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return;
815205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
816205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
81727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (width >= 0) {
81827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // TODO: consider making static vertex buffers for these cases.
81927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // Hairline could be done by just adding closing vertex to
82027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // unitSquareVertexBuffer()
82126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        GrVertexLayout layout =  PaintStageVertexLayoutBits(paint, NULL);
82226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
82327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        static const int worstCaseVertCount = 10;
82427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
82527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
82627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.succeeded()) {
8276513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
82827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
82927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
83027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
83127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPrimitiveType primType;
83227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int vertCount;
83327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPoint* vertex = geo.positions();
83427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
83527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (width > 0) {
83627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 10;
83747059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com            primType = kTriangleStrip_GrPrimitiveType;
83827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            setStrokeRectStrip(vertex, rect, width);
83927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        } else {
84027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // hairline
84127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 5;
84247059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com            primType = kLineStrip_GrPrimitiveType;
84327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[0].set(rect.fLeft, rect.fTop);
84427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[1].set(rect.fRight, rect.fTop);
84527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[2].set(rect.fRight, rect.fBottom);
84627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[3].set(rect.fLeft, rect.fBottom);
84727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[4].set(rect.fLeft, rect.fTop);
84827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
84927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
8508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState::AutoViewMatrixRestore avmr;
85127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != matrix) {
8528f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
8538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            avmr.set(drawState);
8548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatViewMatrix(*matrix);
8558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatSamplerMatrices(stageMask, *matrix);
85627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
85727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
85827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->drawNonIndexed(primType, 0, vertCount);
85927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
8608f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#if GR_STATIC_RECT_VB
86126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
8626513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
8636513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            if (NULL == sqVB) {
8646513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com                GrPrintf("Failed to create static rect vb.\n");
8656513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com                return;
8666513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            }
8676513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            target->setVertexSourceToBuffer(layout, sqVB);
8688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
8698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState::AutoViewMatrixRestore avmr(drawState);
87027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrMatrix m;
8718295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com            m.setAll(rect.width(),    0,             rect.fLeft,
872205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0,            rect.height(), rect.fTop,
873205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0,            0,             GrMatrix::I()[8]);
87427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
87527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (NULL != matrix) {
87627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                m.postConcat(*matrix);
87727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
8788f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatViewMatrix(m);
8798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatSamplerMatrices(stageMask, m);
88026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
88147059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com            target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
8828f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#else
88326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            target->drawSimpleRect(rect, matrix, stageMask);
8848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#endif
88527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
88627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
88727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
88827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRectToRect(const GrPaint& paint,
88927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrRect& dstRect,
89027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrRect& srcRect,
89127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrMatrix* dstMatrix,
89227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrMatrix* srcMatrix) {
893278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRectToRect");
89427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
89526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    // srcRect refers to paint's first texture
89626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    if (NULL == paint.getTexture(0)) {
89727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        drawRect(paint, dstRect, -1, dstMatrix);
89827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
89927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
900de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com
90127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB);
90227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
90327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_STATIC_RECT_VB
90427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
905972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    GrDrawState::AutoTextureRelease atr(fDrawState);
9068f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = target->drawState();
90726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
9088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState::AutoViewMatrixRestore avmr(drawState);
90927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
91027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix m;
91127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
91227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    m.setAll(dstRect.width(), 0,                dstRect.fLeft,
91327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               dstRect.height(), dstRect.fTop,
91427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               0,                GrMatrix::I()[8]);
91527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != dstMatrix) {
91627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        m.postConcat(*dstMatrix);
91727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
9188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->preConcatViewMatrix(m);
91927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
92026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    // srcRect refers to first stage
92126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int otherStageMask = paint.getActiveStageMask() &
92226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                         (~(1 << GrPaint::kFirstTextureStage));
92326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    if (otherStageMask) {
9248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->preConcatSamplerMatrices(otherStageMask, m);
92526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
92626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
92727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    m.setAll(srcRect.width(), 0,                srcRect.fLeft,
92827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               srcRect.height(), srcRect.fTop,
92927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               0,                GrMatrix::I()[8]);
93027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != srcMatrix) {
93127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        m.postConcat(*srcMatrix);
93227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
9338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->sampler(GrPaint::kFirstTextureStage)->preConcatMatrix(m);
93427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
9356513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
9366513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    if (NULL == sqVB) {
9376513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to create static rect vb.\n");
9386513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        return;
9396513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    }
9406513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    target->setVertexSourceToBuffer(layout, sqVB);
94147059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com    target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
94227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
94327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
94427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target;
945de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com#if BATCH_RECT_TO_RECT
94627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = this->prepareToDraw(paint, kBuffered_DrawCategory);
947de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com#else
94827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
94927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
950972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    GrDrawState::AutoTextureRelease atr(fDrawState);
95127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
9529381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
9539381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    const GrMatrix* srcMatrices[GrDrawState::kNumStages] = {NULL};
95427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    srcRects[0] = &srcRect;
95527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    srcMatrices[0] = srcMatrix;
95627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
95727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices);
95827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
95927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
96027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
96127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawVertices(const GrPaint& paint,
96227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             GrPrimitiveType primitiveType,
96327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int vertexCount,
96427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint positions[],
96527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint texCoords[],
96627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrColor colors[],
96727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const uint16_t indices[],
96827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int indexCount) {
969278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawVertices");
97027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
97127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo;
97227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
97327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
974972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    GrDrawState::AutoTextureRelease atr(fDrawState);
97527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
97626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    bool hasTexCoords[GrPaint::kTotalStages] = {
97726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        NULL != texCoords,   // texCoordSrc provides explicit stage 0 coords
97826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        0                    // remaining stages use positions
97926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    };
98026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
98126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, hasTexCoords);
98227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
98327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != colors) {
98427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        layout |= GrDrawTarget::kColor_VertexLayoutBit;
98527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
98626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int vertexSize = GrDrawTarget::VertexSize(layout);
98727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
98827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (sizeof(GrPoint) != vertexSize) {
98927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.set(target, layout, vertexCount, 0)) {
9906513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
99127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
99227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
9939381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        int texOffsets[GrDrawState::kMaxTexCoords];
99427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int colorOffset;
99526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
99626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                                                texOffsets,
997aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com                                                &colorOffset,
998a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                                NULL,
999a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                                NULL);
100027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* curVertex = geo.vertices();
100127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
100227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < vertexCount; ++i) {
100327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            *((GrPoint*)curVertex) = positions[i];
100427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
100527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (texOffsets[0] > 0) {
100627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
100727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
100827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (colorOffset > 0) {
100927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
101027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
101126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            curVertex = (void*)((intptr_t)curVertex + vertexSize);
101227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
101327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
101427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->setVertexSourceToArray(layout, positions, vertexCount);
101527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
101627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1017919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // we don't currently apply offscreen AA to this path. Need improved
1018919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // management of GrDrawTarget's geometry to avoid copying points per-tile.
1019a47a48dca5045d71cbc5de343404045209a13e15bsalomon@google.com
10208295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    if (NULL != indices) {
1021919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        target->setIndexSourceToArray(indices, indexCount);
10228295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
102327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
10248295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawNonIndexed(primitiveType, 0, vertexCount);
10258295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
102627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
102727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
102806afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
1029150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.comnamespace {
1030150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
103193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.comstruct CircleVertex {
103293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrPoint fPos;
103393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrPoint fCenter;
103493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar fOuterRadius;
103593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar fInnerRadius;
103693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com};
103793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
103893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com/* Returns true if will map a circle to another circle. This can be true
103993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com * if the matrix only includes square-scale, rotation, translation.
104093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com */
104193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.cominline bool isSimilarityTransformation(const SkMatrix& matrix,
104293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                                       SkScalar tol = SK_ScalarNearlyZero) {
104393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (matrix.isIdentity() || matrix.getType() == SkMatrix::kTranslate_Mask) {
104493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return true;
104593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
104693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (matrix.hasPerspective()) {
104793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return false;
104893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
104993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
105093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar mx = matrix.get(SkMatrix::kMScaleX);
105193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar sx = matrix.get(SkMatrix::kMSkewX);
105293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar my = matrix.get(SkMatrix::kMScaleY);
105393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar sy = matrix.get(SkMatrix::kMSkewY);
105493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
105593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (mx == 0 && sx == 0 && my == 0 && sy == 0) {
105693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return false;
105793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
105893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
105993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    // it has scales or skews, but it could also be rotation, check it out.
106093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkVector vec[2];
106193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    vec[0].set(mx, sx);
106293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    vec[1].set(sy, my);
106393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
106493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    return SkScalarNearlyZero(vec[0].dot(vec[1]), SkScalarSquare(tol)) &&
106593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com           SkScalarNearlyEqual(vec[0].lengthSqd(), vec[1].lengthSqd(),
106693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                SkScalarSquare(tol));
106793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com}
106893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
106993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com}
107093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
107193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com// TODO: strokeWidth can't be larger than zero right now.
107293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com// It will be fixed when drawPath() can handle strokes.
107393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.comvoid GrContext::drawOval(const GrPaint& paint,
107493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                         const GrRect& rect,
107593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                         SkScalar strokeWidth) {
107693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    DrawCategory category = (DEFER_PATHS) ? kBuffered_DrawCategory :
107793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                                            kUnbuffered_DrawCategory;
107893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, category);
1079972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    GrDrawState::AutoTextureRelease atr(fDrawState);
108093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrDrawState* drawState = target->drawState();
108193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrMatrix vm = drawState->getViewMatrix();
108293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
108393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (!isSimilarityTransformation(vm) ||
108493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        !paint.fAntiAlias ||
108593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        rect.height() != rect.width()) {
108693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        SkPath path;
108793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        path.addOval(rect);
108893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        GrPathFill fill = (strokeWidth == 0) ?
108947059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com                            kHairLine_GrPathFill : kWinding_GrPathFill;
109093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        this->internalDrawPath(paint, path, fill, NULL);
109193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return;
109293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
109393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
109493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    const GrRenderTarget* rt = drawState->getRenderTarget();
109593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (NULL == rt) {
109693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return;
109793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
109893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
109993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrDrawTarget::AutoDeviceCoordDraw adcd(target, paint.getActiveStageMask());
110093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
110193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
110293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    layout |= GrDrawTarget::kEdge_VertexLayoutBit;
110393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrAssert(sizeof(CircleVertex) == GrDrawTarget::VertexSize(layout));
110493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
110593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrPoint center = GrPoint::Make(rect.centerX(), rect.centerY());
110693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar radius = SkScalarHalf(rect.width());
110793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
110893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    vm.mapPoints(&center, 1);
110993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    radius = vm.mapRadius(radius);
111093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
111193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar outerRadius = radius;
111293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar innerRadius = 0;
111393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar halfWidth = 0;
111493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (strokeWidth == 0) {
111593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        halfWidth = SkScalarHalf(SK_Scalar1);
111693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
111793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        outerRadius += halfWidth;
111893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        innerRadius = SkMaxScalar(0, radius - halfWidth);
111993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
112093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
112193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(target, layout, 4, 0);
112293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (!geo.succeeded()) {
112393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
112493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return;
112593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
112693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
112793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
112893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1129a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    // The fragment shader will extend the radius out half a pixel
1130a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    // to antialias. Expand the drawn rect here so all the pixels
1131a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    // will be captured.
1132a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    SkScalar L = center.fX - outerRadius - SkFloatToScalar(0.5f);
1133a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    SkScalar R = center.fX + outerRadius + SkFloatToScalar(0.5f);
1134a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    SkScalar T = center.fY - outerRadius - SkFloatToScalar(0.5f);
1135a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    SkScalar B = center.fY + outerRadius + SkFloatToScalar(0.5f);
113693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
113793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    verts[0].fPos = SkPoint::Make(L, T);
113893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    verts[1].fPos = SkPoint::Make(R, T);
113993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    verts[2].fPos = SkPoint::Make(L, B);
114093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    verts[3].fPos = SkPoint::Make(R, B);
114193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
114293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    for (int i = 0; i < 4; ++i) {
114393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        // this goes to fragment shader, it should be in y-points-up space.
114493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        verts[i].fCenter = SkPoint::Make(center.fX, rt->height() - center.fY);
114593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
114693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        verts[i].fOuterRadius = outerRadius;
114793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        verts[i].fInnerRadius = innerRadius;
114893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
114993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
115093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    drawState->setVertexEdgeType(GrDrawState::kCircle_EdgeType);
115147059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com    target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4);
1152150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
115327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
11548d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comvoid GrContext::drawPath(const GrPaint& paint, const SkPath& path,
115507f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.com                         GrPathFill fill, const GrPoint* translate) {
115627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1157fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (path.isEmpty()) {
1158fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       if (GrIsFillInverted(fill)) {
1159fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com           this->drawPaint(paint);
1160fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       }
1161fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       return;
1162fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
1163fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
116493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkRect ovalRect;
116593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (!GrIsFillInverted(fill) && path.isOval(&ovalRect)) {
116693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        if (translate) {
116793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com            ovalRect.offset(*translate);
116893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        }
116947059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        SkScalar width = (fill == kHairLine_GrPathFill) ? 0 : -SK_Scalar1;
117093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        this->drawOval(paint, ovalRect, width);
117193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return;
117293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
117393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
117493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    internalDrawPath(paint, path, fill, translate);
117593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com}
117693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
11778d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comvoid GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path,
117893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                                 GrPathFill fill, const GrPoint* translate) {
117993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1180fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // Note that below we may sw-rasterize the path into a scratch texture.
1181fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // Scratch textures can be recycled after they are returned to the texture
1182fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // cache. This presents a potential hazard for buffered drawing. However,
1183fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // the writePixels that uploads to the scratch will perform a flush so we're
1184fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // OK.
1185fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    DrawCategory category = (DEFER_PATHS) ? kBuffered_DrawCategory :
1186fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com                                            kUnbuffered_DrawCategory;
1187fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, category);
1188972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    GrDrawState::AutoTextureRelease atr(fDrawState);
1189150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com    GrDrawState::StageMask stageMask = paint.getActiveStageMask();
1190d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
1191289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool prAA = paint.fAntiAlias && !this->getRenderTarget()->isMultisampled();
1192289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
1193d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // An Assumption here is that path renderer would use some form of tweaking
1194d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // the src color (either the input alpha or in the frag shader) to implement
1195d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // aa. If we have some future driver-mojo path AA that can do the right
1196d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // thing WRT to the blend then we'll need some query on the PR.
1197d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (disable_coverage_aa_for_blend(target)) {
11981983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
1199979432ba2621b617f5e85a9ff48c6b6cd1504a0dbsalomon@google.com        //GrPrintf("Turning off AA to correctly apply blend.\n");
12001983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
1201289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        prAA = false;
1202d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    }
1203289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
120472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrPathRenderer* pr = this->getPathRenderer(path, fill, target, prAA, true);
12053008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == pr) {
12061983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
12073008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        GrPrintf("Unable to find path renderer compatible with path.\n");
12081983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
12093008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        return;
12103008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
12113008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
1212c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com    pr->drawPath(path, fill, translate, target, stageMask, prAA);
121327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
12148295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
121527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
121627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1217a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.comvoid GrContext::flush(int flagsBitfield) {
1218a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kDiscard_FlushBit & flagsBitfield) {
1219a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com        fDrawBuffer->reset();
1220a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    } else {
1221c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        this->flushDrawBuffer();
1222a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    }
1223a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) {
122427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fGpu->forceRenderTargetFlush();
122527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
122627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
122727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
122827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::flushDrawBuffer() {
122953a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    if (fDrawBuffer) {
123058b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // With addition of the AA clip path, flushing the draw buffer can
123158b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // result in the generation of an AA clip mask. During this
123258b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // process the SW path renderer may be invoked which recusively
123358b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // calls this method (via internalWriteTexturePixels) creating
123458b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // infinite recursion
123558b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        GrInOrderDrawBuffer* temp = fDrawBuffer;
123658b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        fDrawBuffer = NULL;
123758b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com
123858b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        temp->flushTo(fGpu);
123958b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com
124058b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        fDrawBuffer = temp;
124153a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    }
124227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
124327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
12446f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.comvoid GrContext::internalWriteTexturePixels(GrTexture* texture,
12456f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           int left, int top,
12466f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           int width, int height,
12476f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           GrPixelConfig config,
12486f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           const void* buffer,
12496f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           size_t rowBytes,
12506f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           uint32_t flags) {
12516f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeTexturePixels");
1252bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1253bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
12546f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
12556f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        this->flush();
12566f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
12576f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    // TODO: use scratch texture to perform conversion
12586f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (GrPixelConfigIsUnpremultiplied(texture->config()) !=
12596f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config)) {
12606f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        return;
12616f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
12626f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
12636f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    fGpu->writeTexturePixels(texture, left, top, width, height,
12646f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                             config, buffer, rowBytes);
12656f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com}
12666f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
12676f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.combool GrContext::internalReadTexturePixels(GrTexture* texture,
12686f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          int left, int top,
12696f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          int width, int height,
12706f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          GrPixelConfig config,
12716f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          void* buffer,
12726f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          size_t rowBytes,
12736f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          uint32_t flags) {
1274278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readTexturePixels");
1275bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1276669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1277a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // TODO: code read pixels for textures that aren't also rendertargets
1278669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    GrRenderTarget* target = texture->asRenderTarget();
1279669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    if (NULL != target) {
12806f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        return this->internalReadRenderTargetPixels(target,
12816f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    left, top, width, height,
12826f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    config, buffer, rowBytes,
12836f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    flags);
1284669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    } else {
1285669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com        return false;
1286669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    }
1287669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com}
1288669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1289a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com#include "SkConfig8888.h"
1290a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
1291a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.comnamespace {
1292a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com/**
1293a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * Converts a GrPixelConfig to a SkCanvas::Config8888. Only byte-per-channel
1294a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * formats are representable as Config8888 and so the function returns false
1295a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * if the GrPixelConfig has no equivalent Config8888.
1296a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com */
1297a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.combool grconfig_to_config8888(GrPixelConfig config,
1298a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                            SkCanvas::Config8888* config8888) {
1299a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    switch (config) {
1300a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kRGBA_8888_PM_GrPixelConfig:
1301a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kRGBA_Premul_Config8888;
1302a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1303a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kRGBA_8888_UPM_GrPixelConfig:
1304a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
1305a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1306a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kBGRA_8888_PM_GrPixelConfig:
1307a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kBGRA_Premul_Config8888;
1308a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1309a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kBGRA_8888_UPM_GrPixelConfig:
1310a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kBGRA_Unpremul_Config8888;
1311a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1312a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        default:
1313a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return false;
1314a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1315a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
1316a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
1317a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
13186f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.combool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target,
13196f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               int left, int top,
13206f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               int width, int height,
13216f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               GrPixelConfig config,
13226f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               void* buffer,
13236f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               size_t rowBytes,
13246f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               uint32_t flags) {
1325278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
1326bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
1327bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
1328669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    if (NULL == target) {
132910e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        target = fDrawState->getRenderTarget();
1330c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (NULL == target) {
1331c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            return false;
1332c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1333c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1334669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
13356f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
13366f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        this->flush();
13376f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
1338c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1339a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    if (!GrPixelConfigIsUnpremultiplied(target->config()) &&
1340a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config) &&
1341a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        !fGpu->canPreserveReadWriteUnpremulPixels()) {
1342a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkCanvas::Config8888 srcConfig8888, dstConfig8888;
1343a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        if (!grconfig_to_config8888(target->config(), &srcConfig8888) ||
1344a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            !grconfig_to_config8888(config, &dstConfig8888)) {
1345a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return false;
1346a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        }
1347a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // do read back using target's own config
1348a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        this->internalReadRenderTargetPixels(target,
1349a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             left, top,
1350a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             width, height,
1351a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             target->config(),
1352a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             buffer, rowBytes,
1353a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             kDontFlush_PixelOpsFlag);
1354a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // sw convert the pixels to unpremul config
1355a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        uint32_t* pixels = reinterpret_cast<uint32_t*>(buffer);
1356a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkConvertConfig8888Pixels(pixels, rowBytes, dstConfig8888,
1357a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  pixels, rowBytes, srcConfig8888,
1358a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  width, height);
1359a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        return true;
1360a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1361a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
1362c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    GrTexture* src = target->asTexture();
13630a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    bool swapRAndB = NULL != src &&
13640a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                     fGpu->preferredReadPixelsConfig(config) ==
13650a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                     GrPixelConfigSwapRAndB(config);
1366c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1367c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    bool flipY = NULL != src &&
1368c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                 fGpu->readPixelsWillPayForYFlip(target, left, top,
1369c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 width, height, config,
1370c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 rowBytes);
13710a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    bool alphaConversion = (!GrPixelConfigIsUnpremultiplied(target->config()) &&
13720a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                             GrPixelConfigIsUnpremultiplied(config));
1373c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
13740a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    if (NULL == src && alphaConversion) {
13750a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // we should fallback to cpu conversion here. This could happen when
13760a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // we were given an external render target by the client that is not
13770a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // also a texture (e.g. FBO 0 in GL)
13780a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        return false;
13790a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    }
13800a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    // we draw to a scratch texture if any of these conversion are applied
1381c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com    GrAutoScratchTexture ast;
13820a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    if (flipY || swapRAndB || alphaConversion) {
13830a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        GrAssert(NULL != src);
13840a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        if (swapRAndB) {
13850a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com            config = GrPixelConfigSwapRAndB(config);
13860a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com            GrAssert(kUnknown_GrPixelConfig != config);
1387c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1388c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        // Make the scratch a render target because we don't have a robust
1389c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        // readTexturePixels as of yet (it calls this function).
139075b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        GrTextureDesc desc;
139175b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fFlags = kRenderTarget_GrTextureFlagBit;
139275b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fWidth = width;
139375b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fHeight = height;
139475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fConfig = config;
1395c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com
139656d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // When a full readback is faster than a partial we could always make
139756d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // the scratch exactly match the passed rect. However, if we see many
139856d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // different size rectangles we will trash our texture cache and pay the
139956d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // cost of creating and destroying many textures. So, we only request
140056d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // an exact match when the caller is reading an entire RT.
140156d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ScratchTexMatch match = kApprox_ScratchTexMatch;
140256d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        if (0 == left &&
140356d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            0 == top &&
140456d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->width() == width &&
140556d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->height() == height &&
140656d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            fGpu->fullReadPixelsIsFasterThanPartial()) {
140756d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            match = kExact_ScratchTexMatch;
140856d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        }
140956d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ast.set(this, desc, match);
1410c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrTexture* texture = ast.texture();
1411c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (!texture) {
1412c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            return false;
1413c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1414c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        target = texture->asRenderTarget();
1415c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrAssert(NULL != target);
1416c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1417873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com        GrDrawTarget::AutoStateRestore asr(fGpu,
1418873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com                                           GrDrawTarget::kReset_ASRInit);
14198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState* drawState = fGpu->drawState();
14208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setRenderTarget(target);
1421c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1422c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrMatrix matrix;
1423c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (flipY) {
1424c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.setTranslate(SK_Scalar1 * left,
1425c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                SK_Scalar1 * (top + height));
1426c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.set(GrMatrix::kMScaleY, -GR_Scalar1);
1427c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        } else {
1428c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
1429c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1430c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        matrix.postIDiv(src->width(), src->height());
14311e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com        drawState->sampler(0)->reset(matrix);
14321e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com        drawState->sampler(0)->setRAndBSwap(swapRAndB);
14338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setTexture(0, src);
1434c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrRect rect;
1435c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        rect.setXYWH(0, 0, SK_Scalar1 * width, SK_Scalar1 * height);
1436c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        fGpu->drawSimpleRect(rect, NULL, 0x1);
1437c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        left = 0;
1438c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        top = 0;
1439c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1440669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    return fGpu->readPixels(target,
1441c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                            left, top, width, height,
1442c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                            config, buffer, rowBytes, flipY);
144327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
144427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
144575f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.comvoid GrContext::resolveRenderTarget(GrRenderTarget* target) {
144675f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    GrAssert(target);
144775f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
144875f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // In the future we may track whether there are any pending draws to this
144975f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // target. We don't today so we always perform a flush. We don't promise
145075f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // this to our clients, though.
145175f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    this->flush();
145275f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    fGpu->resolveRenderTarget(target);
145375f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com}
145475f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com
1455ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.orgvoid GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst) {
1456ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    if (NULL == src || NULL == dst) {
1457ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        return;
1458ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
1459ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(src);
1460ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
14611ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // Writes pending to the source texture are not tracked, so a flush
14621ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // is required to ensure that the copy captures the most recent contents
14631ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // of the source texture. See similar behaviour in
14641ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // GrContext::resolveRenderTarget.
14651ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    this->flush();
14661ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com
1467873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
14688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
14698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(dst);
1470ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    GrMatrix sampleM;
1471ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    sampleM.setIDiv(src->width(), src->height());
14728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setTexture(0, src);
14731e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->reset(sampleM);
14745db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com    SkRect rect = SkRect::MakeXYWH(0, 0,
14755db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                                   SK_Scalar1 * src->width(),
14765db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                                   SK_Scalar1 * src->height());
1477ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    fGpu->drawSimpleRect(rect, NULL, 1 << 0);
1478ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org}
1479ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
14806f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.comvoid GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target,
14816f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                int left, int top,
14826f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                int width, int height,
14836f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                GrPixelConfig config,
14846f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                const void* buffer,
14856f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                size_t rowBytes,
14866f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                uint32_t flags) {
14876f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
1488bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
14896f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
14906f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (NULL == target) {
1491873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com        target = fDrawState->getRenderTarget();
14926f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        if (NULL == target) {
14936f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com            return;
14946f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        }
14956f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
149627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
149727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // TODO: when underlying api has a direct way to do this we should use it
149827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // (e.g. glDrawPixels on desktop GL).
149927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1500a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // If the RT is also a texture and we don't have to do PM/UPM conversion
1501a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // then take the texture path, which we expect to be at least as fast or
1502a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // faster since it doesn't use an intermediate texture as we do below.
1503a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1504a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#if !GR_MAC_BUILD
1505a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // At least some drivers on the Mac get confused when glTexImage2D is called
1506a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // on a texture attached to an FBO. The FBO still sees the old image. TODO:
1507a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // determine what OS versions and/or HW is affected.
1508a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    if (NULL != target->asTexture() &&
1509a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        GrPixelConfigIsUnpremultiplied(target->config()) ==
1510a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config)) {
1511a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1512a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        this->internalWriteTexturePixels(target->asTexture(),
1513a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                                         left, top, width, height,
1514a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                                         config, buffer, rowBytes, flags);
1515a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        return;
1516a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1517a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#endif
1518a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    if (!GrPixelConfigIsUnpremultiplied(target->config()) &&
1519a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config) &&
1520a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        !fGpu->canPreserveReadWriteUnpremulPixels()) {
1521a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkCanvas::Config8888 srcConfig8888, dstConfig8888;
1522a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        if (!grconfig_to_config8888(config, &srcConfig8888) ||
1523a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            !grconfig_to_config8888(target->config(), &dstConfig8888)) {
1524a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return;
1525a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        }
1526a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // allocate a tmp buffer and sw convert the pixels to premul
1527a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(width * height);
1528a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        const uint32_t* src = reinterpret_cast<const uint32_t*>(buffer);
1529a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkConvertConfig8888Pixels(tmpPixels.get(), 4 * width, dstConfig8888,
1530a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  src, rowBytes, srcConfig8888,
1531a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  width, height);
1532a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // upload the already premul pixels
1533a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        this->internalWriteRenderTargetPixels(target,
1534a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             left, top,
1535a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             width, height,
1536a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             target->config(),
1537a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             tmpPixels, 4 * width, flags);
1538a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        return;
1539a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1540a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1541a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    bool swapRAndB = fGpu->preferredReadPixelsConfig(config) ==
1542a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                     GrPixelConfigSwapRAndB(config);
1543a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    if (swapRAndB) {
1544a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        config = GrPixelConfigSwapRAndB(config);
1545a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1546a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
154775b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc desc;
154875b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fWidth = width;
154975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fHeight = height;
155075b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fConfig = config;
155175b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com
155250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrAutoScratchTexture ast(this, desc);
155350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrTexture* texture = ast.texture();
155427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL == texture) {
155527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
155627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
15576f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    this->internalWriteTexturePixels(texture, 0, 0, width, height,
15586f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                     config, buffer, rowBytes, flags);
155927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1560873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrDrawTarget::AutoStateRestore  asr(fGpu, GrDrawTarget::kReset_ASRInit);
15618f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
156227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
156327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix matrix;
156427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
15658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setViewMatrix(matrix);
15668f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(target);
15678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setTexture(0, texture);
156827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
15695c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com    matrix.setIDiv(texture->width(), texture->height());
15701e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
15711e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                 GrSamplerState::kNearest_Filter,
15721e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com                                 matrix);
15731e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->setRAndBSwap(swapRAndB);
157427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
157527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
157627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    static const int VCOUNT = 4;
15776513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    // TODO: Use GrGpu::drawRect here
157827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
157927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (!geo.succeeded()) {
15806513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
158127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
158227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
158327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
158447059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com    fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, VCOUNT);
158527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
158627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
158727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
158810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.comvoid GrContext::setPaint(const GrPaint& paint) {
158926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
159026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kMaxTextures; ++i) {
159126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        int s = i + GrPaint::kFirstTextureStage;
159210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->setTexture(s, paint.getTexture(i));
1593bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com        ASSERT_OWNED_RESOURCE(paint.getTexture(i));
1594f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        if (paint.getTexture(i)) {
159510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com            *fDrawState->sampler(s) = paint.getTextureSampler(i);
1596f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        }
159726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
159826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
159910e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setFirstCoverageStage(GrPaint::kFirstMaskStage);
160026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
160126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kMaxMasks; ++i) {
160226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        int s = i + GrPaint::kFirstMaskStage;
160310e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->setTexture(s, paint.getMask(i));
1604bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com        ASSERT_OWNED_RESOURCE(paint.getMask(i));
1605f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        if (paint.getMask(i)) {
160610e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com            *fDrawState->sampler(s) = paint.getMaskSampler(i);
1607f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        }
160826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
160926936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com
161026936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com    // disable all stages not accessible via the paint
161126936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com    for (int s = GrPaint::kTotalStages; s < GrDrawState::kNumStages; ++s) {
161210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->setTexture(s, NULL);
161326936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com    }
161426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
161510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setColor(paint.fColor);
161627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
161727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (paint.fDither) {
161810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->enableState(GrDrawState::kDither_StateBit);
161927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
162010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->disableState(GrDrawState::kDither_StateBit);
162127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
162227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (paint.fAntiAlias) {
162310e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->enableState(GrDrawState::kHWAntialias_StateBit);
162427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
162510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->disableState(GrDrawState::kHWAntialias_StateBit);
162627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
162750bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    if (paint.fColorMatrixEnabled) {
162810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->enableState(GrDrawState::kColorMatrix_StateBit);
162910e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->setColorMatrix(paint.fColorMatrix);
163050bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    } else {
163110e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->disableState(GrDrawState::kColorMatrix_StateBit);
163250bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    }
163310e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
163410e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
163510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setCoverage(paint.fCoverage);
16364b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#if GR_DEBUG_PARTIAL_COVERAGE_CHECK
1637e79c815bca39fa552983b7a8107219aa5084acdbbsalomon@google.com    if ((paint.getActiveMaskStageMask() || 0xff != paint.fCoverage) &&
163810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        !fGpu->canApplyCoverage()) {
1639d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com        GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
1640d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    }
164195cd7bdf2b4dee54739f0a375fe99a02f86178b0bsalomon@google.com#endif
164227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
164327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1644de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.comGrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
164527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                       DrawCategory category) {
164627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (category != fLastDrawCategory) {
1647fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com        this->flushDrawBuffer();
164827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fLastDrawCategory = category;
164927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
165010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    this->setPaint(paint);
165127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = fGpu;
165227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    switch (category) {
1653193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com        case kUnbuffered_DrawCategory:
1654193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            target = fGpu;
1655193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            break;
1656193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com        case kBuffered_DrawCategory:
1657193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            target = fDrawBuffer;
1658193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            fDrawBuffer->setClip(fGpu->getClip());
1659193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            break;
1660193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com        default:
1661193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            GrCrash("Unexpected DrawCategory.");
1662193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            break;
166327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
166427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return target;
166527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
166627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
166772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com/*
166872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * This method finds a path renderer that can draw the specified path on
166972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * the provided target.
167072176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * Due to its expense, the software path renderer has split out so it can
167172176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * can be individually allowed/disallowed via the "allowSW" boolean.
167272176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com */
16738d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comGrPathRenderer* GrContext::getPathRenderer(const SkPath& path,
1674289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           GrPathFill fill,
1675c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com                                           const GrDrawTarget* target,
167672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                           bool antiAlias,
167772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                           bool allowSW) {
16783008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == fPathRendererChain) {
16793008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        fPathRendererChain =
16803008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com            new GrPathRendererChain(this, GrPathRendererChain::kNone_UsageFlag);
16813008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
168272176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
168372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(path, fill,
168472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                                             target,
168572176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                                             antiAlias);
168672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
168772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    if (NULL == pr && allowSW) {
168872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        if (NULL == fSoftwarePathRenderer) {
168972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com            fSoftwarePathRenderer = new GrSoftwarePathRenderer(this);
169072176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        }
169172176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
169272176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        pr = fSoftwarePathRenderer;
169372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    }
169472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
169572176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    return pr;
16963008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com}
16973008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
169827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
169927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
170027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setRenderTarget(GrRenderTarget* target) {
1701bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
170210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    if (fDrawState->getRenderTarget() != target) {
1703fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com        this->flush(false);
170410e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->setRenderTarget(target);
1705fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    }
170627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
170727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
170827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrRenderTarget* GrContext::getRenderTarget() {
170910e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    return fDrawState->getRenderTarget();
171027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
171127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
171227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrRenderTarget* GrContext::getRenderTarget() const {
171310e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    return fDrawState->getRenderTarget();
171427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
171527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
171699a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.combool GrContext::isConfigRenderable(GrPixelConfig config) const {
171799a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com    return fGpu->isConfigRenderable(config);
171899a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com}
171999a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com
172027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrMatrix& GrContext::getMatrix() const {
172110e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    return fDrawState->getViewMatrix();
172227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
172327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
172427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setMatrix(const GrMatrix& m) {
172510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setViewMatrix(m);
172627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
172727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
172827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::concatMatrix(const GrMatrix& m) const {
172910e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->preConcatViewMatrix(m);
173027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
173127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
173227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
173327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    intptr_t mask = 1 << shift;
173427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (pred) {
173527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        bits |= mask;
173627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
173727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        bits &= ~mask;
173827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
173927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return bits;
174027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
174127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1742583a1e38503ebd57ba9bd39a3fabe89bead8e76cbsalomon@google.comGrContext::GrContext(GrGpu* gpu) {
1743c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    ++THREAD_INSTANCE_COUNT;
1744c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
174527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu = gpu;
174627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->ref();
1747669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    fGpu->setContext(this);
17488fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
174910e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState = new GrDrawState();
175010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fGpu->setDrawState(fDrawState);
175110e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com
17523008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    fPathRendererChain = NULL;
175372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    fSoftwarePathRenderer = NULL;
1754dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com
17558f7e1dac5c92bf1f53feb603a9bd249d53afa81absalomon@google.com    fTextureCache = new GrResourceCache(kDefaultTextureCacheBudget);
175627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fFontCache = new GrFontCache(fGpu);
175727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
175827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fLastDrawCategory = kUnbuffered_DrawCategory;
175927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
17608fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
17618fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
17628fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
17638fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1764f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer = new GrAARectRenderer;
176510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com
17668fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->setupDrawBuffer();
17678fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
17688fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
17698fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::setupDrawBuffer() {
17708fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
17718fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBuffer);
17728fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBufferVBAllocPool);
17738fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBufferIBAllocPool);
17748fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
177592edd316e5425f7f7fbecbae28483da2851248bbbsalomon@google.com#if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT || DEFER_PATHS
1776de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferVBAllocPool =
17778fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com        new GrVertexBufferAllocPool(fGpu, false,
177827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                    DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
177927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                    DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS);
1780de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferIBAllocPool =
17818fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com        new GrIndexBufferAllocPool(fGpu, false,
1782de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com                                   DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
178327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                   DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS);
178427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1785471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com    fDrawBuffer = new GrInOrderDrawBuffer(fGpu,
1786471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com                                          fDrawBufferVBAllocPool,
178727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                          fDrawBufferIBAllocPool);
17883c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com#endif
17893c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com
17903c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com#if BATCH_RECT_TO_RECT
179127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
17923c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com#endif
1793fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    fDrawBuffer->setAutoFlushTarget(fGpu);
179410e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawBuffer->setDrawState(fDrawState);
179527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
179627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
179727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
179827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if DEFER_TEXT_RENDERING
1799193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com    return prepareToDraw(paint, kBuffered_DrawCategory);
180027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
180110e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    return prepareToDraw(paint, kUnbuffered_DrawCategory);
180227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
180327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
180427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
180527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
180627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return fGpu->getQuadIndexBuffer();
180727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
1808dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com
18093b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgGrTexture* GrContext::gaussianBlur(GrTexture* srcTexture,
18103b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                   GrAutoScratchTexture* temp1,
18113b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                   GrAutoScratchTexture* temp2,
18123b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                   const SkRect& rect,
18133b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                   float sigmaX, float sigmaY) {
1814ceb441476e1712861e87a9bb428f119349ef6bb5senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(srcTexture);
18153b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrRenderTarget* oldRenderTarget = this->getRenderTarget();
18163b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrClip oldClip = this->getClip();
18173b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrTexture* origTexture = srcTexture;
18183b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrAutoMatrix avm(this, GrMatrix::I());
18193b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    SkIRect clearRect;
1820b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    int scaleFactorX, radiusX;
1821b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    int scaleFactorY, radiusY;
1822b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
1823b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);
18243b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18253b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    SkRect srcRect(rect);
18263b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
18273b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    srcRect.roundOut();
18288637a365518a82901d313d61eecd83a0c5102fe9robertphillips@google.com    scale_rect(&srcRect, static_cast<float>(scaleFactorX),
18298637a365518a82901d313d61eecd83a0c5102fe9robertphillips@google.com                         static_cast<float>(scaleFactorY));
18303b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setClip(srcRect);
1831bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
183299a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com    GrAssert(kBGRA_8888_PM_GrPixelConfig == srcTexture->config() ||
183399a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com             kRGBA_8888_PM_GrPixelConfig == srcTexture->config() ||
183499a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com             kAlpha_8_GrPixelConfig == srcTexture->config());
183599a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com
183675b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc desc;
183775b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
183875b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fWidth = SkScalarFloorToInt(srcRect.width());
183975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fHeight = SkScalarFloorToInt(srcRect.height());
184075b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fConfig = srcTexture->config();
18411e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com
18423b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    temp1->set(this, desc);
184399a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com    if (temp2) {
184499a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com        temp2->set(this, desc);
184599a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com    }
18463b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18473b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrTexture* dstTexture = temp1->texture();
18483b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrPaint paint;
18493b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    paint.reset();
18503b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    paint.textureSampler(0)->setFilter(GrSamplerState::kBilinear_Filter);
18513b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18523b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
18533b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(),
18543b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                                   srcTexture->height());
18553b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
18563b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkRect dstRect(srcRect);
18573b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
18583b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                            i < scaleFactorY ? 0.5f : 1.0f);
18593b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.setTexture(0, srcTexture);
18603b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->drawRectToRect(paint, dstRect, srcRect);
18613b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        srcRect = dstRect;
18623b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkTSwap(srcTexture, dstTexture);
18633b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // If temp2 is non-NULL, don't render back to origTexture
1864972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        if (temp2 && dstTexture == origTexture) {
1865972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com            dstTexture = temp2->texture();
1866972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        }
18673b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
18683b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18697a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com    SkIRect srcIRect;
18707a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com    srcRect.roundOut(&srcIRect);
18717a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com
18723b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (sigmaX > 0.0f) {
18733b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        if (scaleFactorX > 1) {
1874b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com            // Clear out a radius to the right of the srcRect to prevent the
18753b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            // X convolution from reading garbage.
18767a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com            clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
1877b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                                          radiusX, srcIRect.height());
18783b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            this->clear(&clearRect, 0x0);
18793b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        }
188005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
18813b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
1882b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        convolve_gaussian(fGpu, srcTexture, srcRect, sigmaX, radiusX,
1883b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                          Gr1DKernelEffect::kX_Direction);
18843b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkTSwap(srcTexture, dstTexture);
188599a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com        if (temp2 && dstTexture == origTexture) {
188699a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com            dstTexture = temp2->texture();
188799a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com        }
18883b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
18893b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18903b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (sigmaY > 0.0f) {
18913b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        if (scaleFactorY > 1 || sigmaX > 0.0f) {
1892b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com            // Clear out a radius below the srcRect to prevent the Y
18933b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            // convolution from reading garbage.
18947a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com            clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
1895b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                                          srcIRect.width(), radiusY);
18963b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            this->clear(&clearRect, 0x0);
18973b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        }
18983b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18993b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
1900b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        convolve_gaussian(fGpu, srcTexture, srcRect, sigmaY, radiusY,
1901b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                          Gr1DKernelEffect::kY_Direction);
19023b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkTSwap(srcTexture, dstTexture);
190399a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com        if (temp2 && dstTexture == origTexture) {
190499a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com            dstTexture = temp2->texture();
190599a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com        }
19063b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
19073b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
19083b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (scaleFactorX > 1 || scaleFactorY > 1) {
19093b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // Clear one pixel to the right and below, to accommodate bilinear
19103b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // upsampling.
19117a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com        clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
19127a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                                      srcIRect.width() + 1, 1);
19133b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->clear(&clearRect, 0x0);
19147a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com        clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
19157a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                                      1, srcIRect.height());
19163b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->clear(&clearRect, 0x0);
19173b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // FIXME:  This should be mitchell, not bilinear.
19183b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.textureSampler(0)->setFilter(GrSamplerState::kBilinear_Filter);
19193b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(),
19203b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                                   srcTexture->height());
19213b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
19223b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.setTexture(0, srcTexture);
19233b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkRect dstRect(srcRect);
19247a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com        scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
19253b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->drawRectToRect(paint, dstRect, srcRect);
19263b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        srcRect = dstRect;
19273b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkTSwap(srcTexture, dstTexture);
19283b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
19293b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setRenderTarget(oldRenderTarget);
19303b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setClip(oldClip);
19313b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    return srcTexture;
19323b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
19333b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
19343b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgGrTexture* GrContext::applyMorphology(GrTexture* srcTexture,
19353b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                      const GrRect& rect,
19363b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                      GrTexture* temp1, GrTexture* temp2,
1937b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                                      MorphologyType morphType,
19383b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                      SkISize radius) {
1939ceb441476e1712861e87a9bb428f119349ef6bb5senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(srcTexture);
19403b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrRenderTarget* oldRenderTarget = this->getRenderTarget();
19413b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrAutoMatrix avm(this, GrMatrix::I());
19423b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrClip oldClip = this->getClip();
19437a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com    this->setClip(GrRect::MakeWH(SkIntToScalar(srcTexture->width()),
19447a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                                 SkIntToScalar(srcTexture->height())));
19453b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (radius.fWidth > 0) {
19463b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(temp1->asRenderTarget());
1947b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        apply_morphology(fGpu, srcTexture, rect, radius.fWidth, morphType,
1948b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                         Gr1DKernelEffect::kX_Direction);
19497a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com        SkIRect clearRect = SkIRect::MakeXYWH(
19507a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                    SkScalarFloorToInt(rect.fLeft),
19517a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                    SkScalarFloorToInt(rect.fBottom),
19527a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                    SkScalarFloorToInt(rect.width()),
19537a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                    radius.fHeight);
19543b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->clear(&clearRect, 0x0);
19553b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        srcTexture = temp1;
19563b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
19573b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (radius.fHeight > 0) {
19583b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(temp2->asRenderTarget());
1959b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        apply_morphology(fGpu, srcTexture, rect, radius.fHeight, morphType,
1960b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                         Gr1DKernelEffect::kY_Direction);
19613b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        srcTexture = temp2;
19623b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
19633b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setRenderTarget(oldRenderTarget);
19643b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setClip(oldClip);
19653b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    return srcTexture;
1966027de5f922e8ad1acc5402829f716b8c513fdd8dsenorblanco@chromium.org}
1967c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
196849d9fd5fdb9ffd48538c8fc5a2f6f2d43a2e4fe9robertphillips@google.comvoid GrContext::postClipPush() {
196949d9fd5fdb9ffd48538c8fc5a2f6f2d43a2e4fe9robertphillips@google.com    fGpu->postClipPush();
197049d9fd5fdb9ffd48538c8fc5a2f6f2d43a2e4fe9robertphillips@google.com}
197149d9fd5fdb9ffd48538c8fc5a2f6f2d43a2e4fe9robertphillips@google.com
197249d9fd5fdb9ffd48538c8fc5a2f6f2d43a2e4fe9robertphillips@google.comvoid GrContext::preClipPop() {
197349d9fd5fdb9ffd48538c8fc5a2f6f2d43a2e4fe9robertphillips@google.com    fGpu->preClipPop();
197449d9fd5fdb9ffd48538c8fc5a2f6f2d43a2e4fe9robertphillips@google.com};
197549d9fd5fdb9ffd48538c8fc5a2f6f2d43a2e4fe9robertphillips@google.com
1976c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
1977