180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkGpuDevice.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "effects/GrTextureDomainEffect.h"
11d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#include "effects/GrSimpleTextureEffect.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrContext.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrTextContext.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkGrTexturePixelRef.h"
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorFilter.h"
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkDeviceImageFilterProxy.h"
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkDrawProcs.h"
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkGlyphCache.h"
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkImageFilter.h"
23363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkPathEffect.h"
24363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkStroke.h"
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkUtils.h"
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define CACHE_COMPATIBLE_DEVICE_TEXTURES 1
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    extern bool (*gShouldDrawProc)();
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CHECK_SHOULD_DRAW(draw, forceI)                     \
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {                                                    \
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (gShouldDrawProc && !gShouldDrawProc()) return;  \
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this->prepareDraw(draw, forceI);                    \
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (0)
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CHECK_SHOULD_DRAW(draw, forceI) this->prepareDraw(draw, forceI)
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// we use the same texture slot on GrPaint for bitmaps and shaders
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// (since drawBitmap, drawSprite, and drawDevice ignore skia's shader)
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruenum {
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kBitmapTextureIdx = 0,
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kShaderTextureIdx = 0,
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kColorFilterTextureIdx = 1
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define MAX_BLUR_SIGMA 4.0f
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// FIXME:  This value comes from from SkBlurMaskFilter.cpp.
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Should probably be put in a common header someplace.
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define MAX_BLUR_RADIUS SkIntToScalar(128)
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// This constant approximates the scaling done in the software path's
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)).
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// IMHO, it actually should be 1:  we blur "less" than we should do
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// according to the CSS and canvas specs, simply because Safari does the same.
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Firefox used to do the same too, until 4.0 where they fixed it.  So at some
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// point we should probably get rid of these scaling constants and rebaseline
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// all the blur tests.
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define BLUR_SIGMA_SCALE 0.6f
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// This constant represents the screen alignment criterion in texels for
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// requiring texture domain clamping to prevent color bleeding when drawing
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// a sub region of a larger source image.
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define COLOR_BLEED_TOLERANCE SkFloatToScalar(0.001f)
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
65363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#define DO_DEFERRED_CLEAR()             \
66363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    do {                                \
67363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (fNeedClear) {               \
68363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->clear(SK_ColorTRANSPARENT); \
69363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }                               \
70363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    } while (false)                     \
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define CHECK_FOR_NODRAW_ANNOTATION(paint) \
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do { if (paint.isNoDrawAnnotation()) { return; } } while (0)
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkGpuDevice::SkAutoCachedTexture : public ::SkNoncopyable {
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoCachedTexture()
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : fDevice(NULL)
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        , fTexture(NULL) {
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoCachedTexture(SkGpuDevice* device,
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        const SkBitmap& bitmap,
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        const GrTextureParams* params,
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        GrTexture** texture)
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : fDevice(NULL)
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        , fTexture(NULL) {
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(NULL != texture);
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *texture = this->set(device, bitmap, params);
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ~SkAutoCachedTexture() {
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL != fTexture) {
99d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            GrUnlockAndUnrefCachedBitmapTexture(fTexture);
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTexture* set(SkGpuDevice* device,
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                   const SkBitmap& bitmap,
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                   const GrTextureParams* params) {
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL != fTexture) {
107d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            GrUnlockAndUnrefCachedBitmapTexture(fTexture);
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fTexture = NULL;
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDevice = device;
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrTexture* result = (GrTexture*)bitmap.getTexture();
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == result) {
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // Cannot return the native texture so look it up in our cache
114d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            fTexture = GrLockAndRefCachedBitmapTexture(device->context(), bitmap, params);
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            result = fTexture;
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return result;
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkGpuDevice* fDevice;
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTexture*   fTexture;
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustruct GrSkDrawProcs : public SkDrawProcs {
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrContext* fContext;
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTextContext* fTextContext;
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrFontScaler* fFontScaler;  // cached in the skia glyphcache
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkBitmap::Config grConfig2skConfig(GrPixelConfig config, bool* isOpaque) {
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (config) {
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kAlpha_8_GrPixelConfig:
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *isOpaque = false;
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkBitmap::kA8_Config;
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kRGB_565_GrPixelConfig:
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *isOpaque = true;
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkBitmap::kRGB_565_Config;
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kRGBA_4444_GrPixelConfig:
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *isOpaque = false;
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkBitmap::kARGB_4444_Config;
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kSkia8888_PM_GrPixelConfig:
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // we don't currently have a way of knowing whether
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // a 8888 is opaque based on the config.
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *isOpaque = false;
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkBitmap::kARGB_8888_Config;
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *isOpaque = false;
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkBitmap::kNo_Config;
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkBitmap make_bitmap(GrContext* context, GrRenderTarget* renderTarget) {
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPixelConfig config = renderTarget->config();
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool isOpaque;
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmap bitmap;
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bitmap.setConfig(grConfig2skConfig(config, &isOpaque),
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                     renderTarget->width(), renderTarget->height());
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bitmap.setIsOpaque(isOpaque);
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return bitmap;
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkGpuDevice::SkGpuDevice(GrContext* context, GrTexture* texture)
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru: SkDevice(make_bitmap(context, texture->asRenderTarget())) {
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->initFromRenderTarget(context, texture->asRenderTarget(), false);
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkGpuDevice::SkGpuDevice(GrContext* context, GrRenderTarget* renderTarget)
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru: SkDevice(make_bitmap(context, renderTarget)) {
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->initFromRenderTarget(context, renderTarget, false);
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::initFromRenderTarget(GrContext* context,
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                       GrRenderTarget* renderTarget,
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                       bool cached) {
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawProcs = NULL;
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext = context;
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->ref();
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRenderTarget = NULL;
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fNeedClear = false;
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(NULL != renderTarget);
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRenderTarget = renderTarget;
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRenderTarget->ref();
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Hold onto to the texture in the pixel ref (if there is one) because the texture holds a ref
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // on the RT but not vice-versa.
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // TODO: Remove this trickery once we figure out how to make SkGrPixelRef do this without
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // busting chrome (for a currently unknown reason).
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrSurface* surface = fRenderTarget->asTexture();
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == surface) {
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        surface = fRenderTarget;
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (surface, cached));
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setPixelRef(pr, 0)->unref();
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkGpuDevice::SkGpuDevice(GrContext* context,
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         SkBitmap::Config config,
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         int width,
210363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                         int height,
211363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                         int sampleCount)
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    : SkDevice(config, width, height, false /*isOpaque*/) {
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawProcs = NULL;
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext = context;
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->ref();
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRenderTarget = NULL;
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fNeedClear = false;
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (config != SkBitmap::kRGB_565_Config) {
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        config = SkBitmap::kARGB_8888_Config;
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTextureDesc desc;
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fFlags = kRenderTarget_GrTextureFlagBit;
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fWidth = width;
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fHeight = height;
230363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    desc.fConfig = SkBitmapConfig2GrPixelConfig(config);
231363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    desc.fSampleCnt = sampleCount;
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoTUnref<GrTexture> texture(fContext->createUncachedTexture(desc, NULL, 0));
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != texture) {
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fRenderTarget = texture->asRenderTarget();
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fRenderTarget->ref();
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(NULL != fRenderTarget);
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // wrap the bitmap with a pixelref to expose our texture
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkGrPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (texture));
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setPixelRef(pr, 0)->unref();
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrPrintf("--- failed to create gpu-offscreen [%d %d]\n",
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 width, height);
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(false);
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkGpuDevice::~SkGpuDevice() {
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fDrawProcs) {
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        delete fDrawProcs;
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // The GrContext takes a ref on the target. We don't want to cause the render
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // target to be unnecessarily kept alive.
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fContext->getRenderTarget() == fRenderTarget) {
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fContext->setRenderTarget(NULL);
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
262363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (fContext->getClip() == &fClipData) {
263363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fContext->setClip(NULL);
264363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
265363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSafeUnref(fRenderTarget);
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->unref();
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::makeRenderTargetCurrent() {
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    DO_DEFERRED_CLEAR();
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->setRenderTarget(fRenderTarget);
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrPixelConfig config8888_to_grconfig_and_flags(SkCanvas::Config8888 config8888, uint32_t* flags) {
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (config8888) {
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkCanvas::kNative_Premul_Config8888:
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *flags = 0;
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return kSkia8888_GrPixelConfig;
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkCanvas::kNative_Unpremul_Config8888:
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *flags = GrContext::kUnpremul_PixelOpsFlag;
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return kSkia8888_PM_GrPixelConfig;
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkCanvas::kBGRA_Premul_Config8888:
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *flags = 0;
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return kBGRA_8888_GrPixelConfig;
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkCanvas::kBGRA_Unpremul_Config8888:
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *flags = GrContext::kUnpremul_PixelOpsFlag;
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return kBGRA_8888_GrPixelConfig;
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkCanvas::kRGBA_Premul_Config8888:
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *flags = 0;
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return kRGBA_8888_GrPixelConfig;
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkCanvas::kRGBA_Unpremul_Config8888:
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *flags = GrContext::kUnpremul_PixelOpsFlag;
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return kRGBA_8888_GrPixelConfig;
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrCrash("Unexpected Config8888.");
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *flags = 0; // suppress warning
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return kSkia8888_PM_GrPixelConfig;
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkGpuDevice::onReadPixels(const SkBitmap& bitmap,
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               int x, int y,
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               SkCanvas::Config8888 config8888) {
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    DO_DEFERRED_CLEAR();
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(!bitmap.isNull());
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height())));
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoLockPixels alp(bitmap);
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPixelConfig config;
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t flags;
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    config = config8888_to_grconfig_and_flags(config8888, &flags);
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fContext->readRenderTargetPixels(fRenderTarget,
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            x, y,
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            bitmap.width(),
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            bitmap.height(),
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            config,
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            bitmap.getPixels(),
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            bitmap.rowBytes(),
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            flags);
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y,
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              SkCanvas::Config8888 config8888) {
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoLockPixels alp(bitmap);
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!bitmap.readyToDraw()) {
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPixelConfig config;
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t flags;
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkBitmap::kARGB_8888_Config == bitmap.config()) {
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        config = config8888_to_grconfig_and_flags(config8888, &flags);
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        flags = 0;
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        config= SkBitmapConfig2GrPixelConfig(bitmap.config());
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRenderTarget->writePixels(x, y, bitmap.width(), bitmap.height(),
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               config, bitmap.getPixels(), bitmap.rowBytes(), flags);
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
351d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergervoid purgeClipCB(int genID, void* ) {
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkClipStack::kInvalidGenID == genID ||
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkClipStack::kEmptyGenID == genID ||
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkClipStack::kWideOpenGenID == genID) {
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // none of these cases will have a cached clip mask
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::onAttachToCanvas(SkCanvas* canvas) {
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    INHERITED::onAttachToCanvas(canvas);
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Canvas promises that this ptr is valid until onDetachFromCanvas is called
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fClipData.fClipStack = canvas->getClipStack();
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fClipData.fClipStack->addPurgeClipCallback(purgeClipCB, fContext);
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::onDetachFromCanvas() {
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    INHERITED::onDetachFromCanvas();
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // TODO: iterate through the clip stack and clean up any cached clip masks
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fClipData.fClipStack->removePurgeClipCallback(purgeClipCB, fContext);
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fClipData.fClipStack = NULL;
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void check_bounds(const GrClipData& clipData,
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const SkRegion& clipRegion,
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         int renderTargetWidth,
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         int renderTargetHeight) {
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect devBound;
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    devBound.setLTRB(0, 0, renderTargetWidth, renderTargetHeight);
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkClipStack::BoundsType boundType;
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect canvTemp;
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    clipData.fClipStack->getBounds(&canvTemp, &boundType);
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkClipStack::kNormal_BoundsType == boundType) {
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkIRect devTemp;
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        canvTemp.roundOut(&devTemp);
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        devTemp.offset(-clipData.fOrigin.fX, -clipData.fOrigin.fY);
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!devBound.intersect(devTemp)) {
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            devBound.setEmpty();
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(devBound.contains(clipRegion.getBounds()));
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// call this every draw call, to ensure that the context reflects our state,
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// and not the state from some other canvas/device
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::prepareDraw(const SkDraw& draw, bool forceIdentity) {
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(NULL != fClipData.fClipStack);
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->setRenderTarget(fRenderTarget);
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(draw.fClipStack && draw.fClipStack == fClipData.fClipStack);
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (forceIdentity) {
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fContext->setIdentityMatrix();
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fContext->setMatrix(*draw.fMatrix);
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fClipData.fOrigin = this->getOrigin();
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    check_bounds(fClipData, *draw.fClip, fRenderTarget->width(), fRenderTarget->height());
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->setClip(&fClipData);
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    DO_DEFERRED_CLEAR();
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkGpuRenderTarget* SkGpuDevice::accessRenderTarget() {
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    DO_DEFERRED_CLEAR();
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return (SkGpuRenderTarget*)fRenderTarget;
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkGpuDevice::bindDeviceAsTexture(GrPaint* paint) {
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTexture* texture = fRenderTarget->asTexture();
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != texture) {
446363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        paint->colorStage(kBitmapTextureIdx)->setEffect(
447d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            GrSimpleTextureEffect::Create(texture, SkMatrix::I()))->unref();
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_COMPILE_ASSERT(SkShader::kNone_BitmapType == 0, shader_type_mismatch);
45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_COMPILE_ASSERT(SkShader::kDefault_BitmapType == 1, shader_type_mismatch);
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_COMPILE_ASSERT(SkShader::kRadial_BitmapType == 2, shader_type_mismatch);
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_COMPILE_ASSERT(SkShader::kSweep_BitmapType == 3, shader_type_mismatch);
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_COMPILE_ASSERT(SkShader::kTwoPointRadial_BitmapType == 4,
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                  shader_type_mismatch);
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_COMPILE_ASSERT(SkShader::kTwoPointConical_BitmapType == 5,
46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                  shader_type_mismatch);
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_COMPILE_ASSERT(SkShader::kLinear_BitmapType == 6, shader_type_mismatch);
46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_COMPILE_ASSERT(SkShader::kLast_BitmapType == 6, shader_type_mismatch);
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// converts a SkPaint to a GrPaint, ignoring the skPaint's shader
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// justAlpha indicates that skPaint's alpha should be used rather than the color
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Callers may subsequently modify the GrPaint. Setting constantColor indicates
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// that the final paint will draw the same color at every pixel. This allows
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// an optimization where the the color filter can be applied to the skPaint's
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// color once while converting to GrPaint and then ignored.
47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruinline bool skPaint2GrPaintNoShader(SkGpuDevice* dev,
47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    const SkPaint& skPaint,
47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    bool justAlpha,
47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    bool constantColor,
47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    GrPaint* grPaint) {
47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    grPaint->setDither(skPaint.isDither());
48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    grPaint->setAntiAlias(skPaint.isAntiAlias());
48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermode::Coeff sm = SkXfermode::kOne_Coeff;
48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermode::Coeff dm = SkXfermode::kISA_Coeff;
48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermode* mode = skPaint.getXfermode();
48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (mode) {
48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!mode->asCoeff(&sm, &dm)) {
48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
49380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    grPaint->setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm));
49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (justAlpha) {
49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        uint8_t alpha = skPaint.getAlpha();
49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        grPaint->setColor(GrColorPackRGBA(alpha, alpha, alpha, alpha));
50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // justAlpha is currently set to true only if there is a texture,
50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // so constantColor should not also be true.
50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(!constantColor);
50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        grPaint->setColor(SkColor2GrColor(skPaint.getColor()));
50580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(!grPaint->isColorStageEnabled(kShaderTextureIdx));
50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
507363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkColorFilter* colorFilter = skPaint.getColorFilter();
509363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (NULL != colorFilter) {
510363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // if the source color is a constant then apply the filter here once rather than per pixel
511363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // in a shader.
512363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (constantColor) {
51380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkColor filtered = colorFilter->filterColor(skPaint.getColor());
51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            grPaint->setColor(SkColor2GrColor(filtered));
515363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        } else {
516d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            SkAutoTUnref<GrEffectRef> effect(colorFilter->asNewEffect(dev->context()));
517363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            if (NULL != effect.get()) {
518363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                grPaint->colorStage(kColorFilterTextureIdx)->setEffect(effect);
519363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            } else {
520363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                // TODO: rewrite this using asNewEffect()
521363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                SkColor color;
522363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                SkXfermode::Mode filterMode;
523363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                if (colorFilter->asColorMode(&color, &filterMode)) {
524363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    grPaint->setXfermodeColorFilter(filterMode, SkColor2GrColor(color));
525363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                }
526363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
52880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
529363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
53080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
53180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
53280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// This function is similar to skPaint2GrPaintNoShader but also converts
534363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// skPaint's shader to a GrTexture/GrEffectStage if possible. The texture to
53580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// be used is set on grPaint and returned in param act. constantColor has the
53680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// same meaning as in skPaint2GrPaintNoShader.
53780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruinline bool skPaint2GrPaintShader(SkGpuDevice* dev,
53880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  const SkPaint& skPaint,
53980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  bool constantColor,
54080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  GrPaint* grPaint) {
54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkShader* shader = skPaint.getShader();
54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == shader) {
543d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return skPaint2GrPaintNoShader(dev, skPaint, false, constantColor, grPaint);
544d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    } else if (!skPaint2GrPaintNoShader(dev, skPaint, true, false, grPaint)) {
54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
548d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkAutoTUnref<GrEffectRef> effect(shader->asNewEffect(dev->context(), skPaint));
549d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (NULL != effect.get()) {
550d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        grPaint->colorStage(kShaderTextureIdx)->setEffect(effect);
55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
554d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // We still don't have SkColorShader::asNewEffect() implemented.
555d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkShader::GradientInfo info;
556d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkColor                color;
55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
558d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    info.fColors = &color;
559d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    info.fColorOffsets = NULL;
560d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    info.fColorCount = 1;
561d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (SkShader::kColor_GradientType == shader->asAGradient(&info)) {
562d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkPaint copy(skPaint);
563d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        copy.setShader(NULL);
564d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        // modulate the paint alpha by the shader's solid color alpha
565d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        U8CPU newA = SkMulDiv255Round(SkColorGetA(color), copy.getAlpha());
566d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        copy.setColor(SkColorSetA(color, newA));
567d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return skPaint2GrPaintNoShader(dev, copy, false, constantColor, grPaint);
568363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
569d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    return false;
57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
57280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
57480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::clear(SkColor color) {
575d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
576d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    fContext->clear(&rect, SkColor2GrColor(color), fRenderTarget);
57780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fNeedClear = false;
57880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
58180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CHECK_SHOULD_DRAW(draw, false);
58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
58380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPaint grPaint;
584d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
58780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
58880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->drawPaint(grPaint);
58980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
59080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
59180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// must be in SkCanvas::PointMode order
59280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const GrPrimitiveType gPointMode2PrimtiveType[] = {
59380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kPoints_GrPrimitiveType,
59480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kLines_GrPrimitiveType,
59580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kLineStrip_GrPrimitiveType
59680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
59780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
59880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
59980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             size_t count, const SkPoint pts[], const SkPaint& paint) {
60080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CHECK_SHOULD_DRAW(draw, false);
60180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar width = paint.getStrokeWidth();
60380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (width < 0) {
60480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
60580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
60680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we only handle hairlines and paints without path effects or mask filters,
60880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // else we let the SkDraw call our drawPath()
60980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (width > 0 || paint.getPathEffect() || paint.getMaskFilter()) {
61080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        draw.drawPoints(mode, count, pts, paint, true);
61180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
61280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
61380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPaint grPaint;
615d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
61680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
61780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->drawVertices(grPaint,
62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           gPointMode2PrimtiveType[mode],
62180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           count,
62280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           (GrPoint*)pts,
62380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           NULL,
62480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           NULL,
62580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           NULL,
62680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           0);
62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
63080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
63280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           const SkPaint& paint) {
63380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CHECK_FOR_NODRAW_ANNOTATION(paint);
63480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CHECK_SHOULD_DRAW(draw, false);
63580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool doStroke = paint.getStyle() != SkPaint::kFill_Style;
63780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar width = paint.getStrokeWidth();
63880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /*
64080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        We have special code for hairline strokes, miter-strokes, and fills.
64180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Anything else we just call our path code.
64280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
64380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool usePath = doStroke && width > 0 &&
64480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    paint.getStrokeJoin() != SkPaint::kMiter_Join;
64580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // another two reasons we might need to call drawPath...
64680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (paint.getMaskFilter() || paint.getPathEffect()) {
64780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        usePath = true;
64880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
64980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // until we aa rotated rects...
65080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!usePath && paint.isAntiAlias() && !fContext->getMatrix().rectStaysRect()) {
65180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        usePath = true;
65280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
65380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // small miter limit means right angles show bevel...
65480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkPaint::kMiter_Join == paint.getStrokeJoin() &&
65580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.getStrokeMiter() < SK_ScalarSqrt2)
65680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
65780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        usePath = true;
65880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
65980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // until we can both stroke and fill rectangles
66080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (paint.getStyle() == SkPaint::kStrokeAndFill_Style) {
66180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        usePath = true;
66280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
66380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
66480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (usePath) {
66580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPath path;
66680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        path.addRect(rect);
66780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->drawPath(draw, path, paint, NULL, true);
66880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
66980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
67080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
67180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPaint grPaint;
672d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
67380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
67480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
67580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->drawRect(grPaint, rect, doStroke ? width : -1);
67680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
67780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
678d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
679d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
680d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergervoid SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval,
681d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                           const SkPaint& paint) {
682d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    CHECK_FOR_NODRAW_ANNOTATION(paint);
683d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    CHECK_SHOULD_DRAW(draw, false);
684d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
685d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    bool usePath = false;
686d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // some basic reasons we might need to call drawPath...
687d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (paint.getMaskFilter() || paint.getPathEffect()) {
688d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        usePath = true;
689d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
690d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
691d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (usePath) {
692d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkPath path;
693d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        path.addOval(oval);
694d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        this->drawPath(draw, path, paint, NULL, true);
695d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return;
696d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
697d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
698d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrPaint grPaint;
699d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
700d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return;
701d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
702d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkStrokeRec stroke(paint);
703d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
704d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    fContext->drawOval(grPaint, oval, stroke);
705d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
706d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
70780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMaskFilter.h"
70880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkBounder.h"
70980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
71080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
71180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
71280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// helpers for applying mask filters
71380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
71480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
71580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// We prefer to blur small rect with small radius via CPU.
71680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define MIN_GPU_BLUR_SIZE SkIntToScalar(64)
71780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define MIN_GPU_BLUR_RADIUS SkIntToScalar(32)
71880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruinline bool shouldDrawBlurWithCPU(const SkRect& rect, SkScalar radius) {
71980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (rect.width() <= MIN_GPU_BLUR_SIZE &&
72080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rect.height() <= MIN_GPU_BLUR_SIZE &&
72180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        radius <= MIN_GPU_BLUR_RADIUS) {
72280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
72380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
72480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
72580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
72680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
727363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath, const SkStrokeRec& stroke,
72880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           SkMaskFilter* filter, const SkRegion& clip,
729363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                           SkBounder* bounder, GrPaint* grp) {
73080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMaskFilter::BlurInfo info;
73180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMaskFilter::BlurType blurType = filter->asABlur(&info);
73280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkMaskFilter::kNone_BlurType == blurType) {
73380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
73480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
73580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar radius = info.fIgnoreTransform ? info.fRadius
73680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            : context->getMatrix().mapRadius(info.fRadius);
73780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    radius = SkMinScalar(radius, MAX_BLUR_RADIUS);
73880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (radius <= 0) {
73980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
74080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
74180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
74280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect srcRect = devPath.getBounds();
74380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (shouldDrawBlurWithCPU(srcRect, radius)) {
74480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
74580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
74680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
74780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float sigma = SkScalarToFloat(radius) * BLUR_SIGMA_SCALE;
74880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float sigma3 = sigma * 3.0f;
74980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
75080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect clipRect;
75180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    clipRect.set(clip.getBounds());
75280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
75380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Outset srcRect and clipRect by 3 * sigma, to compute affected blur area.
75480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    srcRect.inset(SkFloatToScalar(-sigma3), SkFloatToScalar(-sigma3));
75580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    clipRect.inset(SkFloatToScalar(-sigma3), SkFloatToScalar(-sigma3));
75680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    srcRect.intersect(clipRect);
75780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect finalRect = srcRect;
75880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect finalIRect;
75980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    finalRect.roundOut(&finalIRect);
76080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (clip.quickReject(finalIRect)) {
76180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
76280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
76380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (bounder && !bounder->doIRect(finalIRect)) {
76480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
76580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
76680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPoint offset = GrPoint::Make(-srcRect.fLeft, -srcRect.fTop);
76780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    srcRect.offset(offset);
76880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTextureDesc desc;
76980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fFlags = kRenderTarget_GrTextureFlagBit;
77080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fWidth = SkScalarCeilToInt(srcRect.width());
77180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fHeight = SkScalarCeilToInt(srcRect.height());
77280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // We actually only need A8, but it often isn't supported as a
77380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // render target so default to RGBA_8888
77480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fConfig = kRGBA_8888_GrPixelConfig;
77580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
77680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (context->isConfigRenderable(kAlpha_8_GrPixelConfig)) {
77780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        desc.fConfig = kAlpha_8_GrPixelConfig;
77880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
77980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
78080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAutoScratchTexture pathEntry(context, desc);
78180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTexture* pathTexture = pathEntry.texture();
78280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == pathTexture) {
78380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
78480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
78580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
78680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoTUnref<GrTexture> blurTexture;
78780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
78880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
78980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrContext::AutoRenderTarget art(context, pathTexture->asRenderTarget());
79080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrContext::AutoClip ac(context, srcRect);
79180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
79280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        context->clear(NULL, 0);
79380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
79480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrPaint tempPaint;
79580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (grp->isAntiAlias()) {
79680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tempPaint.setAntiAlias(true);
79780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // AA uses the "coverage" stages on GrDrawTarget. Coverage with a dst
79880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // blend coeff of zero requires dual source blending support in order
79980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // to properly blend partially covered pixels. This means the AA
80080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // code path may not be taken. So we use a dst blend coeff of ISA. We
80180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // could special case AA draws to a dst surface with known alpha=0 to
80280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // use a zero dst coeff when dual source blending isn't available.f
80380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tempPaint.setBlendFunc(kOne_GrBlendCoeff, kISC_GrBlendCoeff);
80480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
80580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
80680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrContext::AutoMatrix am;
80780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
80880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Draw hard shadow to pathTexture with path top-left at origin using tempPaint.
809363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkMatrix translate;
81080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        translate.setTranslate(offset.fX, offset.fY);
81180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        am.set(context, translate);
812363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        context->drawPath(tempPaint, devPath, stroke);
81380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
81480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // If we're doing a normal blur, we can clobber the pathTexture in the
81580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // gaussianBlur.  Otherwise, we need to save it for later compositing.
81680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool isNormalBlur = blurType == SkMaskFilter::kNormal_BlurType;
81780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        blurTexture.reset(context->gaussianBlur(pathTexture, isNormalBlur,
81880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                srcRect, sigma, sigma));
819363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (NULL == blurTexture) {
820363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            return false;
821363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
82280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
82380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!isNormalBlur) {
82480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            context->setIdentityMatrix();
82580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrPaint paint;
826363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkMatrix matrix;
82780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            matrix.setIDiv(pathTexture->width(), pathTexture->height());
82880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // Blend pathTexture over blurTexture.
82980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            context->setRenderTarget(blurTexture->asRenderTarget());
830d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            paint.colorStage(0)->setEffect(
831d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                GrSimpleTextureEffect::Create(pathTexture, matrix))->unref();
83280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (SkMaskFilter::kInner_BlurType == blurType) {
83380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // inner:  dst = dst * src
83480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                paint.setBlendFunc(kDC_GrBlendCoeff, kZero_GrBlendCoeff);
83580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else if (SkMaskFilter::kSolid_BlurType == blurType) {
83680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // solid:  dst = src + dst - src * dst
83780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                //             = (1 - dst) * src + 1 * dst
83880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                paint.setBlendFunc(kIDC_GrBlendCoeff, kOne_GrBlendCoeff);
83980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else if (SkMaskFilter::kOuter_BlurType == blurType) {
84080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // outer:  dst = dst * (1 - src)
84180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                //             = 0 * src + (1 - src) * dst
84280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                paint.setBlendFunc(kZero_GrBlendCoeff, kISC_GrBlendCoeff);
84380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
84480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            context->drawRect(paint, srcRect);
84580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
84680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
84780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
84880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrContext::AutoMatrix am;
84980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!am.setIdentity(context, grp)) {
85080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
85180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
85280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
85380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const int MASK_IDX = GrPaint::kMaxCoverageStages - 1;
85480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we assume the last mask index is available for use
85580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(!grp->isCoverageStageEnabled(MASK_IDX));
85680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
857363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMatrix matrix;
85880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    matrix.setTranslate(-finalRect.fLeft, -finalRect.fTop);
85980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    matrix.postIDiv(blurTexture->width(), blurTexture->height());
86080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
861363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    grp->coverageStage(MASK_IDX)->reset();
862d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    grp->coverageStage(MASK_IDX)->setEffect(
863d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        GrSimpleTextureEffect::Create(blurTexture, matrix))->unref();
86480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    context->drawRect(*grp, finalRect);
86580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
86680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
86780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
86880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool drawWithMaskFilter(GrContext* context, const SkPath& devPath,
86980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkMaskFilter* filter, const SkRegion& clip, SkBounder* bounder,
87080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        GrPaint* grp, SkPaint::Style style) {
87180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMask  srcM, dstM;
87280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
87380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!SkDraw::DrawToMask(devPath, &clip.getBounds(), filter, &context->getMatrix(), &srcM,
87480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkMask::kComputeBoundsAndRenderImage_CreateMode, style)) {
87580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
87680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
87780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoMaskFreeImage autoSrc(srcM.fImage);
87880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
87980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!filter->filterMask(&dstM, srcM, context->getMatrix(), NULL)) {
88080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
88180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
88280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // this will free-up dstM when we're done (allocated in filterMask())
88380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoMaskFreeImage autoDst(dstM.fImage);
88480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
88580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (clip.quickReject(dstM.fBounds)) {
88680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
88780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
88880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (bounder && !bounder->doIRect(dstM.fBounds)) {
88980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
89080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
89180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
89280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we now have a device-aligned 8bit mask in dstM, ready to be drawn using
89380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // the current clip (and identity matrix) and GrPaint settings
89480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrContext::AutoMatrix am;
89580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    am.setIdentity(context, grp);
89680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
89780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTextureDesc desc;
89880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fWidth = dstM.fBounds.width();
89980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fHeight = dstM.fBounds.height();
90080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fConfig = kAlpha_8_GrPixelConfig;
90180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
90280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAutoScratchTexture ast(context, desc);
90380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTexture* texture = ast.texture();
90480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
90580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == texture) {
90680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
90780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
90880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
90980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               dstM.fImage, dstM.fRowBytes);
91080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
91180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const int MASK_IDX = GrPaint::kMaxCoverageStages - 1;
91280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we assume the last mask index is available for use
91380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(!grp->isCoverageStageEnabled(MASK_IDX));
91480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
915363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMatrix m;
91680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.setTranslate(-dstM.fBounds.fLeft*SK_Scalar1, -dstM.fBounds.fTop*SK_Scalar1);
91780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.postIDiv(texture->width(), texture->height());
91880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
919d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    grp->coverageStage(MASK_IDX)->setEffect(GrSimpleTextureEffect::Create(texture, m))->unref();
92080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrRect d;
921363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    d.setLTRB(SkIntToScalar(dstM.fBounds.fLeft),
922363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger              SkIntToScalar(dstM.fBounds.fTop),
923363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger              SkIntToScalar(dstM.fBounds.fRight),
924363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger              SkIntToScalar(dstM.fBounds.fBottom));
92580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
92680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    context->drawRect(*grp, d);
92780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
92880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
92980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
93080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
93180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
93280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
93380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
93480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
93580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           const SkPaint& paint, const SkMatrix* prePathMatrix,
93680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           bool pathIsMutable) {
93780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CHECK_FOR_NODRAW_ANNOTATION(paint);
93880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CHECK_SHOULD_DRAW(draw, false);
93980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
94080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPaint grPaint;
941d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
94280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
94380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
94480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
945d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // can we cheat, and treat a thin stroke as a hairline w/ coverage
94680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // if we can, we draw lots faster (raster device does this same test)
94780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar hairlineCoverage;
948363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    bool doHairLine = SkDrawTreatAsHairline(paint, fContext->getMatrix(), &hairlineCoverage);
949363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (doHairLine) {
95080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        grPaint.setCoverage(SkScalarRoundToInt(hairlineCoverage * grPaint.getCoverage()));
95180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
95280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
95380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // If we have a prematrix, apply it to the path, optimizing for the case
95480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // where the original path can in fact be modified in place (even though
95580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // its parameter type is const).
95680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
957363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkPath  tmpPath, effectPath;
95880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
95980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (prePathMatrix) {
96080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPath* result = pathPtr;
96180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
96280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!pathIsMutable) {
96380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            result = &tmpPath;
96480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            pathIsMutable = true;
96580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
96680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // should I push prePathMatrix on our MV stack temporarily, instead
96780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // of applying it here? See SkDraw.cpp
96880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        pathPtr->transform(*prePathMatrix, result);
96980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        pathPtr = result;
97080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
97180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // at this point we're done with prePathMatrix
97280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
97380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
974363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkStrokeRec stroke(paint);
975363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkPathEffect* pathEffect = paint.getPathEffect();
976d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    const SkRect* cullRect = NULL;  // TODO: what is our bounds?
977d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (pathEffect && pathEffect->filterPath(&effectPath, *pathPtr, &stroke,
978d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                             cullRect)) {
979363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        pathPtr = &effectPath;
980363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
981363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
982363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (!pathEffect && doHairLine) {
983363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        stroke.setHairlineStyle();
98480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
98580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
98680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (paint.getMaskFilter()) {
987363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (!stroke.isHairlineStyle()) {
988363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            if (stroke.applyToPath(&tmpPath, *pathPtr)) {
989363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                pathPtr = &tmpPath;
990363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                stroke.setFillStyle();
991363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
992363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
993363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
99480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // avoid possibly allocating a new path in transform if we can
99580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
99680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
99780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // transform the path into device space
99880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        pathPtr->transform(fContext->getMatrix(), devPathPtr);
999363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (!drawWithGPUMaskFilter(fContext, *devPathPtr, stroke, paint.getMaskFilter(),
1000363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                   *draw.fClip, draw.fBounder, &grPaint)) {
1001363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkPaint::Style style = stroke.isHairlineStyle() ? SkPaint::kStroke_Style :
1002363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                                              SkPaint::kFill_Style;
100380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
100480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               *draw.fClip, draw.fBounder, &grPaint, style);
100580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
100680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
100780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
100880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1009363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fContext->drawPath(grPaint, *pathPtr, stroke);
101080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
101180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
101280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
101380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
101480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruinline int get_tile_count(int l, int t, int r, int b, int tileSize)  {
101580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int tilesX = (r / tileSize) - (l / tileSize) + 1;
101680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int tilesY = (b / tileSize) - (t / tileSize) + 1;
101780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return tilesX * tilesY;
101880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
101980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
102080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruinline int determine_tile_size(const SkBitmap& bitmap,
102180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               const SkRect& src,
102280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               int maxTextureSize) {
102380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const int kSmallTileSize = 1 << 10;
102480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (maxTextureSize <= kSmallTileSize) {
102580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return maxTextureSize;
102680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
102780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
102880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t maxTexTotalTileSize;
102980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t smallTotalTileSize;
103080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
103180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect iSrc;
103280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    src.roundOut(&iSrc);
103380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
103480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    maxTexTotalTileSize = get_tile_count(iSrc.fLeft,
103580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                         iSrc.fTop,
103680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                         iSrc.fRight,
103780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                         iSrc.fBottom,
103880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                         maxTextureSize);
103980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    smallTotalTileSize = get_tile_count(iSrc.fLeft,
104080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        iSrc.fTop,
104180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        iSrc.fRight,
104280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        iSrc.fBottom,
104380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        kSmallTileSize);
104480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
104580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    maxTexTotalTileSize *= maxTextureSize * maxTextureSize;
104680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    smallTotalTileSize *= kSmallTileSize * kSmallTileSize;
104780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
104880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (maxTexTotalTileSize > 2 * smallTotalTileSize) {
104980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return kSmallTileSize;
105080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
105180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return maxTextureSize;
105280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
105380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
105480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
105580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
105680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
105780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   const GrTextureParams& params,
105880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   const SkRect* srcRectPtr) const {
105980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // if bitmap is explictly texture backed then just use the texture
106080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != bitmap.getTexture()) {
106180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
106280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
106380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // if it's larger than the max texture size, then we have no choice but
106480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // tiling
106580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const int maxTextureSize = fContext->getMaxTextureSize();
106680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (bitmap.width() > maxTextureSize ||
106780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bitmap.height() > maxTextureSize) {
106880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
106980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
107080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // if we are going to have to draw the whole thing, then don't tile
107180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == srcRectPtr) {
107280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
107380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
107480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // if the entire texture is already in our cache then no reason to tile it
1075d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (GrIsBitmapInCache(fContext, bitmap, &params)) {
107680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
107780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
107880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
107980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // At this point we know we could do the draw by uploading the entire bitmap
108080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // as a texture. However, if the texture would be large compared to the
108180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // cache size and we don't require most of it for this draw then tile to
108280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // reduce the amount of upload and cache spill.
108380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
108480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // assumption here is that sw bitmap size is a good proxy for its size as
108580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // a texture
108680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t bmpSize = bitmap.getSize();
108780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t cacheSize;
108880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->getTextureCacheLimits(NULL, &cacheSize);
108980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (bmpSize < cacheSize / 2) {
109080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
109180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
109280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
109380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar fracUsed = SkScalarMul(srcRectPtr->width() / bitmap.width(),
109480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    srcRectPtr->height() / bitmap.height());
109580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fracUsed <= SK_ScalarHalf) {
109680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
109780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
109880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
109980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
110080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
110180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
110280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawBitmap(const SkDraw& draw,
110380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const SkBitmap& bitmap,
110480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const SkIRect* srcRectPtr,
110580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const SkMatrix& m,
110680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const SkPaint& paint) {
110780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
110880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect  tmp;
110980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect* tmpPtr = NULL;
111080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
111180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // convert from SkIRect to SkRect
111280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != srcRectPtr) {
111380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp.set(*srcRectPtr);
111480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmpPtr = &tmp;
111580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
111680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
111780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // We cannot call drawBitmapRect here since 'm' could be anything
111880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->drawBitmapCommon(draw, bitmap, tmpPtr, m, paint);
111980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
112080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
112180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
112280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   const SkBitmap& bitmap,
112380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   const SkRect* srcRectPtr,
112480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   const SkMatrix& m,
112580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   const SkPaint& paint) {
112680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CHECK_SHOULD_DRAW(draw, false);
112780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
112880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect srcRect;
112980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == srcRectPtr) {
113080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        srcRect.set(0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
113180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
113280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        srcRect = *srcRectPtr;
113380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
113480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
113580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (paint.getMaskFilter()){
113680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Convert the bitmap to a shader so that the rect can be drawn
113780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // through drawRect, which supports mask filters.
113880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkMatrix        newM(m);
113980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkBitmap        tmp;    // subset of bitmap, if necessary
114080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkBitmap* bitmapPtr = &bitmap;
114180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL != srcRectPtr) {
114280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkIRect iSrc;
114380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            srcRect.roundOut(&iSrc);
114480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!bitmap.extractSubset(&tmp, iSrc)) {
114580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return;     // extraction failed
114680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
114780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            bitmapPtr = &tmp;
114880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            srcRect.offset(SkIntToScalar(-iSrc.fLeft), SkIntToScalar(-iSrc.fTop));
114980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // The source rect has changed so update the matrix
115080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            newM.preTranslate(SkIntToScalar(iSrc.fLeft), SkIntToScalar(iSrc.fTop));
115180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
115280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
115380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPaint paintWithTexture(paint);
115480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paintWithTexture.setShader(SkShader::CreateBitmapShader(*bitmapPtr,
115580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkShader::kClamp_TileMode, SkShader::kClamp_TileMode))->unref();
115680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
115780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Transform 'newM' needs to be concatenated to the current matrix,
115880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // rather than transforming the primitive directly, so that 'newM' will
115980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // also affect the behavior of the mask filter.
116080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkMatrix drawMatrix;
116180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        drawMatrix.setConcat(fContext->getMatrix(), newM);
116280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDraw transformedDraw(draw);
116380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        transformedDraw.fMatrix = &drawMatrix;
116480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
116580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->drawRect(transformedDraw, srcRect, paintWithTexture);
116680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
116780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
116880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
116980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
117080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPaint grPaint;
1171d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1172d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    bool alphaOnly = !(SkBitmap::kA8_Config == bitmap.config());
1173d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (!skPaint2GrPaintNoShader(this, paint, alphaOnly, false, &grPaint)) {
117480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
117580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
117680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTextureParams params;
117780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    params.setBilerp(paint.isFilterBitmap());
117880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
117980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!this->shouldTileBitmap(bitmap, params, srcRectPtr)) {
118080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // take the simple case
118180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->internalDrawBitmap(bitmap, srcRect, m, params, &grPaint);
118280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
118380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->drawTiledBitmap(bitmap, srcRect, m, params, &grPaint);
118480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
118580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
118680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
118780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Break 'bitmap' into several tiles to draw it since it has already
118880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// been determined to be too large to fit in VRAM
118980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
119080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  const SkRect& srcRect,
119180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  const SkMatrix& m,
119280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  const GrTextureParams& params,
119380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  GrPaint* grPaint) {
119480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const int maxTextureSize = fContext->getMaxTextureSize();
119580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
119680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int tileSize = determine_tile_size(bitmap, srcRect, maxTextureSize);
119780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
119880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // compute clip bounds in local coordinates
119980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect clipRect;
120080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
120180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const GrRenderTarget* rt = fContext->getRenderTarget();
120280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        clipRect.setWH(SkIntToScalar(rt->width()), SkIntToScalar(rt->height()));
120380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!fContext->getClip()->fClipStack->intersectRectWithClip(&clipRect)) {
120480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
120580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
120680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkMatrix matrix, inverse;
120780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        matrix.setConcat(fContext->getMatrix(), m);
120880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!matrix.invert(&inverse)) {
120980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
121080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
121180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        inverse.mapRect(&clipRect);
121280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
121380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
121480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int nx = bitmap.width() / tileSize;
121580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int ny = bitmap.height() / tileSize;
121680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int x = 0; x <= nx; x++) {
121780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int y = 0; y <= ny; y++) {
121880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkRect tileR;
121980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tileR.set(SkIntToScalar(x * tileSize),
122080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      SkIntToScalar(y * tileSize),
122180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      SkIntToScalar((x + 1) * tileSize),
122280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      SkIntToScalar((y + 1) * tileSize));
122380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
122480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!SkRect::Intersects(tileR, clipRect)) {
122580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                continue;
122680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
122780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
122880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!tileR.intersect(srcRect)) {
122980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                continue;
123080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
123180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
123280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkBitmap tmpB;
123380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkIRect iTileR;
123480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tileR.roundOut(&iTileR);
123580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (bitmap.extractSubset(&tmpB, iTileR)) {
123680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // now offset it to make it "local" to our tmp bitmap
123780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                tileR.offset(SkIntToScalar(-iTileR.fLeft), SkIntToScalar(-iTileR.fTop));
123880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkMatrix tmpM(m);
123980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                tmpM.preTranslate(SkIntToScalar(iTileR.fLeft),
124080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  SkIntToScalar(iTileR.fTop));
124180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
124280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                this->internalDrawBitmap(tmpB, tileR, tmpM, params, grPaint);
124380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
124480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
124580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
124680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
124780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
124880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
124980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
125080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool hasAlignedSamples(const SkRect& srcRect, const SkRect& transformedRect) {
125180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // detect pixel disalignment
125280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) -
125380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            transformedRect.left()) < COLOR_BLEED_TOLERANCE &&
125480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalarAbs(SkScalarRoundToScalar(transformedRect.top()) -
125580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            transformedRect.top()) < COLOR_BLEED_TOLERANCE &&
125680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalarAbs(transformedRect.width() - srcRect.width()) <
125780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            COLOR_BLEED_TOLERANCE &&
125880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalarAbs(transformedRect.height() - srcRect.height()) <
125980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            COLOR_BLEED_TOLERANCE) {
126080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
126180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
126280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
126380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
126480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
126580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool mayColorBleed(const SkRect& srcRect, const SkRect& transformedRect,
126680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                   const SkMatrix& m) {
126780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Only gets called if hasAlignedSamples returned false.
126880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // So we can assume that sampling is axis aligned but not texel aligned.
126980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(!hasAlignedSamples(srcRect, transformedRect));
127080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect innerSrcRect(srcRect), innerTransformedRect,
127180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        outerTransformedRect(transformedRect);
127280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf);
127380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    m.mapRect(&innerTransformedRect, innerSrcRect);
127480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
127580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // The gap between outerTransformedRect and innerTransformedRect
127680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // represents the projection of the source border area, which is
127780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // problematic for color bleeding.  We must check whether any
127880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // destination pixels sample the border area.
127980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    outerTransformedRect.inset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
128080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    innerTransformedRect.outset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
128180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect outer, inner;
128280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    outerTransformedRect.round(&outer);
128380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    innerTransformedRect.round(&inner);
128480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // If the inner and outer rects round to the same result, it means the
128580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // border does not overlap any pixel centers. Yay!
128680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return inner != outer;
128780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
128880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
128980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} // unnamed namespace
129080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
129180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
129280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  This is called by drawBitmap(), which has to handle images that may be too
129380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  large to be represented by a single texture.
129480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
129580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  internalDrawBitmap assumes that the specified bitmap will fit in a texture
129680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  and that non-texture portion of the GrPaint has already been setup.
129780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
129880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
129980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     const SkRect& srcRect,
130080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     const SkMatrix& m,
130180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     const GrTextureParams& params,
130280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     GrPaint* grPaint) {
130380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() &&
130480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             bitmap.height() <= fContext->getMaxTextureSize());
130580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
130680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoLockPixels alp(bitmap, !bitmap.getTexture());
130780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
130880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDebugf("nothing to draw\n");
130980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
131080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
131180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
131280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTexture* texture;
131380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoCachedTexture act(this, bitmap, &params, &texture);
131480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == texture) {
131580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
131680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
131780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
131880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrRect dstRect(srcRect);
131980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrRect paintRect;
132080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar wInv = SkScalarInvert(SkIntToScalar(bitmap.width()));
132180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar hInv = SkScalarInvert(SkIntToScalar(bitmap.height()));
132280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    paintRect.setLTRB(SkScalarMul(srcRect.fLeft,   wInv),
132380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      SkScalarMul(srcRect.fTop,    hInv),
132480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      SkScalarMul(srcRect.fRight,  wInv),
132580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      SkScalarMul(srcRect.fBottom, hInv));
132680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
132780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool needsTextureDomain = false;
132880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (params.isBilerp()) {
132980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Need texture domain if drawing a sub rect.
133080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        needsTextureDomain = srcRect.width() < bitmap.width() ||
133180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             srcRect.height() < bitmap.height();
133280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (m.rectStaysRect() && fContext->getMatrix().rectStaysRect()) {
133380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // sampling is axis-aligned
133480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrRect transformedRect;
133580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkMatrix srcToDeviceMatrix(m);
133680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            srcToDeviceMatrix.postConcat(fContext->getMatrix());
133780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            srcToDeviceMatrix.mapRect(&transformedRect, srcRect);
133880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
133980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (hasAlignedSamples(srcRect, transformedRect)) {
134080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // We could also turn off filtering here (but we already did a cache lookup with
134180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // params).
134280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                needsTextureDomain = false;
134380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
134480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                needsTextureDomain = needsTextureDomain &&
134580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    mayColorBleed(srcRect, transformedRect, m);
134680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
134780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
134880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
134980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
135080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrRect textureDomain = GrRect::MakeEmpty();
1351d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkAutoTUnref<GrEffectRef> effect;
135280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (needsTextureDomain) {
135380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Use a constrained texture domain to avoid color bleeding
1354363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkScalar left, top, right, bottom;
1355363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (srcRect.width() > SK_Scalar1) {
1356363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkScalar border = SK_ScalarHalf / bitmap.width();
135780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            left = paintRect.left() + border;
135880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            right = paintRect.right() - border;
135980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
1360363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            left = right = SkScalarHalf(paintRect.left() + paintRect.right());
136180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
1362363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (srcRect.height() > SK_Scalar1) {
1363363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkScalar border = SK_ScalarHalf / bitmap.height();
136480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            top = paintRect.top() + border;
136580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            bottom = paintRect.bottom() - border;
136680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
1367363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            top = bottom = SkScalarHalf(paintRect.top() + paintRect.bottom());
136880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
136980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        textureDomain.setLTRB(left, top, right, bottom);
1370363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        effect.reset(GrTextureDomainEffect::Create(texture,
1371363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                                   SkMatrix::I(),
1372363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                                   textureDomain,
1373363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                                   GrTextureDomainEffect::kClamp_WrapMode,
1374363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                                   params.isBilerp()));
137580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
1376d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        effect.reset(GrSimpleTextureEffect::Create(texture, SkMatrix::I(), params));
137780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
1378363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    grPaint->colorStage(kBitmapTextureIdx)->setEffect(effect);
137980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->drawRectToRect(*grPaint, dstRect, paintRect, &m);
138080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
138180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
138280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
138380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1384363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid apply_effect(GrContext* context,
1385363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                  GrTexture* srcTexture,
1386363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                  GrTexture* dstTexture,
1387363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                  const GrRect& rect,
1388d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                  GrEffectRef* effect) {
138980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(srcTexture && srcTexture->getContext() == context);
139080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrContext::AutoMatrix am;
139180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    am.setIdentity(context);
139280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrContext::AutoRenderTarget art(context, dstTexture->asRenderTarget());
139380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrContext::AutoClip acs(context, rect);
139480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
139580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPaint paint;
1396363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    paint.colorStage(0)->setEffect(effect);
139780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    context->drawRect(paint, rect);
139880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
139980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
140080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
140180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1402d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergerstatic SkBitmap wrap_texture(GrTexture* texture) {
1403d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkBitmap result;
1404d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    bool dummy;
1405d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkBitmap::Config config = grConfig2skConfig(texture->config(), &dummy);
1406d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    result.setConfig(config, texture->width(), texture->height());
1407d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (texture)))->unref();
1408d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    return result;
1409d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
1410d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
1411d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergerstatic bool filter_texture(SkDevice* device, GrContext* context,
1412d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                           GrTexture* texture, SkImageFilter* filter,
1413d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                           int w, int h, SkBitmap* result) {
141480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(filter);
141580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDeviceImageFilterProxy proxy(device);
141680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
141780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTextureDesc desc;
141880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fFlags = kRenderTarget_GrTextureFlagBit,
1419d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    desc.fWidth = w;
1420d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    desc.fHeight = h;
142180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fConfig = kRGBA_8888_GrPixelConfig;
1422d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrEffectRef* effect;
142380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
142480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (filter->canFilterImageGPU()) {
1425363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // Save the render target and set it to NULL, so we don't accidentally draw to it in the
1426363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // filter.  Also set the clip wide open and the matrix to identity.
1427363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        GrContext::AutoWideOpenIdentityDraw awo(context, NULL);
1428d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return filter->filterImageGPU(&proxy, wrap_texture(texture), result);
1429363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    } else if (filter->asNewEffect(&effect, texture)) {
143080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAutoScratchTexture dst(context, desc);
1431d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkRect r = SkRect::MakeWH(SkIntToScalar(w), SkIntToScalar(h));
1432d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        apply_effect(context, texture, dst.texture(), r, effect);
1433d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkAutoTUnref<GrTexture> resultTex(dst.detach());
1434363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        effect->unref();
1435d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        *result = wrap_texture(resultTex.get());
1436d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return true;
1437d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    } else {
1438d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return false;
143980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
144080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
144180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
144280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
144380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             int left, int top, const SkPaint& paint) {
144480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // drawSprite is defined to be in device coords.
144580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CHECK_SHOULD_DRAW(draw, true);
144680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
144780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoLockPixels alp(bitmap, !bitmap.getTexture());
144880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
144980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
145080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
145180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
145280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int w = bitmap.width();
145380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int h = bitmap.height();
145480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
145580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPaint grPaint;
1456d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if(!skPaint2GrPaintNoShader(this, paint, true, false, &grPaint)) {
145780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
145880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
145980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1460363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    GrEffectStage* stage = grPaint.colorStage(kBitmapTextureIdx);
146180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
146280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTexture* texture;
1463363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    stage->reset();
146480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // draw sprite uses the default texture params
146580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoCachedTexture act(this, bitmap, NULL, &texture);
1466d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    grPaint.colorStage(kBitmapTextureIdx)->setEffect(
1467d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        GrSimpleTextureEffect::Create(texture, SkMatrix::I()))->unref();
146880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
146980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkImageFilter* filter = paint.getImageFilter();
147080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != filter) {
1471d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkBitmap filterBitmap;
1472d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (filter_texture(this, fContext, texture, filter, w, h, &filterBitmap)) {
1473d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            grPaint.colorStage(kBitmapTextureIdx)->setEffect(
1474d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                GrSimpleTextureEffect::Create((GrTexture*) filterBitmap.getTexture(), SkMatrix::I()))->unref();
1475d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            texture = (GrTexture*) filterBitmap.getTexture();
1476d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            w = filterBitmap.width();
1477d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            h = filterBitmap.height();
147880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
147980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
148080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
148180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->drawRectToRect(grPaint,
1482363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            GrRect::MakeXYWH(SkIntToScalar(left),
1483363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                            SkIntToScalar(top),
1484363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                            SkIntToScalar(w),
1485363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                            SkIntToScalar(h)),
1486363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            GrRect::MakeWH(SK_Scalar1 * w / texture->width(),
1487363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                        SK_Scalar1 * h / texture->height()));
148880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
148980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
149080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
149180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                 const SkRect* src, const SkRect& dst,
149280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                 const SkPaint& paint) {
149380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMatrix    matrix;
149480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect      bitmapBounds, tmpSrc;
149580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
149680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bitmapBounds.set(0, 0,
149780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                     SkIntToScalar(bitmap.width()),
149880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                     SkIntToScalar(bitmap.height()));
149980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
150080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Compute matrix from the two rectangles
150180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != src) {
150280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmpSrc = *src;
150380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
150480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmpSrc = bitmapBounds;
150580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
150680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
150780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
150880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // clip the tmpSrc to the bounds of the bitmap. No check needed if src==null.
150980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != src) {
151080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!bitmapBounds.contains(tmpSrc)) {
151180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!tmpSrc.intersect(bitmapBounds)) {
151280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return; // nothing to draw
151380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
151480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
151580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
151680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
151780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->drawBitmapCommon(draw, bitmap, &tmpSrc, matrix, paint);
151880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
151980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
152080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* device,
152180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             int x, int y, const SkPaint& paint) {
152280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // clear of the source device must occur before CHECK_SHOULD_DRAW
152380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkGpuDevice* dev = static_cast<SkGpuDevice*>(device);
152480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (dev->fNeedClear) {
152580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // TODO: could check here whether we really need to draw at all
152680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dev->clear(0x0);
152780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
152880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
152980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // drawDevice is defined to be in device coords.
153080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CHECK_SHOULD_DRAW(draw, true);
153180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
153280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPaint grPaint;
1533363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    grPaint.colorStage(kBitmapTextureIdx)->reset();
153480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!dev->bindDeviceAsTexture(&grPaint) ||
1535d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        !skPaint2GrPaintNoShader(this, paint, true, false, &grPaint)) {
153680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
153780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
153880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1539d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrTexture* devTex = (*grPaint.getColorStage(kBitmapTextureIdx).getEffect())->texture(0);
154080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(NULL != devTex);
154180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1542d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    const SkBitmap& bm = dev->accessBitmap(false);
1543d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    int w = bm.width();
1544d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    int h = bm.height();
1545d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
154680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkImageFilter* filter = paint.getImageFilter();
154780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != filter) {
1548d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkBitmap filterBitmap;
1549d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (filter_texture(this, fContext, devTex, filter, w, h, &filterBitmap)) {
1550d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            grPaint.colorStage(kBitmapTextureIdx)->setEffect(
1551d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                GrSimpleTextureEffect::Create((GrTexture*) filterBitmap.getTexture(), SkMatrix::I()))->unref();
1552d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            devTex = (GrTexture*) filterBitmap.getTexture();
1553d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            w = filterBitmap.width();
1554d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            h = filterBitmap.height();
155580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
155680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
155780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1558363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    GrRect dstRect = GrRect::MakeXYWH(SkIntToScalar(x),
1559363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                      SkIntToScalar(y),
1560363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                      SkIntToScalar(w),
1561363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                      SkIntToScalar(h));
156280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
156380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // The device being drawn may not fill up its texture (saveLayer uses
156480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // the approximate ).
1565363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    GrRect srcRect = GrRect::MakeWH(SK_Scalar1 * w / devTex->width(),
1566363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                    SK_Scalar1 * h / devTex->height());
156780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
156880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->drawRectToRect(grPaint, dstRect, srcRect);
156980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
157080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
157180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkGpuDevice::canHandleImageFilter(SkImageFilter* filter) {
1572363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (!filter->asNewEffect(NULL, NULL) &&
157380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        !filter->canFilterImageGPU()) {
157480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
157580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
157680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
157780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
157880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
157980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkGpuDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
158080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              const SkMatrix& ctm,
158180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              SkBitmap* result, SkIPoint* offset) {
158280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // want explicitly our impl, so guard against a subclass of us overriding it
158380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!this->SkGpuDevice::canHandleImageFilter(filter)) {
158480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
158580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
158680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
158780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoLockPixels alp(src, !src.getTexture());
158880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!src.getTexture() && !src.readyToDraw()) {
158980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
159080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
159180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
159280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPaint paint;
159380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
159480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTexture* texture;
159580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // We assume here that the filter will not attempt to tile the src. Otherwise, this cache lookup
159680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // must be pushed upstack.
159780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoCachedTexture act(this, src, NULL, &texture);
159880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1599d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    return filter_texture(this, fContext, texture, filter, src.width(), src.height(), result);
160080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
160180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
160280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
160380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
160480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// must be in SkCanvas::VertexMode order
160580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const GrPrimitiveType gVertexMode2PrimitiveType[] = {
160680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kTriangles_GrPrimitiveType,
160780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kTriangleStrip_GrPrimitiveType,
160880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kTriangleFan_GrPrimitiveType,
160980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
161080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
161180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
161280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              int vertexCount, const SkPoint vertices[],
161380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              const SkPoint texs[], const SkColor colors[],
161480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              SkXfermode* xmode,
161580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              const uint16_t indices[], int indexCount,
161680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              const SkPaint& paint) {
161780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CHECK_SHOULD_DRAW(draw, false);
161880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
161980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrPaint grPaint;
162080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we ignore the shader if texs is null.
162180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == texs) {
1622d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (!skPaint2GrPaintNoShader(this, paint, false, NULL == colors, &grPaint)) {
162380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
162480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
162580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
1626d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (!skPaint2GrPaintShader(this, paint, NULL == colors, &grPaint)) {
162780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
162880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
162980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
163080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
163180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != xmode && NULL != texs && NULL != colors) {
1632d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (!SkXfermode::IsMode(xmode, SkXfermode::kModulate_Mode)) {
163380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf("Unsupported vertex-color/texture xfer mode.\n");
163480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
163580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return
163680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
163780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
163880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
163980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
164080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoSTMalloc<128, GrColor> convertedColors(0);
164180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != colors) {
164280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // need to convert byte order and from non-PM to PM
164380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        convertedColors.reset(vertexCount);
164480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = 0; i < vertexCount; ++i) {
164580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            convertedColors[i] = SkColor2GrColor(colors[i]);
164680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
164780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        colors = convertedColors.get();
164880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
164980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->drawVertices(grPaint,
165080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           gVertexMode2PrimitiveType[vmode],
165180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           vertexCount,
165280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           (GrPoint*) vertices,
165380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           (GrPoint*) texs,
165480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           colors,
165580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           indices,
165680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           indexCount);
165780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
165880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
165980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
166080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
166180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void GlyphCacheAuxProc(void* data) {
166280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrFontScaler* scaler = (GrFontScaler*)data;
166380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSafeUnref(scaler);
166480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
166580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
166680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic GrFontScaler* get_gr_font_scaler(SkGlyphCache* cache) {
166780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void* auxData;
166880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrFontScaler* scaler = NULL;
166980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
167080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        scaler = (GrFontScaler*)auxData;
167180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
167280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == scaler) {
167380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        scaler = SkNEW_ARGS(SkGrFontScaler, (cache));
167480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cache->setAuxProc(GlyphCacheAuxProc, scaler);
167580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
167680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return scaler;
167780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
167880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
167980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void SkGPU_Draw1Glyph(const SkDraw1Glyph& state,
168080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             SkFixed fx, SkFixed fy,
168180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const SkGlyph& glyph) {
168280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
168380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
168480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrSkDrawProcs* procs = static_cast<GrSkDrawProcs*>(state.fDraw->fProcs);
168580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
168680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == procs->fFontScaler) {
168780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        procs->fFontScaler = get_gr_font_scaler(state.fCache);
168880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
168980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
169080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
169180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                       glyph.getSubXFixed(),
169280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                       glyph.getSubYFixed()),
169380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                         SkFixedFloorToFixed(fx),
169480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                         SkFixedFloorToFixed(fy),
169580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                         procs->fFontScaler);
169680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
169780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
169880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) {
169980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
170080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // deferred allocation
170180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == fDrawProcs) {
170280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDrawProcs = SkNEW(GrSkDrawProcs);
170380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDrawProcs->fD1GProc = SkGPU_Draw1Glyph;
170480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDrawProcs->fContext = fContext;
170580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
170680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
170780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // init our (and GL's) state
170880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawProcs->fTextContext = context;
170980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fDrawProcs->fFontScaler = NULL;
171080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fDrawProcs;
171180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
171280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
171380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawText(const SkDraw& draw, const void* text,
171480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          size_t byteLength, SkScalar x, SkScalar y,
171580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          const SkPaint& paint) {
171680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CHECK_SHOULD_DRAW(draw, false);
171780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
171880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fContext->getMatrix().hasPerspective()) {
171980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // this guy will just call our drawPath()
172080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        draw.drawText((const char*)text, byteLength, x, y, paint);
172180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
172280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDraw myDraw(draw);
172380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
172480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrPaint grPaint;
1725d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
172680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
172780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
172880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrTextContext context(fContext, grPaint);
172980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        myDraw.fProcs = this->initDrawForText(&context);
173080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
173180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
173280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
173380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
173480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
173580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             size_t byteLength, const SkScalar pos[],
173680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             SkScalar constY, int scalarsPerPos,
173780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const SkPaint& paint) {
173880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CHECK_SHOULD_DRAW(draw, false);
173980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
174080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fContext->getMatrix().hasPerspective()) {
174180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // this guy will just call our drawPath()
174280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        draw.drawPosText((const char*)text, byteLength, pos, constY,
174380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         scalarsPerPos, paint);
174480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
174580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDraw myDraw(draw);
174680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
174780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrPaint grPaint;
1748d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
174980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
175080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
175180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrTextContext context(fContext, grPaint);
175280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        myDraw.fProcs = this->initDrawForText(&context);
175380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
175480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     scalarsPerPos, paint);
175580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
175680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
175780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
175880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::drawTextOnPath(const SkDraw& draw, const void* text,
175980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                size_t len, const SkPath& path,
176080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                const SkMatrix* m, const SkPaint& paint) {
176180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    CHECK_SHOULD_DRAW(draw, false);
176280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
176380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(draw.fDevice == this);
176480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    draw.drawTextOnPath((const char*)text, len, path, m, paint);
176580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
176680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
176780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
176880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
176980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkGpuDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
177080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!paint.isLCDRenderText()) {
177180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // we're cool with the paint as is
177280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
177380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
177480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
177580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (paint.getShader() ||
177680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.getXfermode() || // unless its srcover
177780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.getMaskFilter() ||
177880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.getRasterizer() ||
177980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.getColorFilter() ||
178080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.getPathEffect() ||
178180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.isFakeBoldText() ||
178280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.getStyle() != SkPaint::kFill_Style) {
178380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // turn off lcd
178480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
178580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        flags->fHinting = paint.getHinting();
178680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
178780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
178880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we're cool with the paint as is
178980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
179080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
179180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
179280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkGpuDevice::flush() {
179380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    DO_DEFERRED_CLEAR();
179480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fContext->resolveRenderTarget(fRenderTarget);
179580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
179680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
179780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
179880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
179980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkDevice* SkGpuDevice::onCreateCompatibleDevice(SkBitmap::Config config,
180080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                int width, int height,
180180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                bool isOpaque,
180280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                Usage usage) {
180380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrTextureDesc desc;
180480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fConfig = fRenderTarget->config();
180580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fFlags = kRenderTarget_GrTextureFlagBit;
180680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fWidth = width;
180780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fHeight = height;
180880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    desc.fSampleCnt = fRenderTarget->numSamples();
180980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1810d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkAutoTUnref<GrTexture> texture;
181180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Skia's convention is to only clear a device if it is non-opaque.
181280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool needClear = !isOpaque;
181380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
181480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if CACHE_COMPATIBLE_DEVICE_TEXTURES
181580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // layers are never draw in repeat modes, so we can request an approx
181680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // match and ignore any padding.
1817d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    const GrContext::ScratchTexMatch match = (kSaveLayer_Usage == usage) ?
1818d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                GrContext::kApprox_ScratchTexMatch :
1819d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                                GrContext::kExact_ScratchTexMatch;
1820d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    texture.reset(fContext->lockAndRefScratchTexture(desc, match));
182180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
1822d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    texture.reset(fContext->createUncachedTexture(desc, NULL, 0));
182380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
1824d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (NULL != texture.get()) {
1825d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return SkNEW_ARGS(SkGpuDevice,(fContext, texture, needClear));
182680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
1827d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        GrPrintf("---- failed to create compatible device texture [%d %d]\n", width, height);
182880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
182980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
183080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
183180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
183280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkGpuDevice::SkGpuDevice(GrContext* context,
183380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         GrTexture* texture,
183480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         bool needClear)
183580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    : SkDevice(make_bitmap(context, texture->asRenderTarget())) {
183680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
183780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(texture && texture->asRenderTarget());
183880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // This constructor is called from onCreateCompatibleDevice. It has locked the RT in the texture
183980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // cache. We pass true for the third argument so that it will get unlocked.
184080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->initFromRenderTarget(context, texture->asRenderTarget(), true);
184180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fNeedClear = needClear;
184280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
1843