Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 
     11 #include "GrContext.h"
     12 #include "GrTextContext.h"
     13 
     14 #include "SkGpuDevice.h"
     15 #include "SkGrTexturePixelRef.h"
     16 
     17 #include "SkColorFilter.h"
     18 #include "SkDrawProcs.h"
     19 #include "SkGlyphCache.h"
     20 #include "SkImageFilter.h"
     21 #include "SkTLazy.h"
     22 #include "SkUtils.h"
     23 
     24 #define CACHE_LAYER_TEXTURES 1
     25 
     26 #if 0
     27     extern bool (*gShouldDrawProc)();
     28     #define CHECK_SHOULD_DRAW(draw)                             \
     29         do {                                                    \
     30             if (gShouldDrawProc && !gShouldDrawProc()) return;  \
     31             this->prepareRenderTarget(draw);                    \
     32         } while (0)
     33 #else
     34     #define CHECK_SHOULD_DRAW(draw) this->prepareRenderTarget(draw)
     35 #endif
     36 
     37 // we use the same texture slot on GrPaint for bitmaps and shaders
     38 // (since drawBitmap, drawSprite, and drawDevice ignore skia's shader)
     39 enum {
     40     kBitmapTextureIdx = 0,
     41     kShaderTextureIdx = 0
     42 };
     43 
     44 
     45 #define MAX_BLUR_SIGMA 4.0f
     46 // FIXME:  This value comes from from SkBlurMaskFilter.cpp.
     47 // Should probably be put in a common header someplace.
     48 #define MAX_BLUR_RADIUS SkIntToScalar(128)
     49 // This constant approximates the scaling done in the software path's
     50 // "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)).
     51 // IMHO, it actually should be 1:  we blur "less" than we should do
     52 // according to the CSS and canvas specs, simply because Safari does the same.
     53 // Firefox used to do the same too, until 4.0 where they fixed it.  So at some
     54 // point we should probably get rid of these scaling constants and rebaseline
     55 // all the blur tests.
     56 #define BLUR_SIGMA_SCALE 0.6f
     57 ///////////////////////////////////////////////////////////////////////////////
     58 
     59 SkGpuDevice::SkAutoCachedTexture::
     60              SkAutoCachedTexture(SkGpuDevice* device,
     61                                  const SkBitmap& bitmap,
     62                                  const GrSamplerState* sampler,
     63                                  GrTexture** texture) {
     64     GrAssert(texture);
     65     *texture = this->set(device, bitmap, sampler);
     66 }
     67 
     68 SkGpuDevice::SkAutoCachedTexture::SkAutoCachedTexture() {
     69 }
     70 
     71 GrTexture* SkGpuDevice::SkAutoCachedTexture::set(SkGpuDevice* device,
     72                                                  const SkBitmap& bitmap,
     73                                                  const GrSamplerState* sampler) {
     74     if (fTex.texture()) {
     75         fDevice->unlockCachedTexture(fTex);
     76     }
     77     fDevice = device;
     78     GrTexture* texture = (GrTexture*)bitmap.getTexture();
     79     if (texture) {
     80         // return the native texture
     81         fTex.reset();
     82     } else {
     83         // look it up in our cache
     84         fTex = device->lockCachedTexture(bitmap, sampler);
     85         texture = fTex.texture();
     86     }
     87     return texture;
     88 }
     89 
     90 SkGpuDevice::SkAutoCachedTexture::~SkAutoCachedTexture() {
     91     if (fTex.texture()) {
     92         fDevice->unlockCachedTexture(fTex);
     93     }
     94 }
     95 
     96 ///////////////////////////////////////////////////////////////////////////////
     97 
     98 bool gDoTraceDraw;
     99 
    100 struct GrSkDrawProcs : public SkDrawProcs {
    101 public:
    102     GrContext* fContext;
    103     GrTextContext* fTextContext;
    104     GrFontScaler* fFontScaler;  // cached in the skia glyphcache
    105 };
    106 
    107 ///////////////////////////////////////////////////////////////////////////////
    108 
    109 static SkBitmap::Config grConfig2skConfig(GrPixelConfig config, bool* isOpaque) {
    110     switch (config) {
    111         case kAlpha_8_GrPixelConfig:
    112             *isOpaque = false;
    113             return SkBitmap::kA8_Config;
    114         case kRGB_565_GrPixelConfig:
    115             *isOpaque = true;
    116             return SkBitmap::kRGB_565_Config;
    117         case kRGBA_4444_GrPixelConfig:
    118             *isOpaque = false;
    119             return SkBitmap::kARGB_4444_Config;
    120         case kSkia8888_PM_GrPixelConfig:
    121             // we don't currently have a way of knowing whether
    122             // a 8888 is opaque based on the config.
    123             *isOpaque = false;
    124             return SkBitmap::kARGB_8888_Config;
    125         default:
    126             *isOpaque = false;
    127             return SkBitmap::kNo_Config;
    128     }
    129 }
    130 
    131 static SkBitmap make_bitmap(GrContext* context, GrRenderTarget* renderTarget) {
    132     GrPixelConfig config = renderTarget->config();
    133 
    134     bool isOpaque;
    135     SkBitmap bitmap;
    136     bitmap.setConfig(grConfig2skConfig(config, &isOpaque),
    137                      renderTarget->width(), renderTarget->height());
    138     bitmap.setIsOpaque(isOpaque);
    139     return bitmap;
    140 }
    141 
    142 SkGpuDevice::SkGpuDevice(GrContext* context, GrTexture* texture)
    143 : SkDevice(make_bitmap(context, texture->asRenderTarget())) {
    144     this->initFromRenderTarget(context, texture->asRenderTarget());
    145 }
    146 
    147 SkGpuDevice::SkGpuDevice(GrContext* context, GrRenderTarget* renderTarget)
    148 : SkDevice(make_bitmap(context, renderTarget)) {
    149     this->initFromRenderTarget(context, renderTarget);
    150 }
    151 
    152 void SkGpuDevice::initFromRenderTarget(GrContext* context,
    153                                        GrRenderTarget* renderTarget) {
    154     fNeedPrepareRenderTarget = false;
    155     fDrawProcs = NULL;
    156 
    157     fContext = context;
    158     fContext->ref();
    159 
    160     fTexture = NULL;
    161     fRenderTarget = NULL;
    162     fNeedClear = false;
    163 
    164     GrAssert(NULL != renderTarget);
    165     fRenderTarget = renderTarget;
    166     fRenderTarget->ref();
    167     // if this RT is also a texture, hold a ref on it
    168     fTexture = fRenderTarget->asTexture();
    169     SkSafeRef(fTexture);
    170 
    171     // Create a pixel ref for the underlying SkBitmap. We prefer a texture pixel
    172     // ref to a render target pixel reft. The pixel ref may get ref'ed outside
    173     // the device via accessBitmap. This external ref may outlive the device.
    174     // Since textures own their render targets (but not vice-versa) we
    175     // are ensuring that both objects will live as long as the pixel ref.
    176     SkPixelRef* pr;
    177     if (fTexture) {
    178         pr = new SkGrTexturePixelRef(fTexture);
    179     } else {
    180         pr = new SkGrRenderTargetPixelRef(fRenderTarget);
    181     }
    182     this->setPixelRef(pr, 0)->unref();
    183 }
    184 
    185 SkGpuDevice::SkGpuDevice(GrContext* context, SkBitmap::Config config, int width,
    186                          int height, Usage usage)
    187 : SkDevice(config, width, height, false /*isOpaque*/) {
    188     fNeedPrepareRenderTarget = false;
    189     fDrawProcs = NULL;
    190 
    191     fContext = context;
    192     fContext->ref();
    193 
    194     fTexture = NULL;
    195     fRenderTarget = NULL;
    196     fNeedClear = false;
    197 
    198     if (config != SkBitmap::kRGB_565_Config) {
    199         config = SkBitmap::kARGB_8888_Config;
    200     }
    201     SkBitmap bm;
    202     bm.setConfig(config, width, height);
    203 
    204 #if CACHE_LAYER_TEXTURES
    205     TexType type = (kSaveLayer_Usage == usage) ?
    206                             kSaveLayerDeviceRenderTarget_TexType :
    207                             kDeviceRenderTarget_TexType;
    208     fCache = this->lockCachedTexture(bm, NULL, type);
    209     fTexture = fCache.texture();
    210     if (fTexture) {
    211         SkASSERT(NULL != fTexture->asRenderTarget());
    212         // hold a ref directly on fTexture (even though fCache has one) to match
    213         // other constructor paths. Simplifies cleanup.
    214         fTexture->ref();
    215     }
    216 #else
    217     const GrTextureDesc desc = {
    218         kRenderTarget_GrTextureFlagBit,
    219         width,
    220         height,
    221         SkGr::Bitmap2PixelConfig(bm),
    222         {0} // samples
    223     };
    224 
    225     fTexture = fContext->createUncachedTexture(desc, NULL, 0);
    226 #endif
    227     if (NULL != fTexture) {
    228         fRenderTarget = fTexture->asRenderTarget();
    229         fRenderTarget->ref();
    230 
    231         GrAssert(NULL != fRenderTarget);
    232 
    233         // we defer the actual clear until our gainFocus()
    234         fNeedClear = true;
    235 
    236         // wrap the bitmap with a pixelref to expose our texture
    237         SkGrTexturePixelRef* pr = new SkGrTexturePixelRef(fTexture);
    238         this->setPixelRef(pr, 0)->unref();
    239     } else {
    240         GrPrintf("--- failed to create gpu-offscreen [%d %d]\n",
    241                  width, height);
    242         GrAssert(false);
    243     }
    244 }
    245 
    246 SkGpuDevice::~SkGpuDevice() {
    247     if (fDrawProcs) {
    248         delete fDrawProcs;
    249     }
    250 
    251     SkSafeUnref(fTexture);
    252     SkSafeUnref(fRenderTarget);
    253     if (fCache.texture()) {
    254         GrAssert(NULL != fTexture);
    255         GrAssert(fRenderTarget == fTexture->asRenderTarget());
    256         fContext->unlockTexture(fCache);
    257     }
    258     fContext->unref();
    259 }
    260 
    261 ///////////////////////////////////////////////////////////////////////////////
    262 
    263 void SkGpuDevice::makeRenderTargetCurrent() {
    264     fContext->setRenderTarget(fRenderTarget);
    265     fContext->flush(true);
    266     fNeedPrepareRenderTarget = true;
    267 }
    268 
    269 ///////////////////////////////////////////////////////////////////////////////
    270 
    271 namespace {
    272 GrPixelConfig config8888_to_gr_config(SkCanvas::Config8888 config8888) {
    273     switch (config8888) {
    274         case SkCanvas::kNative_Premul_Config8888:
    275             return kSkia8888_PM_GrPixelConfig;
    276         case SkCanvas::kNative_Unpremul_Config8888:
    277             return kSkia8888_UPM_GrPixelConfig;
    278         case SkCanvas::kBGRA_Premul_Config8888:
    279             return kBGRA_8888_PM_GrPixelConfig;
    280         case SkCanvas::kBGRA_Unpremul_Config8888:
    281             return kBGRA_8888_UPM_GrPixelConfig;
    282         case SkCanvas::kRGBA_Premul_Config8888:
    283             return kRGBA_8888_PM_GrPixelConfig;
    284         case SkCanvas::kRGBA_Unpremul_Config8888:
    285             return kRGBA_8888_UPM_GrPixelConfig;
    286         default:
    287             GrCrash("Unexpected Config8888.");
    288             return kSkia8888_PM_GrPixelConfig;
    289     }
    290 }
    291 }
    292 
    293 bool SkGpuDevice::onReadPixels(const SkBitmap& bitmap,
    294                                int x, int y,
    295                                SkCanvas::Config8888 config8888) {
    296     SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
    297     SkASSERT(!bitmap.isNull());
    298     SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height())));
    299 
    300     SkAutoLockPixels alp(bitmap);
    301     GrPixelConfig config;
    302     config = config8888_to_gr_config(config8888);
    303     return fContext->readRenderTargetPixels(fRenderTarget,
    304                                             x, y,
    305                                             bitmap.width(),
    306                                             bitmap.height(),
    307                                             config,
    308                                             bitmap.getPixels(),
    309                                             bitmap.rowBytes());
    310 }
    311 
    312 void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y,
    313                               SkCanvas::Config8888 config8888) {
    314     SkAutoLockPixels alp(bitmap);
    315     if (!bitmap.readyToDraw()) {
    316         return;
    317     }
    318 
    319     GrPixelConfig config;
    320     if (SkBitmap::kARGB_8888_Config == bitmap.config()) {
    321         config = config8888_to_gr_config(config8888);
    322     } else {
    323         config= SkGr::BitmapConfig2PixelConfig(bitmap.config(),
    324                                                bitmap.isOpaque());
    325     }
    326 
    327     fRenderTarget->writePixels(x, y, bitmap.width(), bitmap.height(),
    328                                config, bitmap.getPixels(), bitmap.rowBytes());
    329 }
    330 
    331 ///////////////////////////////////////////////////////////////////////////////
    332 
    333 static void convert_matrixclip(GrContext* context, const SkMatrix& matrix,
    334                                const SkClipStack& clipStack,
    335                                const SkRegion& clipRegion,
    336                                const SkIPoint& origin) {
    337     context->setMatrix(matrix);
    338 
    339     SkGrClipIterator iter;
    340     iter.reset(clipStack);
    341     const SkIRect& skBounds = clipRegion.getBounds();
    342     GrRect bounds;
    343     bounds.setLTRB(GrIntToScalar(skBounds.fLeft),
    344                    GrIntToScalar(skBounds.fTop),
    345                    GrIntToScalar(skBounds.fRight),
    346                    GrIntToScalar(skBounds.fBottom));
    347     GrClip grc(&iter, GrIntToScalar(-origin.x()), GrIntToScalar(-origin.y()),
    348                &bounds);
    349     context->setClip(grc);
    350 }
    351 
    352 // call this ever each draw call, to ensure that the context reflects our state,
    353 // and not the state from some other canvas/device
    354 void SkGpuDevice::prepareRenderTarget(const SkDraw& draw) {
    355     if (fNeedPrepareRenderTarget ||
    356         fContext->getRenderTarget() != fRenderTarget) {
    357 
    358         fContext->setRenderTarget(fRenderTarget);
    359         SkASSERT(draw.fClipStack);
    360         convert_matrixclip(fContext, *draw.fMatrix,
    361                            *draw.fClipStack, *draw.fClip, this->getOrigin());
    362         fNeedPrepareRenderTarget = false;
    363     }
    364 }
    365 
    366 void SkGpuDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& clip,
    367                                 const SkClipStack& clipStack) {
    368     this->INHERITED::setMatrixClip(matrix, clip, clipStack);
    369     // We don't need to set them now because the context may not reflect this device.
    370     fNeedPrepareRenderTarget = true;
    371 }
    372 
    373 void SkGpuDevice::gainFocus(SkCanvas* canvas, const SkMatrix& matrix,
    374                             const SkRegion& clip, const SkClipStack& clipStack) {
    375 
    376     fContext->setRenderTarget(fRenderTarget);
    377 
    378     this->INHERITED::gainFocus(canvas, matrix, clip, clipStack);
    379 
    380     convert_matrixclip(fContext, matrix, clipStack, clip, this->getOrigin());
    381 
    382     if (fNeedClear) {
    383         fContext->clear(NULL, 0x0);
    384         fNeedClear = false;
    385     }
    386 }
    387 
    388 SkGpuRenderTarget* SkGpuDevice::accessRenderTarget() {
    389     return (SkGpuRenderTarget*)fRenderTarget;
    390 }
    391 
    392 bool SkGpuDevice::bindDeviceAsTexture(GrPaint* paint) {
    393     if (NULL != fTexture) {
    394         paint->setTexture(kBitmapTextureIdx, fTexture);
    395         return true;
    396     }
    397     return false;
    398 }
    399 
    400 ///////////////////////////////////////////////////////////////////////////////
    401 
    402 SK_COMPILE_ASSERT(SkShader::kNone_BitmapType == 0, shader_type_mismatch);
    403 SK_COMPILE_ASSERT(SkShader::kDefault_BitmapType == 1, shader_type_mismatch);
    404 SK_COMPILE_ASSERT(SkShader::kRadial_BitmapType == 2, shader_type_mismatch);
    405 SK_COMPILE_ASSERT(SkShader::kSweep_BitmapType == 3, shader_type_mismatch);
    406 SK_COMPILE_ASSERT(SkShader::kTwoPointRadial_BitmapType == 4,
    407                   shader_type_mismatch);
    408 SK_COMPILE_ASSERT(SkShader::kLast_BitmapType == 4, shader_type_mismatch);
    409 
    410 static const GrSamplerState::SampleMode sk_bmp_type_to_sample_mode[] = {
    411     (GrSamplerState::SampleMode) -1,                    // kNone_BitmapType
    412     GrSamplerState::kNormal_SampleMode,                 // kDefault_BitmapType
    413     GrSamplerState::kRadial_SampleMode,                 // kRadial_BitmapType
    414     GrSamplerState::kSweep_SampleMode,                  // kSweep_BitmapType
    415     GrSamplerState::kRadial2_SampleMode,                // kTwoPointRadial_BitmapType
    416 };
    417 
    418 bool SkGpuDevice::skPaint2GrPaintNoShader(const SkPaint& skPaint,
    419                                           bool justAlpha,
    420                                           GrPaint* grPaint,
    421                                           bool constantColor) {
    422 
    423     grPaint->fDither    = skPaint.isDither();
    424     grPaint->fAntiAlias = skPaint.isAntiAlias();
    425     grPaint->fCoverage = 0xFF;
    426 
    427     SkXfermode::Coeff sm = SkXfermode::kOne_Coeff;
    428     SkXfermode::Coeff dm = SkXfermode::kISA_Coeff;
    429 
    430     SkXfermode* mode = skPaint.getXfermode();
    431     if (mode) {
    432         if (!mode->asCoeff(&sm, &dm)) {
    433             //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
    434 #if 0
    435             return false;
    436 #endif
    437         }
    438     }
    439     grPaint->fSrcBlendCoeff = sk_blend_to_grblend(sm);
    440     grPaint->fDstBlendCoeff = sk_blend_to_grblend(dm);
    441 
    442     if (justAlpha) {
    443         uint8_t alpha = skPaint.getAlpha();
    444         grPaint->fColor = GrColorPackRGBA(alpha, alpha, alpha, alpha);
    445         // justAlpha is currently set to true only if there is a texture,
    446         // so constantColor should not also be true.
    447         GrAssert(!constantColor);
    448     } else {
    449         grPaint->fColor = SkGr::SkColor2GrColor(skPaint.getColor());
    450         grPaint->setTexture(kShaderTextureIdx, NULL);
    451     }
    452     SkColorFilter* colorFilter = skPaint.getColorFilter();
    453     SkColor color;
    454     SkXfermode::Mode filterMode;
    455     SkScalar matrix[20];
    456     if (colorFilter != NULL && colorFilter->asColorMode(&color, &filterMode)) {
    457         grPaint->fColorMatrixEnabled = false;
    458         if (!constantColor) {
    459             grPaint->fColorFilterColor = SkGr::SkColor2GrColor(color);
    460             grPaint->fColorFilterXfermode = filterMode;
    461         } else {
    462             SkColor filtered = colorFilter->filterColor(skPaint.getColor());
    463             grPaint->fColor = SkGr::SkColor2GrColor(filtered);
    464             grPaint->resetColorFilter();
    465         }
    466     } else if (colorFilter != NULL && colorFilter->asColorMatrix(matrix)) {
    467         grPaint->fColorMatrixEnabled = true;
    468         memcpy(grPaint->fColorMatrix, matrix, sizeof(matrix));
    469         grPaint->fColorFilterXfermode = SkXfermode::kDst_Mode;
    470     } else {
    471         grPaint->resetColorFilter();
    472     }
    473     return true;
    474 }
    475 
    476 bool SkGpuDevice::skPaint2GrPaintShader(const SkPaint& skPaint,
    477                                         SkAutoCachedTexture* act,
    478                                         const SkMatrix& ctm,
    479                                         GrPaint* grPaint,
    480                                         bool constantColor) {
    481 
    482     SkASSERT(NULL != act);
    483 
    484     SkShader* shader = skPaint.getShader();
    485     if (NULL == shader) {
    486         return this->skPaint2GrPaintNoShader(skPaint,
    487                                              false,
    488                                              grPaint,
    489                                              constantColor);
    490     } else if (!this->skPaint2GrPaintNoShader(skPaint, true, grPaint, false)) {
    491         return false;
    492     }
    493 
    494     SkBitmap bitmap;
    495     SkMatrix* matrix = grPaint->textureSampler(kShaderTextureIdx)->matrix();
    496     SkShader::TileMode tileModes[2];
    497     SkScalar twoPointParams[3];
    498     SkShader::BitmapType bmptype = shader->asABitmap(&bitmap, matrix,
    499                                                      tileModes, twoPointParams);
    500 
    501     GrSamplerState::SampleMode sampleMode = sk_bmp_type_to_sample_mode[bmptype];
    502     if (-1 == sampleMode) {
    503         SkShader::GradientInfo info;
    504         SkColor                color;
    505 
    506         info.fColors = &color;
    507         info.fColorOffsets = NULL;
    508         info.fColorCount = 1;
    509         if (SkShader::kColor_GradientType == shader->asAGradient(&info)) {
    510             SkPaint copy(skPaint);
    511             copy.setShader(NULL);
    512             // modulate the paint alpha by the shader's solid color alpha
    513             U8CPU newA = SkMulDiv255Round(SkColorGetA(color), copy.getAlpha());
    514             copy.setColor(SkColorSetA(color, newA));
    515             return this->skPaint2GrPaintNoShader(copy,
    516                                                  false,
    517                                                  grPaint,
    518                                                  constantColor);
    519         }
    520         return false;
    521     }
    522     GrSamplerState* sampler = grPaint->textureSampler(kShaderTextureIdx);
    523     sampler->setSampleMode(sampleMode);
    524     if (skPaint.isFilterBitmap()) {
    525         sampler->setFilter(GrSamplerState::kBilinear_Filter);
    526     } else {
    527         sampler->setFilter(GrSamplerState::kNearest_Filter);
    528     }
    529     sampler->setWrapX(sk_tile_mode_to_grwrap(tileModes[0]));
    530     sampler->setWrapY(sk_tile_mode_to_grwrap(tileModes[1]));
    531     if (GrSamplerState::kRadial2_SampleMode == sampleMode) {
    532         sampler->setRadial2Params(twoPointParams[0],
    533                                   twoPointParams[1],
    534                                   twoPointParams[2] < 0);
    535     }
    536 
    537     GrTexture* texture = act->set(this, bitmap, sampler);
    538     if (NULL == texture) {
    539         SkDebugf("Couldn't convert bitmap to texture.\n");
    540         return false;
    541     }
    542     grPaint->setTexture(kShaderTextureIdx, texture);
    543 
    544     // since our texture coords will be in local space, we wack the texture
    545     // matrix to map them back into 0...1 before we load it
    546     SkMatrix localM;
    547     if (shader->getLocalMatrix(&localM)) {
    548         SkMatrix inverse;
    549         if (localM.invert(&inverse)) {
    550             matrix->preConcat(inverse);
    551         }
    552     }
    553     if (SkShader::kDefault_BitmapType == bmptype) {
    554         GrScalar sx = GrFixedToScalar(GR_Fixed1 / bitmap.width());
    555         GrScalar sy = GrFixedToScalar(GR_Fixed1 / bitmap.height());
    556         matrix->postScale(sx, sy);
    557     } else if (SkShader::kRadial_BitmapType == bmptype) {
    558         GrScalar s = GrFixedToScalar(GR_Fixed1 / bitmap.width());
    559         matrix->postScale(s, s);
    560     }
    561 
    562     return true;
    563 }
    564 
    565 ///////////////////////////////////////////////////////////////////////////////
    566 
    567 void SkGpuDevice::clear(SkColor color) {
    568     fContext->clear(NULL, color);
    569 }
    570 
    571 void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
    572     CHECK_SHOULD_DRAW(draw);
    573 
    574     GrPaint grPaint;
    575     SkAutoCachedTexture act;
    576     if (!this->skPaint2GrPaintShader(paint,
    577                                      &act,
    578                                      *draw.fMatrix,
    579                                      &grPaint,
    580                                      true)) {
    581         return;
    582     }
    583 
    584     fContext->drawPaint(grPaint);
    585 }
    586 
    587 // must be in SkCanvas::PointMode order
    588 static const GrPrimitiveType gPointMode2PrimtiveType[] = {
    589     kPoints_PrimitiveType,
    590     kLines_PrimitiveType,
    591     kLineStrip_PrimitiveType
    592 };
    593 
    594 void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
    595                              size_t count, const SkPoint pts[], const SkPaint& paint) {
    596     CHECK_SHOULD_DRAW(draw);
    597 
    598     SkScalar width = paint.getStrokeWidth();
    599     if (width < 0) {
    600         return;
    601     }
    602 
    603     // we only handle hairlines here, else we let the SkDraw call our drawPath()
    604     if (width > 0) {
    605         draw.drawPoints(mode, count, pts, paint, true);
    606         return;
    607     }
    608 
    609     GrPaint grPaint;
    610     SkAutoCachedTexture act;
    611     if (!this->skPaint2GrPaintShader(paint,
    612                                      &act,
    613                                      *draw.fMatrix,
    614                                      &grPaint,
    615                                      true)) {
    616         return;
    617     }
    618 
    619     fContext->drawVertices(grPaint,
    620                            gPointMode2PrimtiveType[mode],
    621                            count,
    622                            (GrPoint*)pts,
    623                            NULL,
    624                            NULL,
    625                            NULL,
    626                            0);
    627 }
    628 
    629 ///////////////////////////////////////////////////////////////////////////////
    630 
    631 void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
    632                           const SkPaint& paint) {
    633     CHECK_SHOULD_DRAW(draw);
    634 
    635     bool doStroke = paint.getStyle() != SkPaint::kFill_Style;
    636     SkScalar width = paint.getStrokeWidth();
    637 
    638     /*
    639         We have special code for hairline strokes, miter-strokes, and fills.
    640         Anything else we just call our path code.
    641      */
    642     bool usePath = doStroke && width > 0 &&
    643                     paint.getStrokeJoin() != SkPaint::kMiter_Join;
    644     // another reason we might need to call drawPath...
    645     if (paint.getMaskFilter()) {
    646         usePath = true;
    647     }
    648     // until we aa rotated rects...
    649     if (!usePath && paint.isAntiAlias() && !draw.fMatrix->rectStaysRect()) {
    650         usePath = true;
    651     }
    652     // small miter limit means right angles show bevel...
    653     if (SkPaint::kMiter_Join == paint.getStrokeJoin() &&
    654         paint.getStrokeMiter() < SK_ScalarSqrt2)
    655     {
    656         usePath = true;
    657     }
    658     // until we can both stroke and fill rectangles
    659     if (paint.getStyle() == SkPaint::kStrokeAndFill_Style) {
    660         usePath = true;
    661     }
    662 
    663     if (usePath) {
    664         SkPath path;
    665         path.addRect(rect);
    666         this->drawPath(draw, path, paint, NULL, true);
    667         return;
    668     }
    669 
    670     GrPaint grPaint;
    671     SkAutoCachedTexture act;
    672     if (!this->skPaint2GrPaintShader(paint,
    673                                      &act,
    674                                      *draw.fMatrix,
    675                                      &grPaint,
    676                                      true)) {
    677         return;
    678     }
    679     fContext->drawRect(grPaint, rect, doStroke ? width : -1);
    680 }
    681 
    682 #include "SkMaskFilter.h"
    683 #include "SkBounder.h"
    684 
    685 static GrPathFill skToGrFillType(SkPath::FillType fillType) {
    686     switch (fillType) {
    687         case SkPath::kWinding_FillType:
    688             return kWinding_PathFill;
    689         case SkPath::kEvenOdd_FillType:
    690             return kEvenOdd_PathFill;
    691         case SkPath::kInverseWinding_FillType:
    692             return kInverseWinding_PathFill;
    693         case SkPath::kInverseEvenOdd_FillType:
    694             return kInverseEvenOdd_PathFill;
    695         default:
    696             SkDebugf("Unsupported path fill type\n");
    697             return kHairLine_PathFill;
    698     }
    699 }
    700 
    701 static GrTexture* applyMorphology(GrContext* context, GrTexture* texture,
    702                                   const GrRect& srcRect,
    703                                   GrTexture* temp1, GrTexture* temp2,
    704                                   GrSamplerState::Filter filter,
    705                                   SkISize radius) {
    706     GrRenderTarget* oldRenderTarget = context->getRenderTarget();
    707     GrAutoMatrix avm(context, GrMatrix::I());
    708     GrClip oldClip = context->getClip();
    709     context->setClip(GrRect::MakeWH(texture->width(), texture->height()));
    710     if (radius.fWidth > 0) {
    711         context->setRenderTarget(temp1->asRenderTarget());
    712         context->applyMorphology(texture, srcRect, radius.fWidth, filter,
    713                                  GrSamplerState::kX_FilterDirection);
    714         SkIRect clearRect = SkIRect::MakeXYWH(
    715             srcRect.fLeft, srcRect.fBottom,
    716             srcRect.width(), radius.fHeight);
    717         context->clear(&clearRect, 0x0);
    718         texture = temp1;
    719     }
    720     if (radius.fHeight > 0) {
    721         context->setRenderTarget(temp2->asRenderTarget());
    722         context->applyMorphology(texture, srcRect, radius.fHeight, filter,
    723                                  GrSamplerState::kY_FilterDirection);
    724         texture = temp2;
    725     }
    726     context->setRenderTarget(oldRenderTarget);
    727     context->setClip(oldClip);
    728     return texture;
    729 }
    730 
    731 static void buildKernel(float sigma, float* kernel, int kernelWidth) {
    732     int halfWidth = (kernelWidth - 1) / 2;
    733     float sum = 0.0f;
    734     float denom = 1.0f / (2.0f * sigma * sigma);
    735     for (int i = 0; i < kernelWidth; ++i) {
    736         float x = static_cast<float>(i - halfWidth);
    737         // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian
    738         // is dropped here, since we renormalize the kernel below.
    739         kernel[i] = sk_float_exp(- x * x * denom);
    740         sum += kernel[i];
    741     }
    742     // Normalize the kernel
    743     float scale = 1.0f / sum;
    744     for (int i = 0; i < kernelWidth; ++i)
    745         kernel[i] *= scale;
    746 }
    747 
    748 static void scaleRect(SkRect* rect, float xScale, float yScale) {
    749     rect->fLeft *= xScale;
    750     rect->fTop *= yScale;
    751     rect->fRight *= xScale;
    752     rect->fBottom *= yScale;
    753 }
    754 
    755 static float adjustSigma(float sigma, int *scaleFactor, int *halfWidth,
    756                          int *kernelWidth) {
    757     *scaleFactor = 1;
    758     while (sigma > MAX_BLUR_SIGMA) {
    759         *scaleFactor *= 2;
    760         sigma *= 0.5f;
    761     }
    762     *halfWidth = static_cast<int>(ceilf(sigma * 3.0f));
    763     *kernelWidth = *halfWidth * 2 + 1;
    764     return sigma;
    765 }
    766 
    767 // Apply a Gaussian blur to srcTexture by sigmaX and sigmaY, within the given
    768 // rect.
    769 // temp1 and temp2 are used for allocation of intermediate textures.
    770 // If temp2 is non-NULL, srcTexture will be untouched, and the return
    771 // value will be either temp1 or temp2.
    772 // If temp2 is NULL, srcTexture will be overwritten with intermediate
    773 // results, and the return value will either be temp1 or srcTexture.
    774 static GrTexture* gaussianBlur(GrContext* context, GrTexture* srcTexture,
    775                                GrAutoScratchTexture* temp1,
    776                                GrAutoScratchTexture* temp2,
    777                                const SkRect& rect,
    778                                float sigmaX, float sigmaY) {
    779 
    780     GrRenderTarget* oldRenderTarget = context->getRenderTarget();
    781     GrClip oldClip = context->getClip();
    782     GrTexture* origTexture = srcTexture;
    783     GrAutoMatrix avm(context, GrMatrix::I());
    784     SkIRect clearRect;
    785     int scaleFactorX, halfWidthX, kernelWidthX;
    786     int scaleFactorY, halfWidthY, kernelWidthY;
    787     sigmaX = adjustSigma(sigmaX, &scaleFactorX, &halfWidthX, &kernelWidthX);
    788     sigmaY = adjustSigma(sigmaY, &scaleFactorY, &halfWidthY, &kernelWidthY);
    789 
    790     SkRect srcRect(rect);
    791     scaleRect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
    792     srcRect.roundOut();
    793     scaleRect(&srcRect, scaleFactorX, scaleFactorY);
    794     context->setClip(srcRect);
    795 
    796     const GrTextureDesc desc = {
    797         kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit,
    798         srcRect.width(),
    799         srcRect.height(),
    800         kRGBA_8888_GrPixelConfig,
    801         {0} // samples
    802     };
    803 
    804     temp1->set(context, desc);
    805     if (temp2) temp2->set(context, desc);
    806 
    807     GrTexture* dstTexture = temp1->texture();
    808     GrPaint paint;
    809     paint.reset();
    810     paint.textureSampler(0)->setFilter(GrSamplerState::kBilinear_Filter);
    811 
    812     for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
    813         paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(),
    814                                                    srcTexture->height());
    815         context->setRenderTarget(dstTexture->asRenderTarget());
    816         SkRect dstRect(srcRect);
    817         scaleRect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
    818                             i < scaleFactorY ? 0.5f : 1.0f);
    819         paint.setTexture(0, srcTexture);
    820         context->drawRectToRect(paint, dstRect, srcRect);
    821         srcRect = dstRect;
    822         SkTSwap(srcTexture, dstTexture);
    823         // If temp2 is non-NULL, don't render back to origTexture
    824         if (temp2 && dstTexture == origTexture) dstTexture = temp2->texture();
    825     }
    826 
    827     if (sigmaX > 0.0f) {
    828         SkAutoTMalloc<float> kernelStorageX(kernelWidthX);
    829         float* kernelX = kernelStorageX.get();
    830         buildKernel(sigmaX, kernelX, kernelWidthX);
    831 
    832         if (scaleFactorX > 1) {
    833             // Clear out a halfWidth to the right of the srcRect to prevent the
    834             // X convolution from reading garbage.
    835             clearRect = SkIRect::MakeXYWH(
    836                 srcRect.fRight, srcRect.fTop, halfWidthX, srcRect.height());
    837             context->clear(&clearRect, 0x0);
    838         }
    839 
    840         context->setRenderTarget(dstTexture->asRenderTarget());
    841         context->convolve(srcTexture, srcRect, kernelX, kernelWidthX,
    842                           GrSamplerState::kX_FilterDirection);
    843         SkTSwap(srcTexture, dstTexture);
    844         if (temp2 && dstTexture == origTexture) dstTexture = temp2->texture();
    845     }
    846 
    847     if (sigmaY > 0.0f) {
    848         SkAutoTMalloc<float> kernelStorageY(kernelWidthY);
    849         float* kernelY = kernelStorageY.get();
    850         buildKernel(sigmaY, kernelY, kernelWidthY);
    851 
    852         if (scaleFactorY > 1 || sigmaX > 0.0f) {
    853             // Clear out a halfWidth below the srcRect to prevent the Y
    854             // convolution from reading garbage.
    855             clearRect = SkIRect::MakeXYWH(
    856                 srcRect.fLeft, srcRect.fBottom, srcRect.width(), halfWidthY);
    857             context->clear(&clearRect, 0x0);
    858         }
    859 
    860         context->setRenderTarget(dstTexture->asRenderTarget());
    861         context->convolve(srcTexture, srcRect, kernelY, kernelWidthY,
    862                           GrSamplerState::kY_FilterDirection);
    863         SkTSwap(srcTexture, dstTexture);
    864         if (temp2 && dstTexture == origTexture) dstTexture = temp2->texture();
    865     }
    866 
    867     if (scaleFactorX > 1 || scaleFactorY > 1) {
    868         // Clear one pixel to the right and below, to accommodate bilinear
    869         // upsampling.
    870         clearRect = SkIRect::MakeXYWH(
    871             srcRect.fLeft, srcRect.fBottom, srcRect.width() + 1, 1);
    872         context->clear(&clearRect, 0x0);
    873         clearRect = SkIRect::MakeXYWH(
    874             srcRect.fRight, srcRect.fTop, 1, srcRect.height());
    875         context->clear(&clearRect, 0x0);
    876         // FIXME:  This should be mitchell, not bilinear.
    877         paint.textureSampler(0)->setFilter(GrSamplerState::kBilinear_Filter);
    878         paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(),
    879                                                    srcTexture->height());
    880         context->setRenderTarget(dstTexture->asRenderTarget());
    881         paint.setTexture(0, srcTexture);
    882         SkRect dstRect(srcRect);
    883         scaleRect(&dstRect, scaleFactorX, scaleFactorY);
    884         context->drawRectToRect(paint, dstRect, srcRect);
    885         srcRect = dstRect;
    886         SkTSwap(srcTexture, dstTexture);
    887     }
    888     context->setRenderTarget(oldRenderTarget);
    889     context->setClip(oldClip);
    890     return srcTexture;
    891 }
    892 
    893 static bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
    894                                   SkMaskFilter* filter, const SkMatrix& matrix,
    895                                   const SkRegion& clip, SkBounder* bounder,
    896                                   GrPaint* grp) {
    897 #ifdef SK_DISABLE_GPU_BLUR
    898     return false;
    899 #endif
    900     SkMaskFilter::BlurInfo info;
    901     SkMaskFilter::BlurType blurType = filter->asABlur(&info);
    902     if (SkMaskFilter::kNone_BlurType == blurType) {
    903         return false;
    904     }
    905     SkScalar radius = info.fIgnoreTransform ? info.fRadius
    906                                             : matrix.mapRadius(info.fRadius);
    907     radius = SkMinScalar(radius, MAX_BLUR_RADIUS);
    908     if (radius <= 0) {
    909         return false;
    910     }
    911     float sigma = SkScalarToFloat(radius) * BLUR_SIGMA_SCALE;
    912     float sigma3 = sigma * 3.0f;
    913 
    914     SkRect srcRect = path.getBounds();
    915     SkRect clipRect;
    916     clipRect.set(clip.getBounds());
    917 
    918     // Outset srcRect and clipRect by 3 * sigma, to compute affected blur area.
    919     srcRect.inset(-sigma3, -sigma3);
    920     clipRect.inset(-sigma3, -sigma3);
    921     srcRect.intersect(clipRect);
    922     SkRect finalRect = srcRect;
    923     SkIRect finalIRect;
    924     finalRect.roundOut(&finalIRect);
    925     if (clip.quickReject(finalIRect)) {
    926         return true;
    927     }
    928     if (bounder && !bounder->doIRect(finalIRect)) {
    929         return true;
    930     }
    931     GrPoint offset = GrPoint::Make(-srcRect.fLeft, -srcRect.fTop);
    932     srcRect.offset(offset);
    933     const GrTextureDesc desc = {
    934         kRenderTarget_GrTextureFlagBit,
    935         srcRect.width(),
    936         srcRect.height(),
    937         // We actually only need A8, but it often isn't supported as a
    938         // render target
    939         kRGBA_8888_PM_GrPixelConfig,
    940         {0} // samples
    941     };
    942 
    943     GrAutoScratchTexture pathEntry(context, desc);
    944     GrTexture* pathTexture = pathEntry.texture();
    945     if (NULL == pathTexture) {
    946         return false;
    947     }
    948     GrRenderTarget* oldRenderTarget = context->getRenderTarget();
    949     // Once this code moves into GrContext, this should be changed to use
    950     // an AutoClipRestore.
    951     GrClip oldClip = context->getClip();
    952     context->setRenderTarget(pathTexture->asRenderTarget());
    953     context->setClip(srcRect);
    954     context->clear(NULL, 0);
    955     GrPaint tempPaint;
    956     tempPaint.reset();
    957 
    958     GrAutoMatrix avm(context, GrMatrix::I());
    959     tempPaint.fAntiAlias = grp->fAntiAlias;
    960     if (tempPaint.fAntiAlias) {
    961         // AA uses the "coverage" stages on GrDrawTarget. Coverage with a dst
    962         // blend coeff of zero requires dual source blending support in order
    963         // to properly blend partially covered pixels. This means the AA
    964         // code path may not be taken. So we use a dst blend coeff of ISA. We
    965         // could special case AA draws to a dst surface with known alpha=0 to
    966         // use a zero dst coeff when dual source blending isn't available.
    967         tempPaint.fSrcBlendCoeff = kOne_BlendCoeff;
    968         tempPaint.fDstBlendCoeff = kISC_BlendCoeff;
    969     }
    970     // Draw hard shadow to pathTexture with path topleft at origin 0,0.
    971     context->drawPath(tempPaint, path, skToGrFillType(path.getFillType()), &offset);
    972 
    973     GrAutoScratchTexture temp1, temp2;
    974     // If we're doing a normal blur, we can clobber the pathTexture in the
    975     // gaussianBlur.  Otherwise, we need to save it for later compositing.
    976     bool isNormalBlur = blurType == SkMaskFilter::kNormal_BlurType;
    977     GrTexture* blurTexture = gaussianBlur(context, pathTexture,
    978                                           &temp1, isNormalBlur ? NULL : &temp2,
    979                                           srcRect, sigma, sigma);
    980 
    981     if (!isNormalBlur) {
    982         GrPaint paint;
    983         paint.reset();
    984         paint.textureSampler(0)->setFilter(GrSamplerState::kNearest_Filter);
    985         paint.textureSampler(0)->matrix()->setIDiv(pathTexture->width(),
    986                                                    pathTexture->height());
    987         // Blend pathTexture over blurTexture.
    988         context->setRenderTarget(blurTexture->asRenderTarget());
    989         paint.setTexture(0, pathTexture);
    990         if (SkMaskFilter::kInner_BlurType == blurType) {
    991             // inner:  dst = dst * src
    992             paint.fSrcBlendCoeff = kDC_BlendCoeff;
    993             paint.fDstBlendCoeff = kZero_BlendCoeff;
    994         } else if (SkMaskFilter::kSolid_BlurType == blurType) {
    995             // solid:  dst = src + dst - src * dst
    996             //             = (1 - dst) * src + 1 * dst
    997             paint.fSrcBlendCoeff = kIDC_BlendCoeff;
    998             paint.fDstBlendCoeff = kOne_BlendCoeff;
    999         } else if (SkMaskFilter::kOuter_BlurType == blurType) {
   1000             // outer:  dst = dst * (1 - src)
   1001             //             = 0 * src + (1 - src) * dst
   1002             paint.fSrcBlendCoeff = kZero_BlendCoeff;
   1003             paint.fDstBlendCoeff = kISC_BlendCoeff;
   1004         }
   1005         context->drawRect(paint, srcRect);
   1006     }
   1007     context->setRenderTarget(oldRenderTarget);
   1008     context->setClip(oldClip);
   1009 
   1010     if (grp->hasTextureOrMask()) {
   1011         GrMatrix inverse;
   1012         if (!matrix.invert(&inverse)) {
   1013             return false;
   1014         }
   1015         grp->preConcatActiveSamplerMatrices(inverse);
   1016     }
   1017 
   1018     static const int MASK_IDX = GrPaint::kMaxMasks - 1;
   1019     // we assume the last mask index is available for use
   1020     GrAssert(NULL == grp->getMask(MASK_IDX));
   1021     grp->setMask(MASK_IDX, blurTexture);
   1022     grp->maskSampler(MASK_IDX)->reset();
   1023 
   1024     grp->maskSampler(MASK_IDX)->matrix()->setTranslate(-finalRect.fLeft,
   1025                                                        -finalRect.fTop);
   1026     grp->maskSampler(MASK_IDX)->matrix()->postIDiv(blurTexture->width(),
   1027                                                    blurTexture->height());
   1028     context->drawRect(*grp, finalRect);
   1029     return true;
   1030 }
   1031 
   1032 static bool drawWithMaskFilter(GrContext* context, const SkPath& path,
   1033                                SkMaskFilter* filter, const SkMatrix& matrix,
   1034                                const SkRegion& clip, SkBounder* bounder,
   1035                                GrPaint* grp) {
   1036     SkMask  srcM, dstM;
   1037 
   1038     if (!SkDraw::DrawToMask(path, &clip.getBounds(), filter, &matrix, &srcM,
   1039                             SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
   1040         return false;
   1041     }
   1042     SkAutoMaskFreeImage autoSrc(srcM.fImage);
   1043 
   1044     if (!filter->filterMask(&dstM, srcM, matrix, NULL)) {
   1045         return false;
   1046     }
   1047     // this will free-up dstM when we're done (allocated in filterMask())
   1048     SkAutoMaskFreeImage autoDst(dstM.fImage);
   1049 
   1050     if (clip.quickReject(dstM.fBounds)) {
   1051         return false;
   1052     }
   1053     if (bounder && !bounder->doIRect(dstM.fBounds)) {
   1054         return false;
   1055     }
   1056 
   1057     // we now have a device-aligned 8bit mask in dstM, ready to be drawn using
   1058     // the current clip (and identity matrix) and grpaint settings
   1059 
   1060     // used to compute inverse view, if necessary
   1061     GrMatrix ivm = context->getMatrix();
   1062 
   1063     GrAutoMatrix avm(context, GrMatrix::I());
   1064 
   1065     const GrTextureDesc desc = {
   1066         kNone_GrTextureFlags,
   1067         dstM.fBounds.width(),
   1068         dstM.fBounds.height(),
   1069         kAlpha_8_GrPixelConfig,
   1070         {0}, // samples
   1071     };
   1072 
   1073     GrAutoScratchTexture ast(context, desc);
   1074     GrTexture* texture = ast.texture();
   1075 
   1076     if (NULL == texture) {
   1077         return false;
   1078     }
   1079     texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
   1080                                dstM.fImage, dstM.fRowBytes);
   1081 
   1082     if (grp->hasTextureOrMask() && ivm.invert(&ivm)) {
   1083         grp->preConcatActiveSamplerMatrices(ivm);
   1084     }
   1085 
   1086     static const int MASK_IDX = GrPaint::kMaxMasks - 1;
   1087     // we assume the last mask index is available for use
   1088     GrAssert(NULL == grp->getMask(MASK_IDX));
   1089     grp->setMask(MASK_IDX, texture);
   1090     grp->maskSampler(MASK_IDX)->reset();
   1091 
   1092     GrRect d;
   1093     d.setLTRB(GrIntToScalar(dstM.fBounds.fLeft),
   1094               GrIntToScalar(dstM.fBounds.fTop),
   1095               GrIntToScalar(dstM.fBounds.fRight),
   1096               GrIntToScalar(dstM.fBounds.fBottom));
   1097 
   1098     GrMatrix* m = grp->maskSampler(MASK_IDX)->matrix();
   1099     m->setTranslate(-dstM.fBounds.fLeft*SK_Scalar1,
   1100                          -dstM.fBounds.fTop*SK_Scalar1);
   1101     m->postIDiv(texture->width(), texture->height());
   1102     context->drawRect(*grp, d);
   1103     return true;
   1104 }
   1105 
   1106 void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
   1107                            const SkPaint& paint, const SkMatrix* prePathMatrix,
   1108                            bool pathIsMutable) {
   1109     CHECK_SHOULD_DRAW(draw);
   1110 
   1111     bool             doFill = true;
   1112 
   1113     SkScalar coverage = SK_Scalar1;
   1114     // can we cheat, and threat a thin stroke as a hairline w/ coverage
   1115     // if we can, we draw lots faster (raster device does this same test)
   1116     if (SkDrawTreatAsHairline(paint, *draw.fMatrix, &coverage)) {
   1117         doFill = false;
   1118     }
   1119 
   1120     GrPaint grPaint;
   1121     SkAutoCachedTexture act;
   1122     if (!this->skPaint2GrPaintShader(paint,
   1123                                      &act,
   1124                                      *draw.fMatrix,
   1125                                      &grPaint,
   1126                                      true)) {
   1127         return;
   1128     }
   1129 
   1130     grPaint.fCoverage = SkScalarRoundToInt(coverage * grPaint.fCoverage);
   1131 
   1132     // If we have a prematrix, apply it to the path, optimizing for the case
   1133     // where the original path can in fact be modified in place (even though
   1134     // its parameter type is const).
   1135     SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
   1136     SkPath  tmpPath;
   1137 
   1138     if (prePathMatrix) {
   1139         SkPath* result = pathPtr;
   1140 
   1141         if (!pathIsMutable) {
   1142             result = &tmpPath;
   1143             pathIsMutable = true;
   1144         }
   1145         // should I push prePathMatrix on our MV stack temporarily, instead
   1146         // of applying it here? See SkDraw.cpp
   1147         pathPtr->transform(*prePathMatrix, result);
   1148         pathPtr = result;
   1149     }
   1150     // at this point we're done with prePathMatrix
   1151     SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
   1152 
   1153     if (paint.getPathEffect() ||
   1154         (doFill && paint.getStyle() != SkPaint::kFill_Style)) {
   1155         // it is safe to use tmpPath here, even if we already used it for the
   1156         // prepathmatrix, since getFillPath can take the same object for its
   1157         // input and output safely.
   1158         doFill = paint.getFillPath(*pathPtr, &tmpPath);
   1159         pathPtr = &tmpPath;
   1160     }
   1161 
   1162     if (paint.getMaskFilter()) {
   1163         // avoid possibly allocating a new path in transform if we can
   1164         SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
   1165 
   1166         // transform the path into device space
   1167         pathPtr->transform(*draw.fMatrix, devPathPtr);
   1168         if (!drawWithGPUMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
   1169                                    *draw.fMatrix, *draw.fClip, draw.fBounder,
   1170                                    &grPaint)) {
   1171             drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
   1172                                *draw.fMatrix, *draw.fClip, draw.fBounder,
   1173                                &grPaint);
   1174         }
   1175         return;
   1176     }
   1177 
   1178     GrPathFill fill = kHairLine_PathFill;
   1179 
   1180     if (doFill) {
   1181         switch (pathPtr->getFillType()) {
   1182             case SkPath::kWinding_FillType:
   1183                 fill = kWinding_PathFill;
   1184                 break;
   1185             case SkPath::kEvenOdd_FillType:
   1186                 fill = kEvenOdd_PathFill;
   1187                 break;
   1188             case SkPath::kInverseWinding_FillType:
   1189                 fill = kInverseWinding_PathFill;
   1190                 break;
   1191             case SkPath::kInverseEvenOdd_FillType:
   1192                 fill = kInverseEvenOdd_PathFill;
   1193                 break;
   1194             default:
   1195                 SkDebugf("Unsupported path fill type\n");
   1196                 return;
   1197         }
   1198     }
   1199 
   1200     fContext->drawPath(grPaint, *pathPtr, fill);
   1201 }
   1202 
   1203 namespace {
   1204 
   1205 inline int get_tile_count(int l, int t, int r, int b, int tileSize)  {
   1206     int tilesX = (r / tileSize) - (l / tileSize) + 1;
   1207     int tilesY = (b / tileSize) - (t / tileSize) + 1;
   1208     return tilesX * tilesY;
   1209 }
   1210 
   1211 inline int determine_tile_size(const SkBitmap& bitmap,
   1212                                const SkIRect* srcRectPtr,
   1213                                int maxTextureSize) {
   1214     static const int kSmallTileSize = 1 << 10;
   1215     if (maxTextureSize <= kSmallTileSize) {
   1216         return maxTextureSize;
   1217     }
   1218 
   1219     size_t maxTexTotalTileSize;
   1220     size_t smallTotalTileSize;
   1221 
   1222     if (NULL == srcRectPtr) {
   1223         int w = bitmap.width();
   1224         int h = bitmap.height();
   1225         maxTexTotalTileSize = get_tile_count(0, 0, w, h, maxTextureSize);
   1226         smallTotalTileSize = get_tile_count(0, 0, w, h, kSmallTileSize);
   1227     } else {
   1228         maxTexTotalTileSize = get_tile_count(srcRectPtr->fLeft,
   1229                                              srcRectPtr->fTop,
   1230                                              srcRectPtr->fRight,
   1231                                              srcRectPtr->fBottom,
   1232                                              maxTextureSize);
   1233         smallTotalTileSize = get_tile_count(srcRectPtr->fLeft,
   1234                                             srcRectPtr->fTop,
   1235                                             srcRectPtr->fRight,
   1236                                             srcRectPtr->fBottom,
   1237                                             kSmallTileSize);
   1238     }
   1239     maxTexTotalTileSize *= maxTextureSize * maxTextureSize;
   1240     smallTotalTileSize *= kSmallTileSize * kSmallTileSize;
   1241 
   1242     if (maxTexTotalTileSize > 2 * smallTotalTileSize) {
   1243         return kSmallTileSize;
   1244     } else {
   1245         return maxTextureSize;
   1246     }
   1247 }
   1248 }
   1249 
   1250 bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
   1251                                    const GrSamplerState& sampler,
   1252                                    const SkIRect* srcRectPtr,
   1253                                    int* tileSize) const {
   1254     SkASSERT(NULL != tileSize);
   1255 
   1256     // if bitmap is explictly texture backed then just use the texture
   1257     if (NULL != bitmap.getTexture()) {
   1258         return false;
   1259     }
   1260     // if it's larger than the max texture size, then we have no choice but
   1261     // tiling
   1262     const int maxTextureSize = fContext->getMaxTextureSize();
   1263     if (bitmap.width() > maxTextureSize ||
   1264         bitmap.height() > maxTextureSize) {
   1265         *tileSize = determine_tile_size(bitmap, srcRectPtr, maxTextureSize);
   1266         return true;
   1267     }
   1268     // if we are going to have to draw the whole thing, then don't tile
   1269     if (NULL == srcRectPtr) {
   1270         return false;
   1271     }
   1272     // if the entire texture is already in our cache then no reason to tile it
   1273     if (this->isBitmapInTextureCache(bitmap, sampler)) {
   1274         return false;
   1275     }
   1276 
   1277     // At this point we know we could do the draw by uploading the entire bitmap
   1278     // as a texture. However, if the texture would be large compared to the
   1279     // cache size and we don't require most of it for this draw then tile to
   1280     // reduce the amount of upload and cache spill.
   1281 
   1282     // assumption here is that sw bitmap size is a good proxy for its size as
   1283     // a texture
   1284     size_t bmpSize = bitmap.getSize();
   1285     size_t cacheSize;
   1286     fContext->getTextureCacheLimits(NULL, &cacheSize);
   1287     if (bmpSize < cacheSize / 2) {
   1288         return false;
   1289     }
   1290 
   1291     SkFixed fracUsed =
   1292         SkFixedMul((srcRectPtr->width() << 16) / bitmap.width(),
   1293                    (srcRectPtr->height() << 16) / bitmap.height());
   1294     if (fracUsed <= SK_FixedHalf) {
   1295         *tileSize = determine_tile_size(bitmap, srcRectPtr, maxTextureSize);
   1296         return true;
   1297     } else {
   1298         return false;
   1299     }
   1300 }
   1301 
   1302 void SkGpuDevice::drawBitmap(const SkDraw& draw,
   1303                              const SkBitmap& bitmap,
   1304                              const SkIRect* srcRectPtr,
   1305                              const SkMatrix& m,
   1306                              const SkPaint& paint) {
   1307     CHECK_SHOULD_DRAW(draw);
   1308 
   1309     SkIRect srcRect;
   1310     if (NULL == srcRectPtr) {
   1311         srcRect.set(0, 0, bitmap.width(), bitmap.height());
   1312     } else {
   1313         srcRect = *srcRectPtr;
   1314     }
   1315 
   1316     if (paint.getMaskFilter()){
   1317         // Convert the bitmap to a shader so that the rect can be drawn
   1318         // through drawRect, which supports mask filters.
   1319         SkBitmap        tmp;    // subset of bitmap, if necessary
   1320         const SkBitmap* bitmapPtr = &bitmap;
   1321         if (srcRectPtr) {
   1322             if (!bitmap.extractSubset(&tmp, srcRect)) {
   1323                 return;     // extraction failed
   1324             }
   1325             bitmapPtr = &tmp;
   1326             srcRect.set(0,0, srcRect.width(), srcRect.height());
   1327         }
   1328         SkPaint paintWithTexture(paint);
   1329         paintWithTexture.setShader(SkShader::CreateBitmapShader( *bitmapPtr,
   1330             SkShader::kClamp_TileMode, SkShader::kClamp_TileMode))->unref();
   1331         SkRect ScalarRect;
   1332         ScalarRect.set(srcRect);
   1333 
   1334         // Transform 'm' needs to be concatenated to the draw matrix,
   1335         // rather than transforming the primitive directly, so that 'm' will
   1336         // also affect the behavior of the mask filter.
   1337         SkMatrix drawMatrix;
   1338         drawMatrix.setConcat(*draw.fMatrix, m);
   1339         SkDraw transformedDraw(draw);
   1340         transformedDraw.fMatrix = &drawMatrix;
   1341 
   1342         this->drawRect(transformedDraw, ScalarRect, paintWithTexture);
   1343 
   1344         return;
   1345     }
   1346 
   1347     GrPaint grPaint;
   1348     if (!this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
   1349         return;
   1350     }
   1351     GrSamplerState* sampler = grPaint.textureSampler(kBitmapTextureIdx);
   1352     if (paint.isFilterBitmap()) {
   1353         sampler->setFilter(GrSamplerState::kBilinear_Filter);
   1354     } else {
   1355         sampler->setFilter(GrSamplerState::kNearest_Filter);
   1356     }
   1357 
   1358     int tileSize;
   1359     if (!this->shouldTileBitmap(bitmap, *sampler, srcRectPtr, &tileSize)) {
   1360         // take the simple case
   1361         this->internalDrawBitmap(draw, bitmap, srcRect, m, &grPaint);
   1362         return;
   1363     }
   1364 
   1365     // undo the translate done by SkCanvas
   1366     int DX = SkMax32(0, srcRect.fLeft);
   1367     int DY = SkMax32(0, srcRect.fTop);
   1368     // compute clip bounds in local coordinates
   1369     SkIRect clipRect;
   1370     {
   1371         SkRect r;
   1372         r.set(draw.fClip->getBounds());
   1373         SkMatrix matrix, inverse;
   1374         matrix.setConcat(*draw.fMatrix, m);
   1375         if (!matrix.invert(&inverse)) {
   1376             return;
   1377         }
   1378         inverse.mapRect(&r);
   1379         r.roundOut(&clipRect);
   1380         // apply the canvas' translate to our local clip
   1381         clipRect.offset(DX, DY);
   1382     }
   1383 
   1384     int nx = bitmap.width() / tileSize;
   1385     int ny = bitmap.height() / tileSize;
   1386     for (int x = 0; x <= nx; x++) {
   1387         for (int y = 0; y <= ny; y++) {
   1388             SkIRect tileR;
   1389             tileR.set(x * tileSize, y * tileSize,
   1390                       (x + 1) * tileSize, (y + 1) * tileSize);
   1391             if (!SkIRect::Intersects(tileR, clipRect)) {
   1392                 continue;
   1393             }
   1394 
   1395             SkIRect srcR = tileR;
   1396             if (!srcR.intersect(srcRect)) {
   1397                 continue;
   1398             }
   1399 
   1400             SkBitmap tmpB;
   1401             if (bitmap.extractSubset(&tmpB, tileR)) {
   1402                 // now offset it to make it "local" to our tmp bitmap
   1403                 srcR.offset(-tileR.fLeft, -tileR.fTop);
   1404 
   1405                 SkMatrix tmpM(m);
   1406                 {
   1407                     int dx = tileR.fLeft - DX + SkMax32(0, srcR.fLeft);
   1408                     int dy = tileR.fTop -  DY + SkMax32(0, srcR.fTop);
   1409                     tmpM.preTranslate(SkIntToScalar(dx), SkIntToScalar(dy));
   1410                 }
   1411                 this->internalDrawBitmap(draw, tmpB, srcR, tmpM, &grPaint);
   1412             }
   1413         }
   1414     }
   1415 }
   1416 
   1417 /*
   1418  *  This is called by drawBitmap(), which has to handle images that may be too
   1419  *  large to be represented by a single texture.
   1420  *
   1421  *  internalDrawBitmap assumes that the specified bitmap will fit in a texture
   1422  *  and that non-texture portion of the GrPaint has already been setup.
   1423  */
   1424 void SkGpuDevice::internalDrawBitmap(const SkDraw& draw,
   1425                                      const SkBitmap& bitmap,
   1426                                      const SkIRect& srcRect,
   1427                                      const SkMatrix& m,
   1428                                      GrPaint* grPaint) {
   1429     SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() &&
   1430              bitmap.height() <= fContext->getMaxTextureSize());
   1431 
   1432     SkAutoLockPixels alp(bitmap, !bitmap.getTexture());
   1433     if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
   1434         SkDebugf("nothing to draw\n");
   1435         return;
   1436     }
   1437 
   1438     GrSamplerState* sampler = grPaint->textureSampler(kBitmapTextureIdx);
   1439 
   1440     sampler->setWrapX(GrSamplerState::kClamp_WrapMode);
   1441     sampler->setWrapY(GrSamplerState::kClamp_WrapMode);
   1442     sampler->setSampleMode(GrSamplerState::kNormal_SampleMode);
   1443     sampler->matrix()->reset();
   1444 
   1445     GrTexture* texture;
   1446     SkAutoCachedTexture act(this, bitmap, sampler, &texture);
   1447     if (NULL == texture) {
   1448         return;
   1449     }
   1450 
   1451     grPaint->setTexture(kBitmapTextureIdx, texture);
   1452 
   1453     GrRect dstRect = SkRect::MakeWH(GrIntToScalar(srcRect.width()),
   1454                                     GrIntToScalar(srcRect.height()));
   1455     GrRect paintRect;
   1456     paintRect.setLTRB(GrFixedToScalar((srcRect.fLeft << 16) / bitmap.width()),
   1457                       GrFixedToScalar((srcRect.fTop << 16) / bitmap.height()),
   1458                       GrFixedToScalar((srcRect.fRight << 16) / bitmap.width()),
   1459                       GrFixedToScalar((srcRect.fBottom << 16) / bitmap.height()));
   1460 
   1461     if (GrSamplerState::kNearest_Filter != sampler->getFilter() &&
   1462         (srcRect.width() < bitmap.width() ||
   1463          srcRect.height() < bitmap.height())) {
   1464         // If drawing a subrect of the bitmap and filtering is enabled,
   1465         // use a constrained texture domain to avoid color bleeding
   1466         GrScalar left, top, right, bottom;
   1467         if (srcRect.width() > 1) {
   1468             GrScalar border = GR_ScalarHalf / bitmap.width();
   1469             left = paintRect.left() + border;
   1470             right = paintRect.right() - border;
   1471         } else {
   1472             left = right = GrScalarHalf(paintRect.left() + paintRect.right());
   1473         }
   1474         if (srcRect.height() > 1) {
   1475             GrScalar border = GR_ScalarHalf / bitmap.height();
   1476             top = paintRect.top() + border;
   1477             bottom = paintRect.bottom() - border;
   1478         } else {
   1479             top = bottom = GrScalarHalf(paintRect.top() + paintRect.bottom());
   1480         }
   1481         GrRect textureDomain;
   1482         textureDomain.setLTRB(left, top, right, bottom);
   1483         sampler->setTextureDomain(textureDomain);
   1484     }
   1485 
   1486     fContext->drawRectToRect(*grPaint, dstRect, paintRect, &m);
   1487 }
   1488 
   1489 void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
   1490                             int left, int top, const SkPaint& paint) {
   1491     CHECK_SHOULD_DRAW(draw);
   1492 
   1493     SkAutoLockPixels alp(bitmap);
   1494     if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
   1495         return;
   1496     }
   1497 
   1498     int w = bitmap.width();
   1499     int h = bitmap.height();
   1500 
   1501     GrPaint grPaint;
   1502     if(!this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
   1503         return;
   1504     }
   1505 
   1506     GrAutoMatrix avm(fContext, GrMatrix::I());
   1507 
   1508     GrSamplerState* sampler = grPaint.textureSampler(kBitmapTextureIdx);
   1509 
   1510     GrTexture* texture;
   1511     sampler->reset();
   1512     SkAutoCachedTexture act(this, bitmap, sampler, &texture);
   1513 
   1514     SkImageFilter* imageFilter = paint.getImageFilter();
   1515     SkSize blurSize;
   1516     SkISize radius;
   1517     if (NULL != imageFilter && imageFilter->asABlur(&blurSize)) {
   1518         GrAutoScratchTexture temp1, temp2;
   1519         GrTexture* blurTexture = gaussianBlur(fContext,
   1520                                               texture, &temp1, &temp2,
   1521                                               GrRect::MakeWH(w, h),
   1522                                               blurSize.width(),
   1523                                               blurSize.height());
   1524         texture = blurTexture;
   1525         grPaint.setTexture(kBitmapTextureIdx, texture);
   1526     } else if (NULL != imageFilter && imageFilter->asADilate(&radius)) {
   1527         const GrTextureDesc desc = {
   1528             kRenderTarget_GrTextureFlagBit,
   1529             w,
   1530             h,
   1531             kRGBA_8888_PM_GrPixelConfig,
   1532             {0} // samples
   1533         };
   1534         GrAutoScratchTexture temp1(fContext, desc), temp2(fContext, desc);
   1535         texture = applyMorphology(fContext, texture, GrRect::MakeWH(w, h),
   1536                                   temp1.texture(), temp2.texture(),
   1537                                   GrSamplerState::kDilate_Filter, radius);
   1538         grPaint.setTexture(kBitmapTextureIdx, texture);
   1539     } else if (NULL != imageFilter && imageFilter->asAnErode(&radius)) {
   1540         const GrTextureDesc desc = {
   1541             kRenderTarget_GrTextureFlagBit,
   1542             w,
   1543             h,
   1544             kRGBA_8888_PM_GrPixelConfig,
   1545             {0} // samples
   1546         };
   1547         GrAutoScratchTexture temp1(fContext, desc), temp2(fContext, desc);
   1548         texture = applyMorphology(fContext, texture, GrRect::MakeWH(w, h),
   1549                                   temp1.texture(), temp2.texture(),
   1550                                   GrSamplerState::kErode_Filter, radius);
   1551         grPaint.setTexture(kBitmapTextureIdx, texture);
   1552     } else {
   1553         grPaint.setTexture(kBitmapTextureIdx, texture);
   1554     }
   1555 
   1556     fContext->drawRectToRect(grPaint,
   1557                             GrRect::MakeXYWH(GrIntToScalar(left),
   1558                                             GrIntToScalar(top),
   1559                                             GrIntToScalar(w),
   1560                                             GrIntToScalar(h)),
   1561                             GrRect::MakeWH(GR_Scalar1 * w / texture->width(),
   1562                                         GR_Scalar1 * h / texture->height()));
   1563 }
   1564 
   1565 void SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* dev,
   1566                             int x, int y, const SkPaint& paint) {
   1567     CHECK_SHOULD_DRAW(draw);
   1568 
   1569     GrPaint grPaint;
   1570     if (!((SkGpuDevice*)dev)->bindDeviceAsTexture(&grPaint) ||
   1571         !this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
   1572         return;
   1573     }
   1574 
   1575     GrTexture* devTex = grPaint.getTexture(0);
   1576     SkASSERT(NULL != devTex);
   1577 
   1578     const SkBitmap& bm = dev->accessBitmap(false);
   1579     int w = bm.width();
   1580     int h = bm.height();
   1581 
   1582     GrAutoMatrix avm(fContext, GrMatrix::I());
   1583 
   1584     grPaint.textureSampler(kBitmapTextureIdx)->reset();
   1585 
   1586     GrRect dstRect = GrRect::MakeXYWH(GrIntToScalar(x),
   1587                                       GrIntToScalar(y),
   1588                                       GrIntToScalar(w),
   1589                                       GrIntToScalar(h));
   1590 
   1591     // The device being drawn may not fill up its texture (saveLayer uses
   1592     // the approximate ).
   1593     GrRect srcRect = GrRect::MakeWH(GR_Scalar1 * w / devTex->width(),
   1594                                     GR_Scalar1 * h / devTex->height());
   1595 
   1596     fContext->drawRectToRect(grPaint, dstRect, srcRect);
   1597 }
   1598 
   1599 bool SkGpuDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
   1600                               const SkMatrix& ctm,
   1601                               SkBitmap* result, SkIPoint* offset) {
   1602     SkSize size;
   1603     SkISize radius;
   1604     if (!filter->asABlur(&size) && !filter->asADilate(&radius) && !filter->asAnErode(&radius)) {
   1605         return false;
   1606     }
   1607     SkDevice* dev = this->createCompatibleDevice(SkBitmap::kARGB_8888_Config,
   1608                                                  src.width(),
   1609                                                  src.height(),
   1610                                                  false);
   1611     if (NULL == dev) {
   1612         return false;
   1613     }
   1614     SkAutoUnref aur(dev);
   1615     SkCanvas canvas(dev);
   1616     SkPaint paint;
   1617     paint.setImageFilter(filter);
   1618     canvas.drawSprite(src, 0, 0, &paint);
   1619     *result = dev->accessBitmap(false);
   1620     return true;
   1621 }
   1622 
   1623 ///////////////////////////////////////////////////////////////////////////////
   1624 
   1625 // must be in SkCanvas::VertexMode order
   1626 static const GrPrimitiveType gVertexMode2PrimitiveType[] = {
   1627     kTriangles_PrimitiveType,
   1628     kTriangleStrip_PrimitiveType,
   1629     kTriangleFan_PrimitiveType,
   1630 };
   1631 
   1632 void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
   1633                               int vertexCount, const SkPoint vertices[],
   1634                               const SkPoint texs[], const SkColor colors[],
   1635                               SkXfermode* xmode,
   1636                               const uint16_t indices[], int indexCount,
   1637                               const SkPaint& paint) {
   1638     CHECK_SHOULD_DRAW(draw);
   1639 
   1640     GrPaint grPaint;
   1641     SkAutoCachedTexture act;
   1642     // we ignore the shader if texs is null.
   1643     if (NULL == texs) {
   1644         if (!this->skPaint2GrPaintNoShader(paint,
   1645                                            false,
   1646                                            &grPaint,
   1647                                            NULL == colors)) {
   1648             return;
   1649         }
   1650     } else {
   1651         if (!this->skPaint2GrPaintShader(paint, &act,
   1652                                          *draw.fMatrix,
   1653                                          &grPaint,
   1654                                          NULL == colors)) {
   1655             return;
   1656         }
   1657     }
   1658 
   1659     if (NULL != xmode && NULL != texs && NULL != colors) {
   1660         if (!SkXfermode::IsMode(xmode, SkXfermode::kMultiply_Mode)) {
   1661             SkDebugf("Unsupported vertex-color/texture xfer mode.\n");
   1662 #if 0
   1663             return
   1664 #endif
   1665         }
   1666     }
   1667 
   1668     SkAutoSTMalloc<128, GrColor> convertedColors(0);
   1669     if (NULL != colors) {
   1670         // need to convert byte order and from non-PM to PM
   1671         convertedColors.reset(vertexCount);
   1672         for (int i = 0; i < vertexCount; ++i) {
   1673             convertedColors[i] = SkGr::SkColor2GrColor(colors[i]);
   1674         }
   1675         colors = convertedColors.get();
   1676     }
   1677     fContext->drawVertices(grPaint,
   1678                            gVertexMode2PrimitiveType[vmode],
   1679                            vertexCount,
   1680                            (GrPoint*) vertices,
   1681                            (GrPoint*) texs,
   1682                            colors,
   1683                            indices,
   1684                            indexCount);
   1685 }
   1686 
   1687 ///////////////////////////////////////////////////////////////////////////////
   1688 
   1689 static void GlyphCacheAuxProc(void* data) {
   1690     delete (GrFontScaler*)data;
   1691 }
   1692 
   1693 static GrFontScaler* get_gr_font_scaler(SkGlyphCache* cache) {
   1694     void* auxData;
   1695     GrFontScaler* scaler = NULL;
   1696     if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
   1697         scaler = (GrFontScaler*)auxData;
   1698     }
   1699     if (NULL == scaler) {
   1700         scaler = new SkGrFontScaler(cache);
   1701         cache->setAuxProc(GlyphCacheAuxProc, scaler);
   1702     }
   1703     return scaler;
   1704 }
   1705 
   1706 static void SkGPU_Draw1Glyph(const SkDraw1Glyph& state,
   1707                              SkFixed fx, SkFixed fy,
   1708                              const SkGlyph& glyph) {
   1709     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
   1710 
   1711     GrSkDrawProcs* procs = static_cast<GrSkDrawProcs*>(state.fDraw->fProcs);
   1712 
   1713     if (NULL == procs->fFontScaler) {
   1714         procs->fFontScaler = get_gr_font_scaler(state.fCache);
   1715     }
   1716 
   1717     procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
   1718                                                        glyph.getSubXFixed(),
   1719                                                        glyph.getSubYFixed()),
   1720                                          SkFixedFloorToFixed(fx),
   1721                                          SkFixedFloorToFixed(fy),
   1722                                          procs->fFontScaler);
   1723 }
   1724 
   1725 SkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) {
   1726 
   1727     // deferred allocation
   1728     if (NULL == fDrawProcs) {
   1729         fDrawProcs = new GrSkDrawProcs;
   1730         fDrawProcs->fD1GProc = SkGPU_Draw1Glyph;
   1731         fDrawProcs->fContext = fContext;
   1732     }
   1733 
   1734     // init our (and GL's) state
   1735     fDrawProcs->fTextContext = context;
   1736     fDrawProcs->fFontScaler = NULL;
   1737     return fDrawProcs;
   1738 }
   1739 
   1740 void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
   1741                           size_t byteLength, SkScalar x, SkScalar y,
   1742                           const SkPaint& paint) {
   1743     CHECK_SHOULD_DRAW(draw);
   1744 
   1745     if (draw.fMatrix->hasPerspective()) {
   1746         // this guy will just call our drawPath()
   1747         draw.drawText((const char*)text, byteLength, x, y, paint);
   1748     } else {
   1749         SkDraw myDraw(draw);
   1750 
   1751         GrPaint grPaint;
   1752         SkAutoCachedTexture act;
   1753 
   1754         if (!this->skPaint2GrPaintShader(paint,
   1755                                          &act,
   1756                                          *draw.fMatrix,
   1757                                          &grPaint,
   1758                                          true)) {
   1759             return;
   1760         }
   1761         GrTextContext context(fContext, grPaint, draw.fExtMatrix);
   1762         myDraw.fProcs = this->initDrawForText(&context);
   1763         this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
   1764     }
   1765 }
   1766 
   1767 void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
   1768                              size_t byteLength, const SkScalar pos[],
   1769                              SkScalar constY, int scalarsPerPos,
   1770                              const SkPaint& paint) {
   1771     CHECK_SHOULD_DRAW(draw);
   1772 
   1773     if (draw.fMatrix->hasPerspective()) {
   1774         // this guy will just call our drawPath()
   1775         draw.drawPosText((const char*)text, byteLength, pos, constY,
   1776                          scalarsPerPos, paint);
   1777     } else {
   1778         SkDraw myDraw(draw);
   1779 
   1780         GrPaint grPaint;
   1781         SkAutoCachedTexture act;
   1782         if (!this->skPaint2GrPaintShader(paint,
   1783                                          &act,
   1784                                          *draw.fMatrix,
   1785                                          &grPaint,
   1786                                          true)) {
   1787             return;
   1788         }
   1789 
   1790         GrTextContext context(fContext, grPaint, draw.fExtMatrix);
   1791         myDraw.fProcs = this->initDrawForText(&context);
   1792         this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
   1793                                      scalarsPerPos, paint);
   1794     }
   1795 }
   1796 
   1797 void SkGpuDevice::drawTextOnPath(const SkDraw& draw, const void* text,
   1798                                 size_t len, const SkPath& path,
   1799                                 const SkMatrix* m, const SkPaint& paint) {
   1800     CHECK_SHOULD_DRAW(draw);
   1801 
   1802     SkASSERT(draw.fDevice == this);
   1803     draw.drawTextOnPath((const char*)text, len, path, m, paint);
   1804 }
   1805 
   1806 ///////////////////////////////////////////////////////////////////////////////
   1807 
   1808 bool SkGpuDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
   1809     if (!paint.isLCDRenderText()) {
   1810         // we're cool with the paint as is
   1811         return false;
   1812     }
   1813 
   1814     if (paint.getShader() ||
   1815         paint.getXfermode() || // unless its srcover
   1816         paint.getMaskFilter() ||
   1817         paint.getRasterizer() ||
   1818         paint.getColorFilter() ||
   1819         paint.getPathEffect() ||
   1820         paint.isFakeBoldText() ||
   1821         paint.getStyle() != SkPaint::kFill_Style) {
   1822         // turn off lcd
   1823         flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
   1824         flags->fHinting = paint.getHinting();
   1825         return true;
   1826     }
   1827     // we're cool with the paint as is
   1828     return false;
   1829 }
   1830 
   1831 void SkGpuDevice::flush() {
   1832     fContext->resolveRenderTarget(fRenderTarget);
   1833 }
   1834 
   1835 ///////////////////////////////////////////////////////////////////////////////
   1836 
   1837 SkGpuDevice::TexCache SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap,
   1838                                             const GrSamplerState* sampler,
   1839                                             TexType type) {
   1840     GrContext::TextureCacheEntry entry;
   1841     GrContext* ctx = this->context();
   1842 
   1843     if (kBitmap_TexType != type) {
   1844         const GrTextureDesc desc = {
   1845             kRenderTarget_GrTextureFlagBit,
   1846             bitmap.width(),
   1847             bitmap.height(),
   1848             SkGr::Bitmap2PixelConfig(bitmap),
   1849             {0} // samples
   1850         };
   1851         GrContext::ScratchTexMatch match;
   1852         if (kSaveLayerDeviceRenderTarget_TexType == type) {
   1853             // we know layers will only be drawn through drawDevice.
   1854             // drawDevice has been made to work with content embedded in a
   1855             // larger texture so its okay to use the approximate version.
   1856             match = GrContext::kApprox_ScratchTexMatch;
   1857         } else {
   1858             SkASSERT(kDeviceRenderTarget_TexType == type);
   1859             match = GrContext::kExact_ScratchTexMatch;
   1860         }
   1861         entry = ctx->lockScratchTexture(desc, match);
   1862     } else {
   1863         if (!bitmap.isVolatile()) {
   1864             GrContext::TextureKey key = bitmap.getGenerationID();
   1865             key |= ((uint64_t) bitmap.pixelRefOffset()) << 32;
   1866 
   1867             entry = ctx->findAndLockTexture(key, bitmap.width(),
   1868                                             bitmap.height(), sampler);
   1869             if (NULL == entry.texture()) {
   1870                 entry = sk_gr_create_bitmap_texture(ctx, key, sampler,
   1871                                                     bitmap);
   1872             }
   1873         } else {
   1874             entry = sk_gr_create_bitmap_texture(ctx, gUNCACHED_KEY,
   1875                                                 sampler, bitmap);
   1876         }
   1877         if (NULL == entry.texture()) {
   1878             GrPrintf("---- failed to create texture for cache [%d %d]\n",
   1879                      bitmap.width(), bitmap.height());
   1880         }
   1881     }
   1882     return entry;
   1883 }
   1884 
   1885 void SkGpuDevice::unlockCachedTexture(TexCache cache) {
   1886     this->context()->unlockTexture(cache);
   1887 }
   1888 
   1889 bool SkGpuDevice::isBitmapInTextureCache(const SkBitmap& bitmap,
   1890                                          const GrSamplerState& sampler) const {
   1891     GrContext::TextureKey key = bitmap.getGenerationID();
   1892     key |= ((uint64_t) bitmap.pixelRefOffset()) << 32;
   1893     return this->context()->isTextureInCache(key, bitmap.width(),
   1894                                              bitmap.height(), &sampler);
   1895 
   1896 }
   1897 
   1898 
   1899 SkDevice* SkGpuDevice::onCreateCompatibleDevice(SkBitmap::Config config,
   1900                                                 int width, int height,
   1901                                                 bool isOpaque,
   1902                                                 Usage usage) {
   1903     return SkNEW_ARGS(SkGpuDevice,(this->context(), config,
   1904                                    width, height, usage));
   1905 }
   1906 
   1907