GrContext.cpp revision a292112154f803feb9f5cc002bbfab559f7cb633
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/GrConvolutionEffect.h"
13aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com#include "effects/GrSingleTextureEffect.h"
14a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com#include "effects/GrConfigConversionEffect.h"
15b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com
16278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrBufferAllocPool.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
30fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.comSK_DEFINE_INST_COUNT(GrContext)
31fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.comSK_DEFINE_INST_COUNT(GrDrawState)
32fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com
331d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com// It can be useful to set this to kNo_BufferedDraw to test whether a bug is caused by using the
341d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com// InOrderDrawBuffer, to compare performance of using/not using InOrderDrawBuffer, or to make
351d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com// debugging easier.
361d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com#define DEFAULT_BUFFERING (GR_DISABLE_DRAW_BUFFERING ? kNo_BufferedDraw : kYes_BufferedDraw)
3727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
383b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org#define MAX_BLUR_SIGMA 4.0f
393b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
40d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// When we're using coverage AA but the blend is incompatible (given gpu
41d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// limitations) should we disable AA or draw wrong?
42950d7a8d8def14efc98d12d6947347fde351b737bsalomon@google.com#define DISABLE_COVERAGE_AA_FOR_BLEND 1
43d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
444b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#if GR_DEBUG
454b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    // change this to a 1 to see notifications when partial coverage fails
464b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
474b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#else
484b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
494b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#endif
504b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com
5107fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comstatic const size_t MAX_TEXTURE_CACHE_COUNT = 256;
5207fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comstatic const size_t MAX_TEXTURE_CACHE_BYTES = 16 * 1024 * 1024;
5327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
5460361493548d5259d0a8afae84274c2a3c31dcacbsalomon@google.comstatic const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 15;
5527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
5627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
571d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.comstatic const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 1 << 11;
581d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.comstatic const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 4;
5927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
60bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com#define ASSERT_OWNED_RESOURCE(R) GrAssert(!(R) || (R)->getContext() == this)
61bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
6205ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.comGrContext* GrContext::Create(GrEngine engine,
6305ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com                             GrPlatform3DContext context3D) {
6427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrContext* ctx = NULL;
6527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrGpu* fGpu = GrGpu::Create(engine, context3D);
6627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != fGpu) {
67c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com        ctx = SkNEW_ARGS(GrContext, (fGpu));
6827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fGpu->unref();
6927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
7027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return ctx;
7127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
7227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
73c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comnamespace {
74c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comvoid* CreateThreadInstanceCount() {
75c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    return SkNEW_ARGS(int, (0));
76c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
77c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comvoid DeleteThreadInstanceCount(void* v) {
78c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    delete reinterpret_cast<int*>(v);
79c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
80c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com#define THREAD_INSTANCE_COUNT                                               \
81c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    (*reinterpret_cast<int*>(SkTLS::Get(CreateThreadInstanceCount,          \
82c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com                                        DeleteThreadInstanceCount)))
83c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
84c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
85c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
86c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comint GrContext::GetThreadInstanceCount() {
87c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    return THREAD_INSTANCE_COUNT;
88c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
89c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
9027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrContext::~GrContext() {
918fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
925acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com
935acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // Since the gpu can hold scratch textures, give it a chance to let go
945acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // of them before freeing the texture cache
955acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    fGpu->purgeResources();
965acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com
9727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fTextureCache;
9827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fFontCache;
9927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBuffer;
10027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBufferVBAllocPool;
101de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    delete fDrawBufferIBAllocPool;
1023008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
103f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->unref();
104f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com
105205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->unref();
1063008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeUnref(fPathRendererChain);
10772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrSafeUnref(fSoftwarePathRenderer);
10810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->unref();
109c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
110c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    --THREAD_INSTANCE_COUNT;
11127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
11227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1138fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::contextLost() {
11453a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    contextDestroyed();
11553a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    this->setupDrawBuffer();
11653a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com}
11753a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com
11853a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.comvoid GrContext::contextDestroyed() {
119205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // abandon first to so destructors
120205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // don't try to free the resources in the API.
121205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->abandonResources();
122205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1233008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources that
1243008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // are now unusable
1253008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeSetNull(fPathRendererChain);
12672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrSafeSetNull(fSoftwarePathRenderer);
1273008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
1288fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBuffer;
1298fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
130205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1318fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferVBAllocPool;
1328fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
133205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1348fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferIBAllocPool;
1358fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
1368fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
137f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->reset();
138205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
139a292112154f803feb9f5cc002bbfab559f7cb633bsalomon@google.com    fTextureCache->purgeAllUnlocked();
1408fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
1418fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
1428fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
1438fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1448fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::resetContext() {
1458fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
1468fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
1478fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1488fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::freeGpuResources() {
1498fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
150fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
151ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com    fGpu->purgeResources();
152ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com
153f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->reset();
154f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com
155a292112154f803feb9f5cc002bbfab559f7cb633bsalomon@google.com    fTextureCache->purgeAllUnlocked();
1568fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
1573008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources
1583008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeSetNull(fPathRendererChain);
15972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrSafeSetNull(fSoftwarePathRenderer);
16027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
16127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
16205e70247c31ae927074ef27ea9893634a8dda543twiz@google.comsize_t GrContext::getGpuTextureCacheBytes() const {
16305e70247c31ae927074ef27ea9893634a8dda543twiz@google.com  return fTextureCache->getCachedResourceBytes();
16405e70247c31ae927074ef27ea9893634a8dda543twiz@google.com}
16505e70247c31ae927074ef27ea9893634a8dda543twiz@google.com
166fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
167fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
16850398bf7f1953e640e5529616e710cf540799731bsalomon@google.comnamespace {
169558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
1703b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgvoid scale_rect(SkRect* rect, float xScale, float yScale) {
1715af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com    rect->fLeft = SkScalarMul(rect->fLeft, SkFloatToScalar(xScale));
1725af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com    rect->fTop = SkScalarMul(rect->fTop, SkFloatToScalar(yScale));
1735af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com    rect->fRight = SkScalarMul(rect->fRight, SkFloatToScalar(xScale));
1745af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com    rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale));
1753b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
1763b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
177b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.comfloat adjust_sigma(float sigma, int *scaleFactor, int *radius) {
1783b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    *scaleFactor = 1;
1793b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    while (sigma > MAX_BLUR_SIGMA) {
1803b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        *scaleFactor *= 2;
1813b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        sigma *= 0.5f;
1823b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
183b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    *radius = static_cast<int>(ceilf(sigma * 3.0f));
184b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius);
1853b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    return sigma;
1863b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
1873b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18807ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.comvoid convolve_gaussian(GrDrawTarget* target,
189b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       GrTexture* texture,
190b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       const SkRect& rect,
191b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       float sigma,
192b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       int radius,
193b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       Gr1DKernelEffect::Direction direction) {
19407ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    GrRenderTarget* rt = target->drawState()->getRenderTarget();
19507ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kReset_ASRInit);
19607ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    GrDrawState* drawState = target->drawState();
19707ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    drawState->setRenderTarget(rt);
1983b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrMatrix sampleM;
1993b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    sampleM.setIDiv(texture->width(), texture->height());
200b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    drawState->sampler(0)->reset(sampleM);
201c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    SkAutoTUnref<GrConvolutionEffect> conv(SkNEW_ARGS(GrConvolutionEffect,
202fde2c0af2fd5aae19ab6c8b5228debd5b6209856tomhudson@google.com                                                      (texture, direction, radius,
203fde2c0af2fd5aae19ab6c8b5228debd5b6209856tomhudson@google.com                                                       sigma)));
204b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    drawState->sampler(0)->setCustomStage(conv);
20507ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    target->drawSimpleRect(rect, NULL);
2063b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
2073b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
208fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com}
209fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
2101f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comGrTexture* GrContext::findAndLockTexture(const GrTextureDesc& desc,
2111f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com                                         const GrCacheData& cacheData,
2121f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com                                         const GrTextureParams* params) {
2139c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheData, false);
2141f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    GrResource* resource = fTextureCache->findAndLock(resourceKey,
2151f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com                                                      GrResourceCache::kNested_LockType);
2161f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return static_cast<GrTexture*>(resource);
217558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
218558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
21975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.combool GrContext::isTextureInCache(const GrTextureDesc& desc,
2209c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com                                 const GrCacheData& cacheData,
221b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com                                 const GrTextureParams* params) const {
2229c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheData, false);
223fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    return fTextureCache->hasKey(resourceKey);
224fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com}
225fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com
2261f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comvoid GrContext::addAndLockStencilBuffer(GrStencilBuffer* sb) {
227bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(sb);
22846a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com
22946a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com    GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(sb->width(),
23046a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com                                                            sb->height(),
23146a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com                                                            sb->numSamples());
2321f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    fTextureCache->createAndLock(resourceKey, sb);
233558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
234558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
235558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comGrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
236558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                              int sampleCnt) {
23746a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com    GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(width,
23846a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com                                                            height,
23946a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com                                                            sampleCnt);
2401f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    GrResource* resource = fTextureCache->findAndLock(resourceKey,
241558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                            GrResourceCache::kSingle_LockType);
2421f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return static_cast<GrStencilBuffer*>(resource);
243558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
244558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
2451f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comvoid GrContext::unlockStencilBuffer(GrStencilBuffer* sb) {
2461f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    ASSERT_OWNED_RESOURCE(sb);
2471f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    GrAssert(NULL != sb->getCacheEntry());
2481f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com
2491f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    fTextureCache->unlock(sb->getCacheEntry());
25027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
25127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
25227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic void stretchImage(void* dst,
25327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstW,
25427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstH,
25527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         void* src,
25627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcW,
25727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcH,
25827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int bpp) {
25927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dx = (srcW << 16) / dstW;
26027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dy = (srcH << 16) / dstH;
26127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
26227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed y = dy >> 1;
26327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
26427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    int dstXLimit = dstW*bpp;
26527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    for (int j = 0; j < dstH; ++j) {
26627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrFixed x = dx >> 1;
26727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
26827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* dstRow = (uint8_t*)dst + j*dstW*bpp;
26927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < dstXLimit; i += bpp) {
27027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            memcpy((uint8_t*) dstRow + i,
27127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   (uint8_t*) srcRow + (x>>16)*bpp,
27227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   bpp);
27327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            x += dx;
27427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
27527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        y += dy;
27627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
27727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
27827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
279fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// The desired texture is NPOT and tiled but that isn't supported by
2803319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com// the current hardware. Resize the texture to be a POT
2813319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.comGrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
2823319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                           const GrCacheData& cacheData,
2833319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                           void* srcData,
2843319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                           size_t rowBytes,
2853319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                           bool needsFiltering) {
2861f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    GrTexture* clampedTexture = this->findAndLockTexture(desc, cacheData, NULL);
2873319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
2881f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    if (NULL == clampedTexture) {
2891f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com        clampedTexture = this->createAndLockTexture(NULL, desc, cacheData, srcData, rowBytes);
2901f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com        GrAssert(NULL != clampedTexture);
2911f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com        if (NULL == clampedTexture) {
2923319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com            return NULL;
2933319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        }
2943319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    }
2953319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    GrTextureDesc rtDesc = desc;
2963319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    rtDesc.fFlags =  rtDesc.fFlags |
2973319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                     kRenderTarget_GrTextureFlagBit |
2983319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                     kNoStencil_GrTextureFlagBit;
2993319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    rtDesc.fWidth  = GrNextPow2(GrMax(desc.fWidth, 64));
3003319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    rtDesc.fHeight = GrNextPow2(GrMax(desc.fHeight, 64));
3013319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3023319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
3033319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3043319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    if (NULL != texture) {
3053319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
3063319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        GrDrawState* drawState = fGpu->drawState();
3073319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        drawState->setRenderTarget(texture->asRenderTarget());
3083319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3093319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // if filtering is not desired then we want to ensure all
3103319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // texels in the resampled image are copies of texels from
3113319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // the original.
3123319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        drawState->sampler(0)->reset(SkShader::kClamp_TileMode,
3133319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                     needsFiltering);
3141f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com        drawState->createTextureEffect(0, clampedTexture);
3153319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3163319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        static const GrVertexLayout layout =
3173319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                            GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
3183319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
3193319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3203319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        if (arg.succeeded()) {
3213319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com            GrPoint* verts = (GrPoint*) arg.vertices();
3223319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com            verts[0].setIRectFan(0, 0,
3233319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                    texture->width(),
3243319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                    texture->height(),
3253319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                    2*sizeof(GrPoint));
3263319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com            verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
3273319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com            fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType,
3283319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                    0, 4);
3293319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        }
3303319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        texture->releaseRenderTarget();
3313319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    } else {
3323319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // TODO: Our CPU stretch doesn't filter. But we create separate
3333319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // stretched textures when the sampler state is either filtered or
3343319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // not. Either implement filtered stretch blit on CPU or just create
3353319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // one when FBO case fails.
3363319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3373319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        rtDesc.fFlags = kNone_GrTextureFlags;
3383319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // no longer need to clamp at min RT size.
3393319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        rtDesc.fWidth  = GrNextPow2(desc.fWidth);
3403319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        rtDesc.fHeight = GrNextPow2(desc.fHeight);
3413319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        int bpp = GrBytesPerPixel(desc.fConfig);
3423319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        SkAutoSMalloc<128*128*4> stretchedPixels(bpp *
3433319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                                    rtDesc.fWidth *
3443319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                                    rtDesc.fHeight);
3453319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
3463319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                        srcData, desc.fWidth, desc.fHeight, bpp);
3473319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3483319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        size_t stretchedRowBytes = rtDesc.fWidth * bpp;
3493319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3503319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        GrTexture* texture = fGpu->createTexture(rtDesc,
3513319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                                    stretchedPixels.get(),
3523319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                                    stretchedRowBytes);
3533319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        GrAssert(NULL != texture);
3543319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    }
3551f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    this->unlockTexture(clampedTexture);
3563319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3573319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    return texture;
3583319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com}
3593319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3601f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comGrTexture* GrContext::createAndLockTexture(
361b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com        const GrTextureParams* params,
3621fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrTextureDesc& desc,
3639c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com        const GrCacheData& cacheData,
3641fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        void* srcData,
3651fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        size_t rowBytes) {
366278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::createAndLockTexture");
36727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
36827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_DUMP_TEXTURE_UPLOAD
36927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
37027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
37127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
3729c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheData, false);
373a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
3743319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    GrTexture* texture = NULL;
375a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    if (GrTexture::NeedsResizing(resourceKey)) {
3763319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        texture = this->createResizedTexture(desc, cacheData,
377fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                                             srcData, rowBytes,
3783319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                             GrTexture::NeedsFiltering(resourceKey));
37927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
3803319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        texture = fGpu->createTexture(desc, srcData, rowBytes);
3813319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    }
3823319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3833319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    if (NULL != texture) {
3841f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com        fTextureCache->createAndLock(resourceKey, texture);
38527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
3863319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3871f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return texture;
38827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
38927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
3901f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comGrTexture* GrContext::lockScratchTexture(const GrTextureDesc& inDesc,
3911f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com                                         ScratchTexMatch match) {
392b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    GrTextureDesc desc = inDesc;
3939c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com    GrCacheData cacheData(GrCacheData::kScratch_CacheID);
39475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com
3952afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com    GrAssert((desc.fFlags & kRenderTarget_GrTextureFlagBit) ||
3962afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com             !(desc.fFlags & kNoStencil_GrTextureFlagBit));
3972afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com
39850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (kExact_ScratchTexMatch != match) {
39950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        // bin by pow2 with a reasonable min
40050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        static const int MIN_SIZE = 256;
40150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fWidth  = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
40250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
40350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    }
404b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
4051f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    GrResource* resource = NULL;
406b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origWidth = desc.fWidth;
407b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origHeight = desc.fHeight;
408b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    bool doubledW = false;
409b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    bool doubledH = false;
410b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
411b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    do {
4129c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com        GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL, desc, cacheData, true);
4131f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com        resource = fTextureCache->findAndLock(key,
4141f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com                                              GrResourceCache::kNested_LockType);
415b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        // if we miss, relax the fit of the flags...
416b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        // then try doubling width... then height.
4171f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com        if (NULL != resource || kExact_ScratchTexMatch == match) {
418b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
419b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
420fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        // We no longer try to reuse textures that were previously used as render targets in
4212afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com        // situations where no RT is needed; doing otherwise can confuse the video driver and
4222afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com        // cause significant performance problems in some cases.
4232afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com        if (desc.fFlags & kNoStencil_GrTextureFlagBit) {
424b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit;
425fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        } else if (!doubledW) {
426b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = inDesc.fFlags;
427b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fWidth *= 2;
428b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            doubledW = true;
429b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (!doubledH) {
430b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = inDesc.fFlags;
431b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fWidth = origWidth;
432b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fHeight *= 2;
433b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            doubledH = true;
434b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else {
435b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
436b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
437fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
438b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    } while (true);
439b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
4401f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    if (NULL == resource) {
441b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fFlags = inDesc.fFlags;
442b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fWidth = origWidth;
443b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fHeight = origHeight;
444b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
445b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        if (NULL != texture) {
44675b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com            GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL,
447a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                                                      texture->desc(),
4489c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com                                                      cacheData,
449a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                                                      true);
4501f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com            fTextureCache->createAndLock(key, texture);
4511f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com            resource = texture;
452b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
453b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
454b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
455b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // If the caller gives us the same desc/sampler twice we don't want
456b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // to return the same texture the second time (unless it was previously
457521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // released). So make it exclusive to hide it from future searches.
4581f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    if (NULL != resource) {
459521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com        fTextureCache->makeExclusive(resource->getCacheEntry());
460b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
461521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com
4621f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return static_cast<GrTexture*>(resource);
463b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com}
464b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
46515c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.comvoid GrContext::addExistingTextureToCache(GrTexture* texture) {
46615c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
46715c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    if (NULL == texture) {
46815c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com        return;
46915c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    }
47015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
471521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // This texture should already have a cache entry since it was once
472521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // attached
473521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    GrAssert(NULL != texture->getCacheEntry());
474521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com
475521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // Conceptually, the cache entry is going to assume responsibility
476521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // for the creation ref.
477521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    GrAssert(1 == texture->getRefCnt());
478521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com
479521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // Since this texture came from an AutoScratchTexture it should
480521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // still be in the exclusive pile
481521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    fTextureCache->makeNonExclusive(texture->getCacheEntry());
4829c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com
483521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // and it should still be locked
484521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    fTextureCache->unlock(texture->getCacheEntry());
48515c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com}
48615c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
4871f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comvoid GrContext::unlockTexture(GrTexture* texture) {
4881f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    ASSERT_OWNED_RESOURCE(texture);
4891f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    GrAssert(NULL != texture->getCacheEntry());
4901f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com
49150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // If this is a scratch texture we detached it from the cache
49250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // while it was locked (to avoid two callers simultaneously getting
49350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // the same texture).
4941f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    if (GrTexture::IsScratchTexture(texture->getCacheEntry()->key())) {
495521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com        fTextureCache->makeNonExclusive(texture->getCacheEntry());
496fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
49715c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
498521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    fTextureCache->unlock(texture->getCacheEntry());
49915c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com}
50015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
50175b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.comGrTexture* GrContext::createUncachedTexture(const GrTextureDesc& descIn,
50227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            void* srcData,
50327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            size_t rowBytes) {
50475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc descCopy = descIn;
50575b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    return fGpu->createTexture(descCopy, srcData, rowBytes);
50627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
50727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
50807fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comvoid GrContext::getTextureCacheLimits(int* maxTextures,
50907fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com                                      size_t* maxTextureBytes) const {
51007fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com    fTextureCache->getLimits(maxTextures, maxTextureBytes);
51127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
51227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
51307fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comvoid GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
51407fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com    fTextureCache->setLimits(maxTextures, maxTextureBytes);
51527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
51627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
517919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxTextureSize() const {
51818c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    return fGpu->getCaps().fMaxTextureSize;
519919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com}
520919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
521919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxRenderTargetSize() const {
52218c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    return fGpu->getCaps().fMaxRenderTargetSize;
52327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
52427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
52527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com///////////////////////////////////////////////////////////////////////////////
52627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
527e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrTexture* GrContext::createPlatformTexture(const GrPlatformTextureDesc& desc) {
528e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com    return fGpu->createPlatformTexture(desc);
529e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
530e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
531e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrRenderTarget* GrContext::createPlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) {
532e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com    return fGpu->createPlatformRenderTarget(desc);
533e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
534e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
5355877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
5365877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com
537b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.combool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params,
5381f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com                                          int width, int height) const {
53918c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    const GrDrawTarget::Caps& caps = fGpu->getCaps();
54018c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    if (!caps.f8BitPaletteSupport) {
54127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return false;
54227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
54327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
54427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
54527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
54627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (!isPow2) {
547b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com        bool tiled = NULL != params && params->isTiled();
54818c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com        if (tiled && !caps.fNPOTTextureTileSupport) {
54927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return false;
55027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
55127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
55227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return true;
55327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
55427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
55527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
55627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
557beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.comconst GrClipData* GrContext::getClip() const {
558fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    return fGpu->getClip();
559beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.com}
56005ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com
561beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.comvoid GrContext::setClip(const GrClipData* clipData) {
562beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.com    fGpu->setClip(clipData);
56310e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->enableState(GrDrawState::kClip_StateBit);
56427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
56527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
56627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
56727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
56807ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.comvoid GrContext::clear(const GrIRect* rect,
56907ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com                      const GrColor color,
570c82a8b7aa4ec19fba508c394920a9e88d3e5bd12robertphillips@google.com                      GrRenderTarget* target) {
57107ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    this->prepareToDraw(NULL, DEFAULT_BUFFERING)->clear(rect, color, target);
57227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
57327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
57427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawPaint(const GrPaint& paint) {
57527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // set rect to be big enough to fill the space, but not super-huge, so we
57627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // don't overflow fixed-point implementations
577d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    GrRect r;
578d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    r.setLTRB(0, 0,
579d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com              GrIntToScalar(getRenderTarget()->width()),
580d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com              GrIntToScalar(getRenderTarget()->height()));
58127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix inverse;
5828c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    SkTLazy<GrPaint> tmpPaint;
5838c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    const GrPaint* p = &paint;
584fea85ac3e31842f80493e2df8a93a28f21cd815frobertphillips@google.com    AutoMatrix am;
5858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5864f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // We attempt to map r by the inverse matrix and draw that. mapRect will
5874f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // map the four corners and bound them with a new rect. This will not
5884f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // produce a correct result for some perspective matrices.
5898c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    if (!this->getMatrix().hasPerspective()) {
59010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        if (!fDrawState->getViewInverse(&inverse)) {
591e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            GrPrintf("Could not invert matrix\n");
5928c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            return;
5938c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
59427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        inverse.mapRect(&r);
59527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
596e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        if (paint.hasTextureOrMask()) {
5978c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.set(paint);
5988c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            p = tmpPaint.get();
599e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            if (!tmpPaint.get()->preConcatSamplerMatricesWithInverse(fDrawState->getViewMatrix())) {
600e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                GrPrintf("Could not invert matrix\n");
601e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            }
6028c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
6034f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com        am.set(this, GrMatrix::I());
60427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
6054f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // by definition this fills the entire clip, no need for AA
6064f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    if (paint.fAntiAlias) {
6078c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        if (!tmpPaint.isValid()) {
6088c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.set(paint);
6098c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            p = tmpPaint.get();
6108c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
6118c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        GrAssert(p == tmpPaint.get());
6128c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        tmpPaint.get()->fAntiAlias = false;
6134f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    }
6144f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    this->drawRect(*p, r);
61527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
61627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
617205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
618205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
619d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.comnamespace {
620d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.cominline bool disable_coverage_aa_for_blend(GrDrawTarget* target) {
621d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage();
622d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com}
623d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com}
624d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
62506afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
62606afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
62727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com/*  create a triangle strip that strokes the specified triangle. There are 8
62827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com unique vertices, but we repreat the last 2 to close up. Alternatively we
62927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com could use an indices array, and then only send 8 verts, but not sure that
63027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com would be faster.
63127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com */
632205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
63327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               GrScalar width) {
63427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    const GrScalar rad = GrScalarHalf(width);
635205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    rect.sort();
63627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
63727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[0].set(rect.fLeft + rad, rect.fTop + rad);
63827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[1].set(rect.fLeft - rad, rect.fTop - rad);
63927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[2].set(rect.fRight - rad, rect.fTop + rad);
64027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[3].set(rect.fRight + rad, rect.fTop - rad);
64127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[4].set(rect.fRight - rad, rect.fBottom - rad);
64227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[5].set(rect.fRight + rad, rect.fBottom + rad);
64327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
64427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
64527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[8] = verts[0];
64627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[9] = verts[1];
64727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
64827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
64920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com/**
65020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com * Returns true if the rects edges are integer-aligned.
65120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com */
65220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.comstatic bool isIRect(const GrRect& r) {
653fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    return GrScalarIsInt(r.fLeft) && GrScalarIsInt(r.fTop) &&
65420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com           GrScalarIsInt(r.fRight) && GrScalarIsInt(r.fBottom);
65520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com}
65620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
657205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic bool apply_aa_to_rect(GrDrawTarget* target,
658205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             const GrRect& rect,
659fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                             GrScalar width,
660205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             const GrMatrix* matrix,
661205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             GrMatrix* combinedMatrix,
662a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             GrRect* devRect,
663a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             bool* useVertexCoverage) {
6642eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // we use a simple coverage ramp to do aa on axis-aligned rects
665fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // we check if the rect will be axis-aligned, and the rect won't land on
6662eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // integer coords.
667d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
668a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // we are keeping around the "tweak the alpha" trick because
669a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // it is our only hope for the fixed-pipe implementation.
670a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // In a shader implementation we can give a separate coverage input
671289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    // TODO: remove this ugliness when we drop the fixed-pipe impl
672a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    *useVertexCoverage = false;
673d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (!target->canTweakAlphaForCoverage()) {
6742eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com        if (disable_coverage_aa_for_blend(target)) {
6751983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
6762eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            //GrPrintf("Turning off AA to correctly apply blend.\n");
6771983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
678a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            return false;
6792eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com        } else {
6802eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            *useVertexCoverage = true;
681a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        }
682205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
6838f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    const GrDrawState& drawState = target->getDrawState();
6848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (drawState.getRenderTarget()->isMultisampled()) {
685205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
686205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
687205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
688471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com    if (0 == width && target->willUseHWAALines()) {
689205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
690205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
691205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
6928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (!drawState.getViewMatrix().preservesAxisAlignment()) {
693205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
694205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
695205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
696fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    if (NULL != matrix &&
697205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        !matrix->preservesAxisAlignment()) {
698205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
699205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
700205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
7018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    *combinedMatrix = drawState.getViewMatrix();
702205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL != matrix) {
703205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        combinedMatrix->preConcat(*matrix);
704205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrAssert(combinedMatrix->preservesAxisAlignment());
705205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
706fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
707205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    combinedMatrix->mapRect(devRect, rect);
708205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    devRect->sort();
709205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
710205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (width < 0) {
71120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        return !isIRect(*devRect);
712205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    } else {
713205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return true;
714205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
715205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
716205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
71727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRect(const GrPaint& paint,
71827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         const GrRect& rect,
71927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         GrScalar width,
72027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         const GrMatrix* matrix) {
721278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRect");
72227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
72307ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
7247d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    GrDrawState::AutoStageDisable atr(fDrawState);
72527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
726205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrRect devRect = rect;
727205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrMatrix combinedMatrix;
728a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    bool useVertexCoverage;
729289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool needAA = paint.fAntiAlias &&
730289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                  !this->getRenderTarget()->isMultisampled();
731289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix,
732289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &combinedMatrix, &devRect,
733289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &useVertexCoverage);
734205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
735205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (doAA) {
736e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        GrDrawTarget::AutoDeviceCoordDraw adcd(target);
737e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        if (!adcd.succeeded()) {
738e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            return;
739e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        }
740205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        if (width >= 0) {
741205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            GrVec strokeSize;;
742205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            if (width > 0) {
743205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.set(width, width);
744cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com                combinedMatrix.mapVectors(&strokeSize, 1);
745205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.setAbs(strokeSize);
746205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            } else {
747205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.set(GR_Scalar1, GR_Scalar1);
748205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            }
749fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            fAARectRenderer->strokeAARect(this->getGpu(), target, devRect,
750f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com                                         strokeSize, useVertexCoverage);
751205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        } else {
752fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            fAARectRenderer->fillAARect(this->getGpu(), target,
753f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com                                       devRect, useVertexCoverage);
754205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        }
755205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return;
756205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
757205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
75827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (width >= 0) {
75927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // TODO: consider making static vertex buffers for these cases.
76027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // Hairline could be done by just adding closing vertex to
76127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // unitSquareVertexBuffer()
76226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
76327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        static const int worstCaseVertCount = 10;
764e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        GrDrawTarget::AutoReleaseGeometry geo(target, 0, worstCaseVertCount, 0);
76527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
76627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.succeeded()) {
7676513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
76827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
76927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
77027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
77127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPrimitiveType primType;
77227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int vertCount;
77327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPoint* vertex = geo.positions();
77427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
77527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (width > 0) {
77627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 10;
77747059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com            primType = kTriangleStrip_GrPrimitiveType;
77827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            setStrokeRectStrip(vertex, rect, width);
77927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        } else {
78027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // hairline
78127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 5;
78247059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com            primType = kLineStrip_GrPrimitiveType;
78327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[0].set(rect.fLeft, rect.fTop);
78427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[1].set(rect.fRight, rect.fTop);
78527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[2].set(rect.fRight, rect.fBottom);
78627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[3].set(rect.fLeft, rect.fBottom);
78727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[4].set(rect.fLeft, rect.fTop);
78827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
78927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
7908f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState::AutoViewMatrixRestore avmr;
79127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != matrix) {
7928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
7938f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            avmr.set(drawState);
7948f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatViewMatrix(*matrix);
795e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            drawState->preConcatSamplerMatrices(*matrix);
79627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
79727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
79827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->drawNonIndexed(primType, 0, vertCount);
79927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
8008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#if GR_STATIC_RECT_VB
8016513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
8026513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            if (NULL == sqVB) {
8036513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com                GrPrintf("Failed to create static rect vb.\n");
8046513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com                return;
8056513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            }
806e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            target->setVertexSourceToBuffer(0, sqVB);
8078f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
8088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState::AutoViewMatrixRestore avmr(drawState);
80927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrMatrix m;
8108295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com            m.setAll(rect.width(),    0,             rect.fLeft,
811205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0,            rect.height(), rect.fTop,
812205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0,            0,             GrMatrix::I()[8]);
81327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
81427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (NULL != matrix) {
81527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                m.postConcat(*matrix);
81627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
8178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatViewMatrix(m);
818e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            drawState->preConcatSamplerMatrices(m);
819fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
82047059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com            target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
8218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#else
822e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            target->drawSimpleRect(rect, matrix);
8238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#endif
82427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
82527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
82627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
82727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRectToRect(const GrPaint& paint,
82827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrRect& dstRect,
82927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrRect& srcRect,
83027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrMatrix* dstMatrix,
83127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrMatrix* srcMatrix) {
832278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRectToRect");
83327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
83426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    // srcRect refers to paint's first texture
835f13f58804659175925042a291304d483a4fd9278tomhudson@google.com    if (!paint.isTextureStageEnabled(0)) {
83627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        drawRect(paint, dstRect, -1, dstMatrix);
83727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
83827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
839de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com
84007ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
84127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
84227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_STATIC_RECT_VB
8437d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    GrDrawState::AutoStageDisable atr(fDrawState);
8448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = target->drawState();
8458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState::AutoViewMatrixRestore avmr(drawState);
84627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
84727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix m;
84827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
84927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    m.setAll(dstRect.width(), 0,                dstRect.fLeft,
85027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               dstRect.height(), dstRect.fTop,
85127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               0,                GrMatrix::I()[8]);
85227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != dstMatrix) {
85327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        m.postConcat(*dstMatrix);
85427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
8558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->preConcatViewMatrix(m);
85627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
857e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    // we explicitly setup the correct coords for the first stage. The others
858e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    // must know about the view matrix change.
859e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    for (int s = 1; s < GrPaint::kTotalStages; ++s) {
860e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        if (drawState->isStageEnabled(s)) {
861e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            drawState->sampler(s)->preConcatMatrix(m);
862e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        }
86326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
86426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
86527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    m.setAll(srcRect.width(), 0,                srcRect.fLeft,
86627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               srcRect.height(), srcRect.fTop,
86727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               0,                GrMatrix::I()[8]);
86827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != srcMatrix) {
86927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        m.postConcat(*srcMatrix);
87027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
8718f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->sampler(GrPaint::kFirstTextureStage)->preConcatMatrix(m);
87227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
8736513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
8746513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    if (NULL == sqVB) {
8756513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to create static rect vb.\n");
8766513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        return;
8776513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    }
878e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    target->setVertexSourceToBuffer(0, sqVB);
87947059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com    target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
88027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
8817d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    GrDrawState::AutoStageDisable atr(fDrawState);
88227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
8839381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
8849381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    const GrMatrix* srcMatrices[GrDrawState::kNumStages] = {NULL};
88527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    srcRects[0] = &srcRect;
88627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    srcMatrices[0] = srcMatrix;
88727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
888e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    target->drawRect(dstRect, dstMatrix, srcRects, srcMatrices);
88927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
89027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
89127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
89227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawVertices(const GrPaint& paint,
89327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             GrPrimitiveType primitiveType,
89427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int vertexCount,
89527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint positions[],
89627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint texCoords[],
89727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrColor colors[],
89827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const uint16_t indices[],
89927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int indexCount) {
900278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawVertices");
90127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
90227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo;
90327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
90407ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
9057d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    GrDrawState::AutoStageDisable atr(fDrawState);
90627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
907e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    GrVertexLayout layout = 0;
908e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    if (NULL != texCoords) {
909e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0, 0);
910e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    }
91127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != colors) {
91227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        layout |= GrDrawTarget::kColor_VertexLayoutBit;
91327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
91426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int vertexSize = GrDrawTarget::VertexSize(layout);
91527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
91627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (sizeof(GrPoint) != vertexSize) {
91727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.set(target, layout, vertexCount, 0)) {
9186513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
91927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
92027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
9219381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        int texOffsets[GrDrawState::kMaxTexCoords];
92227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int colorOffset;
92326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
92426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                                                texOffsets,
925aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com                                                &colorOffset,
926a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                                NULL,
927a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                                NULL);
92827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* curVertex = geo.vertices();
92927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
93027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < vertexCount; ++i) {
93127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            *((GrPoint*)curVertex) = positions[i];
93227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
93327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (texOffsets[0] > 0) {
93427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
93527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
93627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (colorOffset > 0) {
93727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
93827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
93926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            curVertex = (void*)((intptr_t)curVertex + vertexSize);
94027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
94127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
94227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->setVertexSourceToArray(layout, positions, vertexCount);
94327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
94427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
945fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // we don't currently apply offscreen AA to this path. Need improved
946919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // management of GrDrawTarget's geometry to avoid copying points per-tile.
947a47a48dca5045d71cbc5de343404045209a13e15bsalomon@google.com
9488295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    if (NULL != indices) {
949919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        target->setIndexSourceToArray(indices, indexCount);
9508295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
95127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
9528295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawNonIndexed(primitiveType, 0, vertexCount);
9538295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
95427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
95527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
95606afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
957150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.comnamespace {
958150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
95993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.comstruct CircleVertex {
96093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrPoint fPos;
96193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrPoint fCenter;
96293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar fOuterRadius;
96393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar fInnerRadius;
96493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com};
96593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
96693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com/* Returns true if will map a circle to another circle. This can be true
96793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com * if the matrix only includes square-scale, rotation, translation.
96893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com */
96993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.cominline bool isSimilarityTransformation(const SkMatrix& matrix,
97093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                                       SkScalar tol = SK_ScalarNearlyZero) {
97193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (matrix.isIdentity() || matrix.getType() == SkMatrix::kTranslate_Mask) {
97293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return true;
97393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
97493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (matrix.hasPerspective()) {
97593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return false;
97693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
97793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
97893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar mx = matrix.get(SkMatrix::kMScaleX);
97993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar sx = matrix.get(SkMatrix::kMSkewX);
98093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar my = matrix.get(SkMatrix::kMScaleY);
98193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar sy = matrix.get(SkMatrix::kMSkewY);
98293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
98393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (mx == 0 && sx == 0 && my == 0 && sy == 0) {
98493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return false;
98593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
98693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
98793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    // it has scales or skews, but it could also be rotation, check it out.
98893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkVector vec[2];
98993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    vec[0].set(mx, sx);
99093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    vec[1].set(sy, my);
99193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
99293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    return SkScalarNearlyZero(vec[0].dot(vec[1]), SkScalarSquare(tol)) &&
99393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com           SkScalarNearlyEqual(vec[0].lengthSqd(), vec[1].lengthSqd(),
99493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                SkScalarSquare(tol));
99593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com}
99693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
99793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com}
99893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
99993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com// TODO: strokeWidth can't be larger than zero right now.
100093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com// It will be fixed when drawPath() can handle strokes.
100193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.comvoid GrContext::drawOval(const GrPaint& paint,
100293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                         const GrRect& rect,
100393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                         SkScalar strokeWidth) {
10040982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com    GrAssert(strokeWidth <= 0);
10050982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com    if (!isSimilarityTransformation(this->getMatrix()) ||
100693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        !paint.fAntiAlias ||
100793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        rect.height() != rect.width()) {
100893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        SkPath path;
100993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        path.addOval(rect);
101093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        GrPathFill fill = (strokeWidth == 0) ?
10110982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com                           kHairLine_GrPathFill : kWinding_GrPathFill;
101293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        this->internalDrawPath(paint, path, fill, NULL);
101393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return;
101493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
101593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
101607ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
101707ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com
10180982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com    GrDrawState* drawState = target->drawState();
10190982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com    GrDrawState::AutoStageDisable atr(fDrawState);
10200982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com    const GrMatrix vm = drawState->getViewMatrix();
10210982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com
102293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    const GrRenderTarget* rt = drawState->getRenderTarget();
102393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (NULL == rt) {
102493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return;
102593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
102693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1027e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    GrDrawTarget::AutoDeviceCoordDraw adcd(target);
1028e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    if (!adcd.succeeded()) {
1029e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        return;
1030e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    }
103193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1032e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    GrVertexLayout layout = GrDrawTarget::kEdge_VertexLayoutBit;
103393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrAssert(sizeof(CircleVertex) == GrDrawTarget::VertexSize(layout));
103493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
103593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrPoint center = GrPoint::Make(rect.centerX(), rect.centerY());
103693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar radius = SkScalarHalf(rect.width());
103793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
103893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    vm.mapPoints(&center, 1);
103993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    radius = vm.mapRadius(radius);
104093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
104193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar outerRadius = radius;
104293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar innerRadius = 0;
104393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar halfWidth = 0;
104493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (strokeWidth == 0) {
104593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        halfWidth = SkScalarHalf(SK_Scalar1);
104693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
104793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        outerRadius += halfWidth;
104893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        innerRadius = SkMaxScalar(0, radius - halfWidth);
104993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
105093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
105193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(target, layout, 4, 0);
105293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (!geo.succeeded()) {
105393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
105493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return;
105593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
105693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
105793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
105893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1059a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    // The fragment shader will extend the radius out half a pixel
1060a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    // to antialias. Expand the drawn rect here so all the pixels
1061a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    // will be captured.
1062a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    SkScalar L = center.fX - outerRadius - SkFloatToScalar(0.5f);
1063a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    SkScalar R = center.fX + outerRadius + SkFloatToScalar(0.5f);
1064a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    SkScalar T = center.fY - outerRadius - SkFloatToScalar(0.5f);
1065a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    SkScalar B = center.fY + outerRadius + SkFloatToScalar(0.5f);
106693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
106793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    verts[0].fPos = SkPoint::Make(L, T);
106893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    verts[1].fPos = SkPoint::Make(R, T);
106993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    verts[2].fPos = SkPoint::Make(L, B);
107093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    verts[3].fPos = SkPoint::Make(R, B);
107193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
107293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    for (int i = 0; i < 4; ++i) {
107393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        // this goes to fragment shader, it should be in y-points-up space.
107493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        verts[i].fCenter = SkPoint::Make(center.fX, rt->height() - center.fY);
107593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
107693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        verts[i].fOuterRadius = outerRadius;
107793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        verts[i].fInnerRadius = innerRadius;
107893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
107993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
108093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    drawState->setVertexEdgeType(GrDrawState::kCircle_EdgeType);
108147059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com    target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4);
1082150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
108327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
10848d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comvoid GrContext::drawPath(const GrPaint& paint, const SkPath& path,
108507f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.com                         GrPathFill fill, const GrPoint* translate) {
108627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1087fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (path.isEmpty()) {
1088fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       if (GrIsFillInverted(fill)) {
1089fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com           this->drawPaint(paint);
1090fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       }
1091fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       return;
1092fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
1093fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
109493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkRect ovalRect;
109593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (!GrIsFillInverted(fill) && path.isOval(&ovalRect)) {
109693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        if (translate) {
109793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com            ovalRect.offset(*translate);
109893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        }
109947059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        SkScalar width = (fill == kHairLine_GrPathFill) ? 0 : -SK_Scalar1;
110093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        this->drawOval(paint, ovalRect, width);
110193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return;
110293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
110393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
110493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    internalDrawPath(paint, path, fill, translate);
110593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com}
110693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
11078d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comvoid GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path,
110893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                                 GrPathFill fill, const GrPoint* translate) {
110993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1110fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // Note that below we may sw-rasterize the path into a scratch texture.
1111fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // Scratch textures can be recycled after they are returned to the texture
1112fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // cache. This presents a potential hazard for buffered drawing. However,
1113fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // the writePixels that uploads to the scratch will perform a flush so we're
1114fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // OK.
111507ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
11167d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    GrDrawState::AutoStageDisable atr(fDrawState);
1117d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
1118289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool prAA = paint.fAntiAlias && !this->getRenderTarget()->isMultisampled();
1119289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
1120d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // An Assumption here is that path renderer would use some form of tweaking
1121d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // the src color (either the input alpha or in the frag shader) to implement
1122d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // aa. If we have some future driver-mojo path AA that can do the right
1123d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // thing WRT to the blend then we'll need some query on the PR.
1124d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (disable_coverage_aa_for_blend(target)) {
11251983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
1126979432ba2621b617f5e85a9ff48c6b6cd1504a0dbsalomon@google.com        //GrPrintf("Turning off AA to correctly apply blend.\n");
11271983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
1128289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        prAA = false;
1129d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    }
1130289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
113172176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrPathRenderer* pr = this->getPathRenderer(path, fill, target, prAA, true);
11323008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == pr) {
11331983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
11343008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        GrPrintf("Unable to find path renderer compatible with path.\n");
11351983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
11363008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        return;
11373008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
11383008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
1139e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    pr->drawPath(path, fill, translate, target, prAA);
114027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
11418295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
114227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
114327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1144a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.comvoid GrContext::flush(int flagsBitfield) {
1145a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kDiscard_FlushBit & flagsBitfield) {
1146a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com        fDrawBuffer->reset();
1147a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    } else {
1148c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        this->flushDrawBuffer();
1149a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    }
1150a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) {
115127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fGpu->forceRenderTargetFlush();
115227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
115327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
115427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
115527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::flushDrawBuffer() {
115653a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    if (fDrawBuffer) {
115758b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // With addition of the AA clip path, flushing the draw buffer can
115858b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // result in the generation of an AA clip mask. During this
115958b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // process the SW path renderer may be invoked which recusively
116058b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // calls this method (via internalWriteTexturePixels) creating
116158b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // infinite recursion
116258b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        GrInOrderDrawBuffer* temp = fDrawBuffer;
116358b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        fDrawBuffer = NULL;
116458b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com
116558b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        temp->flushTo(fGpu);
116658b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com
116758b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        fDrawBuffer = temp;
116853a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    }
116927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
117027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
11710342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.comvoid GrContext::writeTexturePixels(GrTexture* texture,
11720342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                   int left, int top, int width, int height,
11730342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                   GrPixelConfig config, const void* buffer, size_t rowBytes,
11740342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                   uint32_t flags) {
11756f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeTexturePixels");
1176bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1177bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
11786f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    // TODO: use scratch texture to perform conversion
11790342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    if (kUnpremul_PixelOpsFlag & flags) {
11806f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        return;
11816f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
11820342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
11830342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com        this->flush();
11840342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    }
11856f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
1186fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    fGpu->writeTexturePixels(texture, left, top, width, height,
11876f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                             config, buffer, rowBytes);
11886f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com}
11896f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
11900342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.combool GrContext::readTexturePixels(GrTexture* texture,
11910342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                  int left, int top, int width, int height,
11920342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                  GrPixelConfig config, void* buffer, size_t rowBytes,
11930342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                  uint32_t flags) {
1194278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readTexturePixels");
1195bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1196669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1197a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // TODO: code read pixels for textures that aren't also rendertargets
1198669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    GrRenderTarget* target = texture->asRenderTarget();
1199669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    if (NULL != target) {
12000342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com        return this->readRenderTargetPixels(target,
12010342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                            left, top, width, height,
12020342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                            config, buffer, rowBytes,
12030342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                            flags);
1204669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    } else {
1205669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com        return false;
1206669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    }
1207669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com}
1208669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1209a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com#include "SkConfig8888.h"
1210a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
1211a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.comnamespace {
1212a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com/**
1213a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * Converts a GrPixelConfig to a SkCanvas::Config8888. Only byte-per-channel
1214a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * formats are representable as Config8888 and so the function returns false
1215a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * if the GrPixelConfig has no equivalent Config8888.
1216a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com */
1217a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.combool grconfig_to_config8888(GrPixelConfig config,
12180342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                            bool unpremul,
1219a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                            SkCanvas::Config8888* config8888) {
1220a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    switch (config) {
12210342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com        case kRGBA_8888_GrPixelConfig:
12220342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com            if (unpremul) {
12230342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                *config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
12240342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com            } else {
12250342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                *config8888 = SkCanvas::kRGBA_Premul_Config8888;
12260342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com            }
1227a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
12280342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com        case kBGRA_8888_GrPixelConfig:
12290342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com            if (unpremul) {
12300342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                *config8888 = SkCanvas::kBGRA_Unpremul_Config8888;
12310342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com            } else {
12320342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                *config8888 = SkCanvas::kBGRA_Premul_Config8888;
12330342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com            }
1234a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1235a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        default:
1236a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return false;
1237a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1238a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
1239a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1240a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com// It returns a configuration with where the byte position of the R & B components are swapped in
1241a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com// relation to the input config. This should only be called with the result of
1242a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com// grconfig_to_config8888 as it will fail for other configs.
1243a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comSkCanvas::Config8888 swap_config8888_red_and_blue(SkCanvas::Config8888 config8888) {
1244a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    switch (config8888) {
1245a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        case SkCanvas::kBGRA_Premul_Config8888:
1246a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            return SkCanvas::kRGBA_Premul_Config8888;
1247a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        case SkCanvas::kBGRA_Unpremul_Config8888:
1248a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            return SkCanvas::kRGBA_Unpremul_Config8888;
1249a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        case SkCanvas::kRGBA_Premul_Config8888:
1250a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            return SkCanvas::kBGRA_Premul_Config8888;
1251a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        case SkCanvas::kRGBA_Unpremul_Config8888:
1252a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            return SkCanvas::kBGRA_Unpremul_Config8888;
1253a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        default:
1254a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            GrCrash("Unexpected input");
1255a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            return SkCanvas::kBGRA_Unpremul_Config8888;;
1256a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1257a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1258a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
1259a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
12600342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.combool GrContext::readRenderTargetPixels(GrRenderTarget* target,
12610342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                       int left, int top, int width, int height,
12620342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                       GrPixelConfig config, void* buffer, size_t rowBytes,
12630342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                       uint32_t flags) {
1264278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
1265bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
1266bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
1267fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    if (NULL == target) {
126810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        target = fDrawState->getRenderTarget();
1269c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (NULL == target) {
1270c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            return false;
1271c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1272c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1273669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
12746f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
12756f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        this->flush();
12766f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
1277c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1278a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // Determine which conversions have to be applied: flipY, swapRAnd, and/or unpremul.
1279c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1280a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // If fGpu->readPixels would incur a y-flip cost then we will read the pixels upside down. We'll
1281a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // either do the flipY by drawing into a scratch with a matrix or on the cpu after the read.
1282a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    bool flipY = fGpu->readPixelsWillPayForYFlip(target, left, top,
1283c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 width, height, config,
1284c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 rowBytes);
1285a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    bool swapRAndB = fGpu->preferredReadPixelsConfig(config) == GrPixelConfigSwapRAndB(config);
1286a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
12870342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
1288c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1289a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // flipY will get set to false when it is handled below using a scratch. However, in that case
1290a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // we still want to do the read upside down.
1291a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    bool readUpsideDown = flipY;
1292a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1293a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (unpremul && kRGBA_8888_GrPixelConfig != config && kBGRA_8888_GrPixelConfig != config) {
1294a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // The unpremul flag is only allowed for these two configs.
12950a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        return false;
12960a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    }
1297a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1298a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrPixelConfig readConfig;
1299a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (swapRAndB) {
1300a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        readConfig = GrPixelConfigSwapRAndB(config);
1301a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        GrAssert(kUnknown_GrPixelConfig != config);
1302a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    } else {
1303a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        readConfig = config;
1304a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1305a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1306a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // If the src is a texture and we would have to do conversions after read pixels, we instead
1307a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // do the conversions by drawing the src to a scratch texture. If we handle any of the
1308a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // conversions in the draw we set the corresponding bool to false so that we don't reapply it
1309a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // on the read back pixels.
1310a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrTexture* src = target->asTexture();
1311c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com    GrAutoScratchTexture ast;
1312a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (NULL != src && (swapRAndB || unpremul || flipY)) {
1313a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // Make the scratch a render target because we don't have a robust readTexturePixels as of
1314a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // yet. It calls this function.
131575b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        GrTextureDesc desc;
131675b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fFlags = kRenderTarget_GrTextureFlagBit;
131775b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fWidth = width;
131875b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fHeight = height;
1319a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        desc.fConfig = readConfig;
1320c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com
1321a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // When a full readback is faster than a partial we could always make the scratch exactly
1322a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // match the passed rect. However, if we see many different size rectangles we will trash
1323a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // our texture cache and pay the cost of creating and destroying many textures. So, we only
1324a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // request an exact match when the caller is reading an entire RT.
132556d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ScratchTexMatch match = kApprox_ScratchTexMatch;
132656d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        if (0 == left &&
132756d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            0 == top &&
132856d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->width() == width &&
132956d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->height() == height &&
133056d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            fGpu->fullReadPixelsIsFasterThanPartial()) {
133156d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            match = kExact_ScratchTexMatch;
133256d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        }
133356d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ast.set(this, desc, match);
1334c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrTexture* texture = ast.texture();
1335a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        if (texture) {
1336a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            SkAutoTUnref<GrCustomStage> stage;
1337a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            if (unpremul) {
1338a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                stage.reset(this->createPMToUPMEffect(src, swapRAndB));
1339a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            }
1340a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            // If we failed to create a PM->UPM effect and have no other conversions to perform then
1341a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            // there is no longer any point to using the scratch.
1342a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            if (NULL != stage || flipY || swapRAndB) {
1343a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                if (NULL == stage) {
1344a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    stage.reset(GrConfigConversionEffect::Create(src, swapRAndB));
1345a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    GrAssert(NULL != stage);
1346a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                } else {
1347a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    unpremul = false; // we will handle the UPM conversion in the draw
1348a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                }
1349a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                swapRAndB = false; // we will handle the swap in the draw.
1350a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1351a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
1352a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                GrDrawState* drawState = fGpu->drawState();
1353a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                drawState->setRenderTarget(texture->asRenderTarget());
1354a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                GrMatrix matrix;
1355a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                if (flipY) {
1356a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    matrix.setTranslate(SK_Scalar1 * left,
1357a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                        SK_Scalar1 * (top + height));
1358a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    matrix.set(GrMatrix::kMScaleY, -GR_Scalar1);
1359a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    flipY = false; // the y flip will be handled in the draw
1360a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                } else {
1361a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    matrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
1362a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                }
1363a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                matrix.postIDiv(src->width(), src->height());
1364a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                drawState->sampler(0)->reset(matrix);
1365a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                drawState->sampler(0)->setCustomStage(stage);
1366a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                GrRect rect = GrRect::MakeWH(GrIntToScalar(width), GrIntToScalar(height));
1367a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                fGpu->drawSimpleRect(rect, NULL);
1368a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                // we want to read back from the scratch's origin
1369a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                left = 0;
1370a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                top = 0;
1371a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                target = texture->asRenderTarget();
1372a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            }
1373c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1374a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1375a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!fGpu->readPixels(target,
1376a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                          left, top, width, height,
1377a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                          readConfig, buffer, rowBytes, readUpsideDown)) {
1378a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        return false;
1379a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1380a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // Perform any conversions we weren't able to perfom using a scratch texture.
1381a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (unpremul || swapRAndB || flipY) {
1382a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        SkCanvas::Config8888 srcC8888;
1383a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        SkCanvas::Config8888 dstC8888;
1384a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        bool c8888IsValid = grconfig_to_config8888(config, false, &srcC8888);
1385a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        grconfig_to_config8888(config, unpremul, &dstC8888);
1386a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        if (swapRAndB) {
1387a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            GrAssert(c8888IsValid); // we should only do r/b swap on 8888 configs
1388a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            srcC8888 = swap_config8888_red_and_blue(srcC8888);
13890342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com        }
1390c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (flipY) {
1391a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            size_t tightRB = width * GrBytesPerPixel(config);
1392a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            if (0 == rowBytes) {
1393a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                rowBytes = tightRB;
1394a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            }
1395a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            SkAutoSTMalloc<256, uint8_t> tempRow(tightRB);
1396a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            intptr_t top = reinterpret_cast<intptr_t>(buffer);
1397a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            intptr_t bot = top + (height - 1) * rowBytes;
1398a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            while (top < bot) {
1399a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                uint32_t* t = reinterpret_cast<uint32_t*>(top);
1400a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                uint32_t* b = reinterpret_cast<uint32_t*>(bot);
1401a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                uint32_t* temp = reinterpret_cast<uint32_t*>(tempRow.get());
1402a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                memcpy(temp, t, tightRB);
1403a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                if (c8888IsValid) {
1404a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    SkConvertConfig8888Pixels(t, tightRB, dstC8888,
1405a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                              b, tightRB, srcC8888,
1406a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                              width, 1);
1407a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    SkConvertConfig8888Pixels(b, tightRB, dstC8888,
1408a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                              temp, tightRB, srcC8888,
1409a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                              width, 1);
1410a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                } else {
1411a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    memcpy(t, b, tightRB);
1412a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                    memcpy(b, temp, tightRB);
1413a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                }
1414a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                top += rowBytes;
1415a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                bot -= rowBytes;
1416a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            }
1417a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            // The above loop does nothing on the middle row when height is odd.
1418a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            if (top == bot && c8888IsValid && dstC8888 != srcC8888) {
1419a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                uint32_t* mid = reinterpret_cast<uint32_t*>(top);
1420a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                SkConvertConfig8888Pixels(mid, tightRB, dstC8888, mid, tightRB, srcC8888, width, 1);
1421a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            }
1422c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        } else {
1423a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            // if we aren't flipping Y then we have no reason to be here other than doing
1424a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            // conversions for 8888 (r/b swap or upm).
1425a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            GrAssert(c8888IsValid);
1426a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            uint32_t* b32 = reinterpret_cast<uint32_t*>(buffer);
1427a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            SkConvertConfig8888Pixels(b32, rowBytes, dstC8888,
1428a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                      b32, rowBytes, srcC8888,
1429a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                      width, height);
1430c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1431c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1432a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    return true;
143327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
143427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
143575f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.comvoid GrContext::resolveRenderTarget(GrRenderTarget* target) {
143675f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    GrAssert(target);
143775f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
143875f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // In the future we may track whether there are any pending draws to this
143975f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // target. We don't today so we always perform a flush. We don't promise
144075f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // this to our clients, though.
144175f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    this->flush();
144275f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    fGpu->resolveRenderTarget(target);
144375f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com}
144475f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com
1445ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.orgvoid GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst) {
1446ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    if (NULL == src || NULL == dst) {
1447ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        return;
1448ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
1449ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(src);
1450ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
14511ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // Writes pending to the source texture are not tracked, so a flush
14521ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // is required to ensure that the copy captures the most recent contents
14531ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // of the source texture. See similar behaviour in
14541ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // GrContext::resolveRenderTarget.
14551ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    this->flush();
14561ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com
1457873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
14588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
14598f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(dst);
1460ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    GrMatrix sampleM;
1461ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    sampleM.setIDiv(src->width(), src->height());
14621e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->reset(sampleM);
14631e8f016305805d4d8cad74aba3a21b78486f9d6ftomhudson@google.com    drawState->createTextureEffect(0, src);
14645db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com    SkRect rect = SkRect::MakeXYWH(0, 0,
14655db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                                   SK_Scalar1 * src->width(),
14665db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                                   SK_Scalar1 * src->height());
1467e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    fGpu->drawSimpleRect(rect, NULL);
1468ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org}
1469ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
1470fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comvoid GrContext::writeRenderTargetPixels(GrRenderTarget* target,
14710342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                        int left, int top, int width, int height,
14720342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                        GrPixelConfig config,
14730342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                        const void* buffer,
14740342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                        size_t rowBytes,
14750342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                        uint32_t flags) {
14766f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
1477bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
14786f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
1479fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    if (NULL == target) {
1480873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com        target = fDrawState->getRenderTarget();
14816f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        if (NULL == target) {
14826f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com            return;
14836f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        }
14846f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
148527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1486a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // TODO: when underlying api has a direct way to do this we should use it (e.g. glDrawPixels on
1487a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // desktop GL).
1488a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1489a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // We will always call some form of writeTexturePixels and we will pass our flags on to it.
1490a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // Thus, we don't perform a flush here since that call will do it (if the kNoFlush flag isn't
1491a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // set.)
149227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
14930342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    // If the RT is also a texture and we don't have to premultiply then take the texture path.
14940342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    // We expect to be at least as fast or faster since it doesn't use an intermediate texture as
14950342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    // we do below.
1496fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1497a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#if !GR_MAC_BUILD
1498a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // At least some drivers on the Mac get confused when glTexImage2D is called on a texture
1499a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // attached to an FBO. The FBO still sees the old image. TODO: determine what OS versions and/or
1500a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // HW is affected.
15010342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    if (NULL != target->asTexture() && !(kUnpremul_PixelOpsFlag & flags)) {
15020342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com        this->writeTexturePixels(target->asTexture(),
15030342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                 left, top, width, height,
15040342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                 config, buffer, rowBytes, flags);
1505a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        return;
1506a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1507a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#endif
1508a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    SkAutoTUnref<GrCustomStage> stage;
1509a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    bool swapRAndB = (fGpu->preferredReadPixelsConfig(config) == GrPixelConfigSwapRAndB(config));
1510a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1511a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrPixelConfig textureConfig;
1512a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    if (swapRAndB) {
1513a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        textureConfig = GrPixelConfigSwapRAndB(config);
1514a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    } else {
1515a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        textureConfig = config;
1516a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1517a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
151875b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc desc;
151975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fWidth = width;
152075b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fHeight = height;
1521a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    desc.fConfig = textureConfig;
152250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrAutoScratchTexture ast(this, desc);
152350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrTexture* texture = ast.texture();
152427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL == texture) {
152527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
152627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
1527a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // allocate a tmp buffer and sw convert the pixels to premul
1528a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
1529a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1530a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (kUnpremul_PixelOpsFlag & flags) {
1531a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        if (kRGBA_8888_GrPixelConfig != config && kBGRA_8888_GrPixelConfig != config) {
1532a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            return;
1533a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
1534a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        stage.reset(this->createUPMToPMEffect(texture, swapRAndB));
1535a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        if (NULL == stage) {
1536a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            SkCanvas::Config8888 srcConfig8888, dstConfig8888;
1537a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            GR_DEBUGCODE(bool success = )
1538a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            grconfig_to_config8888(config, true, &srcConfig8888);
1539a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            GrAssert(success);
1540a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            GR_DEBUGCODE(success = )
1541a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            grconfig_to_config8888(config, false, &dstConfig8888);
1542a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            GrAssert(success);
1543a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            const uint32_t* src = reinterpret_cast<const uint32_t*>(buffer);
1544a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            tmpPixels.reset(width * height);
1545a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            SkConvertConfig8888Pixels(tmpPixels.get(), 4 * width, dstConfig8888,
1546a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                      src, rowBytes, srcConfig8888,
1547a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                      width, height);
1548a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            buffer = tmpPixels.get();
1549a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            rowBytes = 4 * width;
1550a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
1551a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1552a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (NULL == stage) {
1553a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        stage.reset(GrConfigConversionEffect::Create(texture, swapRAndB));
1554a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        GrAssert(NULL != stage);
1555a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1556a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1557a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    this->writeTexturePixels(texture,
1558a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                             0, 0, width, height,
1559a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                             textureConfig, buffer, rowBytes,
1560a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                             flags & ~kUnpremul_PixelOpsFlag);
156127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1562873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrDrawTarget::AutoStateRestore  asr(fGpu, GrDrawTarget::kReset_ASRInit);
15638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
156427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
156527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix matrix;
156627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
15678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setViewMatrix(matrix);
15688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(target);
156927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
15705c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com    matrix.setIDiv(texture->width(), texture->height());
1571b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com    drawState->sampler(0)->reset(matrix);
1572a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    drawState->sampler(0)->setCustomStage(stage);
1573a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1574a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    fGpu->drawSimpleRect(GrRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), NULL);
157527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
157627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
157727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
157810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.comvoid GrContext::setPaint(const GrPaint& paint) {
1579cb325ceda16fab97fd3281785e6ae10fcb8dcf83tomhudson@google.com    GrAssert(fDrawState->stagesDisabled());
158026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
158126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kMaxTextures; ++i) {
158226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        int s = i + GrPaint::kFirstTextureStage;
1583f13f58804659175925042a291304d483a4fd9278tomhudson@google.com        if (paint.isTextureStageEnabled(i)) {
158410e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com            *fDrawState->sampler(s) = paint.getTextureSampler(i);
1585f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        }
158626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
158726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
158810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setFirstCoverageStage(GrPaint::kFirstMaskStage);
158926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
159026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kMaxMasks; ++i) {
159126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        int s = i + GrPaint::kFirstMaskStage;
1592f13f58804659175925042a291304d483a4fd9278tomhudson@google.com        if (paint.isMaskStageEnabled(i)) {
159310e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com            *fDrawState->sampler(s) = paint.getMaskSampler(i);
1594f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        }
159526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
1596fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
159726936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com    // disable all stages not accessible via the paint
159826936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com    for (int s = GrPaint::kTotalStages; s < GrDrawState::kNumStages; ++s) {
1599676e66096c60615bac52f365111596de5c4ca8a6tomhudson@google.com        fDrawState->disableStage(s);
160026936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com    }
160126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
160210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setColor(paint.fColor);
160327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
160427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (paint.fDither) {
160510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->enableState(GrDrawState::kDither_StateBit);
160627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
160710e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->disableState(GrDrawState::kDither_StateBit);
160827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
160927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (paint.fAntiAlias) {
161010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->enableState(GrDrawState::kHWAntialias_StateBit);
161127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
161210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->disableState(GrDrawState::kHWAntialias_StateBit);
161327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
161450bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    if (paint.fColorMatrixEnabled) {
161510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->enableState(GrDrawState::kColorMatrix_StateBit);
161610e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->setColorMatrix(paint.fColorMatrix);
161750bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    } else {
161810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->disableState(GrDrawState::kColorMatrix_StateBit);
161950bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    }
162010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
162110e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
162210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setCoverage(paint.fCoverage);
16234b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#if GR_DEBUG_PARTIAL_COVERAGE_CHECK
1624e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    if ((paint.hasMask() || 0xff != paint.fCoverage) &&
162510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        !fGpu->canApplyCoverage()) {
1626d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com        GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
1627d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    }
162895cd7bdf2b4dee54739f0a375fe99a02f86178b0bsalomon@google.com#endif
162927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
163027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
163107ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.comGrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, BufferedDraw buffered) {
16321d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com    if (kNo_BufferedDraw == buffered && kYes_BufferedDraw == fLastDrawWasBuffered) {
1633fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com        this->flushDrawBuffer();
16341d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com        fLastDrawWasBuffered = kNo_BufferedDraw;
163527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
163607ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    if (NULL != paint) {
163707ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com        this->setPaint(*paint);
163807ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    }
16391d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com    if (kYes_BufferedDraw == buffered) {
16401d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com        fDrawBuffer->setClip(fGpu->getClip());
16411d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com        fLastDrawWasBuffered = kYes_BufferedDraw;
16421d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com        return fDrawBuffer;
16431d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com    } else {
16441d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com        GrAssert(kNo_BufferedDraw == buffered);
16451d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com        return fGpu;
164627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
164727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
164827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
164972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com/*
165072176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * This method finds a path renderer that can draw the specified path on
165172176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * the provided target.
1652fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * Due to its expense, the software path renderer has split out so it can
165372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * can be individually allowed/disallowed via the "allowSW" boolean.
165472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com */
16558d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comGrPathRenderer* GrContext::getPathRenderer(const SkPath& path,
1656289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           GrPathFill fill,
1657c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com                                           const GrDrawTarget* target,
165872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                           bool antiAlias,
165972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                           bool allowSW) {
16603008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == fPathRendererChain) {
1661fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        fPathRendererChain =
1662c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com            SkNEW_ARGS(GrPathRendererChain,
1663c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                       (this, GrPathRendererChain::kNone_UsageFlag));
16643008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
166572176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
166672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(path, fill,
166772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                                             target,
166872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                                             antiAlias);
166972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
167072176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    if (NULL == pr && allowSW) {
167172176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        if (NULL == fSoftwarePathRenderer) {
1672c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com            fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this));
167372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        }
167472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
167572176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        pr = fSoftwarePathRenderer;
167672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    }
167772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
167872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    return pr;
16793008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com}
16803008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
168127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
168227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
168327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setRenderTarget(GrRenderTarget* target) {
1684bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
168507ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    fDrawState->setRenderTarget(target);
168627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
168727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
168827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrRenderTarget* GrContext::getRenderTarget() {
168910e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    return fDrawState->getRenderTarget();
169027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
169127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
169227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrRenderTarget* GrContext::getRenderTarget() const {
169310e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    return fDrawState->getRenderTarget();
169427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
169527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
169699a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.combool GrContext::isConfigRenderable(GrPixelConfig config) const {
169799a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com    return fGpu->isConfigRenderable(config);
169899a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com}
169999a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com
170027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrMatrix& GrContext::getMatrix() const {
170110e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    return fDrawState->getViewMatrix();
170227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
170327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
170427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setMatrix(const GrMatrix& m) {
170510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setViewMatrix(m);
170627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
170727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
170827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::concatMatrix(const GrMatrix& m) const {
170910e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->preConcatViewMatrix(m);
171027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
171127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
171227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
171327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    intptr_t mask = 1 << shift;
171427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (pred) {
171527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        bits |= mask;
171627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
171727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        bits &= ~mask;
171827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
171927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return bits;
172027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
172127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1722583a1e38503ebd57ba9bd39a3fabe89bead8e76cbsalomon@google.comGrContext::GrContext(GrGpu* gpu) {
1723c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    ++THREAD_INSTANCE_COUNT;
1724c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
172527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu = gpu;
172627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->ref();
1727669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    fGpu->setContext(this);
17288fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1729c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    fDrawState = SkNEW(GrDrawState);
173010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fGpu->setDrawState(fDrawState);
173110e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com
17323008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    fPathRendererChain = NULL;
173372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    fSoftwarePathRenderer = NULL;
1734dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com
1735c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    fTextureCache = SkNEW_ARGS(GrResourceCache,
1736c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                               (MAX_TEXTURE_CACHE_COUNT,
1737c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                                MAX_TEXTURE_CACHE_BYTES));
1738c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    fFontCache = SkNEW_ARGS(GrFontCache, (fGpu));
173927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
17401d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com    fLastDrawWasBuffered = kNo_BufferedDraw;
174127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
17428fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
17438fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
17448fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
17458fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1746c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    fAARectRenderer = SkNEW(GrAARectRenderer);
174710e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com
1748a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    fDidTestPMConversions = false;
1749a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
17508fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->setupDrawBuffer();
17518fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
17528fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
17538fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::setupDrawBuffer() {
17548fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
17558fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBuffer);
17568fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBufferVBAllocPool);
17578fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBufferIBAllocPool);
17588fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1759de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferVBAllocPool =
1760c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com        SkNEW_ARGS(GrVertexBufferAllocPool, (fGpu, false,
176127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                    DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
1762c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                                    DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS));
1763de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferIBAllocPool =
1764c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com        SkNEW_ARGS(GrIndexBufferAllocPool, (fGpu, false,
1765de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com                                   DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
1766c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                                   DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS));
176727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1768c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (fGpu,
1769471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com                                          fDrawBufferVBAllocPool,
1770c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                                          fDrawBufferIBAllocPool));
17713c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com
177227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
17731015e034676a90d88544c396ff4dce3849186aa9bsalomon@google.com    if (fDrawBuffer) {
17741015e034676a90d88544c396ff4dce3849186aa9bsalomon@google.com        fDrawBuffer->setAutoFlushTarget(fGpu);
17751015e034676a90d88544c396ff4dce3849186aa9bsalomon@google.com        fDrawBuffer->setDrawState(fDrawState);
17761015e034676a90d88544c396ff4dce3849186aa9bsalomon@google.com    }
177727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
177827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
177927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
178007ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    return prepareToDraw(&paint, DEFAULT_BUFFERING);
178127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
178227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
178327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
178427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return fGpu->getQuadIndexBuffer();
178527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
1786dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com
1787a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comnamespace {
1788a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comvoid test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
1789a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::PMConversion pmToUPM;
1790a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::PMConversion upmToPM;
1791a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
1792a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    *pmToUPMValue = pmToUPM;
1793a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    *upmToPMValue = upmToPM;
1794a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1795a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1796a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1797a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comGrCustomStage* GrContext::createPMToUPMEffect(GrTexture* texture, bool swapRAndB) {
1798a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!fDidTestPMConversions) {
1799a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
1800a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1801a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::PMConversion pmToUPM =
1802a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
1803a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
1804a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM);
1805a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    } else {
1806a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        return NULL;
1807a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1808a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1809a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1810a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comGrCustomStage* GrContext::createUPMToPMEffect(GrTexture* texture, bool swapRAndB) {
1811a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!fDidTestPMConversions) {
1812a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
1813a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1814a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::PMConversion upmToPM =
1815a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
1816a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
1817a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM);
1818a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    } else {
1819a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        return NULL;
1820a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1821a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1822a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
18233b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgGrTexture* GrContext::gaussianBlur(GrTexture* srcTexture,
18241e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org                                   bool canClobberSrc,
18253b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                   const SkRect& rect,
18263b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                   float sigmaX, float sigmaY) {
1827ceb441476e1712861e87a9bb428f119349ef6bb5senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(srcTexture);
18283b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrRenderTarget* oldRenderTarget = this->getRenderTarget();
1829fea85ac3e31842f80493e2df8a93a28f21cd815frobertphillips@google.com    AutoMatrix avm(this, GrMatrix::I());
18303b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    SkIRect clearRect;
1831b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    int scaleFactorX, radiusX;
1832b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    int scaleFactorY, radiusY;
1833b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
1834b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);
18353b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18363b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    SkRect srcRect(rect);
18373b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
18383b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    srcRect.roundOut();
1839fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    scale_rect(&srcRect, static_cast<float>(scaleFactorX),
18408637a365518a82901d313d61eecd83a0c5102fe9robertphillips@google.com                         static_cast<float>(scaleFactorY));
18413e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com
184256c79b10377e358b8092d9c6ab3e1aacf2cd60e5robertphillips@google.com    AutoClip acs(this, srcRect);
1843bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
18440342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
18450342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com             kRGBA_8888_GrPixelConfig == srcTexture->config() ||
184699a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com             kAlpha_8_GrPixelConfig == srcTexture->config());
184799a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com
184875b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc desc;
184975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
185075b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fWidth = SkScalarFloorToInt(srcRect.width());
185175b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fHeight = SkScalarFloorToInt(srcRect.height());
185275b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fConfig = srcTexture->config();
18531e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com
18541e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    GrAutoScratchTexture temp1, temp2;
18551e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    GrTexture* dstTexture = temp1.set(this, desc);
18561e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(this, desc);
18573b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18583b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrPaint paint;
18593b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    paint.reset();
1860b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com    paint.textureSampler(0)->textureParams()->setBilerp(true);
18613b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18623b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
18633b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(),
18643b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                                   srcTexture->height());
18653b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
18663b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkRect dstRect(srcRect);
18673b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
18683b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                            i < scaleFactorY ? 0.5f : 1.0f);
1869aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com        paint.textureSampler(0)->setCustomStage(SkNEW_ARGS(GrSingleTextureEffect,
1870aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com                                                           (srcTexture)))->unref();
18713b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->drawRectToRect(paint, dstRect, srcRect);
18723b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        srcRect = dstRect;
18731e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture = dstTexture;
18741e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        SkTSwap(dstTexture, tempTexture);
18753b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
18763b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18777a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com    SkIRect srcIRect;
18787a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com    srcRect.roundOut(&srcIRect);
18797a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com
18803b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (sigmaX > 0.0f) {
18813b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        if (scaleFactorX > 1) {
1882b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com            // Clear out a radius to the right of the srcRect to prevent the
18833b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            // X convolution from reading garbage.
1884fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
1885b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                                          radiusX, srcIRect.height());
18863b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            this->clear(&clearRect, 0x0);
18873b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        }
188805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
18893b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
189007ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com        GrDrawTarget* target = this->prepareToDraw(NULL, DEFAULT_BUFFERING);
189107ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com        convolve_gaussian(target, srcTexture, srcRect, sigmaX, radiusX,
1892b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                          Gr1DKernelEffect::kX_Direction);
18931e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture = dstTexture;
18941e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        SkTSwap(dstTexture, tempTexture);
18953b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
18963b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18973b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (sigmaY > 0.0f) {
18983b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        if (scaleFactorY > 1 || sigmaX > 0.0f) {
1899b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com            // Clear out a radius below the srcRect to prevent the Y
19003b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            // convolution from reading garbage.
1901fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
1902b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                                          srcIRect.width(), radiusY);
19033b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            this->clear(&clearRect, 0x0);
19043b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        }
19053b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
19063b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
190707ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com        GrDrawTarget* target = this->prepareToDraw(NULL, DEFAULT_BUFFERING);
190807ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com        convolve_gaussian(target, srcTexture, srcRect, sigmaY, radiusY,
1909b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                          Gr1DKernelEffect::kY_Direction);
19101e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture = dstTexture;
19111e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        SkTSwap(dstTexture, tempTexture);
19123b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
19133b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
19143b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (scaleFactorX > 1 || scaleFactorY > 1) {
19153b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // Clear one pixel to the right and below, to accommodate bilinear
19163b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // upsampling.
1917fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
19187a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                                      srcIRect.width() + 1, 1);
19193b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->clear(&clearRect, 0x0);
1920fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
19217a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                                      1, srcIRect.height());
19223b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->clear(&clearRect, 0x0);
19233b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // FIXME:  This should be mitchell, not bilinear.
1924b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com        paint.textureSampler(0)->textureParams()->setBilerp(true);
19253b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(),
19263b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                                   srcTexture->height());
19273b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
1928aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com        paint.textureSampler(0)->setCustomStage(SkNEW_ARGS(GrSingleTextureEffect,
1929aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com                                                           (srcTexture)))->unref();
19303b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkRect dstRect(srcRect);
19317a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com        scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
19323b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->drawRectToRect(paint, dstRect, srcRect);
19333b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        srcRect = dstRect;
19341e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture = dstTexture;
19351e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        SkTSwap(dstTexture, tempTexture);
19363b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
19373b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setRenderTarget(oldRenderTarget);
19381e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    if (srcTexture == temp1.texture()) {
19391e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        return temp1.detach();
19401e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    } else if (srcTexture == temp2.texture()) {
19411e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        return temp2.detach();
19421e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    } else {
19431e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture->ref();
19441e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        return srcTexture;
19451e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    }
19463b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
19473b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
1948c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
19495f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com#if GR_DEBUG
19505f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.comvoid GrContext::printCacheStats() const {
19515f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com    fTextureCache->printStats();
19525f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com}
19535f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com#endif
1954