GrContext.cpp revision d686ac77c2c485c4a3302eda9c1de597a6f8c568
180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrContext.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "effects/GrConvolutionEffect.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "effects/GrSingleTextureEffect.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "effects/GrConfigConversionEffect.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrBufferAllocPool.h"
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrGpu.h"
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrIndexBuffer.h"
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrInOrderDrawBuffer.h"
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrPathRenderer.h"
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrPathUtils.h"
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrResourceCache.h"
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrSoftwarePathRenderer.h"
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrStencilBuffer.h"
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrTextStrike.h"
26363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkStrokeRec.h"
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTLazy.h"
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTLS.h"
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTrace.h"
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(GrContext)
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(GrDrawState)
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// It can be useful to set this to kNo_BufferedDraw to test whether a bug is caused by using the
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// InOrderDrawBuffer, to compare performance of using/not using InOrderDrawBuffer, or to make
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// debugging easier.
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define DEFAULT_BUFFERING (GR_DISABLE_DRAW_BUFFERING ? kNo_BufferedDraw : kYes_BufferedDraw)
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define MAX_BLUR_SIGMA 4.0f
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// When we're using coverage AA but the blend is incompatible (given gpu
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// limitations) should we disable AA or draw wrong?
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define DISABLE_COVERAGE_AA_FOR_BLEND 1
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_DEBUG
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // change this to a 1 to see notifications when partial coverage fails
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic const size_t MAX_TEXTURE_CACHE_COUNT = 2048;
53363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic const size_t MAX_TEXTURE_CACHE_BYTES = GR_DEFAULT_TEXTURE_CACHE_MB_LIMIT * 1024 * 1024;
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 15;
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 1 << 11;
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 4;
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define ASSERT_OWNED_RESOURCE(R) GrAssert(!(R) || (R)->getContext() == this)
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerGrContext* GrContext::Create(GrBackend backend, GrBackendContext context) {
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrContext* ctx = NULL;
65363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    GrGpu* fGpu = GrGpu::Create(backend, context);
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != fGpu) {
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ctx = SkNEW_ARGS(GrContext, (fGpu));
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fGpu->unref();
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return ctx;
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid* CreateThreadInstanceCount() {
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkNEW_ARGS(int, (0));
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid DeleteThreadInstanceCount(void* v) {
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    delete reinterpret_cast<int*>(v);
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define THREAD_INSTANCE_COUNT                                               \
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    (*reinterpret_cast<int*>(SkTLS::Get(CreateThreadInstanceCount,          \
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        DeleteThreadInstanceCount)))
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint GrContext::GetThreadInstanceCount() {
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return THREAD_INSTANCE_COUNT;
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrContext::~GrContext() {
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < fCleanUpData.count(); ++i) {
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->flush();
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Since the gpu can hold scratch textures, give it a chance to let go
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // of them before freeing the texture cache
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->purgeResources();
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    delete fTextureCache;
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTextureCache = NULL;
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    delete fFontCache;
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    delete fDrawBuffer;
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    delete fDrawBufferVBAllocPool;
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    delete fDrawBufferIBAllocPool;
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fAARectRenderer->unref();
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->unref();
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrSafeUnref(fPathRendererChain);
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrSafeUnref(fSoftwarePathRenderer);
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawState->unref();
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    --THREAD_INSTANCE_COUNT;
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::contextLost() {
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    contextDestroyed();
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setupDrawBuffer();
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::contextDestroyed() {
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // abandon first to so destructors
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // don't try to free the resources in the API.
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->abandonResources();
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // a path renderer may be holding onto resources that
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // are now unusable
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrSafeSetNull(fPathRendererChain);
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrSafeSetNull(fSoftwarePathRenderer);
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    delete fDrawBuffer;
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawBuffer = NULL;
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    delete fDrawBufferVBAllocPool;
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawBufferVBAllocPool = NULL;
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    delete fDrawBufferIBAllocPool;
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawBufferIBAllocPool = NULL;
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fAARectRenderer->reset();
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTextureCache->purgeAllUnlocked();
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fFontCache->freeAll();
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->markContextDirty();
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::resetContext() {
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->markContextDirty();
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::freeGpuResources() {
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->flush();
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->purgeResources();
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fAARectRenderer->reset();
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTextureCache->purgeAllUnlocked();
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fFontCache->freeAll();
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // a path renderer may be holding onto resources
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrSafeSetNull(fPathRendererChain);
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrSafeSetNull(fSoftwarePathRenderer);
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t GrContext::getGpuTextureCacheBytes() const {
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru  return fTextureCache->getCachedResourceBytes();
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru////////////////////////////////////////////////////////////////////////////////
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid scale_rect(SkRect* rect, float xScale, float yScale) {
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    rect->fLeft = SkScalarMul(rect->fLeft, SkFloatToScalar(xScale));
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    rect->fTop = SkScalarMul(rect->fTop, SkFloatToScalar(yScale));
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    rect->fRight = SkScalarMul(rect->fRight, SkFloatToScalar(xScale));
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale));
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querufloat adjust_sigma(float sigma, int *scaleFactor, int *radius) {
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *scaleFactor = 1;
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (sigma > MAX_BLUR_SIGMA) {
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *scaleFactor *= 2;
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sigma *= 0.5f;
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *radius = static_cast<int>(ceilf(sigma * 3.0f));
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius);
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return sigma;
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid convolve_gaussian(GrDrawTarget* target,
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       GrTexture* texture,
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       const SkRect& rect,
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       float sigma,
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       int radius,
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       Gr1DKernelEffect::Direction direction) {
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrRenderTarget* rt = target->drawState()->getRenderTarget();
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kReset_ASRInit);
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawState* drawState = target->drawState();
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    drawState->setRenderTarget(rt);
203d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(texture,
204d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                                       direction,
205d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                                       radius,
206d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                                       sigma));
207d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    drawState->setEffect(0, conv);
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    target->drawSimpleRect(rect, NULL);
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
213d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger////////////////////////////////////////////////////////////////////////////////
214d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
215d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrTexture* GrContext::findAndRefTexture(const GrTextureDesc& desc,
216d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                        const GrCacheID& cacheID,
217d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                        const GrTextureParams* params) {
218d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrResource* resource = fTextureCache->find(resourceKey);
220d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkSafeRef(resource);
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return static_cast<GrTexture*>(resource);
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrContext::isTextureInCache(const GrTextureDesc& desc,
225d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                 const GrCacheID& cacheID,
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                 const GrTextureParams* params) const {
227d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fTextureCache->hasKey(resourceKey);
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::addStencilBuffer(GrStencilBuffer* sb) {
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ASSERT_OWNED_RESOURCE(sb);
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(sb->width(),
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                            sb->height(),
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                            sb->numSamples());
237363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fTextureCache->addResource(resourceKey, sb);
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                              int sampleCnt) {
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(width,
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                            height,
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                            sampleCnt);
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrResource* resource = fTextureCache->find(resourceKey);
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return static_cast<GrStencilBuffer*>(resource);
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void stretchImage(void* dst,
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         int dstW,
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         int dstH,
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         void* src,
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         int srcW,
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         int srcH,
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         int bpp) {
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrFixed dx = (srcW << 16) / dstW;
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrFixed dy = (srcH << 16) / dstH;
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrFixed y = dy >> 1;
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int dstXLimit = dstW*bpp;
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int j = 0; j < dstH; ++j) {
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrFixed x = dx >> 1;
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        void* dstRow = (uint8_t*)dst + j*dstW*bpp;
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = 0; i < dstXLimit; i += bpp) {
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            memcpy((uint8_t*) dstRow + i,
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                   (uint8_t*) srcRow + (x>>16)*bpp,
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                   bpp);
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            x += dx;
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        y += dy;
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// The desired texture is NPOT and tiled but that isn't supported by
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// the current hardware. Resize the texture to be a POT
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
279d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                           const GrCacheID& cacheID,
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                           void* srcData,
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                           size_t rowBytes,
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                           bool needsFiltering) {
283d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkAutoTUnref<GrTexture> clampedTexture(this->findAndRefTexture(desc, cacheID, NULL));
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == clampedTexture) {
285d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        clampedTexture.reset(this->createTexture(NULL, desc, cacheID, srcData, rowBytes));
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == clampedTexture) {
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return NULL;
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTextureDesc rtDesc = desc;
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    rtDesc.fFlags =  rtDesc.fFlags |
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                     kRenderTarget_GrTextureFlagBit |
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                     kNoStencil_GrTextureFlagBit;
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    rtDesc.fWidth  = GrNextPow2(GrMax(desc.fWidth, 64));
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    rtDesc.fHeight = GrNextPow2(GrMax(desc.fHeight, 64));
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != texture) {
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrDrawState* drawState = fGpu->drawState();
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        drawState->setRenderTarget(texture->asRenderTarget());
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // if filtering is not desired then we want to ensure all
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // texels in the resampled image are copies of texels from
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // the original.
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrTextureParams params(SkShader::kClamp_TileMode, needsFiltering);
310363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        drawState->createTextureEffect(0, clampedTexture, SkMatrix::I(), params);
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
312d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        static const GrVertexLayout layout = GrDrawState::StageTexCoordVertexLayoutBit(0,0);
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (arg.succeeded()) {
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrPoint* verts = (GrPoint*) arg.vertices();
317d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            verts[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 * sizeof(GrPoint));
318d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(GrPoint));
319d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        texture->releaseRenderTarget();
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // TODO: Our CPU stretch doesn't filter. But we create separate
324363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // stretched textures when the texture params is either filtered or
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // not. Either implement filtered stretch blit on CPU or just create
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // one when FBO case fails.
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rtDesc.fFlags = kNone_GrTextureFlags;
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // no longer need to clamp at min RT size.
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rtDesc.fWidth  = GrNextPow2(desc.fWidth);
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rtDesc.fHeight = GrNextPow2(desc.fHeight);
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int bpp = GrBytesPerPixel(desc.fConfig);
333363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkAutoSMalloc<128*128*4> stretchedPixels(bpp * rtDesc.fWidth * rtDesc.fHeight);
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
335363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                     srcData, desc.fWidth, desc.fHeight, bpp);
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t stretchedRowBytes = rtDesc.fWidth * bpp;
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
339d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkDEBUGCODE(GrTexture* texture = )fGpu->createTexture(rtDesc, stretchedPixels.get(), stretchedRowBytes);
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(NULL != texture);
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return texture;
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
346d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrTexture* GrContext::createTexture(const GrTextureParams* params,
347d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                    const GrTextureDesc& desc,
348d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                    const GrCacheID& cacheID,
349d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                    void* srcData,
350d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                    size_t rowBytes) {
351d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SK_TRACE_EVENT0("GrContext::createTexture");
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_DUMP_TEXTURE_UPLOAD
354d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrPrintf("GrContext::createTexture[%d %d]\n", desc.fWidth, desc.fHeight);
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
357d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
359d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrTexture* texture;
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (GrTexture::NeedsResizing(resourceKey)) {
361d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        texture = this->createResizedTexture(desc, cacheID,
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             srcData, rowBytes,
363d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                             GrTexture::NeedsFiltering(resourceKey));
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
365d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        texture= fGpu->createTexture(desc, srcData, rowBytes);
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != texture) {
369363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fTextureCache->addResource(resourceKey, texture);
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return texture;
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
375d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, ScratchTexMatch match) {
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTextureDesc desc = inDesc;
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert((desc.fFlags & kRenderTarget_GrTextureFlagBit) ||
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             !(desc.fFlags & kNoStencil_GrTextureFlagBit));
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
381d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (kApprox_ScratchTexMatch == match) {
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // bin by pow2 with a reasonable min
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        static const int MIN_SIZE = 256;
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        desc.fWidth  = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrResource* resource = NULL;
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int origWidth = desc.fWidth;
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int origHeight = desc.fHeight;
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool doubledW = false;
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool doubledH = false;
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do {
395d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        GrResourceKey key = GrTexture::ComputeScratchKey(desc);
396363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // Ensure we have exclusive access to the texture so future 'find' calls don't return it
397363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        resource = fTextureCache->find(key, GrResourceCache::kHide_OwnershipFlag);
398d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (NULL != resource) {
399d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            resource->ref();
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
402d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (kExact_ScratchTexMatch == match) {
403d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            break;
404d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
405d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        // We had a cache miss and we are in approx mode, relax the fit of the flags... then try
406d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        // doubling width... then the height.
407d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // We no longer try to reuse textures that were previously used as render targets in
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // situations where no RT is needed; doing otherwise can confuse the video driver and
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // cause significant performance problems in some cases.
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (desc.fFlags & kNoStencil_GrTextureFlagBit) {
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit;
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else if (!doubledW) {
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            desc.fFlags = inDesc.fFlags;
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            desc.fWidth *= 2;
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            doubledW = true;
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else if (!doubledH) {
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            desc.fFlags = inDesc.fFlags;
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            desc.fWidth = origWidth;
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            desc.fHeight *= 2;
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            doubledH = true;
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } while (true);
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == resource) {
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        desc.fFlags = inDesc.fFlags;
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        desc.fWidth = origWidth;
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        desc.fHeight = origHeight;
432d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL != texture) {
434d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            GrResourceKey key = GrTexture::ComputeScratchKey(texture->desc());
435363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // Make the resource exclusive so future 'find' calls don't return it
436363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fTextureCache->addResource(key, texture, GrResourceCache::kHide_OwnershipFlag);
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            resource = texture;
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return static_cast<GrTexture*>(resource);
44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::addExistingTextureToCache(GrTexture* texture) {
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == texture) {
44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // This texture should already have a cache entry since it was once
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // attached
45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(NULL != texture->getCacheEntry());
45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Conceptually, the cache entry is going to assume responsibility
45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // for the creation ref.
45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(1 == texture->getRefCnt());
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Since this texture came from an AutoScratchTexture it should
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // still be in the exclusive pile
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTextureCache->makeNonExclusive(texture->getCacheEntry());
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->purgeCache();
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::unlockScratchTexture(GrTexture* texture) {
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ASSERT_OWNED_RESOURCE(texture);
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(NULL != texture->getCacheEntry());
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // If this is a scratch texture we detached it from the cache
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // while it was locked (to avoid two callers simultaneously getting
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // the same texture).
473d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (texture->getCacheEntry()->key().isScratch()) {
47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTextureCache->makeNonExclusive(texture->getCacheEntry());
47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->purgeCache();
47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::purgeCache() {
48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != fTextureCache) {
48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTextureCache->purgeAsNeeded();
48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrTexture* GrContext::createUncachedTexture(const GrTextureDesc& descIn,
48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            void* srcData,
48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            size_t rowBytes) {
48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTextureDesc descCopy = descIn;
49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fGpu->createTexture(descCopy, srcData, rowBytes);
49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::getTextureCacheLimits(int* maxTextures,
49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      size_t* maxTextureBytes) const {
49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTextureCache->getLimits(maxTextures, maxTextureBytes);
49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTextureCache->setLimits(maxTextures, maxTextureBytes);
50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint GrContext::getMaxTextureSize() const {
50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fGpu->getCaps().maxTextureSize();
50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
50580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint GrContext::getMaxRenderTargetSize() const {
50780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fGpu->getCaps().maxRenderTargetSize();
50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
50980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
51180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
512363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerGrTexture* GrContext::wrapBackendTexture(const GrBackendTextureDesc& desc) {
513363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return fGpu->wrapBackendTexture(desc);
51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
51580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
516363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerGrRenderTarget* GrContext::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
517363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return fGpu->wrapBackendRenderTarget(desc);
51880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
51980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
52180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params,
52380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                          int width, int height) const {
52480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const GrDrawTarget::Caps& caps = fGpu->getCaps();
52580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!caps.eightBitPaletteSupport()) {
52680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
52880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
53080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!isPow2) {
53280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool tiled = NULL != params && params->isTiled();
53380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (tiled && !caps.npotTextureTileSupport()) {
53480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
53580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
53680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
53780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
53880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
53980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru////////////////////////////////////////////////////////////////////////////////
54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst GrClipData* GrContext::getClip() const {
54380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fGpu->getClip();
54480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::setClip(const GrClipData* clipData) {
54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->setClip(clipData);
54880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawState->setState(GrDrawState::kClip_StateBit,
550363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                         clipData && clipData->fClipStack && !clipData->fClipStack->isWideOpen());
55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru////////////////////////////////////////////////////////////////////////////////
55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::clear(const GrIRect* rect,
55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      const GrColor color,
55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      GrRenderTarget* target) {
55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->prepareToDraw(NULL, DEFAULT_BUFFERING)->clear(rect, color, target);
55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
56080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::drawPaint(const GrPaint& origPaint) {
56280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // set rect to be big enough to fill the space, but not super-huge, so we
56380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // don't overflow fixed-point implementations
56480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrRect r;
56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    r.setLTRB(0, 0,
566363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger              SkIntToScalar(getRenderTarget()->width()),
567363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger              SkIntToScalar(getRenderTarget()->height()));
568363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMatrix inverse;
56980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    AutoMatrix am;
57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // We attempt to map r by the inverse matrix and draw that. mapRect will
57380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // map the four corners and bound them with a new rect. This will not
57480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // produce a correct result for some perspective matrices.
57580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!this->getMatrix().hasPerspective()) {
57680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!fDrawState->getViewInverse(&inverse)) {
57780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrPrintf("Could not invert matrix\n");
57880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        inverse.mapRect(&r);
58180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!am.setIdentity(this, paint.writable())) {
58380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrPrintf("Could not invert matrix\n");
58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
58780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // by definition this fills the entire clip, no need for AA
58880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (paint->isAntiAlias()) {
58980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.writable()->setAntiAlias(false);
59080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
59180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->drawRect(*paint, r);
59280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
59380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
59480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru////////////////////////////////////////////////////////////////////////////////
59580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
59680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
59780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruinline bool disable_coverage_aa_for_blend(GrDrawTarget* target) {
59880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage();
59980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
60080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
60180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru////////////////////////////////////////////////////////////////////////////////
60380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*  create a triangle strip that strokes the specified triangle. There are 8
60580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unique vertices, but we repreat the last 2 to close up. Alternatively we
60680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru could use an indices array, and then only send 8 verts, but not sure that
60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru would be faster.
60880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
60980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
610363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                               SkScalar width) {
611363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const SkScalar rad = SkScalarHalf(width);
61280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    rect.sort();
61380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[0].set(rect.fLeft + rad, rect.fTop + rad);
61580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[1].set(rect.fLeft - rad, rect.fTop - rad);
61680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[2].set(rect.fRight - rad, rect.fTop + rad);
61780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[3].set(rect.fRight + rad, rect.fTop - rad);
61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[4].set(rect.fRight - rad, rect.fBottom - rad);
61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[5].set(rect.fRight + rad, rect.fBottom + rad);
62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
62180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
62280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[8] = verts[0];
62380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[9] = verts[1];
62480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
62580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Returns true if the rects edges are integer-aligned.
62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool isIRect(const GrRect& r) {
630363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return SkScalarIsInt(r.fLeft) && SkScalarIsInt(r.fTop) &&
631363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger           SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom);
63280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
63380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool apply_aa_to_rect(GrDrawTarget* target,
63580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const GrRect& rect,
636363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                             SkScalar width,
637363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                             const SkMatrix* matrix,
638363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                             SkMatrix* combinedMatrix,
63980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             GrRect* devRect,
64080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             bool* useVertexCoverage) {
64180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we use a simple coverage ramp to do aa on axis-aligned rects
64280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we check if the rect will be axis-aligned, and the rect won't land on
64380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // integer coords.
64480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
64580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we are keeping around the "tweak the alpha" trick because
64680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // it is our only hope for the fixed-pipe implementation.
64780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // In a shader implementation we can give a separate coverage input
64880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // TODO: remove this ugliness when we drop the fixed-pipe impl
64980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *useVertexCoverage = false;
65080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!target->canTweakAlphaForCoverage()) {
65180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (disable_coverage_aa_for_blend(target)) {
65280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_DEBUG
65380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            //GrPrintf("Turning off AA to correctly apply blend.\n");
65480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
65580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
65680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
65780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *useVertexCoverage = true;
65880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
65980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
66080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const GrDrawState& drawState = target->getDrawState();
66180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (drawState.getRenderTarget()->isMultisampled()) {
66280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
66380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
66480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
66580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == width && target->willUseHWAALines()) {
66680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
66780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
66880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
66980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!drawState.getViewMatrix().preservesAxisAlignment()) {
67080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
67180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
67280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
67380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != matrix &&
67480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        !matrix->preservesAxisAlignment()) {
67580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
67680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
67780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
67880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *combinedMatrix = drawState.getViewMatrix();
67980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != matrix) {
68080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        combinedMatrix->preConcat(*matrix);
68180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(combinedMatrix->preservesAxisAlignment());
68280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
68380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
68480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    combinedMatrix->mapRect(devRect, rect);
68580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    devRect->sort();
68680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
68780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (width < 0) {
68880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return !isIRect(*devRect);
68980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
69080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
69180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
69280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
69380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
69480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::drawRect(const GrPaint& paint,
69580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const GrRect& rect,
696363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                         SkScalar width,
697363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                         const SkMatrix* matrix) {
69880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_TRACE_EVENT0("GrContext::drawRect");
69980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
70080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
70180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawState::AutoStageDisable atr(fDrawState);
70280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
70380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrRect devRect = rect;
704363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMatrix combinedMatrix;
70580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool useVertexCoverage;
70680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool needAA = paint.isAntiAlias() &&
70780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                  !this->getRenderTarget()->isMultisampled();
70880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix,
70980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                           &combinedMatrix, &devRect,
71080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                           &useVertexCoverage);
71180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
71280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (doAA) {
71380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrDrawState::AutoDeviceCoordDraw adcd(target->drawState());
71480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!adcd.succeeded()) {
71580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
71680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
71780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (width >= 0) {
718363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            GrVec strokeSize;
71980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (width > 0) {
72080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                strokeSize.set(width, width);
72180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                combinedMatrix.mapVectors(&strokeSize, 1);
72280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                strokeSize.setAbs(strokeSize);
72380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
724363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                strokeSize.set(SK_Scalar1, SK_Scalar1);
72580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
72680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fAARectRenderer->strokeAARect(this->getGpu(), target, devRect,
72780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                         strokeSize, useVertexCoverage);
72880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
72980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fAARectRenderer->fillAARect(this->getGpu(), target,
73080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                       devRect, useVertexCoverage);
73180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
73280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
73380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
73480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
73580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (width >= 0) {
73680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // TODO: consider making static vertex buffers for these cases.
73780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Hairline could be done by just adding closing vertex to
73880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // unitSquareVertexBuffer()
73980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
74080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        static const int worstCaseVertCount = 10;
74180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrDrawTarget::AutoReleaseGeometry geo(target, 0, worstCaseVertCount, 0);
74280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
74380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!geo.succeeded()) {
74480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrPrintf("Failed to get space for vertices!\n");
74580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
74680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
74780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
74880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrPrimitiveType primType;
74980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int vertCount;
75080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrPoint* vertex = geo.positions();
75180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
75280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (width > 0) {
75380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            vertCount = 10;
75480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            primType = kTriangleStrip_GrPrimitiveType;
75580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            setStrokeRectStrip(vertex, rect, width);
75680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
75780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // hairline
75880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            vertCount = 5;
75980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            primType = kLineStrip_GrPrimitiveType;
76080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            vertex[0].set(rect.fLeft, rect.fTop);
76180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            vertex[1].set(rect.fRight, rect.fTop);
76280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            vertex[2].set(rect.fRight, rect.fBottom);
76380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            vertex[3].set(rect.fLeft, rect.fBottom);
76480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            vertex[4].set(rect.fLeft, rect.fTop);
76580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
76680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
76780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrDrawState::AutoViewMatrixRestore avmr;
76880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL != matrix) {
76980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrDrawState* drawState = target->drawState();
77080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            avmr.set(drawState, *matrix);
77180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
77280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
77380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        target->drawNonIndexed(primType, 0, vertCount);
77480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
77580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_STATIC_RECT_VB
77680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
77780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (NULL == sqVB) {
77880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                GrPrintf("Failed to create static rect vb.\n");
77980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return;
78080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
78180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            target->setVertexSourceToBuffer(0, sqVB);
78280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrDrawState* drawState = target->drawState();
783363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkMatrix m;
78480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            m.setAll(rect.width(),    0,             rect.fLeft,
78580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        0,            rect.height(), rect.fTop,
786363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                        0,            0,             SkMatrix::I()[8]);
78780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
78880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (NULL != matrix) {
78980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                m.postConcat(*matrix);
79080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
79180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrDrawState::AutoViewMatrixRestore avmr(drawState, m);
79280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
79380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
79480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
79580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            target->drawSimpleRect(rect, matrix);
79680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
79780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
79880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
79980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
80080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::drawRectToRect(const GrPaint& paint,
80180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               const GrRect& dstRect,
80280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               const GrRect& srcRect,
803363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                               const SkMatrix* dstMatrix,
804363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                               const SkMatrix* srcMatrix) {
80580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_TRACE_EVENT0("GrContext::drawRectToRect");
80680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
80780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // srcRect refers to paint's first color stage
80880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!paint.isColorStageEnabled(0)) {
80980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        drawRect(paint, dstRect, -1, dstMatrix);
81080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
81180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
81280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
81380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
81480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
81580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_STATIC_RECT_VB
81680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawState::AutoStageDisable atr(fDrawState);
81780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawState* drawState = target->drawState();
81880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
819363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMatrix m;
82080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
82180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setAll(dstRect.width(), 0,                dstRect.fLeft,
82280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             0,               dstRect.height(), dstRect.fTop,
823363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger             0,               0,                SkMatrix::I()[8]);
82480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != dstMatrix) {
82580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        m.postConcat(*dstMatrix);
82680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
82780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
82880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // The first color stage's coords come from srcRect rather than applying a matrix to dstRect.
82980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // We explicitly compute a matrix for that stage below, no need to adjust here.
83080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const uint32_t kExplicitCoordMask = 1 << GrPaint::kFirstColorStage;
83180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawState::AutoViewMatrixRestore avmr(drawState, m, kExplicitCoordMask);
83280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
83380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setAll(srcRect.width(), 0,                srcRect.fLeft,
83480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             0,               srcRect.height(), srcRect.fTop,
835363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger             0,               0,                SkMatrix::I()[8]);
83680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != srcMatrix) {
83780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        m.postConcat(*srcMatrix);
83880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
839363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
840d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    drawState->preConcatStageMatrices(kExplicitCoordMask, m);
84180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
84280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
84380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == sqVB) {
84480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrPrintf("Failed to create static rect vb.\n");
84580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
84680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
84780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    target->setVertexSourceToBuffer(0, sqVB);
84880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
84980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
85080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawState::AutoStageDisable atr(fDrawState);
85180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
85280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
853363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const SkMatrix* srcMatrices[GrDrawState::kNumStages] = {NULL};
85480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    srcRects[0] = &srcRect;
85580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    srcMatrices[0] = srcMatrix;
85680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
85780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    target->drawRect(dstRect, dstMatrix, srcRects, srcMatrices);
85880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
85980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
86080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
86180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::drawVertices(const GrPaint& paint,
86280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             GrPrimitiveType primitiveType,
86380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             int vertexCount,
86480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const GrPoint positions[],
86580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const GrPoint texCoords[],
86680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const GrColor colors[],
86780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const uint16_t indices[],
86880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             int indexCount) {
86980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_TRACE_EVENT0("GrContext::drawVertices");
87080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
87180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawTarget::AutoReleaseGeometry geo;
87280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
87380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
87480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawState::AutoStageDisable atr(fDrawState);
87580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
87680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrVertexLayout layout = 0;
87780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != texCoords) {
878d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        layout |= GrDrawState::StageTexCoordVertexLayoutBit(0, 0);
87980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
88080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != colors) {
881d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        layout |= GrDrawState::kColor_VertexLayoutBit;
88280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
883d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    int vertexSize = GrDrawState::VertexSize(layout);
88480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
88580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (sizeof(GrPoint) != vertexSize) {
88680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!geo.set(target, layout, vertexCount, 0)) {
88780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrPrintf("Failed to get space for vertices!\n");
88880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
88980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
89080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int texOffsets[GrDrawState::kMaxTexCoords];
89180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int colorOffset;
892d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        GrDrawState::VertexSizeAndOffsetsByIdx(layout,
89380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                texOffsets,
89480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                &colorOffset,
89580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                NULL,
89680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                NULL);
89780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        void* curVertex = geo.vertices();
89880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
89980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = 0; i < vertexCount; ++i) {
90080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *((GrPoint*)curVertex) = positions[i];
90180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
90280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (texOffsets[0] > 0) {
90380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
90480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
90580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (colorOffset > 0) {
90680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
90780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
90880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            curVertex = (void*)((intptr_t)curVertex + vertexSize);
90980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
91080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
91180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        target->setVertexSourceToArray(layout, positions, vertexCount);
91280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
91380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
91480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we don't currently apply offscreen AA to this path. Need improved
91580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // management of GrDrawTarget's geometry to avoid copying points per-tile.
91680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
91780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != indices) {
91880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        target->setIndexSourceToArray(indices, indexCount);
91980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
92080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
92180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        target->drawNonIndexed(primitiveType, 0, vertexCount);
92280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
92380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
92480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
92580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
92680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
92780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
92880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustruct CircleVertex {
92980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPoint fPos;
93080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPoint fCenter;
931363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkScalar fOuterRadius;
932363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkScalar fInnerRadius;
93380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
93480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
935d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergerinline bool circleStaysCircle(const SkMatrix& m) {
936d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    return m.isSimilarity();
937d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
938d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
939d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
940d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
941d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergervoid GrContext::drawOval(const GrPaint& paint,
942d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                         const GrRect& oval,
943d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                         const SkStrokeRec& stroke) {
944d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
945d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (!canDrawOval(paint, oval, stroke)) {
946d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkPath path;
947d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        path.addOval(oval);
948d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        this->drawPath(paint, path, stroke);
949d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return;
95080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
95180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
952d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    internalDrawOval(paint, oval, stroke);
953d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
95480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
955d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergerbool GrContext::canDrawOval(const GrPaint& paint, const GrRect& oval, const SkStrokeRec& stroke) const {
956d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
957d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (!paint.isAntiAlias()) {
95880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
95980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
96080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
961d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // we can draw circles in any style
962d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    bool isCircle = SkScalarNearlyEqual(oval.width(), oval.height())
963d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                    && circleStaysCircle(this->getMatrix());
964d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // and for now, axis-aligned ellipses only with fill or stroke-and-fill
965d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkStrokeRec::Style style = stroke.getStyle();
966d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    bool isStroke = (style == SkStrokeRec::kStroke_Style || style == SkStrokeRec::kHairline_Style);
967d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    bool isFilledAxisAlignedEllipse = this->getMatrix().rectStaysRect() && !isStroke;
96880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
969d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    return isCircle || isFilledAxisAlignedEllipse;
97080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
97180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
972d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergervoid GrContext::internalDrawOval(const GrPaint& paint,
973d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                 const GrRect& oval,
974d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                 const SkStrokeRec& stroke) {
97580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
976d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkScalar xRadius = SkScalarHalf(oval.width());
977d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkScalar yRadius = SkScalarHalf(oval.height());
978d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
979d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkScalar strokeWidth = stroke.getWidth();
980d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkStrokeRec::Style style = stroke.getStyle();
981d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
982d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    bool isCircle = SkScalarNearlyEqual(xRadius, yRadius) && circleStaysCircle(this->getMatrix());
983d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#ifdef SK_DEBUG
984d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    {
985d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        // we should have checked for this previously
986d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        bool isStroke = (style == SkStrokeRec::kStroke_Style || style == SkStrokeRec::kHairline_Style);
987d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        bool isFilledAxisAlignedEllipse = this->getMatrix().rectStaysRect() && !isStroke;
988d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkASSERT(paint.isAntiAlias() && (isCircle || isFilledAxisAlignedEllipse));
98980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
990d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#endif
99180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
99280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
99380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
99480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawState* drawState = target->drawState();
99580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawState::AutoStageDisable atr(fDrawState);
996363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const SkMatrix vm = drawState->getViewMatrix();
99780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
99880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const GrRenderTarget* rt = drawState->getRenderTarget();
99980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == rt) {
100080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
100180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
100280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
100380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawState::AutoDeviceCoordDraw adcd(drawState);
100480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!adcd.succeeded()) {
100580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
100680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
100780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1008d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrVertexLayout layout = GrDrawState::kEdge_VertexLayoutBit;
1009d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrAssert(sizeof(CircleVertex) == GrDrawState::VertexSize(layout));
101080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
101180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawTarget::AutoReleaseGeometry geo(target, layout, 4, 0);
101280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!geo.succeeded()) {
101380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrPrintf("Failed to get space for vertices!\n");
101480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
101580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
101680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
101780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
101880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1019d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrPoint center = GrPoint::Make(oval.centerX(), oval.centerY());
1020d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    vm.mapPoints(&center, 1);
1021d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1022d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkScalar L;
1023d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkScalar R;
1024d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkScalar T;
1025d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkScalar B;
1026d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1027d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (isCircle) {
1028d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        drawState->setVertexEdgeType(GrDrawState::kCircle_EdgeType);
1029d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1030d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        xRadius = vm.mapRadius(xRadius);
1031d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1032d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkScalar outerRadius = xRadius;
1033d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkScalar innerRadius = 0;
1034d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkScalar halfWidth = 0;
1035d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (style != SkStrokeRec::kFill_Style) {
1036d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            strokeWidth = vm.mapRadius(strokeWidth);
1037d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            if (SkScalarNearlyZero(strokeWidth)) {
1038d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                halfWidth = SK_ScalarHalf;
1039d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            } else {
1040d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                halfWidth = SkScalarHalf(strokeWidth);
1041d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            }
1042d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1043d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            outerRadius += halfWidth;
1044d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            if (style == SkStrokeRec::kStroke_Style || style == SkStrokeRec::kHairline_Style) {
1045d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                innerRadius = SkMaxScalar(0, xRadius - halfWidth);
1046d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            }
1047d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
1048d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1049d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        for (int i = 0; i < 4; ++i) {
1050d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            verts[i].fCenter = center;
1051d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            verts[i].fOuterRadius = outerRadius;
1052d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            verts[i].fInnerRadius = innerRadius;
1053d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
1054d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1055d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        L = -outerRadius;
1056d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        R = +outerRadius;
1057d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        T = -outerRadius;
1058d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        B = +outerRadius;
1059d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    } else {  // is axis-aligned ellipse
1060d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        drawState->setVertexEdgeType(GrDrawState::kEllipse_EdgeType);
1061d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1062d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkRect xformedRect;
1063d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        vm.mapRect(&xformedRect, oval);
1064d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1065d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        xRadius = SkScalarHalf(xformedRect.width());
1066d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        yRadius = SkScalarHalf(xformedRect.height());
1067d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1068d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (style == SkStrokeRec::kStrokeAndFill_Style && strokeWidth > 0.0f) {
1069d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            SkScalar halfWidth = SkScalarHalf(strokeWidth);
1070d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            // do (potentially) anisotropic mapping
1071d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            SkVector scaledStroke;
1072d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            scaledStroke.set(halfWidth, halfWidth);
1073d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            vm.mapVectors(&scaledStroke, 1);
1074d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            // this is legit only if scale & translation (which should be the case at the moment)
1075d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            xRadius += scaledStroke.fX;
1076d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            yRadius += scaledStroke.fY;
1077d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
1078d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1079d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkScalar ratio = SkScalarDiv(xRadius, yRadius);
1080d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1081d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        for (int i = 0; i < 4; ++i) {
1082d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            verts[i].fCenter = center;
1083d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            verts[i].fOuterRadius = xRadius;
1084d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            verts[i].fInnerRadius = ratio;
1085d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
1086d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1087d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        L = -xRadius;
1088d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        R = +xRadius;
1089d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        T = -yRadius;
1090d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        B = +yRadius;
1091d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
1092d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
109380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // The fragment shader will extend the radius out half a pixel
109480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // to antialias. Expand the drawn rect here so all the pixels
109580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // will be captured.
1096d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    L += center.fX - SK_ScalarHalf;
1097d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    R += center.fX + SK_ScalarHalf;
1098d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    T += center.fY - SK_ScalarHalf;
1099d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    B += center.fY + SK_ScalarHalf;
110080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
110180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[0].fPos = SkPoint::Make(L, T);
110280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[1].fPos = SkPoint::Make(R, T);
110380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[2].fPos = SkPoint::Make(L, B);
110480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    verts[3].fPos = SkPoint::Make(R, B);
110580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
110680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4);
110780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
110880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1109363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke) {
111080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
111180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (path.isEmpty()) {
1112363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger       if (path.isInverseFillType()) {
111380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru           this->drawPaint(paint);
111480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru       }
111580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru       return;
111680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
111780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
111880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect ovalRect;
1119d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    bool isOval = path.isOval(&ovalRect);
1120d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1121d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (isOval && !path.isInverseFillType() && this->canDrawOval(paint, ovalRect, stroke)) {
1122d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        this->drawOval(paint, ovalRect, stroke);
112380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
112480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
112580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1126d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    this->internalDrawPath(paint, path, stroke);
112780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
112880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1129363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke) {
113080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
113180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Note that below we may sw-rasterize the path into a scratch texture.
113280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Scratch textures can be recycled after they are returned to the texture
113380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // cache. This presents a potential hazard for buffered drawing. However,
113480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // the writePixels that uploads to the scratch will perform a flush so we're
113580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // OK.
113680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
113780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawState::AutoStageDisable atr(fDrawState);
113880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
113980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool prAA = paint.isAntiAlias() && !this->getRenderTarget()->isMultisampled();
114080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
114180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // An Assumption here is that path renderer would use some form of tweaking
114280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // the src color (either the input alpha or in the frag shader) to implement
114380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // aa. If we have some future driver-mojo path AA that can do the right
114480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // thing WRT to the blend then we'll need some query on the PR.
114580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (disable_coverage_aa_for_blend(target)) {
114680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_DEBUG
114780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        //GrPrintf("Turning off AA to correctly apply blend.\n");
114880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
114980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        prAA = false;
115080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
115180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1152363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    GrPathRendererChain::DrawType type = prAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
1153363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                                GrPathRendererChain::kColor_DrawType;
1154363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
1155d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    const SkPath* pathPtr = &path;
1156d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkPath tmpPath;
1157d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkStrokeRec strokeRec(stroke);
1158d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1159d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // Try a 1st time without stroking the path and without allowing the SW renderer
1160d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrPathRenderer* pr = this->getPathRenderer(*pathPtr, strokeRec, target, false, type);
1161d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1162d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (NULL == pr) {
1163d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (!strokeRec.isHairlineStyle()) {
1164d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            // It didn't work the 1st time, so try again with the stroked path
1165d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            if (strokeRec.applyToPath(&tmpPath, *pathPtr)) {
1166d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                pathPtr = &tmpPath;
1167d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                strokeRec.setFillStyle();
1168d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            }
1169d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
1170d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        // This time, allow SW renderer
1171d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        pr = this->getPathRenderer(*pathPtr, strokeRec, target, true, type);
1172d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
1173d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
117480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == pr) {
117580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_DEBUG
117680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrPrintf("Unable to find path renderer compatible with path.\n");
117780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
117880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
117980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
118080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1181d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    pr->drawPath(*pathPtr, strokeRec, target, prAA);
118280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
118380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
118480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru////////////////////////////////////////////////////////////////////////////////
118580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
118680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::flush(int flagsBitfield) {
118780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (kDiscard_FlushBit & flagsBitfield) {
118880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDrawBuffer->reset();
118980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
119080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->flushDrawBuffer();
119180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
119280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) {
119380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fGpu->forceRenderTargetFlush();
119480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
119580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
119680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
119780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::flushDrawBuffer() {
119880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fDrawBuffer) {
119980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // With addition of the AA clip path, flushing the draw buffer can
120080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // result in the generation of an AA clip mask. During this
120180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // process the SW path renderer may be invoked which recusively
120280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // calls this method (via internalWriteTexturePixels) creating
120380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // infinite recursion
120480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrInOrderDrawBuffer* temp = fDrawBuffer;
120580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDrawBuffer = NULL;
120680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
120780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        temp->flushTo(fGpu);
120880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
120980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDrawBuffer = temp;
121080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
121180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
121280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
121380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::writeTexturePixels(GrTexture* texture,
121480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   int left, int top, int width, int height,
121580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   GrPixelConfig config, const void* buffer, size_t rowBytes,
121680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   uint32_t flags) {
121780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_TRACE_EVENT0("GrContext::writeTexturePixels");
121880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ASSERT_OWNED_RESOURCE(texture);
121980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
122080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // TODO: use scratch texture to perform conversion
122180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (kUnpremul_PixelOpsFlag & flags) {
122280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
122380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
122480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!(kDontFlush_PixelOpsFlag & flags)) {
122580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->flush();
122680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
122780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
122880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->writeTexturePixels(texture, left, top, width, height,
122980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             config, buffer, rowBytes);
123080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
123180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
123280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrContext::readTexturePixels(GrTexture* texture,
123380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  int left, int top, int width, int height,
123480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  GrPixelConfig config, void* buffer, size_t rowBytes,
123580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  uint32_t flags) {
123680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_TRACE_EVENT0("GrContext::readTexturePixels");
123780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ASSERT_OWNED_RESOURCE(texture);
123880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
123980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // TODO: code read pixels for textures that aren't also rendertargets
124080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrRenderTarget* target = texture->asRenderTarget();
124180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != target) {
124280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return this->readRenderTargetPixels(target,
124380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            left, top, width, height,
124480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            config, buffer, rowBytes,
124580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            flags);
124680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
124780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
124880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
124980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
125080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
125180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkConfig8888.h"
125280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
125380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
125480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
125580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Converts a GrPixelConfig to a SkCanvas::Config8888. Only byte-per-channel
125680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * formats are representable as Config8888 and so the function returns false
125780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * if the GrPixelConfig has no equivalent Config8888.
125880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
125980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool grconfig_to_config8888(GrPixelConfig config,
126080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            bool unpremul,
126180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkCanvas::Config8888* config8888) {
126280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (config) {
126380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kRGBA_8888_GrPixelConfig:
126480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (unpremul) {
126580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
126680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
126780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *config8888 = SkCanvas::kRGBA_Premul_Config8888;
126880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
126980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
127080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kBGRA_8888_GrPixelConfig:
127180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (unpremul) {
127280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *config8888 = SkCanvas::kBGRA_Unpremul_Config8888;
127380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
127480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *config8888 = SkCanvas::kBGRA_Premul_Config8888;
127580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
127680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
127780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
127880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
127980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
128080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
128180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
128280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// It returns a configuration with where the byte position of the R & B components are swapped in
128380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// relation to the input config. This should only be called with the result of
128480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// grconfig_to_config8888 as it will fail for other configs.
128580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkCanvas::Config8888 swap_config8888_red_and_blue(SkCanvas::Config8888 config8888) {
128680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (config8888) {
128780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkCanvas::kBGRA_Premul_Config8888:
128880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkCanvas::kRGBA_Premul_Config8888;
128980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkCanvas::kBGRA_Unpremul_Config8888:
129080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkCanvas::kRGBA_Unpremul_Config8888;
129180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkCanvas::kRGBA_Premul_Config8888:
129280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkCanvas::kBGRA_Premul_Config8888;
129380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkCanvas::kRGBA_Unpremul_Config8888:
129480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkCanvas::kBGRA_Unpremul_Config8888;
129580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
129680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrCrash("Unexpected input");
129780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkCanvas::kBGRA_Unpremul_Config8888;;
129880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
129980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
130080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
130180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
130280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrContext::readRenderTargetPixels(GrRenderTarget* target,
130380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                       int left, int top, int width, int height,
130480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                       GrPixelConfig config, void* buffer, size_t rowBytes,
130580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                       uint32_t flags) {
130680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
130780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ASSERT_OWNED_RESOURCE(target);
130880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
130980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == target) {
131080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        target = fDrawState->getRenderTarget();
131180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == target) {
131280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
131380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
131480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
131580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
131680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!(kDontFlush_PixelOpsFlag & flags)) {
131780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->flush();
131880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
131980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
132080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Determine which conversions have to be applied: flipY, swapRAnd, and/or unpremul.
132180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
132280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // If fGpu->readPixels would incur a y-flip cost then we will read the pixels upside down. We'll
132380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // either do the flipY by drawing into a scratch with a matrix or on the cpu after the read.
132480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool flipY = fGpu->readPixelsWillPayForYFlip(target, left, top,
132580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                 width, height, config,
132680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                 rowBytes);
132780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool swapRAndB = fGpu->preferredReadPixelsConfig(config) == GrPixelConfigSwapRAndB(config);
132880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
132980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
133080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
133180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // flipY will get set to false when it is handled below using a scratch. However, in that case
133280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we still want to do the read upside down.
133380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool readUpsideDown = flipY;
133480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
133580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (unpremul && kRGBA_8888_GrPixelConfig != config && kBGRA_8888_GrPixelConfig != config) {
133680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // The unpremul flag is only allowed for these two configs.
133780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
133880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
133980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
134080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPixelConfig readConfig;
134180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (swapRAndB) {
134280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        readConfig = GrPixelConfigSwapRAndB(config);
134380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(kUnknown_GrPixelConfig != config);
134480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
134580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        readConfig = config;
134680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
134780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
134880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // If the src is a texture and we would have to do conversions after read pixels, we instead
134980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // do the conversions by drawing the src to a scratch texture. If we handle any of the
135080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // conversions in the draw we set the corresponding bool to false so that we don't reapply it
135180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // on the read back pixels.
135280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTexture* src = target->asTexture();
135380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAutoScratchTexture ast;
135480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != src && (swapRAndB || unpremul || flipY)) {
135580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Make the scratch a render target because we don't have a robust readTexturePixels as of
135680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // yet. It calls this function.
135780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrTextureDesc desc;
135880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        desc.fFlags = kRenderTarget_GrTextureFlagBit;
135980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        desc.fWidth = width;
136080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        desc.fHeight = height;
136180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        desc.fConfig = readConfig;
136280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
136380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // When a full readback is faster than a partial we could always make the scratch exactly
136480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // match the passed rect. However, if we see many different size rectangles we will trash
136580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // our texture cache and pay the cost of creating and destroying many textures. So, we only
136680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // request an exact match when the caller is reading an entire RT.
136780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ScratchTexMatch match = kApprox_ScratchTexMatch;
136880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (0 == left &&
136980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            0 == top &&
137080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            target->width() == width &&
137180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            target->height() == height &&
137280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fGpu->fullReadPixelsIsFasterThanPartial()) {
137380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            match = kExact_ScratchTexMatch;
137480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
137580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ast.set(this, desc, match);
137680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrTexture* texture = ast.texture();
137780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (texture) {
1378363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // compute a matrix to perform the draw
1379363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkMatrix textureMatrix;
1380363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            if (flipY) {
1381363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                textureMatrix.setTranslate(SK_Scalar1 * left,
1382363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                    SK_Scalar1 * (top + height));
1383363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                textureMatrix.set(SkMatrix::kMScaleY, -SK_Scalar1);
1384363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            } else {
1385363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
1386363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
1387363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            textureMatrix.postIDiv(src->width(), src->height());
1388363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
1389d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            SkAutoTUnref<const GrEffectRef> effect;
139080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (unpremul) {
1391d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                effect.reset(this->createPMToUPMEffect(src, swapRAndB, textureMatrix));
1392d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                if (NULL != effect) {
1393363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    unpremul = false; // we no longer need to do this on CPU after the readback.
1394363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                }
139580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
139680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // If we failed to create a PM->UPM effect and have no other conversions to perform then
139780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // there is no longer any point to using the scratch.
1398d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            if (NULL != effect || flipY || swapRAndB) {
1399d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                if (!effect) {
1400d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                    effect.reset(GrConfigConversionEffect::Create(
1401d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                    src,
1402d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                    swapRAndB,
1403d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                    GrConfigConversionEffect::kNone_PMConversion,
1404d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                    textureMatrix));
140580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
140680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                swapRAndB = false; // we will handle the swap in the draw.
1407363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                flipY = false; // we already incorporated the y flip in the matrix
140880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
140980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
141080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                GrDrawState* drawState = fGpu->drawState();
1411d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                GrAssert(effect);
1412d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                drawState->setEffect(0, effect);
1413363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
141480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                drawState->setRenderTarget(texture->asRenderTarget());
1415363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                GrRect rect = GrRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
141680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fGpu->drawSimpleRect(rect, NULL);
141780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // we want to read back from the scratch's origin
141880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                left = 0;
141980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                top = 0;
142080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                target = texture->asRenderTarget();
142180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
142280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
142380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
142480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!fGpu->readPixels(target,
142580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          left, top, width, height,
142680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          readConfig, buffer, rowBytes, readUpsideDown)) {
142780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
142880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
1429363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // Perform any conversions we weren't able to perform using a scratch texture.
143080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (unpremul || swapRAndB || flipY) {
143180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // These are initialized to suppress a warning
143280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkCanvas::Config8888 srcC8888 = SkCanvas::kNative_Premul_Config8888;
143380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkCanvas::Config8888 dstC8888 = SkCanvas::kNative_Premul_Config8888;
143480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
143580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool c8888IsValid = grconfig_to_config8888(config, false, &srcC8888);
143680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        grconfig_to_config8888(config, unpremul, &dstC8888);
143780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
143880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (swapRAndB) {
143980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrAssert(c8888IsValid); // we should only do r/b swap on 8888 configs
144080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            srcC8888 = swap_config8888_red_and_blue(srcC8888);
144180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
144280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (flipY) {
144380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            size_t tightRB = width * GrBytesPerPixel(config);
144480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (0 == rowBytes) {
144580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                rowBytes = tightRB;
144680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
144780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkAutoSTMalloc<256, uint8_t> tempRow(tightRB);
144880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            intptr_t top = reinterpret_cast<intptr_t>(buffer);
144980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            intptr_t bot = top + (height - 1) * rowBytes;
145080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            while (top < bot) {
145180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                uint32_t* t = reinterpret_cast<uint32_t*>(top);
145280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                uint32_t* b = reinterpret_cast<uint32_t*>(bot);
145380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                uint32_t* temp = reinterpret_cast<uint32_t*>(tempRow.get());
145480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                memcpy(temp, t, tightRB);
145580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (c8888IsValid) {
145680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkConvertConfig8888Pixels(t, tightRB, dstC8888,
145780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                              b, tightRB, srcC8888,
145880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                              width, 1);
145980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkConvertConfig8888Pixels(b, tightRB, dstC8888,
146080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                              temp, tightRB, srcC8888,
146180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                              width, 1);
146280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                } else {
146380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    memcpy(t, b, tightRB);
146480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    memcpy(b, temp, tightRB);
146580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
146680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                top += rowBytes;
146780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                bot -= rowBytes;
146880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
146980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // The above loop does nothing on the middle row when height is odd.
147080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (top == bot && c8888IsValid && dstC8888 != srcC8888) {
147180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                uint32_t* mid = reinterpret_cast<uint32_t*>(top);
147280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkConvertConfig8888Pixels(mid, tightRB, dstC8888, mid, tightRB, srcC8888, width, 1);
147380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
147480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
147580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // if we aren't flipping Y then we have no reason to be here other than doing
147680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // conversions for 8888 (r/b swap or upm).
147780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrAssert(c8888IsValid);
147880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            uint32_t* b32 = reinterpret_cast<uint32_t*>(buffer);
147980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkConvertConfig8888Pixels(b32, rowBytes, dstC8888,
148080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      b32, rowBytes, srcC8888,
148180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      width, height);
148280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
148380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
148480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
148580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
148680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
148780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::resolveRenderTarget(GrRenderTarget* target) {
148880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(target);
148980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ASSERT_OWNED_RESOURCE(target);
149080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // In the future we may track whether there are any pending draws to this
149180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // target. We don't today so we always perform a flush. We don't promise
149280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // this to our clients, though.
149380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->flush();
149480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->resolveRenderTarget(target);
149580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
149680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1497363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint* topLeft) {
149880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == src || NULL == dst) {
149980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
150080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
150180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ASSERT_OWNED_RESOURCE(src);
150280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
150380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Writes pending to the source texture are not tracked, so a flush
150480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // is required to ensure that the copy captures the most recent contents
1505d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // of the source texture. See similar behavior in
150680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // GrContext::resolveRenderTarget.
150780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->flush();
150880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
150980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
151080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawState* drawState = fGpu->drawState();
151180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    drawState->setRenderTarget(dst);
1512363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMatrix sampleM;
151380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sampleM.setIDiv(src->width(), src->height());
1514363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkIRect srcRect = SkIRect::MakeWH(dst->width(), dst->height());
1515363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (NULL != topLeft) {
1516363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        srcRect.offset(*topLeft);
1517363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
1518363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkIRect srcBounds = SkIRect::MakeWH(src->width(), src->height());
1519363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (!srcRect.intersect(srcBounds)) {
1520363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return;
1521363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
1522363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    sampleM.preTranslate(SkIntToScalar(srcRect.fLeft), SkIntToScalar(srcRect.fTop));
152380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    drawState->createTextureEffect(0, src, sampleM);
1524363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkRect dstR = SkRect::MakeWH(SkIntToScalar(srcRect.width()), SkIntToScalar(srcRect.height()));
1525363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fGpu->drawSimpleRect(dstR, NULL);
152680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
152780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
152880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::writeRenderTargetPixels(GrRenderTarget* target,
152980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        int left, int top, int width, int height,
153080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        GrPixelConfig config,
153180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        const void* buffer,
153280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        size_t rowBytes,
153380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        uint32_t flags) {
153480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
153580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ASSERT_OWNED_RESOURCE(target);
153680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
153780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == target) {
153880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        target = fDrawState->getRenderTarget();
153980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == target) {
154080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
154180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
154280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
154380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
154480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // TODO: when underlying api has a direct way to do this we should use it (e.g. glDrawPixels on
154580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // desktop GL).
154680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
154780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // We will always call some form of writeTexturePixels and we will pass our flags on to it.
154880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Thus, we don't perform a flush here since that call will do it (if the kNoFlush flag isn't
154980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // set.)
155080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
155180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // If the RT is also a texture and we don't have to premultiply then take the texture path.
155280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // We expect to be at least as fast or faster since it doesn't use an intermediate texture as
155380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we do below.
155480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
155580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if !GR_MAC_BUILD
155680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // At least some drivers on the Mac get confused when glTexImage2D is called on a texture
155780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // attached to an FBO. The FBO still sees the old image. TODO: determine what OS versions and/or
155880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // HW is affected.
155980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != target->asTexture() && !(kUnpremul_PixelOpsFlag & flags)) {
156080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->writeTexturePixels(target->asTexture(),
156180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                 left, top, width, height,
156280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                 config, buffer, rowBytes, flags);
156380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
156480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
156580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
1566363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
156780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool swapRAndB = (fGpu->preferredReadPixelsConfig(config) == GrPixelConfigSwapRAndB(config));
156880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
156980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPixelConfig textureConfig;
157080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (swapRAndB) {
157180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        textureConfig = GrPixelConfigSwapRAndB(config);
157280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
157380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        textureConfig = config;
157480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
157580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
157680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTextureDesc desc;
157780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fWidth = width;
157880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fHeight = height;
157980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fConfig = textureConfig;
158080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAutoScratchTexture ast(this, desc);
158180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTexture* texture = ast.texture();
158280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == texture) {
158380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
158480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
1585363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
1586d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkAutoTUnref<const GrEffectRef> effect;
1587363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMatrix textureMatrix;
1588363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    textureMatrix.setIDiv(texture->width(), texture->height());
1589363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
159080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // allocate a tmp buffer and sw convert the pixels to premul
159180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
159280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
159380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (kUnpremul_PixelOpsFlag & flags) {
159480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (kRGBA_8888_GrPixelConfig != config && kBGRA_8888_GrPixelConfig != config) {
159580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
159680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
1597d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        effect.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
1598d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (NULL == effect) {
159980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkCanvas::Config8888 srcConfig8888, dstConfig8888;
160080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GR_DEBUGCODE(bool success = )
160180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            grconfig_to_config8888(config, true, &srcConfig8888);
160280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrAssert(success);
160380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GR_DEBUGCODE(success = )
160480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            grconfig_to_config8888(config, false, &dstConfig8888);
160580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrAssert(success);
160680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            const uint32_t* src = reinterpret_cast<const uint32_t*>(buffer);
160780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmpPixels.reset(width * height);
160880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkConvertConfig8888Pixels(tmpPixels.get(), 4 * width, dstConfig8888,
160980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      src, rowBytes, srcConfig8888,
161080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      width, height);
161180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            buffer = tmpPixels.get();
161280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            rowBytes = 4 * width;
161380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
161480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
1615d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (NULL == effect) {
1616d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        effect.reset(GrConfigConversionEffect::Create(texture,
1617d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                      swapRAndB,
1618d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                      GrConfigConversionEffect::kNone_PMConversion,
1619d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                      textureMatrix));
162080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
162180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
162280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->writeTexturePixels(texture,
162380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             0, 0, width, height,
162480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             textureConfig, buffer, rowBytes,
162580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             flags & ~kUnpremul_PixelOpsFlag);
162680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
162780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawTarget::AutoStateRestore  asr(fGpu, GrDrawTarget::kReset_ASRInit);
162880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrDrawState* drawState = fGpu->drawState();
1629d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrAssert(effect);
1630d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    drawState->setEffect(0, effect);
163180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1632363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMatrix matrix;
1633363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
163480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    drawState->setViewMatrix(matrix);
163580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    drawState->setRenderTarget(target);
163680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
163780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->drawSimpleRect(GrRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), NULL);
163880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
163980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru////////////////////////////////////////////////////////////////////////////////
164080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
164180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, BufferedDraw buffered) {
164280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (kNo_BufferedDraw == buffered && kYes_BufferedDraw == fLastDrawWasBuffered) {
164380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->flushDrawBuffer();
164480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fLastDrawWasBuffered = kNo_BufferedDraw;
164580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
164680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != paint) {
164780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(fDrawState->stagesDisabled());
164880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDrawState->setFromPaint(*paint);
164980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_DEBUG_PARTIAL_COVERAGE_CHECK
165080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if ((paint->hasMask() || 0xff != paint->fCoverage) &&
165180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            !fGpu->canApplyCoverage()) {
165280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
165380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
165480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
165580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
165680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (kYes_BufferedDraw == buffered) {
165780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDrawBuffer->setClip(fGpu->getClip());
165880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fLastDrawWasBuffered = kYes_BufferedDraw;
165980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return fDrawBuffer;
166080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
166180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(kNo_BufferedDraw == buffered);
166280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return fGpu;
166380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
166480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
166580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
166680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
166780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * This method finds a path renderer that can draw the specified path on
166880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * the provided target.
166980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Due to its expense, the software path renderer has split out so it can
167080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * can be individually allowed/disallowed via the "allowSW" boolean.
167180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
167280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrPathRenderer* GrContext::getPathRenderer(const SkPath& path,
1673363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                           const SkStrokeRec& stroke,
167480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                           const GrDrawTarget* target,
1675363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                           bool allowSW,
1676363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                           GrPathRendererChain::DrawType drawType,
1677363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                           GrPathRendererChain::StencilSupport* stencilSupport) {
1678363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
167980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == fPathRendererChain) {
1680363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this));
168180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
168280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1683363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(path,
1684363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                                             stroke,
168580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                             target,
1686363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                                             drawType,
1687363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                                             stencilSupport);
168880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
168980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == pr && allowSW) {
169080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == fSoftwarePathRenderer) {
169180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this));
169280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
169380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        pr = fSoftwarePathRenderer;
169480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
169580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
169680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return pr;
169780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
169880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
169980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru////////////////////////////////////////////////////////////////////////////////
170080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
170180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::setRenderTarget(GrRenderTarget* target) {
170280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ASSERT_OWNED_RESOURCE(target);
170380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawState->setRenderTarget(target);
170480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
170580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
170680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrRenderTarget* GrContext::getRenderTarget() {
170780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fDrawState->getRenderTarget();
170880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
170980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
171080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst GrRenderTarget* GrContext::getRenderTarget() const {
171180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fDrawState->getRenderTarget();
171280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
171380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
171480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrContext::isConfigRenderable(GrPixelConfig config) const {
171580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fGpu->isConfigRenderable(config);
171680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
171780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1718363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerconst SkMatrix& GrContext::getMatrix() const {
171980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fDrawState->getViewMatrix();
172080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
172180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1722363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid GrContext::setMatrix(const SkMatrix& m) {
172380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawState->setViewMatrix(m);
172480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
172580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
172680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::setIdentityMatrix() {
172780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawState->viewMatrix()->reset();
172880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
172980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1730363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid GrContext::concatMatrix(const SkMatrix& m) const {
173180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawState->preConcatViewMatrix(m);
173280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
173380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
173480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
173580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    intptr_t mask = 1 << shift;
173680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (pred) {
173780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bits |= mask;
173880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
173980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bits &= ~mask;
174080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
174180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return bits;
174280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
174380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
174480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrContext::GrContext(GrGpu* gpu) {
174580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ++THREAD_INSTANCE_COUNT;
174680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
174780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu = gpu;
174880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->ref();
174980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->setContext(this);
175080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
175180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawState = SkNEW(GrDrawState);
175280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->setDrawState(fDrawState);
175380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
175480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fPathRendererChain = NULL;
175580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fSoftwarePathRenderer = NULL;
175680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
175780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTextureCache = SkNEW_ARGS(GrResourceCache,
175880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               (MAX_TEXTURE_CACHE_COUNT,
175980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                MAX_TEXTURE_CACHE_BYTES));
176080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fFontCache = SkNEW_ARGS(GrFontCache, (fGpu));
176180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
176280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fLastDrawWasBuffered = kNo_BufferedDraw;
176380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
176480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawBuffer = NULL;
176580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawBufferVBAllocPool = NULL;
176680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawBufferIBAllocPool = NULL;
176780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
176880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fAARectRenderer = SkNEW(GrAARectRenderer);
176980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
177080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDidTestPMConversions = false;
177180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
177280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setupDrawBuffer();
177380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
177480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
177580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::setupDrawBuffer() {
177680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
177780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(NULL == fDrawBuffer);
177880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(NULL == fDrawBufferVBAllocPool);
177980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(NULL == fDrawBufferIBAllocPool);
178080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
178180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawBufferVBAllocPool =
178280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkNEW_ARGS(GrVertexBufferAllocPool, (fGpu, false,
178380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
178480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS));
178580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawBufferIBAllocPool =
178680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkNEW_ARGS(GrIndexBufferAllocPool, (fGpu, false,
178780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
178880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS));
178980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
179080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (fGpu,
179180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                          fDrawBufferVBAllocPool,
179280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                          fDrawBufferIBAllocPool));
179380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
179480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fDrawBuffer) {
179580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDrawBuffer->setAutoFlushTarget(fGpu);
179680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDrawBuffer->setDrawState(fDrawState);
179780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
179880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
179980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
180080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
180180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return prepareToDraw(&paint, DEFAULT_BUFFERING);
180280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
180380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
180480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
180580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fGpu->getQuadIndexBuffer();
180680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
180780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
180880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
180980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
181080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrConfigConversionEffect::PMConversion pmToUPM;
181180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrConfigConversionEffect::PMConversion upmToPM;
181280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
181380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *pmToUPMValue = pmToUPM;
181480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *upmToPMValue = upmToPM;
181580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
181680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
181780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1818d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergerconst GrEffectRef* GrContext::createPMToUPMEffect(GrTexture* texture,
1819d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                  bool swapRAndB,
1820d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                  const SkMatrix& matrix) {
182180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!fDidTestPMConversions) {
182280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
182380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDidTestPMConversions = true;
182480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
182580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrConfigConversionEffect::PMConversion pmToUPM =
182680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
182780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
1828d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, matrix);
182980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
1830d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return NULL;
183180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
183280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
183380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1834d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergerconst GrEffectRef* GrContext::createUPMToPMEffect(GrTexture* texture,
1835d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                  bool swapRAndB,
1836d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                  const SkMatrix& matrix) {
183780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!fDidTestPMConversions) {
183880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
183980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDidTestPMConversions = true;
184080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
184180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrConfigConversionEffect::PMConversion upmToPM =
184280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
184380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
1844d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, matrix);
184580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
1846d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return NULL;
184780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
184880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
184980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
185080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrTexture* GrContext::gaussianBlur(GrTexture* srcTexture,
185180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   bool canClobberSrc,
185280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   const SkRect& rect,
185380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   float sigmaX, float sigmaY) {
185480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ASSERT_OWNED_RESOURCE(srcTexture);
185580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
185680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    AutoRenderTarget art(this);
185780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
185880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    AutoMatrix am;
185980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    am.setIdentity(this);
186080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
186180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect clearRect;
186280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int scaleFactorX, radiusX;
186380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int scaleFactorY, radiusY;
186480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
186580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);
186680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
186780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect srcRect(rect);
186880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
186980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    srcRect.roundOut();
187080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    scale_rect(&srcRect, static_cast<float>(scaleFactorX),
187180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         static_cast<float>(scaleFactorY));
187280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
187380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    AutoClip acs(this, srcRect);
187480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
187580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
187680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             kRGBA_8888_GrPixelConfig == srcTexture->config() ||
187780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             kAlpha_8_GrPixelConfig == srcTexture->config());
187880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
187980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTextureDesc desc;
188080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
188180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fWidth = SkScalarFloorToInt(srcRect.width());
188280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fHeight = SkScalarFloorToInt(srcRect.height());
188380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fConfig = srcTexture->config();
188480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
188580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAutoScratchTexture temp1, temp2;
188680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTexture* dstTexture = temp1.set(this, desc);
188780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(this, desc);
1888363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (NULL == dstTexture || NULL == tempTexture) {
1889363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return NULL;
1890363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
189180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
189280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPaint paint;
189380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    paint.reset();
189480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
189580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
1896363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkMatrix matrix;
189780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        matrix.setIDiv(srcTexture->width(), srcTexture->height());
189880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setRenderTarget(dstTexture->asRenderTarget());
189980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkRect dstRect(srcRect);
190080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
190180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             i < scaleFactorY ? 0.5f : 1.0f);
190280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1903d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        paint.colorStage(0)->setEffect(GrSimpleTextureEffect::Create(srcTexture,
1904d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                                     matrix,
1905d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                                     true))->unref();
190680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->drawRectToRect(paint, dstRect, srcRect);
190780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        srcRect = dstRect;
190880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        srcTexture = dstTexture;
190980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkTSwap(dstTexture, tempTexture);
191080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
191180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
191280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect srcIRect;
191380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    srcRect.roundOut(&srcIRect);
191480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
191580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (sigmaX > 0.0f) {
191680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (scaleFactorX > 1) {
191780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // Clear out a radius to the right of the srcRect to prevent the
191880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // X convolution from reading garbage.
191980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
192080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                          radiusX, srcIRect.height());
192180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this->clear(&clearRect, 0x0);
192280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
192380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
192480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setRenderTarget(dstTexture->asRenderTarget());
192580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrDrawTarget* target = this->prepareToDraw(NULL, DEFAULT_BUFFERING);
192680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        convolve_gaussian(target, srcTexture, srcRect, sigmaX, radiusX,
192780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          Gr1DKernelEffect::kX_Direction);
192880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        srcTexture = dstTexture;
192980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkTSwap(dstTexture, tempTexture);
193080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
193180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
193280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (sigmaY > 0.0f) {
193380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (scaleFactorY > 1 || sigmaX > 0.0f) {
193480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // Clear out a radius below the srcRect to prevent the Y
193580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // convolution from reading garbage.
193680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
193780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                          srcIRect.width(), radiusY);
193880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this->clear(&clearRect, 0x0);
193980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
194080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
194180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setRenderTarget(dstTexture->asRenderTarget());
194280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrDrawTarget* target = this->prepareToDraw(NULL, DEFAULT_BUFFERING);
194380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        convolve_gaussian(target, srcTexture, srcRect, sigmaY, radiusY,
194480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          Gr1DKernelEffect::kY_Direction);
194580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        srcTexture = dstTexture;
194680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkTSwap(dstTexture, tempTexture);
194780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
194880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
194980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (scaleFactorX > 1 || scaleFactorY > 1) {
195080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Clear one pixel to the right and below, to accommodate bilinear
195180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // upsampling.
195280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
195380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      srcIRect.width() + 1, 1);
195480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->clear(&clearRect, 0x0);
195580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
195680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      1, srcIRect.height());
195780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->clear(&clearRect, 0x0);
1958363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkMatrix matrix;
195980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // FIXME:  This should be mitchell, not bilinear.
196080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        matrix.setIDiv(srcTexture->width(), srcTexture->height());
196180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setRenderTarget(dstTexture->asRenderTarget());
1962d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        paint.colorStage(0)->setEffect(GrSimpleTextureEffect::Create(srcTexture,
1963d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                                     matrix,
1964d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                                     true))->unref();
196580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkRect dstRect(srcRect);
196680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
196780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->drawRectToRect(paint, dstRect, srcRect);
196880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        srcRect = dstRect;
196980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        srcTexture = dstTexture;
197080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkTSwap(dstTexture, tempTexture);
197180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
197280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (srcTexture == temp1.texture()) {
197380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return temp1.detach();
197480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (srcTexture == temp2.texture()) {
197580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return temp2.detach();
197680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
197780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        srcTexture->ref();
197880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return srcTexture;
197980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
198080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
198180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
198280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
198380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_CACHE_STATS
198480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrContext::printCacheStats() const {
198580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTextureCache->printStats();
198680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
198780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
1988