GrContext.cpp revision beb1af78d016d2700c350487a383c6bcfa7e2e20
127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com */
827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
101fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com#include "GrContext.h"
111fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com
12b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com#include "effects/GrMorphologyEffect.h"
13b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com#include "effects/GrConvolutionEffect.h"
14aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com#include "effects/GrSingleTextureEffect.h"
15b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com
16278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrBufferAllocPool.h"
17278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrClipIterator.h"
1805ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com#include "GrGpu.h"
1927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrIndexBuffer.h"
2027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrInOrderDrawBuffer.h"
2127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrPathRenderer.h"
22d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com#include "GrPathUtils.h"
2350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com#include "GrResourceCache.h"
2472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com#include "GrSoftwarePathRenderer.h"
25558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com#include "GrStencilBuffer.h"
26278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrTextStrike.h"
278c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com#include "SkTLazy.h"
28c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com#include "SkTLS.h"
290c8d93a94099dee2dff8da6000ded9ad59676488tomhudson@google.com#include "SkTrace.h"
3027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
31fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.comSK_DEFINE_INST_COUNT(GrContext)
32fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.comSK_DEFINE_INST_COUNT(GrDrawState)
33fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com
343c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com#define DEFER_TEXT_RENDERING 1
3527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
363c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com#define DEFER_PATHS 1
37fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com
383c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com#define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)
3927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
403b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org#define MAX_BLUR_SIGMA 4.0f
413b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
42d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// When we're using coverage AA but the blend is incompatible (given gpu
43d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// limitations) should we disable AA or draw wrong?
44950d7a8d8def14efc98d12d6947347fde351b737bsalomon@google.com#define DISABLE_COVERAGE_AA_FOR_BLEND 1
45d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
464b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#if GR_DEBUG
474b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    // change this to a 1 to see notifications when partial coverage fails
484b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
494b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#else
504b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
514b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#endif
524b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com
5307fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comstatic const size_t MAX_TEXTURE_CACHE_COUNT = 256;
5407fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comstatic const size_t MAX_TEXTURE_CACHE_BYTES = 16 * 1024 * 1024;
5527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
5660361493548d5259d0a8afae84274c2a3c31dcacbsalomon@google.comstatic const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 15;
5727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
5827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
59fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com// path rendering is the only thing we defer today that uses non-static indices
60fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.comstatic const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = DEFER_PATHS ? 1 << 11 : 0;
61fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.comstatic const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = DEFER_PATHS ? 4 : 0;
6227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
63bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com#define ASSERT_OWNED_RESOURCE(R) GrAssert(!(R) || (R)->getContext() == this)
64bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
6505ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.comGrContext* GrContext::Create(GrEngine engine,
6605ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com                             GrPlatform3DContext context3D) {
6727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrContext* ctx = NULL;
6827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrGpu* fGpu = GrGpu::Create(engine, context3D);
6927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != fGpu) {
70c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com        ctx = SkNEW_ARGS(GrContext, (fGpu));
7127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fGpu->unref();
7227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
7327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return ctx;
7427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
7527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
76c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comnamespace {
77c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comvoid* CreateThreadInstanceCount() {
78c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    return SkNEW_ARGS(int, (0));
79c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
80c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comvoid DeleteThreadInstanceCount(void* v) {
81c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    delete reinterpret_cast<int*>(v);
82c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
83c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com#define THREAD_INSTANCE_COUNT                                               \
84c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    (*reinterpret_cast<int*>(SkTLS::Get(CreateThreadInstanceCount,          \
85c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com                                        DeleteThreadInstanceCount)))
86c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
87c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
88c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
89c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comint GrContext::GetThreadInstanceCount() {
90c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    return THREAD_INSTANCE_COUNT;
91c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
92c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
9327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrContext::~GrContext() {
948fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
955acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com
965acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // Since the gpu can hold scratch textures, give it a chance to let go
975acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // of them before freeing the texture cache
985acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    fGpu->purgeResources();
995acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com
10027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fTextureCache;
10127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fFontCache;
10227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBuffer;
10327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBufferVBAllocPool;
104de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    delete fDrawBufferIBAllocPool;
1053008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
106f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->unref();
107f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com
108205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->unref();
1093008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeUnref(fPathRendererChain);
11072176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrSafeUnref(fSoftwarePathRenderer);
11110e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->unref();
112c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
113c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    --THREAD_INSTANCE_COUNT;
11427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
11527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1168fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::contextLost() {
11753a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    contextDestroyed();
11853a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    this->setupDrawBuffer();
11953a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com}
12053a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com
12153a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.comvoid GrContext::contextDestroyed() {
122205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // abandon first to so destructors
123205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // don't try to free the resources in the API.
124205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->abandonResources();
125205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1263008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources that
1273008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // are now unusable
1283008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeSetNull(fPathRendererChain);
12972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrSafeSetNull(fSoftwarePathRenderer);
1303008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
1318fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBuffer;
1328fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
133205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1348fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferVBAllocPool;
1358fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
136205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1378fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferIBAllocPool;
1388fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
1398fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
140f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->reset();
141205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1428fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fTextureCache->removeAll();
1438fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
1448fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
1458fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
1468fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1478fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::resetContext() {
1488fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
1498fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
1508fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1518fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::freeGpuResources() {
1528fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
153ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com
154ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com    fGpu->purgeResources();
155ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com
156f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->reset();
157f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com
1588fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fTextureCache->removeAll();
1598fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
1603008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources
1613008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    GrSafeSetNull(fPathRendererChain);
16272176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrSafeSetNull(fSoftwarePathRenderer);
16327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
16427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
16505e70247c31ae927074ef27ea9893634a8dda543twiz@google.comsize_t GrContext::getGpuTextureCacheBytes() const {
16605e70247c31ae927074ef27ea9893634a8dda543twiz@google.com  return fTextureCache->getCachedResourceBytes();
16705e70247c31ae927074ef27ea9893634a8dda543twiz@google.com}
16805e70247c31ae927074ef27ea9893634a8dda543twiz@google.com
169fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
170fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
17150398bf7f1953e640e5529616e710cf540799731bsalomon@google.comGrTexture* GrContext::TextureCacheEntry::texture() const {
17250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (NULL == fEntry) {
17350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        return NULL;
17450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    } else {
17550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        return (GrTexture*) fEntry->resource();
17650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    }
17750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com}
17850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
17950398bf7f1953e640e5529616e710cf540799731bsalomon@google.comnamespace {
180558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
181558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com// we should never have more than one stencil buffer with same combo of
182558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com// (width,height,samplecount)
183558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid gen_stencil_key_values(int width, int height,
184558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                            int sampleCnt, uint32_t v[4]) {
185558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[0] = width;
186558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[1] = height;
187558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    v[2] = sampleCnt;
188a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    v[3] = GrResourceKey::kStencilBuffer_TypeBit;
189558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
190558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
191558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid gen_stencil_key_values(const GrStencilBuffer* sb,
192558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                            uint32_t v[4]) {
193558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(sb->width(), sb->height(),
194558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                           sb->numSamples(), v);
195558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
19682c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com
1973b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgvoid scale_rect(SkRect* rect, float xScale, float yScale) {
1985af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com    rect->fLeft = SkScalarMul(rect->fLeft, SkFloatToScalar(xScale));
1995af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com    rect->fTop = SkScalarMul(rect->fTop, SkFloatToScalar(yScale));
2005af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com    rect->fRight = SkScalarMul(rect->fRight, SkFloatToScalar(xScale));
2015af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com    rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale));
2023b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
2033b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
204b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.comfloat adjust_sigma(float sigma, int *scaleFactor, int *radius) {
2053b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    *scaleFactor = 1;
2063b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    while (sigma > MAX_BLUR_SIGMA) {
2073b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        *scaleFactor *= 2;
2083b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        sigma *= 0.5f;
2093b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
210b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    *radius = static_cast<int>(ceilf(sigma * 3.0f));
211b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius);
2123b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    return sigma;
2133b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
2143b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
2153b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgvoid apply_morphology(GrGpu* gpu,
2163b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                      GrTexture* texture,
2173b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                      const SkRect& rect,
2183b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                      int radius,
219b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                      GrContext::MorphologyType morphType,
220b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                      Gr1DKernelEffect::Direction direction) {
2213b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
222873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrRenderTarget* target = gpu->drawState()->getRenderTarget();
223873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit);
2243b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrDrawState* drawState = gpu->drawState();
2253b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->setRenderTarget(target);
2263b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrMatrix sampleM;
2273b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    sampleM.setIDiv(texture->width(), texture->height());
228b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    drawState->sampler(0)->reset(sampleM);
229b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    SkAutoTUnref<GrCustomStage> morph(
230d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com        SkNEW_ARGS(GrMorphologyEffect, (texture, direction, radius, morphType)));
231b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    drawState->sampler(0)->setCustomStage(morph);
232e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    gpu->drawSimpleRect(rect, NULL);
2333b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
2343b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
235b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.comvoid convolve_gaussian(GrGpu* gpu,
236b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       GrTexture* texture,
237b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       const SkRect& rect,
238b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       float sigma,
239b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       int radius,
240b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                       Gr1DKernelEffect::Direction direction) {
241873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrRenderTarget* target = gpu->drawState()->getRenderTarget();
242873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit);
2433b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrDrawState* drawState = gpu->drawState();
2443b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    drawState->setRenderTarget(target);
2453b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrMatrix sampleM;
2463b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    sampleM.setIDiv(texture->width(), texture->height());
247b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    drawState->sampler(0)->reset(sampleM);
248c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    SkAutoTUnref<GrConvolutionEffect> conv(SkNEW_ARGS(GrConvolutionEffect,
249fde2c0af2fd5aae19ab6c8b5228debd5b6209856tomhudson@google.com                                                      (texture, direction, radius,
250fde2c0af2fd5aae19ab6c8b5228debd5b6209856tomhudson@google.com                                                       sigma)));
251b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    drawState->sampler(0)->setCustomStage(conv);
252e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    gpu->drawSimpleRect(rect, NULL);
2533b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
2543b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
255fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com}
256fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
257b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.comGrContext::TextureCacheEntry GrContext::findAndLockTexture(const GrTextureDesc& desc,
258b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com                                                           const GrTextureParams* params) {
259b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, false);
260558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    return TextureCacheEntry(fTextureCache->findAndLock(resourceKey,
261558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                            GrResourceCache::kNested_LockType));
262558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
263558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
26475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.combool GrContext::isTextureInCache(const GrTextureDesc& desc,
265b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com                                 const GrTextureParams* params) const {
266b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, false);
267fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    return fTextureCache->hasKey(resourceKey);
268fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com}
269fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com
270558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comGrResourceEntry* GrContext::addAndLockStencilBuffer(GrStencilBuffer* sb) {
271bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(sb);
272558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    uint32_t v[4];
273558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(sb, v);
274558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceKey resourceKey(v);
275558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    return fTextureCache->createAndLock(resourceKey, sb);
276558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
277558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
278558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comGrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
279558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                              int sampleCnt) {
280558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    uint32_t v[4];
281558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    gen_stencil_key_values(width, height, sampleCnt, v);
282558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceKey resourceKey(v);
283558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    GrResourceEntry* entry = fTextureCache->findAndLock(resourceKey,
284558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                            GrResourceCache::kSingle_LockType);
285558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    if (NULL != entry) {
286558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        GrStencilBuffer* sb = (GrStencilBuffer*) entry->resource();
287558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        return sb;
288558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    } else {
289558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        return NULL;
290558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    }
291558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
292558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
293558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comvoid GrContext::unlockStencilBuffer(GrResourceEntry* sbEntry) {
294bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(sbEntry->resource());
295558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com    fTextureCache->unlock(sbEntry);
29627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
29727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
29827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic void stretchImage(void* dst,
29927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstW,
30027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstH,
30127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         void* src,
30227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcW,
30327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcH,
30427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int bpp) {
30527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dx = (srcW << 16) / dstW;
30627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dy = (srcH << 16) / dstH;
30727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
30827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed y = dy >> 1;
30927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
31027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    int dstXLimit = dstW*bpp;
31127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    for (int j = 0; j < dstH; ++j) {
31227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrFixed x = dx >> 1;
31327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
31427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* dstRow = (uint8_t*)dst + j*dstW*bpp;
31527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < dstXLimit; i += bpp) {
31627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            memcpy((uint8_t*) dstRow + i,
31727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   (uint8_t*) srcRow + (x>>16)*bpp,
31827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   bpp);
31927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            x += dx;
32027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
32127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        y += dy;
32227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
32327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
32427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
3251fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.comGrContext::TextureCacheEntry GrContext::createAndLockTexture(
326b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com        const GrTextureParams* params,
3271fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        const GrTextureDesc& desc,
3281fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        void* srcData,
3291fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com        size_t rowBytes) {
330278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::createAndLockTexture");
33127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
33227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_DUMP_TEXTURE_UPLOAD
33327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
33427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
33527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
33650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    TextureCacheEntry entry;
33750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com
338b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, false);
339a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
340a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    if (GrTexture::NeedsResizing(resourceKey)) {
341a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        // The desired texture is NPOT and tiled but that isn't supported by
342a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        // the current hardware. Resize the texture to be a POT
343b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com        GrAssert(NULL != params);
344b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com        TextureCacheEntry clampEntry = this->findAndLockTexture(desc, NULL);
34527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
34650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        if (NULL == clampEntry.texture()) {
347b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com            clampEntry = this->createAndLockTexture(NULL, desc, srcData, rowBytes);
34850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            GrAssert(NULL != clampEntry.texture());
34950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            if (NULL == clampEntry.texture()) {
35050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                return entry;
35127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
35227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
353fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        GrTextureDesc rtDesc = desc;
354fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com        rtDesc.fFlags =  rtDesc.fFlags |
355fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com                         kRenderTarget_GrTextureFlagBit |
356fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com                         kNoStencil_GrTextureFlagBit;
3579962108c400dadcae913614e8a5ab781780981d8bsalomon@google.com        rtDesc.fWidth  = GrNextPow2(GrMax(desc.fWidth, 64));
3589962108c400dadcae913614e8a5ab781780981d8bsalomon@google.com        rtDesc.fHeight = GrNextPow2(GrMax(desc.fHeight, 64));
35927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
36027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
36127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
36227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != texture) {
363b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com            GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
3648f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = fGpu->drawState();
3658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->setRenderTarget(texture->asRenderTarget());
36682c7bd8f25682fcacfeea12ed899976504a767ffbsalomon@google.com
3676aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // if filtering is not desired then we want to ensure all
3686aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // texels in the resampled image are copies of texels from
3696aef1fb4ebf8b8b2ed352eb81e961565fbbd56cbbsalomon@google.com            // the original.
370b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com            drawState->sampler(0)->reset(SkShader::kClamp_TileMode,
371b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com                                         GrTexture::NeedsFiltering(resourceKey));
3728f4fdc9968123d508d4bb17b5d15946a990613d4bsalomon@google.com            drawState->createTextureEffect(0, clampEntry.texture());
37327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
37427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            static const GrVertexLayout layout =
37527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
37627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
37727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
37827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (arg.succeeded()) {
37927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                GrPoint* verts = (GrPoint*) arg.vertices();
38027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                verts[0].setIRectFan(0, 0,
38127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     texture->width(),
38227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     texture->height(),
38327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     2*sizeof(GrPoint));
38427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
38547059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com                fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType,
38627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                     0, 4);
38750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                entry.set(fTextureCache->createAndLock(resourceKey, texture));
38827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
3891da0746fa155cdca982ae8deb68cc64f540c92dfbsalomon@google.com            texture->releaseRenderTarget();
39027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        } else {
39127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // TODO: Our CPU stretch doesn't filter. But we create separate
39227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // stretched textures when the sampler state is either filtered or
39327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // not. Either implement filtered stretch blit on CPU or just create
39427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // one when FBO case fails.
39527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
396fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com            rtDesc.fFlags = kNone_GrTextureFlags;
39727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // no longer need to clamp at min RT size.
39827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            rtDesc.fWidth  = GrNextPow2(desc.fWidth);
39927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            rtDesc.fHeight = GrNextPow2(desc.fHeight);
40064c4fe4113424bcfab8b3e0c7049887fda5ab4ffbsalomon@google.com            int bpp = GrBytesPerPixel(desc.fConfig);
4013582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com            SkAutoSMalloc<128*128*4> stretchedPixels(bpp *
40227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     rtDesc.fWidth *
40327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     rtDesc.fHeight);
40427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
40527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         srcData, desc.fWidth, desc.fHeight, bpp);
40627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
40727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            size_t stretchedRowBytes = rtDesc.fWidth * bpp;
40827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
40927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrTexture* texture = fGpu->createTexture(rtDesc,
41027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     stretchedPixels.get(),
41127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                                     stretchedRowBytes);
41227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrAssert(NULL != texture);
41350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            entry.set(fTextureCache->createAndLock(resourceKey, texture));
41427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
41550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->unlock(clampEntry.cacheEntry());
41627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
41727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
41827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
41927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != texture) {
42050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com            entry.set(fTextureCache->createAndLock(resourceKey, texture));
42127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
42227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
42327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return entry;
42427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
42527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
42650398bf7f1953e640e5529616e710cf540799731bsalomon@google.comGrContext::TextureCacheEntry GrContext::lockScratchTexture(
42750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                                const GrTextureDesc& inDesc,
42850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com                                                ScratchTexMatch match) {
429b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    GrTextureDesc desc = inDesc;
43075b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fClientCacheID = kScratch_CacheID;
43175b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com
43250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    if (kExact_ScratchTexMatch != match) {
43350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        // bin by pow2 with a reasonable min
43450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        static const int MIN_SIZE = 256;
43550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fWidth  = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
43650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
43750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    }
438b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
43950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrResourceEntry* entry;
440b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origWidth = desc.fWidth;
441b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origHeight = desc.fHeight;
442b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    bool doubledW = false;
443b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    bool doubledH = false;
444b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
445b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    do {
44675b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL, desc, true);
447558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com        entry = fTextureCache->findAndLock(key,
448558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                           GrResourceCache::kNested_LockType);
449b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        // if we miss, relax the fit of the flags...
450b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        // then try doubling width... then height.
45150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        if (NULL != entry || kExact_ScratchTexMatch == match) {
452b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
453b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
454b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        if (!(desc.fFlags & kRenderTarget_GrTextureFlagBit)) {
455b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = desc.fFlags | kRenderTarget_GrTextureFlagBit;
456b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (desc.fFlags & kNoStencil_GrTextureFlagBit) {
457b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit;
458b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (!doubledW) {
459b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = inDesc.fFlags;
460b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fWidth *= 2;
461b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            doubledW = true;
462b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else if (!doubledH) {
463b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = inDesc.fFlags;
464b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fWidth = origWidth;
465b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fHeight *= 2;
466b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            doubledH = true;
467b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else {
468b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
469b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
470b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
471b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    } while (true);
472b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
473b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    if (NULL == entry) {
474b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fFlags = inDesc.fFlags;
475b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fWidth = origWidth;
476b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fHeight = origHeight;
477b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
478b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        if (NULL != texture) {
47975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com            GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL,
480a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                                                      texture->desc(),
481a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                                                      true);
482b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            entry = fTextureCache->createAndLock(key, texture);
483b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
484b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
485b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
486b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // If the caller gives us the same desc/sampler twice we don't want
487b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // to return the same texture the second time (unless it was previously
488b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    // released). So we detach the entry from the cache and reattach at release.
489b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    if (NULL != entry) {
490b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        fTextureCache->detach(entry);
491b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
49250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    return TextureCacheEntry(entry);
493b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com}
494b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
49515c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.comvoid GrContext::addExistingTextureToCache(GrTexture* texture) {
49615c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
49715c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    if (NULL == texture) {
49815c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com        return;
49915c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    }
50015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
50115c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL,
50215c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com                                              texture->desc(),
50315c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com                                              true);
50415c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    fTextureCache->attach(key, texture);
50515c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com}
50615c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
50750398bf7f1953e640e5529616e710cf540799731bsalomon@google.comvoid GrContext::unlockTexture(TextureCacheEntry entry) {
508bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(entry.texture());
50950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // If this is a scratch texture we detached it from the cache
51050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // while it was locked (to avoid two callers simultaneously getting
51150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // the same texture).
512a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    if (GrTexture::IsScratchTexture(entry.cacheEntry()->key())) {
51350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->reattachAndUnlock(entry.cacheEntry());
514fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    } else {
51550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        fTextureCache->unlock(entry.cacheEntry());
516fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
51727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
51827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
51915c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.comvoid GrContext::freeEntry(TextureCacheEntry entry) {
52015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    ASSERT_OWNED_RESOURCE(entry.texture());
52115c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
52215c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    fTextureCache->freeEntry(entry.cacheEntry());
52315c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com}
52415c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
52575b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.comGrTexture* GrContext::createUncachedTexture(const GrTextureDesc& descIn,
52627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            void* srcData,
52727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            size_t rowBytes) {
52875b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc descCopy = descIn;
52975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    descCopy.fClientCacheID = kUncached_CacheID;
53075b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    return fGpu->createTexture(descCopy, srcData, rowBytes);
53127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
53227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
53307fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comvoid GrContext::getTextureCacheLimits(int* maxTextures,
53407fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com                                      size_t* maxTextureBytes) const {
53507fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com    fTextureCache->getLimits(maxTextures, maxTextureBytes);
53627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
53727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
53807fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comvoid GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
53907fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com    fTextureCache->setLimits(maxTextures, maxTextureBytes);
54027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
54127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
542919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxTextureSize() const {
54318c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    return fGpu->getCaps().fMaxTextureSize;
544919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com}
545919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
546919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxRenderTargetSize() const {
54718c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    return fGpu->getCaps().fMaxRenderTargetSize;
54827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
54927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
55027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com///////////////////////////////////////////////////////////////////////////////
55127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
552e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrTexture* GrContext::createPlatformTexture(const GrPlatformTextureDesc& desc) {
553e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com    return fGpu->createPlatformTexture(desc);
554e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
555e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
556e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrRenderTarget* GrContext::createPlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) {
557e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com    return fGpu->createPlatformRenderTarget(desc);
558e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
559e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
5605877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
5615877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com
562b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.combool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params,
5631f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com                                          int width, int height) const {
56418c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    const GrDrawTarget::Caps& caps = fGpu->getCaps();
56518c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com    if (!caps.f8BitPaletteSupport) {
56627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return false;
56727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
56827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
56927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
57027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
57127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (!isPow2) {
572b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com        bool tiled = NULL != params && params->isTiled();
57318c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com        if (tiled && !caps.fNPOTTextureTileSupport) {
57427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return false;
57527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
57627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
57727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return true;
57827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
57927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
58027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
58127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
582beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.comconst GrClipData* GrContext::getClip() const {
583beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.com    return fGpu->getClip();
584beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.com}
58505ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com
586beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.comvoid GrContext::setClip(const GrClipData* clipData) {
587beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.com    fGpu->setClip(clipData);
58810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->enableState(GrDrawState::kClip_StateBit);
58927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
59027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
59127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
59227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
593c82a8b7aa4ec19fba508c394920a9e88d3e5bd12robertphillips@google.comvoid GrContext::clear(const GrIRect* rect,
594c82a8b7aa4ec19fba508c394920a9e88d3e5bd12robertphillips@google.com                      const GrColor color,
595c82a8b7aa4ec19fba508c394920a9e88d3e5bd12robertphillips@google.com                      GrRenderTarget* target) {
596398109cc3e56b8122ad21c4d43a74a83be5b42a8bsalomon@google.com    this->flush();
597c82a8b7aa4ec19fba508c394920a9e88d3e5bd12robertphillips@google.com    fGpu->clear(rect, color, target);
59827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
59927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
60027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawPaint(const GrPaint& paint) {
60127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // set rect to be big enough to fill the space, but not super-huge, so we
60227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // don't overflow fixed-point implementations
603d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    GrRect r;
604d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    r.setLTRB(0, 0,
605d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com              GrIntToScalar(getRenderTarget()->width()),
606d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com              GrIntToScalar(getRenderTarget()->height()));
60727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix inverse;
6088c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    SkTLazy<GrPaint> tmpPaint;
6098c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    const GrPaint* p = &paint;
610fea85ac3e31842f80493e2df8a93a28f21cd815frobertphillips@google.com    AutoMatrix am;
6118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6124f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // We attempt to map r by the inverse matrix and draw that. mapRect will
6134f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // map the four corners and bound them with a new rect. This will not
6144f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // produce a correct result for some perspective matrices.
6158c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    if (!this->getMatrix().hasPerspective()) {
61610e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        if (!fDrawState->getViewInverse(&inverse)) {
617e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            GrPrintf("Could not invert matrix\n");
6188c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            return;
6198c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
62027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        inverse.mapRect(&r);
62127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
622e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        if (paint.hasTextureOrMask()) {
6238c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.set(paint);
6248c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            p = tmpPaint.get();
625e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            if (!tmpPaint.get()->preConcatSamplerMatricesWithInverse(fDrawState->getViewMatrix())) {
626e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                GrPrintf("Could not invert matrix\n");
627e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            }
6288c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
6294f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com        am.set(this, GrMatrix::I());
63027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
6314f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // by definition this fills the entire clip, no need for AA
6324f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    if (paint.fAntiAlias) {
6338c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        if (!tmpPaint.isValid()) {
6348c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            tmpPaint.set(paint);
6358c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            p = tmpPaint.get();
6368c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
6378c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        GrAssert(p == tmpPaint.get());
6388c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        tmpPaint.get()->fAntiAlias = false;
6394f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    }
6404f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    this->drawRect(*p, r);
64127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
64227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
643205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
644205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
645d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.comnamespace {
646d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.cominline bool disable_coverage_aa_for_blend(GrDrawTarget* target) {
647d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage();
648d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com}
649d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com}
650d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
65106afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
65206afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com
65327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com/*  create a triangle strip that strokes the specified triangle. There are 8
65427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com unique vertices, but we repreat the last 2 to close up. Alternatively we
65527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com could use an indices array, and then only send 8 verts, but not sure that
65627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com would be faster.
65727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com */
658205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
65927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               GrScalar width) {
66027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    const GrScalar rad = GrScalarHalf(width);
661205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    rect.sort();
66227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
66327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[0].set(rect.fLeft + rad, rect.fTop + rad);
66427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[1].set(rect.fLeft - rad, rect.fTop - rad);
66527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[2].set(rect.fRight - rad, rect.fTop + rad);
66627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[3].set(rect.fRight + rad, rect.fTop - rad);
66727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[4].set(rect.fRight - rad, rect.fBottom - rad);
66827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[5].set(rect.fRight + rad, rect.fBottom + rad);
66927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
67027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
67127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[8] = verts[0];
67227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[9] = verts[1];
67327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
67427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
67520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com/**
67620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com * Returns true if the rects edges are integer-aligned.
67720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com */
67820efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.comstatic bool isIRect(const GrRect& r) {
67920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com    return GrScalarIsInt(r.fLeft) && GrScalarIsInt(r.fTop) &&
68020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com           GrScalarIsInt(r.fRight) && GrScalarIsInt(r.fBottom);
68120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com}
68220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com
683205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic bool apply_aa_to_rect(GrDrawTarget* target,
684205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             const GrRect& rect,
685205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             GrScalar width,
686205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             const GrMatrix* matrix,
687205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                             GrMatrix* combinedMatrix,
688a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             GrRect* devRect,
689a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             bool* useVertexCoverage) {
6902eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // we use a simple coverage ramp to do aa on axis-aligned rects
6912eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // we check if the rect will be axis-aligned, and the rect won't land on
6922eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // integer coords.
693d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
694a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // we are keeping around the "tweak the alpha" trick because
695a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // it is our only hope for the fixed-pipe implementation.
696a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // In a shader implementation we can give a separate coverage input
697289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    // TODO: remove this ugliness when we drop the fixed-pipe impl
698a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    *useVertexCoverage = false;
699d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (!target->canTweakAlphaForCoverage()) {
7002eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com        if (disable_coverage_aa_for_blend(target)) {
7011983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
7022eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            //GrPrintf("Turning off AA to correctly apply blend.\n");
7031983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
704a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            return false;
7052eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com        } else {
7062eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            *useVertexCoverage = true;
707a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        }
708205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
7098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    const GrDrawState& drawState = target->getDrawState();
7108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (drawState.getRenderTarget()->isMultisampled()) {
711205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
712205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
713205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
714471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com    if (0 == width && target->willUseHWAALines()) {
715205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
716205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
717205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
7188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (!drawState.getViewMatrix().preservesAxisAlignment()) {
719205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
720205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
721205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
722205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL != matrix &&
723205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        !matrix->preservesAxisAlignment()) {
724205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
725205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
726205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
7278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    *combinedMatrix = drawState.getViewMatrix();
728205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (NULL != matrix) {
729205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        combinedMatrix->preConcat(*matrix);
730205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        GrAssert(combinedMatrix->preservesAxisAlignment());
731205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
732205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
733205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    combinedMatrix->mapRect(devRect, rect);
734205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    devRect->sort();
735205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
736205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (width < 0) {
73720efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com        return !isIRect(*devRect);
738205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    } else {
739205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return true;
740205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
741205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
742205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
74327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRect(const GrPaint& paint,
74427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         const GrRect& rect,
74527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         GrScalar width,
74627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         const GrMatrix* matrix) {
747278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRect");
74827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
74927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
7507d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    GrDrawState::AutoStageDisable atr(fDrawState);
75127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
752205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrRect devRect = rect;
753205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    GrMatrix combinedMatrix;
754a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    bool useVertexCoverage;
755289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool needAA = paint.fAntiAlias &&
756289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                  !this->getRenderTarget()->isMultisampled();
757289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix,
758289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &combinedMatrix, &devRect,
759289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &useVertexCoverage);
760205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
761205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (doAA) {
762e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        GrDrawTarget::AutoDeviceCoordDraw adcd(target);
763e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        if (!adcd.succeeded()) {
764e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            return;
765e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        }
766205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        if (width >= 0) {
767205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            GrVec strokeSize;;
768205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            if (width > 0) {
769205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.set(width, width);
770cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com                combinedMatrix.mapVectors(&strokeSize, 1);
771205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.setAbs(strokeSize);
772205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            } else {
773205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                strokeSize.set(GR_Scalar1, GR_Scalar1);
774205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com            }
775f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com            fAARectRenderer->strokeAARect(this->getGpu(), target, devRect,
776f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com                                         strokeSize, useVertexCoverage);
777205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        } else {
778f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com            fAARectRenderer->fillAARect(this->getGpu(), target,
779f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com                                       devRect, useVertexCoverage);
780205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        }
781205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return;
782205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
783205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
78427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (width >= 0) {
78527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // TODO: consider making static vertex buffers for these cases.
78627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // Hairline could be done by just adding closing vertex to
78727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // unitSquareVertexBuffer()
78826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
78927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        static const int worstCaseVertCount = 10;
790e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        GrDrawTarget::AutoReleaseGeometry geo(target, 0, worstCaseVertCount, 0);
79127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
79227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.succeeded()) {
7936513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
79427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
79527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
79627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
79727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPrimitiveType primType;
79827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int vertCount;
79927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPoint* vertex = geo.positions();
80027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
80127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (width > 0) {
80227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 10;
80347059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com            primType = kTriangleStrip_GrPrimitiveType;
80427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            setStrokeRectStrip(vertex, rect, width);
80527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        } else {
80627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // hairline
80727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 5;
80847059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com            primType = kLineStrip_GrPrimitiveType;
80927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[0].set(rect.fLeft, rect.fTop);
81027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[1].set(rect.fRight, rect.fTop);
81127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[2].set(rect.fRight, rect.fBottom);
81227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[3].set(rect.fLeft, rect.fBottom);
81327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[4].set(rect.fLeft, rect.fTop);
81427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
81527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
8168f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState::AutoViewMatrixRestore avmr;
81727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != matrix) {
8188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
8198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            avmr.set(drawState);
8208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatViewMatrix(*matrix);
821e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            drawState->preConcatSamplerMatrices(*matrix);
82227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
82327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
82427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->drawNonIndexed(primType, 0, vertCount);
82527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
8268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#if GR_STATIC_RECT_VB
8276513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
8286513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            if (NULL == sqVB) {
8296513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com                GrPrintf("Failed to create static rect vb.\n");
8306513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com                return;
8316513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            }
832e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            target->setVertexSourceToBuffer(0, sqVB);
8338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
8348f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState::AutoViewMatrixRestore avmr(drawState);
83527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            GrMatrix m;
8368295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com            m.setAll(rect.width(),    0,             rect.fLeft,
837205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0,            rect.height(), rect.fTop,
838205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com                        0,            0,             GrMatrix::I()[8]);
83927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
84027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (NULL != matrix) {
84127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                m.postConcat(*matrix);
84227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
8438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            drawState->preConcatViewMatrix(m);
844e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            drawState->preConcatSamplerMatrices(m);
84526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
84647059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com            target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
8478f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#else
848e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            target->drawSimpleRect(rect, matrix);
8498f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#endif
85027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
85127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
85227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
85327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRectToRect(const GrPaint& paint,
85427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrRect& dstRect,
85527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrRect& srcRect,
85627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrMatrix* dstMatrix,
85727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                               const GrMatrix* srcMatrix) {
858278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRectToRect");
85927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
86026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    // srcRect refers to paint's first texture
861f13f58804659175925042a291304d483a4fd9278tomhudson@google.com    if (!paint.isTextureStageEnabled(0)) {
86227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        drawRect(paint, dstRect, -1, dstMatrix);
86327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
86427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
865de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com
86627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB);
86727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
86827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_STATIC_RECT_VB
86927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
8707d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    GrDrawState::AutoStageDisable atr(fDrawState);
8718f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = target->drawState();
8728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState::AutoViewMatrixRestore avmr(drawState);
87327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
87427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix m;
87527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
87627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    m.setAll(dstRect.width(), 0,                dstRect.fLeft,
87727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               dstRect.height(), dstRect.fTop,
87827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               0,                GrMatrix::I()[8]);
87927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != dstMatrix) {
88027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        m.postConcat(*dstMatrix);
88127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
8828f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->preConcatViewMatrix(m);
88327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
884e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    // we explicitly setup the correct coords for the first stage. The others
885e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    // must know about the view matrix change.
886e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    for (int s = 1; s < GrPaint::kTotalStages; ++s) {
887e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        if (drawState->isStageEnabled(s)) {
888e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            drawState->sampler(s)->preConcatMatrix(m);
889e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        }
89026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
89126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
89227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    m.setAll(srcRect.width(), 0,                srcRect.fLeft,
89327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               srcRect.height(), srcRect.fTop,
89427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com             0,               0,                GrMatrix::I()[8]);
89527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != srcMatrix) {
89627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        m.postConcat(*srcMatrix);
89727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
8988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->sampler(GrPaint::kFirstTextureStage)->preConcatMatrix(m);
89927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
9006513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
9016513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    if (NULL == sqVB) {
9026513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to create static rect vb.\n");
9036513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        return;
9046513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    }
905e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    target->setVertexSourceToBuffer(0, sqVB);
90647059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com    target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
90727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
90827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
90927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target;
910de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com#if BATCH_RECT_TO_RECT
91127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = this->prepareToDraw(paint, kBuffered_DrawCategory);
912de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com#else
91327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
91427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
9157d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    GrDrawState::AutoStageDisable atr(fDrawState);
91627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
9179381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
9189381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    const GrMatrix* srcMatrices[GrDrawState::kNumStages] = {NULL};
91927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    srcRects[0] = &srcRect;
92027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    srcMatrices[0] = srcMatrix;
92127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
922e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    target->drawRect(dstRect, dstMatrix, srcRects, srcMatrices);
92327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
92427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
92527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
92627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawVertices(const GrPaint& paint,
92727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             GrPrimitiveType primitiveType,
92827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int vertexCount,
92927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint positions[],
93027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint texCoords[],
93127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrColor colors[],
93227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const uint16_t indices[],
93327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int indexCount) {
934278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawVertices");
93527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
93627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo;
93727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
93827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
9397d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    GrDrawState::AutoStageDisable atr(fDrawState);
94027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
941e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    GrVertexLayout layout = 0;
942e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    if (NULL != texCoords) {
943e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0, 0);
944e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    }
94527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL != colors) {
94627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        layout |= GrDrawTarget::kColor_VertexLayoutBit;
94727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
94826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    int vertexSize = GrDrawTarget::VertexSize(layout);
94927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
95027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (sizeof(GrPoint) != vertexSize) {
95127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.set(target, layout, vertexCount, 0)) {
9526513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
95327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
95427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
9559381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        int texOffsets[GrDrawState::kMaxTexCoords];
95627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int colorOffset;
95726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
95826c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com                                                texOffsets,
959aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com                                                &colorOffset,
960a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                                NULL,
961a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                                                NULL);
96227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* curVertex = geo.vertices();
96327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
96427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < vertexCount; ++i) {
96527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            *((GrPoint*)curVertex) = positions[i];
96627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
96727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (texOffsets[0] > 0) {
96827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
96927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
97027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            if (colorOffset > 0) {
97127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
97227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
97326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            curVertex = (void*)((intptr_t)curVertex + vertexSize);
97427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
97527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
97627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->setVertexSourceToArray(layout, positions, vertexCount);
97727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
97827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
979919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // we don't currently apply offscreen AA to this path. Need improved
980919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // management of GrDrawTarget's geometry to avoid copying points per-tile.
981a47a48dca5045d71cbc5de343404045209a13e15bsalomon@google.com
9828295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    if (NULL != indices) {
983919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        target->setIndexSourceToArray(indices, indexCount);
9848295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
98527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
9868295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawNonIndexed(primitiveType, 0, vertexCount);
9878295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
98827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
98927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
99006afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
991150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.comnamespace {
992150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com
99393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.comstruct CircleVertex {
99493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrPoint fPos;
99593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrPoint fCenter;
99693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar fOuterRadius;
99793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar fInnerRadius;
99893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com};
99993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
100093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com/* Returns true if will map a circle to another circle. This can be true
100193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com * if the matrix only includes square-scale, rotation, translation.
100293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com */
100393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.cominline bool isSimilarityTransformation(const SkMatrix& matrix,
100493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                                       SkScalar tol = SK_ScalarNearlyZero) {
100593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (matrix.isIdentity() || matrix.getType() == SkMatrix::kTranslate_Mask) {
100693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return true;
100793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
100893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (matrix.hasPerspective()) {
100993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return false;
101093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
101193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
101293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar mx = matrix.get(SkMatrix::kMScaleX);
101393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar sx = matrix.get(SkMatrix::kMSkewX);
101493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar my = matrix.get(SkMatrix::kMScaleY);
101593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar sy = matrix.get(SkMatrix::kMSkewY);
101693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
101793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (mx == 0 && sx == 0 && my == 0 && sy == 0) {
101893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return false;
101993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
102093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
102193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    // it has scales or skews, but it could also be rotation, check it out.
102293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkVector vec[2];
102393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    vec[0].set(mx, sx);
102493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    vec[1].set(sy, my);
102593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
102693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    return SkScalarNearlyZero(vec[0].dot(vec[1]), SkScalarSquare(tol)) &&
102793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com           SkScalarNearlyEqual(vec[0].lengthSqd(), vec[1].lengthSqd(),
102893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                SkScalarSquare(tol));
102993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com}
103093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
103193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com}
103293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
103393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com// TODO: strokeWidth can't be larger than zero right now.
103493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com// It will be fixed when drawPath() can handle strokes.
103593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.comvoid GrContext::drawOval(const GrPaint& paint,
103693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                         const GrRect& rect,
103793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                         SkScalar strokeWidth) {
103893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    DrawCategory category = (DEFER_PATHS) ? kBuffered_DrawCategory :
103993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                                            kUnbuffered_DrawCategory;
104093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, category);
10417d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    GrDrawState::AutoStageDisable atr(fDrawState);
104293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrDrawState* drawState = target->drawState();
104393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrMatrix vm = drawState->getViewMatrix();
104493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
104593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (!isSimilarityTransformation(vm) ||
104693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        !paint.fAntiAlias ||
104793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        rect.height() != rect.width()) {
104893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        SkPath path;
104993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        path.addOval(rect);
105093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        GrPathFill fill = (strokeWidth == 0) ?
105147059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com                            kHairLine_GrPathFill : kWinding_GrPathFill;
105293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        this->internalDrawPath(paint, path, fill, NULL);
105393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return;
105493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
105593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
105693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    const GrRenderTarget* rt = drawState->getRenderTarget();
105793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (NULL == rt) {
105893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return;
105993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
106093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1061e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    GrDrawTarget::AutoDeviceCoordDraw adcd(target);
1062e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    if (!adcd.succeeded()) {
1063e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        return;
1064e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    }
106593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1066e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    GrVertexLayout layout = GrDrawTarget::kEdge_VertexLayoutBit;
106793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrAssert(sizeof(CircleVertex) == GrDrawTarget::VertexSize(layout));
106893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
106993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrPoint center = GrPoint::Make(rect.centerX(), rect.centerY());
107093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar radius = SkScalarHalf(rect.width());
107193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
107293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    vm.mapPoints(&center, 1);
107393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    radius = vm.mapRadius(radius);
107493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
107593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar outerRadius = radius;
107693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrScalar innerRadius = 0;
107793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkScalar halfWidth = 0;
107893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (strokeWidth == 0) {
107993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        halfWidth = SkScalarHalf(SK_Scalar1);
108093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
108193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        outerRadius += halfWidth;
108293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        innerRadius = SkMaxScalar(0, radius - halfWidth);
108393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
108493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
108593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(target, layout, 4, 0);
108693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (!geo.succeeded()) {
108793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
108893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return;
108993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
109093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
109193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
109293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1093a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    // The fragment shader will extend the radius out half a pixel
1094a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    // to antialias. Expand the drawn rect here so all the pixels
1095a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    // will be captured.
1096a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    SkScalar L = center.fX - outerRadius - SkFloatToScalar(0.5f);
1097a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    SkScalar R = center.fX + outerRadius + SkFloatToScalar(0.5f);
1098a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    SkScalar T = center.fY - outerRadius - SkFloatToScalar(0.5f);
1099a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com    SkScalar B = center.fY + outerRadius + SkFloatToScalar(0.5f);
110093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
110193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    verts[0].fPos = SkPoint::Make(L, T);
110293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    verts[1].fPos = SkPoint::Make(R, T);
110393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    verts[2].fPos = SkPoint::Make(L, B);
110493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    verts[3].fPos = SkPoint::Make(R, B);
110593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
110693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    for (int i = 0; i < 4; ++i) {
110793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        // this goes to fragment shader, it should be in y-points-up space.
110893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        verts[i].fCenter = SkPoint::Make(center.fX, rt->height() - center.fY);
110993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
111093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        verts[i].fOuterRadius = outerRadius;
111193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        verts[i].fInnerRadius = innerRadius;
111293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
111393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
111493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    drawState->setVertexEdgeType(GrDrawState::kCircle_EdgeType);
111547059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com    target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4);
1116150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
111727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
11188d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comvoid GrContext::drawPath(const GrPaint& paint, const SkPath& path,
111907f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.com                         GrPathFill fill, const GrPoint* translate) {
112027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1121fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (path.isEmpty()) {
1122fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       if (GrIsFillInverted(fill)) {
1123fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com           this->drawPaint(paint);
1124fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       }
1125fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       return;
1126fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
1127fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
112893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkRect ovalRect;
112993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    if (!GrIsFillInverted(fill) && path.isOval(&ovalRect)) {
113093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        if (translate) {
113193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com            ovalRect.offset(*translate);
113293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        }
113347059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        SkScalar width = (fill == kHairLine_GrPathFill) ? 0 : -SK_Scalar1;
113493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        this->drawOval(paint, ovalRect, width);
113593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        return;
113693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
113793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
113893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    internalDrawPath(paint, path, fill, translate);
113993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com}
114093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
11418d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comvoid GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path,
114293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com                                 GrPathFill fill, const GrPoint* translate) {
114393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1144fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // Note that below we may sw-rasterize the path into a scratch texture.
1145fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // Scratch textures can be recycled after they are returned to the texture
1146fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // cache. This presents a potential hazard for buffered drawing. However,
1147fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // the writePixels that uploads to the scratch will perform a flush so we're
1148fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    // OK.
1149fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    DrawCategory category = (DEFER_PATHS) ? kBuffered_DrawCategory :
1150fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com                                            kUnbuffered_DrawCategory;
1151fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    GrDrawTarget* target = this->prepareToDraw(paint, category);
11527d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    GrDrawState::AutoStageDisable atr(fDrawState);
1153d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
1154289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    bool prAA = paint.fAntiAlias && !this->getRenderTarget()->isMultisampled();
1155289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
1156d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // An Assumption here is that path renderer would use some form of tweaking
1157d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // the src color (either the input alpha or in the frag shader) to implement
1158d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // aa. If we have some future driver-mojo path AA that can do the right
1159d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // thing WRT to the blend then we'll need some query on the PR.
1160d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    if (disable_coverage_aa_for_blend(target)) {
11611983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
1162979432ba2621b617f5e85a9ff48c6b6cd1504a0dbsalomon@google.com        //GrPrintf("Turning off AA to correctly apply blend.\n");
11631983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
1164289533ada623f2238a83771eec977f204f75994fbsalomon@google.com        prAA = false;
1165d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    }
1166289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
116772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrPathRenderer* pr = this->getPathRenderer(path, fill, target, prAA, true);
11683008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == pr) {
11691983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG
11703008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        GrPrintf("Unable to find path renderer compatible with path.\n");
11711983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
11723008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        return;
11733008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
11743008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
1175e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    pr->drawPath(path, fill, translate, target, prAA);
117627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
11778295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
117827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
117927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1180a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.comvoid GrContext::flush(int flagsBitfield) {
1181a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kDiscard_FlushBit & flagsBitfield) {
1182a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com        fDrawBuffer->reset();
1183a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    } else {
1184c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        this->flushDrawBuffer();
1185a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    }
1186a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) {
118727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fGpu->forceRenderTargetFlush();
118827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
118927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
119027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
119127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::flushDrawBuffer() {
119253a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    if (fDrawBuffer) {
119358b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // With addition of the AA clip path, flushing the draw buffer can
119458b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // result in the generation of an AA clip mask. During this
119558b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // process the SW path renderer may be invoked which recusively
119658b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // calls this method (via internalWriteTexturePixels) creating
119758b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        // infinite recursion
119858b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        GrInOrderDrawBuffer* temp = fDrawBuffer;
119958b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        fDrawBuffer = NULL;
120058b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com
120158b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        temp->flushTo(fGpu);
120258b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com
120358b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com        fDrawBuffer = temp;
120453a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    }
120527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
120627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
12076f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.comvoid GrContext::internalWriteTexturePixels(GrTexture* texture,
12086f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           int left, int top,
12096f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           int width, int height,
12106f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           GrPixelConfig config,
12116f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           const void* buffer,
12126f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           size_t rowBytes,
12136f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                           uint32_t flags) {
12146f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeTexturePixels");
1215bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1216bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
12176f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
12186f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        this->flush();
12196f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
12206f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    // TODO: use scratch texture to perform conversion
12216f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (GrPixelConfigIsUnpremultiplied(texture->config()) !=
12226f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config)) {
12236f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        return;
12246f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
12256f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
12266f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    fGpu->writeTexturePixels(texture, left, top, width, height,
12276f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                             config, buffer, rowBytes);
12286f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com}
12296f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
12306f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.combool GrContext::internalReadTexturePixels(GrTexture* texture,
12316f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          int left, int top,
12326f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          int width, int height,
12336f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          GrPixelConfig config,
12346f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          void* buffer,
12356f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          size_t rowBytes,
12366f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                          uint32_t flags) {
1237278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readTexturePixels");
1238bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1239669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1240a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // TODO: code read pixels for textures that aren't also rendertargets
1241669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    GrRenderTarget* target = texture->asRenderTarget();
1242669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    if (NULL != target) {
12436f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        return this->internalReadRenderTargetPixels(target,
12446f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    left, top, width, height,
12456f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    config, buffer, rowBytes,
12466f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                    flags);
1247669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    } else {
1248669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com        return false;
1249669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    }
1250669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com}
1251669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1252a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com#include "SkConfig8888.h"
1253a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
1254a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.comnamespace {
1255a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com/**
1256a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * Converts a GrPixelConfig to a SkCanvas::Config8888. Only byte-per-channel
1257a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * formats are representable as Config8888 and so the function returns false
1258a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * if the GrPixelConfig has no equivalent Config8888.
1259a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com */
1260a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.combool grconfig_to_config8888(GrPixelConfig config,
1261a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                            SkCanvas::Config8888* config8888) {
1262a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    switch (config) {
1263a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kRGBA_8888_PM_GrPixelConfig:
1264a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kRGBA_Premul_Config8888;
1265a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1266a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kRGBA_8888_UPM_GrPixelConfig:
1267a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
1268a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1269a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kBGRA_8888_PM_GrPixelConfig:
1270a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kBGRA_Premul_Config8888;
1271a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1272a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        case kBGRA_8888_UPM_GrPixelConfig:
1273a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            *config8888 = SkCanvas::kBGRA_Unpremul_Config8888;
1274a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1275a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        default:
1276a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return false;
1277a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1278a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
1279a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
1280a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
12816f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.combool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target,
12826f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               int left, int top,
12836f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               int width, int height,
12846f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               GrPixelConfig config,
12856f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               void* buffer,
12866f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               size_t rowBytes,
12876f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                               uint32_t flags) {
1288278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
1289bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
1290bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
1291669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    if (NULL == target) {
129210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        target = fDrawState->getRenderTarget();
1293c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (NULL == target) {
1294c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            return false;
1295c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1296c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1297669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
12986f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
12996f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        this->flush();
13006f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
1301c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1302a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    if (!GrPixelConfigIsUnpremultiplied(target->config()) &&
1303a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config) &&
1304a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        !fGpu->canPreserveReadWriteUnpremulPixels()) {
1305a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkCanvas::Config8888 srcConfig8888, dstConfig8888;
1306a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        if (!grconfig_to_config8888(target->config(), &srcConfig8888) ||
1307a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            !grconfig_to_config8888(config, &dstConfig8888)) {
1308a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return false;
1309a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        }
1310a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // do read back using target's own config
1311a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        this->internalReadRenderTargetPixels(target,
1312a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             left, top,
1313a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             width, height,
1314a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             target->config(),
1315a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             buffer, rowBytes,
1316a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             kDontFlush_PixelOpsFlag);
1317a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // sw convert the pixels to unpremul config
1318a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        uint32_t* pixels = reinterpret_cast<uint32_t*>(buffer);
1319a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkConvertConfig8888Pixels(pixels, rowBytes, dstConfig8888,
1320a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  pixels, rowBytes, srcConfig8888,
1321a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  width, height);
1322a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        return true;
1323a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1324a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
1325c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    GrTexture* src = target->asTexture();
13260a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    bool swapRAndB = NULL != src &&
13270a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                     fGpu->preferredReadPixelsConfig(config) ==
13280a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                     GrPixelConfigSwapRAndB(config);
1329c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1330c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    bool flipY = NULL != src &&
1331c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                 fGpu->readPixelsWillPayForYFlip(target, left, top,
1332c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 width, height, config,
1333c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 rowBytes);
13340a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    bool alphaConversion = (!GrPixelConfigIsUnpremultiplied(target->config()) &&
13350a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com                             GrPixelConfigIsUnpremultiplied(config));
1336c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
13370a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    if (NULL == src && alphaConversion) {
13380a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // we should fallback to cpu conversion here. This could happen when
13390a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // we were given an external render target by the client that is not
13400a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        // also a texture (e.g. FBO 0 in GL)
13410a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        return false;
13420a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    }
13430a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    // we draw to a scratch texture if any of these conversion are applied
1344c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com    GrAutoScratchTexture ast;
13450a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    if (flipY || swapRAndB || alphaConversion) {
13460a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        GrAssert(NULL != src);
13470a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        if (swapRAndB) {
13480a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com            config = GrPixelConfigSwapRAndB(config);
13490a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com            GrAssert(kUnknown_GrPixelConfig != config);
1350c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1351c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        // Make the scratch a render target because we don't have a robust
1352c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        // readTexturePixels as of yet (it calls this function).
135375b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        GrTextureDesc desc;
135475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fFlags = kRenderTarget_GrTextureFlagBit;
135575b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fWidth = width;
135675b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fHeight = height;
135775b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fConfig = config;
1358c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com
135956d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // When a full readback is faster than a partial we could always make
136056d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // the scratch exactly match the passed rect. However, if we see many
136156d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // different size rectangles we will trash our texture cache and pay the
136256d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // cost of creating and destroying many textures. So, we only request
136356d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        // an exact match when the caller is reading an entire RT.
136456d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ScratchTexMatch match = kApprox_ScratchTexMatch;
136556d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        if (0 == left &&
136656d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            0 == top &&
136756d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->width() == width &&
136856d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->height() == height &&
136956d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            fGpu->fullReadPixelsIsFasterThanPartial()) {
137056d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            match = kExact_ScratchTexMatch;
137156d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        }
137256d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ast.set(this, desc, match);
1373c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrTexture* texture = ast.texture();
1374c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (!texture) {
1375c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            return false;
1376c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1377c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        target = texture->asRenderTarget();
1378c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrAssert(NULL != target);
1379c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1380873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com        GrDrawTarget::AutoStateRestore asr(fGpu,
1381873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com                                           GrDrawTarget::kReset_ASRInit);
13828f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState* drawState = fGpu->drawState();
13838f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        drawState->setRenderTarget(target);
1384c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1385c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrMatrix matrix;
1386c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (flipY) {
1387c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.setTranslate(SK_Scalar1 * left,
1388c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                SK_Scalar1 * (top + height));
1389c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.set(GrMatrix::kMScaleY, -GR_Scalar1);
1390c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        } else {
1391c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            matrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
1392c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1393c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        matrix.postIDiv(src->width(), src->height());
13941e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com        drawState->sampler(0)->reset(matrix);
13951e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com        drawState->sampler(0)->setRAndBSwap(swapRAndB);
13961e8f016305805d4d8cad74aba3a21b78486f9d6ftomhudson@google.com        drawState->createTextureEffect(0, src);
1397c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrRect rect;
1398c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        rect.setXYWH(0, 0, SK_Scalar1 * width, SK_Scalar1 * height);
1399e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        fGpu->drawSimpleRect(rect, NULL);
1400c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        left = 0;
1401c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        top = 0;
1402c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1403669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    return fGpu->readPixels(target,
1404c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                            left, top, width, height,
1405c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                            config, buffer, rowBytes, flipY);
140627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
140727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
140875f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.comvoid GrContext::resolveRenderTarget(GrRenderTarget* target) {
140975f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    GrAssert(target);
141075f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
141175f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // In the future we may track whether there are any pending draws to this
141275f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // target. We don't today so we always perform a flush. We don't promise
141375f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // this to our clients, though.
141475f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    this->flush();
141575f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    fGpu->resolveRenderTarget(target);
141675f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com}
141775f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com
1418ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.orgvoid GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst) {
1419ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    if (NULL == src || NULL == dst) {
1420ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        return;
1421ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
1422ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(src);
1423ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
14241ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // Writes pending to the source texture are not tracked, so a flush
14251ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // is required to ensure that the copy captures the most recent contents
14261ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // of the source texture. See similar behaviour in
14271ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // GrContext::resolveRenderTarget.
14281ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    this->flush();
14291ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com
1430873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
14318f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
14328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(dst);
1433ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    GrMatrix sampleM;
1434ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    sampleM.setIDiv(src->width(), src->height());
14351e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->reset(sampleM);
14361e8f016305805d4d8cad74aba3a21b78486f9d6ftomhudson@google.com    drawState->createTextureEffect(0, src);
14375db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com    SkRect rect = SkRect::MakeXYWH(0, 0,
14385db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                                   SK_Scalar1 * src->width(),
14395db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com                                   SK_Scalar1 * src->height());
1440e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    fGpu->drawSimpleRect(rect, NULL);
1441ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org}
1442ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
14436f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.comvoid GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target,
14446f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                int left, int top,
14456f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                int width, int height,
14466f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                GrPixelConfig config,
14476f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                const void* buffer,
14486f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                size_t rowBytes,
14496f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                                uint32_t flags) {
14506f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
1451bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
14526f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
14536f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (NULL == target) {
1454873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com        target = fDrawState->getRenderTarget();
14556f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        if (NULL == target) {
14566f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com            return;
14576f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        }
14586f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
145927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
146027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // TODO: when underlying api has a direct way to do this we should use it
146127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // (e.g. glDrawPixels on desktop GL).
146227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1463a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // If the RT is also a texture and we don't have to do PM/UPM conversion
1464a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // then take the texture path, which we expect to be at least as fast or
1465a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // faster since it doesn't use an intermediate texture as we do below.
1466a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1467a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#if !GR_MAC_BUILD
1468a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // At least some drivers on the Mac get confused when glTexImage2D is called
1469a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // on a texture attached to an FBO. The FBO still sees the old image. TODO:
1470a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    // determine what OS versions and/or HW is affected.
1471a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    if (NULL != target->asTexture() &&
1472a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        GrPixelConfigIsUnpremultiplied(target->config()) ==
1473a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config)) {
1474a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1475a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        this->internalWriteTexturePixels(target->asTexture(),
1476a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                                         left, top, width, height,
1477a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                                         config, buffer, rowBytes, flags);
1478a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        return;
1479a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1480a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#endif
1481a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    if (!GrPixelConfigIsUnpremultiplied(target->config()) &&
1482a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        GrPixelConfigIsUnpremultiplied(config) &&
1483a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        !fGpu->canPreserveReadWriteUnpremulPixels()) {
1484a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkCanvas::Config8888 srcConfig8888, dstConfig8888;
1485a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        if (!grconfig_to_config8888(config, &srcConfig8888) ||
1486a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            !grconfig_to_config8888(target->config(), &dstConfig8888)) {
1487a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return;
1488a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        }
1489a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // allocate a tmp buffer and sw convert the pixels to premul
1490a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(width * height);
1491a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        const uint32_t* src = reinterpret_cast<const uint32_t*>(buffer);
1492a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        SkConvertConfig8888Pixels(tmpPixels.get(), 4 * width, dstConfig8888,
1493a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  src, rowBytes, srcConfig8888,
1494a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                  width, height);
1495a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        // upload the already premul pixels
1496a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        this->internalWriteRenderTargetPixels(target,
1497a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             left, top,
1498a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             width, height,
1499a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             target->config(),
1500a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                                             tmpPixels, 4 * width, flags);
1501a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        return;
1502a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1503a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
1504a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    bool swapRAndB = fGpu->preferredReadPixelsConfig(config) ==
1505a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com                     GrPixelConfigSwapRAndB(config);
1506a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    if (swapRAndB) {
1507a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com        config = GrPixelConfigSwapRAndB(config);
1508a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1509a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
151075b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc desc;
151175b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fWidth = width;
151275b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fHeight = height;
151375b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fConfig = config;
151475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com
151550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrAutoScratchTexture ast(this, desc);
151650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrTexture* texture = ast.texture();
151727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL == texture) {
151827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
151927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
15206f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    this->internalWriteTexturePixels(texture, 0, 0, width, height,
15216f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                     config, buffer, rowBytes, flags);
152227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1523873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrDrawTarget::AutoStateRestore  asr(fGpu, GrDrawTarget::kReset_ASRInit);
15248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
152527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
152627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrMatrix matrix;
152727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
15288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setViewMatrix(matrix);
15298f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(target);
153027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
15315c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com    matrix.setIDiv(texture->width(), texture->height());
1532b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com    drawState->sampler(0)->reset(matrix);
15331e8f016305805d4d8cad74aba3a21b78486f9d6ftomhudson@google.com    drawState->createTextureEffect(0, texture);
15341e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com    drawState->sampler(0)->setRAndBSwap(swapRAndB);
153527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1536b213ed8b767b424cb076bfbab11e936d16526635tomhudson@google.com    static const GrVertexLayout layout = 0;
153727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    static const int VCOUNT = 4;
15386513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com    // TODO: Use GrGpu::drawRect here
153927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
154027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (!geo.succeeded()) {
15416513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com        GrPrintf("Failed to get space for vertices!\n");
154227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return;
154327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
154427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
154547059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com    fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, VCOUNT);
154627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
154727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
154827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
154910e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.comvoid GrContext::setPaint(const GrPaint& paint) {
1550cb325ceda16fab97fd3281785e6ae10fcb8dcf83tomhudson@google.com    GrAssert(fDrawState->stagesDisabled());
155126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
155226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kMaxTextures; ++i) {
155326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        int s = i + GrPaint::kFirstTextureStage;
1554bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com        ASSERT_OWNED_RESOURCE(paint.getTexture(i));
1555f13f58804659175925042a291304d483a4fd9278tomhudson@google.com        if (paint.isTextureStageEnabled(i)) {
1556f13f58804659175925042a291304d483a4fd9278tomhudson@google.com            fDrawState->setTexture(s, paint.getTexture(i));
155710e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com            *fDrawState->sampler(s) = paint.getTextureSampler(i);
1558f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        }
155926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
156026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
156110e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setFirstCoverageStage(GrPaint::kFirstMaskStage);
156226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
156326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    for (int i = 0; i < GrPaint::kMaxMasks; ++i) {
156426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com        int s = i + GrPaint::kFirstMaskStage;
1565bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com        ASSERT_OWNED_RESOURCE(paint.getMask(i));
1566f13f58804659175925042a291304d483a4fd9278tomhudson@google.com        if (paint.isMaskStageEnabled(i)) {
1567f13f58804659175925042a291304d483a4fd9278tomhudson@google.com            fDrawState->setTexture(s, paint.getMask(i));
156810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com            *fDrawState->sampler(s) = paint.getMaskSampler(i);
1569f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com        }
157026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com    }
157126936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com
157226936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com    // disable all stages not accessible via the paint
157326936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com    for (int s = GrPaint::kTotalStages; s < GrDrawState::kNumStages; ++s) {
1574676e66096c60615bac52f365111596de5c4ca8a6tomhudson@google.com        fDrawState->disableStage(s);
157526936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com    }
157626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
157710e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setColor(paint.fColor);
157827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
157927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (paint.fDither) {
158010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->enableState(GrDrawState::kDither_StateBit);
158127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
158210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->disableState(GrDrawState::kDither_StateBit);
158327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
158427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (paint.fAntiAlias) {
158510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->enableState(GrDrawState::kHWAntialias_StateBit);
158627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
158710e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->disableState(GrDrawState::kHWAntialias_StateBit);
158827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
158950bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    if (paint.fColorMatrixEnabled) {
159010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->enableState(GrDrawState::kColorMatrix_StateBit);
159110e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->setColorMatrix(paint.fColorMatrix);
159250bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    } else {
159310e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->disableState(GrDrawState::kColorMatrix_StateBit);
159450bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org    }
159510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
159610e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
159710e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setCoverage(paint.fCoverage);
15984b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#if GR_DEBUG_PARTIAL_COVERAGE_CHECK
1599e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    if ((paint.hasMask() || 0xff != paint.fCoverage) &&
160010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        !fGpu->canApplyCoverage()) {
1601d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com        GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
1602d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    }
160395cd7bdf2b4dee54739f0a375fe99a02f86178b0bsalomon@google.com#endif
160427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
160527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1606de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.comGrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
160727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                       DrawCategory category) {
160827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (category != fLastDrawCategory) {
1609fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com        this->flushDrawBuffer();
161027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        fLastDrawCategory = category;
161127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
161210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    this->setPaint(paint);
161327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrDrawTarget* target = fGpu;
161427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    switch (category) {
1615193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com        case kUnbuffered_DrawCategory:
1616193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            target = fGpu;
1617193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            break;
1618193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com        case kBuffered_DrawCategory:
1619193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            target = fDrawBuffer;
1620193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            fDrawBuffer->setClip(fGpu->getClip());
1621193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            break;
1622193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com        default:
1623193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            GrCrash("Unexpected DrawCategory.");
1624193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com            break;
162527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
162627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return target;
162727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
162827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
162972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com/*
163072176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * This method finds a path renderer that can draw the specified path on
163172176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * the provided target.
163272176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * Due to its expense, the software path renderer has split out so it can
163372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * can be individually allowed/disallowed via the "allowSW" boolean.
163472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com */
16358d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comGrPathRenderer* GrContext::getPathRenderer(const SkPath& path,
1636289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           GrPathFill fill,
1637c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com                                           const GrDrawTarget* target,
163872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                           bool antiAlias,
163972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                           bool allowSW) {
16403008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == fPathRendererChain) {
16413008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        fPathRendererChain =
1642c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com            SkNEW_ARGS(GrPathRendererChain,
1643c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                       (this, GrPathRendererChain::kNone_UsageFlag));
16443008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
164572176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
164672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(path, fill,
164772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                                             target,
164872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                                             antiAlias);
164972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
165072176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    if (NULL == pr && allowSW) {
165172176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        if (NULL == fSoftwarePathRenderer) {
1652c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com            fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this));
165372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        }
165472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
165572176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        pr = fSoftwarePathRenderer;
165672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    }
165772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
165872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    return pr;
16593008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com}
16603008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
166127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
166227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
166327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setRenderTarget(GrRenderTarget* target) {
1664bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
166510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    if (fDrawState->getRenderTarget() != target) {
1666fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com        this->flush(false);
166710e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com        fDrawState->setRenderTarget(target);
1668fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com    }
166927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
167027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
167127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrRenderTarget* GrContext::getRenderTarget() {
167210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    return fDrawState->getRenderTarget();
167327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
167427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
167527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrRenderTarget* GrContext::getRenderTarget() const {
167610e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    return fDrawState->getRenderTarget();
167727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
167827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
167999a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.combool GrContext::isConfigRenderable(GrPixelConfig config) const {
168099a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com    return fGpu->isConfigRenderable(config);
168199a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com}
168299a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com
168327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrMatrix& GrContext::getMatrix() const {
168410e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    return fDrawState->getViewMatrix();
168527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
168627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
168727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setMatrix(const GrMatrix& m) {
168810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->setViewMatrix(m);
168927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
169027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
169127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::concatMatrix(const GrMatrix& m) const {
169210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->preConcatViewMatrix(m);
169327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
169427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
169527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
169627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    intptr_t mask = 1 << shift;
169727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (pred) {
169827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        bits |= mask;
169927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
170027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        bits &= ~mask;
170127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
170227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return bits;
170327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
170427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1705583a1e38503ebd57ba9bd39a3fabe89bead8e76cbsalomon@google.comGrContext::GrContext(GrGpu* gpu) {
1706c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com    ++THREAD_INSTANCE_COUNT;
1707c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
170827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu = gpu;
170927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fGpu->ref();
1710669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    fGpu->setContext(this);
17118fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1712c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    fDrawState = SkNEW(GrDrawState);
171310e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fGpu->setDrawState(fDrawState);
171410e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com
17153008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    fPathRendererChain = NULL;
171672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    fSoftwarePathRenderer = NULL;
1717dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com
1718c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    fTextureCache = SkNEW_ARGS(GrResourceCache,
1719c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                               (MAX_TEXTURE_CACHE_COUNT,
1720c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                                MAX_TEXTURE_CACHE_BYTES));
1721c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    fFontCache = SkNEW_ARGS(GrFontCache, (fGpu));
172227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
172327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fLastDrawCategory = kUnbuffered_DrawCategory;
172427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
17258fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
17268fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
17278fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
17288fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1729c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    fAARectRenderer = SkNEW(GrAARectRenderer);
173010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com
17318fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->setupDrawBuffer();
17328fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
17338fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
17348fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::setupDrawBuffer() {
17358fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
17368fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBuffer);
17378fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBufferVBAllocPool);
17388fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    GrAssert(NULL == fDrawBufferIBAllocPool);
17398fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
174092edd316e5425f7f7fbecbae28483da2851248bbbsalomon@google.com#if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT || DEFER_PATHS
1741de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferVBAllocPool =
1742c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com        SkNEW_ARGS(GrVertexBufferAllocPool, (fGpu, false,
174327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                    DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
1744c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                                    DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS));
1745de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferIBAllocPool =
1746c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com        SkNEW_ARGS(GrIndexBufferAllocPool, (fGpu, false,
1747de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com                                   DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
1748c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                                   DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS));
174927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1750c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (fGpu,
1751471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com                                          fDrawBufferVBAllocPool,
1752c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                                          fDrawBufferIBAllocPool));
17533c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com#endif
17543c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com
17553c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com#if BATCH_RECT_TO_RECT
175627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
17573c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com#endif
17581015e034676a90d88544c396ff4dce3849186aa9bsalomon@google.com    if (fDrawBuffer) {
17591015e034676a90d88544c396ff4dce3849186aa9bsalomon@google.com        fDrawBuffer->setAutoFlushTarget(fGpu);
17601015e034676a90d88544c396ff4dce3849186aa9bsalomon@google.com        fDrawBuffer->setDrawState(fDrawState);
17611015e034676a90d88544c396ff4dce3849186aa9bsalomon@google.com    }
176227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
176327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
176427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
176527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if DEFER_TEXT_RENDERING
1766193395c7a391bc0046b7793d633487d510457aecbsalomon@google.com    return prepareToDraw(paint, kBuffered_DrawCategory);
176727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else
176810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    return prepareToDraw(paint, kUnbuffered_DrawCategory);
176927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif
177027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
177127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
177227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
177327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return fGpu->getQuadIndexBuffer();
177427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
1775dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com
17763b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgGrTexture* GrContext::gaussianBlur(GrTexture* srcTexture,
17771e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org                                   bool canClobberSrc,
17783b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                   const SkRect& rect,
17793b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                   float sigmaX, float sigmaY) {
1780ceb441476e1712861e87a9bb428f119349ef6bb5senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(srcTexture);
17813b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrRenderTarget* oldRenderTarget = this->getRenderTarget();
1782fea85ac3e31842f80493e2df8a93a28f21cd815frobertphillips@google.com    AutoMatrix avm(this, GrMatrix::I());
17833b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    SkIRect clearRect;
1784b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    int scaleFactorX, radiusX;
1785b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    int scaleFactorY, radiusY;
1786b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
1787b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);
17883b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
17893b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    SkRect srcRect(rect);
17903b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
17913b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    srcRect.roundOut();
17928637a365518a82901d313d61eecd83a0c5102fe9robertphillips@google.com    scale_rect(&srcRect, static_cast<float>(scaleFactorX),
17938637a365518a82901d313d61eecd83a0c5102fe9robertphillips@google.com                         static_cast<float>(scaleFactorY));
17943e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com
179556c79b10377e358b8092d9c6ab3e1aacf2cd60e5robertphillips@google.com    AutoClip acs(this, srcRect);
1796bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
179799a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com    GrAssert(kBGRA_8888_PM_GrPixelConfig == srcTexture->config() ||
179899a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com             kRGBA_8888_PM_GrPixelConfig == srcTexture->config() ||
179999a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com             kAlpha_8_GrPixelConfig == srcTexture->config());
180099a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com
180175b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc desc;
180275b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
180375b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fWidth = SkScalarFloorToInt(srcRect.width());
180475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fHeight = SkScalarFloorToInt(srcRect.height());
180575b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fConfig = srcTexture->config();
18061e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com
18071e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    GrAutoScratchTexture temp1, temp2;
18081e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    GrTexture* dstTexture = temp1.set(this, desc);
18091e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(this, desc);
18103b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18113b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrPaint paint;
18123b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    paint.reset();
1813b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com    paint.textureSampler(0)->textureParams()->setBilerp(true);
18143b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18153b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
18163b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(),
18173b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                                   srcTexture->height());
18183b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
18193b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkRect dstRect(srcRect);
18203b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
18213b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                            i < scaleFactorY ? 0.5f : 1.0f);
1822aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com        paint.textureSampler(0)->setCustomStage(SkNEW_ARGS(GrSingleTextureEffect,
1823aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com                                                           (srcTexture)))->unref();
18243b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->drawRectToRect(paint, dstRect, srcRect);
18253b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        srcRect = dstRect;
18261e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture = dstTexture;
18271e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        SkTSwap(dstTexture, tempTexture);
18283b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
18293b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18307a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com    SkIRect srcIRect;
18317a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com    srcRect.roundOut(&srcIRect);
18327a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com
18333b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (sigmaX > 0.0f) {
18343b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        if (scaleFactorX > 1) {
1835b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com            // Clear out a radius to the right of the srcRect to prevent the
18363b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            // X convolution from reading garbage.
18377a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com            clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
1838b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                                          radiusX, srcIRect.height());
18393b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            this->clear(&clearRect, 0x0);
18403b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        }
184105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
18423b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
1843b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        convolve_gaussian(fGpu, srcTexture, srcRect, sigmaX, radiusX,
1844b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                          Gr1DKernelEffect::kX_Direction);
18451e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture = dstTexture;
18461e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        SkTSwap(dstTexture, tempTexture);
18473b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
18483b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18493b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (sigmaY > 0.0f) {
18503b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        if (scaleFactorY > 1 || sigmaX > 0.0f) {
1851b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com            // Clear out a radius below the srcRect to prevent the Y
18523b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            // convolution from reading garbage.
18537a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com            clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
1854b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                                          srcIRect.width(), radiusY);
18553b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org            this->clear(&clearRect, 0x0);
18563b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        }
18573b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18583b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
1859b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        convolve_gaussian(fGpu, srcTexture, srcRect, sigmaY, radiusY,
1860b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                          Gr1DKernelEffect::kY_Direction);
18611e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture = dstTexture;
18621e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        SkTSwap(dstTexture, tempTexture);
18633b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
18643b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18653b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (scaleFactorX > 1 || scaleFactorY > 1) {
18663b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // Clear one pixel to the right and below, to accommodate bilinear
18673b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // upsampling.
18687a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com        clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
18697a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                                      srcIRect.width() + 1, 1);
18703b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->clear(&clearRect, 0x0);
18717a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com        clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
18727a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                                      1, srcIRect.height());
18733b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->clear(&clearRect, 0x0);
18743b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        // FIXME:  This should be mitchell, not bilinear.
1875b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com        paint.textureSampler(0)->textureParams()->setBilerp(true);
18763b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(),
18773b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                                   srcTexture->height());
18783b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->setRenderTarget(dstTexture->asRenderTarget());
1879aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com        paint.textureSampler(0)->setCustomStage(SkNEW_ARGS(GrSingleTextureEffect,
1880aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com                                                           (srcTexture)))->unref();
18813b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        SkRect dstRect(srcRect);
18827a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com        scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
18833b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->drawRectToRect(paint, dstRect, srcRect);
18843b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        srcRect = dstRect;
18851e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture = dstTexture;
18861e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        SkTSwap(dstTexture, tempTexture);
18873b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
18883b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setRenderTarget(oldRenderTarget);
18891e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    if (srcTexture == temp1.texture()) {
18901e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        return temp1.detach();
18911e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    } else if (srcTexture == temp2.texture()) {
18921e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        return temp2.detach();
18931e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    } else {
18941e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture->ref();
18951e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        return srcTexture;
18961e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    }
18973b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org}
18983b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org
18993b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgGrTexture* GrContext::applyMorphology(GrTexture* srcTexture,
19003b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                      const GrRect& rect,
1901b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                                      MorphologyType morphType,
19023b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org                                      SkISize radius) {
1903ceb441476e1712861e87a9bb428f119349ef6bb5senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(srcTexture);
19041e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    srcTexture->ref();
19053b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    GrRenderTarget* oldRenderTarget = this->getRenderTarget();
190656c79b10377e358b8092d9c6ab3e1aacf2cd60e5robertphillips@google.com
1907fea85ac3e31842f80493e2df8a93a28f21cd815frobertphillips@google.com    AutoMatrix avm(this, GrMatrix::I());
19083e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com
190956c79b10377e358b8092d9c6ab3e1aacf2cd60e5robertphillips@google.com    AutoClip acs(this, GrRect::MakeWH(SkIntToScalar(srcTexture->width()),
1910beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.com                                      SkIntToScalar(srcTexture->height())));
19111e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    GrTextureDesc desc;
19121e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
19131e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    desc.fWidth = SkScalarCeilToInt(rect.width());
19141e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    desc.fHeight = SkScalarCeilToInt(rect.height());
19151e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org    desc.fConfig = kRGBA_8888_PM_GrPixelConfig;
19163b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (radius.fWidth > 0) {
19171e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        GrAutoScratchTexture ast(this, desc);
19181e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        this->setRenderTarget(ast.texture()->asRenderTarget());
1919b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        apply_morphology(fGpu, srcTexture, rect, radius.fWidth, morphType,
1920b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                         Gr1DKernelEffect::kX_Direction);
19217a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com        SkIRect clearRect = SkIRect::MakeXYWH(
19227a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                    SkScalarFloorToInt(rect.fLeft),
19237a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                    SkScalarFloorToInt(rect.fBottom),
19247a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                    SkScalarFloorToInt(rect.width()),
19257a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com                    radius.fHeight);
19263b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org        this->clear(&clearRect, 0x0);
19271e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture->unref();
19281e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture = ast.detach();
19293b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
19303b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    if (radius.fHeight > 0) {
19311e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        GrAutoScratchTexture ast(this, desc);
19321e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        this->setRenderTarget(ast.texture()->asRenderTarget());
1933b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        apply_morphology(fGpu, srcTexture, rect, radius.fHeight, morphType,
1934b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com                         Gr1DKernelEffect::kY_Direction);
19351e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture->unref();
19361e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org        srcTexture = ast.detach();
19373b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    }
19383b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    this->setRenderTarget(oldRenderTarget);
19393b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org    return srcTexture;
1940027de5f922e8ad1acc5402829f716b8c513fdd8dsenorblanco@chromium.org}
1941c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1942c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
1943