Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkGpuDevice.h"
      9 
     10 #include "GrContext.h"
     11 #include "GrGpu.h"
     12 #include "GrGpuResourcePriv.h"
     13 #include "GrLayerHoister.h"
     14 #include "GrRecordReplaceDraw.h"
     15 #include "GrStrokeInfo.h"
     16 #include "GrTextContext.h"
     17 #include "GrTracing.h"
     18 #include "SkCanvasPriv.h"
     19 #include "SkDeviceImageFilterProxy.h"
     20 #include "SkDrawProcs.h"
     21 #include "SkErrorInternals.h"
     22 #include "SkGlyphCache.h"
     23 #include "SkGrTexturePixelRef.h"
     24 #include "SkImage_Base.h"
     25 #include "SkImageFilter.h"
     26 #include "SkLayerInfo.h"
     27 #include "SkMaskFilter.h"
     28 #include "SkPathEffect.h"
     29 #include "SkPicture.h"
     30 #include "SkPictureData.h"
     31 #include "SkRRect.h"
     32 #include "SkRecord.h"
     33 #include "SkStroke.h"
     34 #include "SkSurface.h"
     35 #include "SkSurface_Gpu.h"
     36 #include "SkTLazy.h"
     37 #include "SkUtils.h"
     38 #include "SkVertState.h"
     39 #include "SkXfermode.h"
     40 #include "effects/GrBicubicEffect.h"
     41 #include "effects/GrDashingEffect.h"
     42 #include "effects/GrSimpleTextureEffect.h"
     43 #include "effects/GrTextureDomain.h"
     44 
     45 #if SK_SUPPORT_GPU
     46 
     47 enum { kDefaultImageFilterCacheSize = 32 * 1024 * 1024 };
     48 
     49 #if 0
     50     extern bool (*gShouldDrawProc)();
     51     #define CHECK_SHOULD_DRAW(draw)                             \
     52         do {                                                    \
     53             if (gShouldDrawProc && !gShouldDrawProc()) return;  \
     54             this->prepareDraw(draw);                            \
     55         } while (0)
     56 #else
     57     #define CHECK_SHOULD_DRAW(draw) this->prepareDraw(draw)
     58 #endif
     59 
     60 // This constant represents the screen alignment criterion in texels for
     61 // requiring texture domain clamping to prevent color bleeding when drawing
     62 // a sub region of a larger source image.
     63 #define COLOR_BLEED_TOLERANCE 0.001f
     64 
     65 #define DO_DEFERRED_CLEAR()             \
     66     do {                                \
     67         if (fNeedClear) {               \
     68             this->clearAll();           \
     69         }                               \
     70     } while (false)                     \
     71 
     72 ///////////////////////////////////////////////////////////////////////////////
     73 
     74 #define CHECK_FOR_ANNOTATION(paint) \
     75     do { if (paint.getAnnotation()) { return; } } while (0)
     76 
     77 ///////////////////////////////////////////////////////////////////////////////
     78 
     79 // Helper for turning a bitmap into a texture. If the bitmap is GrTexture backed this
     80 // just accesses the backing GrTexture. Otherwise, it creates a cached texture
     81 // representation and releases it in the destructor.
     82 class AutoBitmapTexture : public SkNoncopyable {
     83 public:
     84     AutoBitmapTexture() {}
     85 
     86     AutoBitmapTexture(GrContext* context,
     87                       const SkBitmap& bitmap,
     88                       const GrTextureParams* params,
     89                       GrTexture** texture) {
     90         SkASSERT(texture);
     91         *texture = this->set(context, bitmap, params);
     92     }
     93 
     94     GrTexture* set(GrContext* context,
     95                    const SkBitmap& bitmap,
     96                    const GrTextureParams* params) {
     97         // Either get the texture directly from the bitmap, or else use the cache and
     98         // remember to unref it.
     99         if (GrTexture* bmpTexture = bitmap.getTexture()) {
    100             fTexture.reset(NULL);
    101             return bmpTexture;
    102         } else {
    103             fTexture.reset(GrRefCachedBitmapTexture(context, bitmap, params));
    104             return fTexture.get();
    105         }
    106     }
    107 
    108 private:
    109     SkAutoTUnref<GrTexture> fTexture;
    110 };
    111 
    112 ///////////////////////////////////////////////////////////////////////////////
    113 
    114 struct GrSkDrawProcs : public SkDrawProcs {
    115 public:
    116     GrContext* fContext;
    117     GrTextContext* fTextContext;
    118     GrFontScaler* fFontScaler;  // cached in the skia glyphcache
    119 };
    120 
    121 ///////////////////////////////////////////////////////////////////////////////
    122 
    123 SkGpuDevice* SkGpuDevice::Create(GrRenderTarget* rt, const SkSurfaceProps* props, unsigned flags) {
    124     return SkGpuDevice::Create(rt, rt->width(), rt->height(), props, flags);
    125 }
    126 
    127 SkGpuDevice* SkGpuDevice::Create(GrRenderTarget* rt, int width, int height,
    128                                  const SkSurfaceProps* props, unsigned flags) {
    129     if (!rt || rt->wasDestroyed()) {
    130         return NULL;
    131     }
    132     return SkNEW_ARGS(SkGpuDevice, (rt, width, height, props, flags));
    133 }
    134 
    135 static SkDeviceProperties surfaceprops_to_deviceprops(const SkSurfaceProps* props) {
    136     if (props) {
    137         return SkDeviceProperties(props->pixelGeometry());
    138     } else {
    139         return SkDeviceProperties(SkDeviceProperties::kLegacyLCD_InitType);
    140     }
    141 }
    142 
    143 static SkSurfaceProps copy_or_default_props(const SkSurfaceProps* props) {
    144     if (props) {
    145         return SkSurfaceProps(*props);
    146     } else {
    147         return SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType);
    148     }
    149 }
    150 
    151 SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, int width, int height,
    152                          const SkSurfaceProps* props, unsigned flags)
    153     : INHERITED(surfaceprops_to_deviceprops(props))
    154     , fSurfaceProps(copy_or_default_props(props))
    155 {
    156     fDrawProcs = NULL;
    157 
    158     fContext = SkRef(rt->getContext());
    159     fNeedClear = flags & kNeedClear_Flag;
    160 
    161     fRenderTarget = SkRef(rt);
    162 
    163     SkImageInfo info = rt->surfacePriv().info().makeWH(width, height);
    164     SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, rt));
    165     fLegacyBitmap.setInfo(info);
    166     fLegacyBitmap.setPixelRef(pr)->unref();
    167 
    168     bool useDFT = fSurfaceProps.isUseDistanceFieldFonts();
    169     fTextContext = fContext->createTextContext(fRenderTarget, this, this->getLeakyProperties(),
    170                                                useDFT);
    171 }
    172 
    173 GrRenderTarget* SkGpuDevice::CreateRenderTarget(GrContext* context, SkSurface::Budgeted budgeted,
    174                                                 const SkImageInfo& origInfo, int sampleCount) {
    175     if (kUnknown_SkColorType == origInfo.colorType() ||
    176         origInfo.width() < 0 || origInfo.height() < 0) {
    177         return NULL;
    178     }
    179 
    180     if (!context) {
    181         return NULL;
    182     }
    183 
    184     SkColorType ct = origInfo.colorType();
    185     SkAlphaType at = origInfo.alphaType();
    186     if (kRGB_565_SkColorType == ct) {
    187         at = kOpaque_SkAlphaType;  // force this setting
    188     } else if (ct != kBGRA_8888_SkColorType && ct != kRGBA_8888_SkColorType) {
    189         // Fall back from whatever ct was to default of kRGBA or kBGRA which is aliased as kN32
    190         ct = kN32_SkColorType;
    191     }
    192     if (kOpaque_SkAlphaType != at) {
    193         at = kPremul_SkAlphaType;  // force this setting
    194     }
    195     const SkImageInfo info = SkImageInfo::Make(origInfo.width(), origInfo.height(), ct, at);
    196 
    197     GrSurfaceDesc desc;
    198     desc.fFlags = kRenderTarget_GrSurfaceFlag;
    199     desc.fWidth = info.width();
    200     desc.fHeight = info.height();
    201     desc.fConfig = SkImageInfo2GrPixelConfig(info);
    202     desc.fSampleCnt = sampleCount;
    203     GrTexture* texture = context->textureProvider()->createTexture(
    204         desc, SkToBool(budgeted), NULL, 0);
    205     if (NULL == texture) {
    206         return NULL;
    207     }
    208     SkASSERT(NULL != texture->asRenderTarget());
    209     return texture->asRenderTarget();
    210 }
    211 
    212 SkGpuDevice* SkGpuDevice::Create(GrContext* context, SkSurface::Budgeted budgeted,
    213                                  const SkImageInfo& info, int sampleCount,
    214                                  const SkSurfaceProps* props, unsigned flags) {
    215 
    216     SkAutoTUnref<GrRenderTarget> rt(CreateRenderTarget(context, budgeted, info,  sampleCount));
    217     if (NULL == rt) {
    218         return NULL;
    219     }
    220 
    221     return SkNEW_ARGS(SkGpuDevice, (rt, info.width(), info.height(), props, flags));
    222 }
    223 
    224 SkGpuDevice::~SkGpuDevice() {
    225     if (fDrawProcs) {
    226         delete fDrawProcs;
    227     }
    228 
    229     delete fTextContext;
    230 
    231     fRenderTarget->unref();
    232     fContext->unref();
    233 }
    234 
    235 ///////////////////////////////////////////////////////////////////////////////
    236 
    237 bool SkGpuDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
    238                                int x, int y) {
    239     DO_DEFERRED_CLEAR();
    240 
    241     // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
    242     GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo);
    243     if (kUnknown_GrPixelConfig == config) {
    244         return false;
    245     }
    246 
    247     uint32_t flags = 0;
    248     if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
    249         flags = GrContext::kUnpremul_PixelOpsFlag;
    250     }
    251     return fContext->readRenderTargetPixels(fRenderTarget, x, y, dstInfo.width(), dstInfo.height(),
    252                                             config, dstPixels, dstRowBytes, flags);
    253 }
    254 
    255 bool SkGpuDevice::onWritePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes,
    256                                 int x, int y) {
    257     // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
    258     GrPixelConfig config = SkImageInfo2GrPixelConfig(info);
    259     if (kUnknown_GrPixelConfig == config) {
    260         return false;
    261     }
    262     uint32_t flags = 0;
    263     if (kUnpremul_SkAlphaType == info.alphaType()) {
    264         flags = GrContext::kUnpremul_PixelOpsFlag;
    265     }
    266     fRenderTarget->writePixels(x, y, info.width(), info.height(), config, pixels, rowBytes, flags);
    267 
    268     // need to bump our genID for compatibility with clients that "know" we have a bitmap
    269     fLegacyBitmap.notifyPixelsChanged();
    270 
    271     return true;
    272 }
    273 
    274 const SkBitmap& SkGpuDevice::onAccessBitmap() {
    275     DO_DEFERRED_CLEAR();
    276     return fLegacyBitmap;
    277 }
    278 
    279 void SkGpuDevice::onAttachToCanvas(SkCanvas* canvas) {
    280     INHERITED::onAttachToCanvas(canvas);
    281 
    282     // Canvas promises that this ptr is valid until onDetachFromCanvas is called
    283     fClipStack.reset(SkRef(canvas->getClipStack()));
    284 }
    285 
    286 void SkGpuDevice::onDetachFromCanvas() {
    287     INHERITED::onDetachFromCanvas();
    288     fClip.reset();
    289     fClipStack.reset(NULL);
    290 }
    291 
    292 // call this every draw call, to ensure that the context reflects our state,
    293 // and not the state from some other canvas/device
    294 void SkGpuDevice::prepareDraw(const SkDraw& draw) {
    295     SkASSERT(fClipStack.get());
    296 
    297     SkASSERT(draw.fClipStack && draw.fClipStack == fClipStack);
    298 
    299     fClip.setClipStack(fClipStack, &this->getOrigin());
    300 
    301     DO_DEFERRED_CLEAR();
    302 }
    303 
    304 GrRenderTarget* SkGpuDevice::accessRenderTarget() {
    305     DO_DEFERRED_CLEAR();
    306     return fRenderTarget;
    307 }
    308 
    309 void SkGpuDevice::clearAll() {
    310     GrColor color = 0;
    311     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::clearAll", fContext);
    312     SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
    313     fContext->clear(&rect, color, true, fRenderTarget);
    314     fNeedClear = false;
    315 }
    316 
    317 void SkGpuDevice::replaceRenderTarget(bool shouldRetainContent) {
    318     // Caller must have accessed the render target, because it knows the rt must be replaced.
    319     SkASSERT(!fNeedClear);
    320 
    321     SkSurface::Budgeted budgeted =
    322             fRenderTarget->resourcePriv().isBudgeted() ? SkSurface::kYes_Budgeted
    323                                                        : SkSurface::kNo_Budgeted;
    324 
    325     SkAutoTUnref<GrRenderTarget> newRT(CreateRenderTarget(
    326         fRenderTarget->getContext(), budgeted, this->imageInfo(), fRenderTarget->numSamples()));
    327 
    328     if (NULL == newRT) {
    329         return;
    330     }
    331 
    332     if (shouldRetainContent) {
    333         if (fRenderTarget->wasDestroyed()) {
    334             return;
    335         }
    336         this->context()->copySurface(newRT, fRenderTarget);
    337     }
    338 
    339     SkASSERT(fRenderTarget != newRT);
    340 
    341     fRenderTarget->unref();
    342     fRenderTarget = newRT.detach();
    343 
    344     SkASSERT(fRenderTarget->surfacePriv().info() == fLegacyBitmap.info());
    345     SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (fRenderTarget->surfacePriv().info(), fRenderTarget));
    346     fLegacyBitmap.setPixelRef(pr)->unref();
    347 }
    348 
    349 ///////////////////////////////////////////////////////////////////////////////
    350 
    351 void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
    352     CHECK_SHOULD_DRAW(draw);
    353     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPaint", fContext);
    354 
    355     GrPaint grPaint;
    356     if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
    357         return;
    358     }
    359 
    360     fContext->drawPaint(fRenderTarget, fClip, grPaint, *draw.fMatrix);
    361 }
    362 
    363 // must be in SkCanvas::PointMode order
    364 static const GrPrimitiveType gPointMode2PrimtiveType[] = {
    365     kPoints_GrPrimitiveType,
    366     kLines_GrPrimitiveType,
    367     kLineStrip_GrPrimitiveType
    368 };
    369 
    370 void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
    371                              size_t count, const SkPoint pts[], const SkPaint& paint) {
    372     CHECK_FOR_ANNOTATION(paint);
    373     CHECK_SHOULD_DRAW(draw);
    374 
    375     SkScalar width = paint.getStrokeWidth();
    376     if (width < 0) {
    377         return;
    378     }
    379 
    380     if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mode) {
    381         GrStrokeInfo strokeInfo(paint, SkPaint::kStroke_Style);
    382         GrPaint grPaint;
    383         if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true,
    384                              &grPaint)) {
    385             return;
    386         }
    387         SkPath path;
    388         path.setIsVolatile(true);
    389         path.moveTo(pts[0]);
    390         path.lineTo(pts[1]);
    391         fContext->drawPath(fRenderTarget, fClip, grPaint, *draw.fMatrix, path, strokeInfo);
    392         return;
    393     }
    394 
    395     // we only handle hairlines and paints without path effects or mask filters,
    396     // else we let the SkDraw call our drawPath()
    397     if (width > 0 || paint.getPathEffect() || paint.getMaskFilter()) {
    398         draw.drawPoints(mode, count, pts, paint, true);
    399         return;
    400     }
    401 
    402     GrPaint grPaint;
    403     if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
    404         return;
    405     }
    406 
    407     fContext->drawVertices(fRenderTarget,
    408                            fClip,
    409                            grPaint,
    410                            *draw.fMatrix,
    411                            gPointMode2PrimtiveType[mode],
    412                            SkToS32(count),
    413                            (SkPoint*)pts,
    414                            NULL,
    415                            NULL,
    416                            NULL,
    417                            0);
    418 }
    419 
    420 ///////////////////////////////////////////////////////////////////////////////
    421 
    422 void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
    423                            const SkPaint& paint) {
    424     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawRect", fContext);
    425 
    426     CHECK_FOR_ANNOTATION(paint);
    427     CHECK_SHOULD_DRAW(draw);
    428 
    429     bool doStroke = paint.getStyle() != SkPaint::kFill_Style;
    430     SkScalar width = paint.getStrokeWidth();
    431 
    432     /*
    433         We have special code for hairline strokes, miter-strokes, bevel-stroke
    434         and fills. Anything else we just call our path code.
    435      */
    436     bool usePath = doStroke && width > 0 &&
    437                    (paint.getStrokeJoin() == SkPaint::kRound_Join ||
    438                     (paint.getStrokeJoin() == SkPaint::kBevel_Join && rect.isEmpty()));
    439     // another two reasons we might need to call drawPath...
    440 
    441     if (paint.getMaskFilter()) {
    442         usePath = true;
    443     }
    444 
    445     if (!usePath && paint.isAntiAlias() && !draw.fMatrix->rectStaysRect()) {
    446 #if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
    447         if (doStroke) {
    448 #endif
    449             usePath = true;
    450 #if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
    451         } else {
    452             usePath = !draw.fMatrix->preservesRightAngles();
    453         }
    454 #endif
    455     }
    456     // until we can both stroke and fill rectangles
    457     if (paint.getStyle() == SkPaint::kStrokeAndFill_Style) {
    458         usePath = true;
    459     }
    460 
    461     GrStrokeInfo strokeInfo(paint);
    462 
    463     const SkPathEffect* pe = paint.getPathEffect();
    464     if (!usePath && pe && !strokeInfo.isDashed()) {
    465         usePath = true;
    466     }
    467 
    468     if (usePath) {
    469         SkPath path;
    470         path.setIsVolatile(true);
    471         path.addRect(rect);
    472         this->drawPath(draw, path, paint, NULL, true);
    473         return;
    474     }
    475 
    476     GrPaint grPaint;
    477     if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
    478         return;
    479     }
    480 
    481     fContext->drawRect(fRenderTarget, fClip, grPaint, *draw.fMatrix, rect, &strokeInfo);
    482 }
    483 
    484 ///////////////////////////////////////////////////////////////////////////////
    485 
    486 void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rect,
    487                             const SkPaint& paint) {
    488     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawRRect", fContext);
    489     CHECK_FOR_ANNOTATION(paint);
    490     CHECK_SHOULD_DRAW(draw);
    491 
    492     GrPaint grPaint;
    493     if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
    494         return;
    495     }
    496 
    497     GrStrokeInfo strokeInfo(paint);
    498     if (paint.getMaskFilter()) {
    499         // try to hit the fast path for drawing filtered round rects
    500 
    501         SkRRect devRRect;
    502         if (rect.transform(*draw.fMatrix, &devRRect)) {
    503             if (devRRect.allCornersCircular()) {
    504                 SkRect maskRect;
    505                 if (paint.getMaskFilter()->canFilterMaskGPU(devRRect.rect(),
    506                                                             draw.fClip->getBounds(),
    507                                                             *draw.fMatrix,
    508                                                             &maskRect)) {
    509                     SkIRect finalIRect;
    510                     maskRect.roundOut(&finalIRect);
    511                     if (draw.fClip->quickReject(finalIRect)) {
    512                         // clipped out
    513                         return;
    514                     }
    515                     if (paint.getMaskFilter()->directFilterRRectMaskGPU(fContext,
    516                                                                         fRenderTarget,
    517                                                                         &grPaint,
    518                                                                         fClip,
    519                                                                         *draw.fMatrix,
    520                                                                         strokeInfo.getStrokeRec(),
    521                                                                         devRRect)) {
    522                         return;
    523                     }
    524                 }
    525 
    526             }
    527         }
    528 
    529     }
    530 
    531     bool usePath = false;
    532 
    533     if (paint.getMaskFilter()) {
    534         usePath = true;
    535     } else {
    536         const SkPathEffect* pe = paint.getPathEffect();
    537         if (pe && !strokeInfo.isDashed()) {
    538             usePath = true;
    539         }
    540     }
    541 
    542 
    543     if (usePath) {
    544         SkPath path;
    545         path.setIsVolatile(true);
    546         path.addRRect(rect);
    547         this->drawPath(draw, path, paint, NULL, true);
    548         return;
    549     }
    550 
    551     fContext->drawRRect(fRenderTarget, fClip, grPaint, *draw.fMatrix, rect, strokeInfo);
    552 }
    553 
    554 void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
    555                              const SkRRect& inner, const SkPaint& paint) {
    556     SkStrokeRec stroke(paint);
    557     if (stroke.isFillStyle()) {
    558 
    559         CHECK_FOR_ANNOTATION(paint);
    560         CHECK_SHOULD_DRAW(draw);
    561 
    562         GrPaint grPaint;
    563         if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true,
    564                              &grPaint)) {
    565             return;
    566         }
    567 
    568         if (NULL == paint.getMaskFilter() && NULL == paint.getPathEffect()) {
    569             fContext->drawDRRect(fRenderTarget, fClip, grPaint, *draw.fMatrix, outer, inner);
    570             return;
    571         }
    572     }
    573 
    574     SkPath path;
    575     path.setIsVolatile(true);
    576     path.addRRect(outer);
    577     path.addRRect(inner);
    578     path.setFillType(SkPath::kEvenOdd_FillType);
    579 
    580     this->drawPath(draw, path, paint, NULL, true);
    581 }
    582 
    583 
    584 /////////////////////////////////////////////////////////////////////////////
    585 
    586 void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval,
    587                            const SkPaint& paint) {
    588     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawOval", fContext);
    589     CHECK_FOR_ANNOTATION(paint);
    590     CHECK_SHOULD_DRAW(draw);
    591 
    592     GrStrokeInfo strokeInfo(paint);
    593 
    594     bool usePath = false;
    595     // some basic reasons we might need to call drawPath...
    596     if (paint.getMaskFilter()) {
    597         usePath = true;
    598     } else {
    599         const SkPathEffect* pe = paint.getPathEffect();
    600         if (pe && !strokeInfo.isDashed()) {
    601             usePath = true;
    602         }
    603     }
    604 
    605     if (usePath) {
    606         SkPath path;
    607         path.setIsVolatile(true);
    608         path.addOval(oval);
    609         this->drawPath(draw, path, paint, NULL, true);
    610         return;
    611     }
    612 
    613     GrPaint grPaint;
    614     if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
    615         return;
    616     }
    617 
    618     fContext->drawOval(fRenderTarget, fClip, grPaint, *draw.fMatrix, oval, strokeInfo);
    619 }
    620 
    621 #include "SkMaskFilter.h"
    622 
    623 ///////////////////////////////////////////////////////////////////////////////
    624 
    625 // helpers for applying mask filters
    626 namespace {
    627 
    628 // Draw a mask using the supplied paint. Since the coverage/geometry
    629 // is already burnt into the mask this boils down to a rect draw.
    630 // Return true if the mask was successfully drawn.
    631 bool draw_mask(GrContext* context,
    632                GrRenderTarget* rt,
    633                const GrClip& clip,
    634                const SkMatrix& viewMatrix,
    635                const SkRect& maskRect,
    636                GrPaint* grp,
    637                GrTexture* mask) {
    638     SkMatrix matrix;
    639     matrix.setTranslate(-maskRect.fLeft, -maskRect.fTop);
    640     matrix.postIDiv(mask->width(), mask->height());
    641 
    642     grp->addCoverageProcessor(GrSimpleTextureEffect::Create(mask, matrix,
    643                                                             kDevice_GrCoordSet))->unref();
    644 
    645     SkMatrix inverse;
    646     if (!viewMatrix.invert(&inverse)) {
    647         return false;
    648     }
    649     context->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), maskRect, inverse);
    650     return true;
    651 }
    652 
    653 static bool clip_bounds_quick_reject(const SkIRect& clipBounds, const SkIRect& rect) {
    654     return clipBounds.isEmpty() || rect.isEmpty() || !SkIRect::Intersects(clipBounds, rect);
    655 }
    656 
    657 bool draw_with_mask_filter(GrContext* context,
    658                            GrRenderTarget* rt,
    659                            const GrClip& clipData,
    660                            const SkMatrix& viewMatrix,
    661                            const SkPath& devPath,
    662                            SkMaskFilter* filter,
    663                            const SkIRect& clipBounds,
    664                            GrPaint* grp,
    665                            SkPaint::Style style) {
    666     SkMask  srcM, dstM;
    667 
    668     if (!SkDraw::DrawToMask(devPath, &clipBounds, filter, &viewMatrix, &srcM,
    669                             SkMask::kComputeBoundsAndRenderImage_CreateMode, style)) {
    670         return false;
    671     }
    672     SkAutoMaskFreeImage autoSrc(srcM.fImage);
    673 
    674     if (!filter->filterMask(&dstM, srcM, viewMatrix, NULL)) {
    675         return false;
    676     }
    677     // this will free-up dstM when we're done (allocated in filterMask())
    678     SkAutoMaskFreeImage autoDst(dstM.fImage);
    679 
    680     if (clip_bounds_quick_reject(clipBounds, dstM.fBounds)) {
    681         return false;
    682     }
    683 
    684     // we now have a device-aligned 8bit mask in dstM, ready to be drawn using
    685     // the current clip (and identity matrix) and GrPaint settings
    686     GrSurfaceDesc desc;
    687     desc.fWidth = dstM.fBounds.width();
    688     desc.fHeight = dstM.fBounds.height();
    689     desc.fConfig = kAlpha_8_GrPixelConfig;
    690 
    691     SkAutoTUnref<GrTexture> texture(context->textureProvider()->refScratchTexture(
    692         desc, GrTextureProvider::kApprox_ScratchTexMatch));
    693     if (!texture) {
    694         return false;
    695     }
    696     texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
    697                                dstM.fImage, dstM.fRowBytes);
    698 
    699     SkRect maskRect = SkRect::Make(dstM.fBounds);
    700 
    701     return draw_mask(context, rt, clipData, viewMatrix, maskRect, grp, texture);
    702 }
    703 
    704 // Create a mask of 'devPath' and place the result in 'mask'.
    705 GrTexture* create_mask_GPU(GrContext* context,
    706                            GrRenderTarget* rt,
    707                            const SkRect& maskRect,
    708                            const SkPath& devPath,
    709                            const GrStrokeInfo& strokeInfo,
    710                            bool doAA,
    711                            int sampleCnt) {
    712     GrSurfaceDesc desc;
    713     desc.fFlags = kRenderTarget_GrSurfaceFlag;
    714     desc.fWidth = SkScalarCeilToInt(maskRect.width());
    715     desc.fHeight = SkScalarCeilToInt(maskRect.height());
    716     desc.fSampleCnt = doAA ? sampleCnt : 0;
    717     // We actually only need A8, but it often isn't supported as a
    718     // render target so default to RGBA_8888
    719     desc.fConfig = kRGBA_8888_GrPixelConfig;
    720 
    721     if (context->isConfigRenderable(kAlpha_8_GrPixelConfig,
    722                                     desc.fSampleCnt > 0)) {
    723         desc.fConfig = kAlpha_8_GrPixelConfig;
    724     }
    725 
    726     GrTexture* mask = context->textureProvider()->refScratchTexture(
    727         desc, GrTextureProvider::kApprox_ScratchTexMatch);
    728     if (NULL == mask) {
    729         return NULL;
    730     }
    731 
    732     SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height());
    733 
    734     context->clear(NULL, 0x0, true, mask->asRenderTarget());
    735 
    736     GrPaint tempPaint;
    737     tempPaint.setAntiAlias(doAA);
    738     tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);
    739 
    740     // setup new clip
    741     GrClip clip(clipRect);
    742 
    743     // Draw the mask into maskTexture with the path's top-left at the origin using tempPaint.
    744     SkMatrix translate;
    745     translate.setTranslate(-maskRect.fLeft, -maskRect.fTop);
    746     context->drawPath(mask->asRenderTarget(), clip, tempPaint, translate, devPath, strokeInfo);
    747     return mask;
    748 }
    749 
    750 SkBitmap wrap_texture(GrTexture* texture, int width, int height) {
    751     SkBitmap result;
    752     result.setInfo(SkImageInfo::MakeN32Premul(width, height));
    753     result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unref();
    754     return result;
    755 }
    756 
    757 };
    758 
    759 void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
    760                            const SkPaint& paint, const SkMatrix* prePathMatrix,
    761                            bool pathIsMutable) {
    762     CHECK_FOR_ANNOTATION(paint);
    763     CHECK_SHOULD_DRAW(draw);
    764     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPath", fContext);
    765 
    766     return this->internalDrawPath(origSrcPath, paint, *draw.fMatrix, prePathMatrix,
    767                                   draw.fClip->getBounds(), pathIsMutable);
    768 }
    769 
    770 void SkGpuDevice::internalDrawPath(const SkPath& origSrcPath, const SkPaint& paint,
    771                                    const SkMatrix& origViewMatrix, const SkMatrix* prePathMatrix,
    772                                    const SkIRect& clipBounds, bool pathIsMutable) {
    773     SkASSERT(!pathIsMutable || origSrcPath.isVolatile());
    774 
    775     GrStrokeInfo strokeInfo(paint);
    776 
    777     // If we have a prematrix, apply it to the path, optimizing for the case
    778     // where the original path can in fact be modified in place (even though
    779     // its parameter type is const).
    780     SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
    781     SkTLazy<SkPath> tmpPath;
    782     SkTLazy<SkPath> effectPath;
    783     SkPathEffect* pathEffect = paint.getPathEffect();
    784 
    785     SkMatrix viewMatrix = origViewMatrix;
    786 
    787     if (prePathMatrix) {
    788         // stroking, path effects, and blurs are supposed to be applied *after* the prePathMatrix.
    789         // The pre-path-matrix also should not affect shading.
    790         if (NULL == paint.getMaskFilter() && NULL == pathEffect && NULL == paint.getShader() &&
    791             (strokeInfo.getStrokeRec().isFillStyle() ||
    792              strokeInfo.getStrokeRec().isHairlineStyle())) {
    793             viewMatrix.preConcat(*prePathMatrix);
    794         } else {
    795             SkPath* result = pathPtr;
    796 
    797             if (!pathIsMutable) {
    798                 result = tmpPath.init();
    799                 result->setIsVolatile(true);
    800                 pathIsMutable = true;
    801             }
    802             // should I push prePathMatrix on our MV stack temporarily, instead
    803             // of applying it here? See SkDraw.cpp
    804             pathPtr->transform(*prePathMatrix, result);
    805             pathPtr = result;
    806         }
    807     }
    808     // at this point we're done with prePathMatrix
    809     SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
    810 
    811     GrPaint grPaint;
    812     if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, viewMatrix, true, &grPaint)) {
    813         return;
    814     }
    815 
    816     const SkRect* cullRect = NULL;  // TODO: what is our bounds?
    817     SkStrokeRec* strokePtr = strokeInfo.getStrokeRecPtr();
    818     if (!strokeInfo.isDashed() && pathEffect && pathEffect->filterPath(effectPath.init(), *pathPtr,
    819                                                                        strokePtr, cullRect)) {
    820         pathPtr = effectPath.get();
    821         pathIsMutable = true;
    822     }
    823 
    824     const SkStrokeRec& stroke = strokeInfo.getStrokeRec();
    825     if (paint.getMaskFilter()) {
    826         if (!stroke.isHairlineStyle()) {
    827             SkPath* strokedPath = pathIsMutable ? pathPtr : tmpPath.init();
    828             if (strokeInfo.isDashed()) {
    829                 if (pathEffect->filterPath(strokedPath, *pathPtr, strokePtr, cullRect)) {
    830                     pathPtr = strokedPath;
    831                     pathIsMutable = true;
    832                 }
    833                 strokeInfo.removeDash();
    834             }
    835             if (stroke.applyToPath(strokedPath, *pathPtr)) {
    836                 pathPtr = strokedPath;
    837                 pathIsMutable = true;
    838                 strokeInfo.setFillStyle();
    839             }
    840         }
    841 
    842         // avoid possibly allocating a new path in transform if we can
    843         SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath.init();
    844         if (!pathIsMutable) {
    845             devPathPtr->setIsVolatile(true);
    846         }
    847 
    848         // transform the path into device space
    849         pathPtr->transform(viewMatrix, devPathPtr);
    850 
    851         SkRect maskRect;
    852         if (paint.getMaskFilter()->canFilterMaskGPU(devPathPtr->getBounds(),
    853                                                     clipBounds,
    854                                                     viewMatrix,
    855                                                     &maskRect)) {
    856             SkIRect finalIRect;
    857             maskRect.roundOut(&finalIRect);
    858             if (clip_bounds_quick_reject(clipBounds, finalIRect)) {
    859                 // clipped out
    860                 return;
    861             }
    862 
    863             if (paint.getMaskFilter()->directFilterMaskGPU(fContext,
    864                                                            fRenderTarget,
    865                                                            &grPaint,
    866                                                            fClip,
    867                                                            viewMatrix,
    868                                                            stroke,
    869                                                            *devPathPtr)) {
    870                 // the mask filter was able to draw itself directly, so there's nothing
    871                 // left to do.
    872                 return;
    873             }
    874 
    875 
    876             SkAutoTUnref<GrTexture> mask(create_mask_GPU(fContext,
    877                                                          fRenderTarget,
    878                                                          maskRect,
    879                                                          *devPathPtr,
    880                                                          strokeInfo,
    881                                                          grPaint.isAntiAlias(),
    882                                                          fRenderTarget->numSamples()));
    883             if (mask) {
    884                 GrTexture* filtered;
    885 
    886                 if (paint.getMaskFilter()->filterMaskGPU(mask, viewMatrix, maskRect, &filtered, true)) {
    887                     // filterMaskGPU gives us ownership of a ref to the result
    888                     SkAutoTUnref<GrTexture> atu(filtered);
    889                     if (draw_mask(fContext,
    890                                   fRenderTarget,
    891                                   fClip,
    892                                   viewMatrix,
    893                                   maskRect,
    894                                   &grPaint,
    895                                   filtered)) {
    896                         // This path is completely drawn
    897                         return;
    898                     }
    899                 }
    900             }
    901         }
    902 
    903         // draw the mask on the CPU - this is a fallthrough path in case the
    904         // GPU path fails
    905         SkPaint::Style style = stroke.isHairlineStyle() ? SkPaint::kStroke_Style :
    906                                                           SkPaint::kFill_Style;
    907         draw_with_mask_filter(fContext, fRenderTarget, fClip, viewMatrix, *devPathPtr,
    908                               paint.getMaskFilter(), clipBounds, &grPaint, style);
    909         return;
    910     }
    911 
    912     fContext->drawPath(fRenderTarget, fClip, grPaint, viewMatrix, *pathPtr, strokeInfo);
    913 }
    914 
    915 static const int kBmpSmallTileSize = 1 << 10;
    916 
    917 static inline int get_tile_count(const SkIRect& srcRect, int tileSize)  {
    918     int tilesX = (srcRect.fRight / tileSize) - (srcRect.fLeft / tileSize) + 1;
    919     int tilesY = (srcRect.fBottom / tileSize) - (srcRect.fTop / tileSize) + 1;
    920     return tilesX * tilesY;
    921 }
    922 
    923 static int determine_tile_size(const SkBitmap& bitmap, const SkIRect& src, int maxTileSize) {
    924     if (maxTileSize <= kBmpSmallTileSize) {
    925         return maxTileSize;
    926     }
    927 
    928     size_t maxTileTotalTileSize = get_tile_count(src, maxTileSize);
    929     size_t smallTotalTileSize = get_tile_count(src, kBmpSmallTileSize);
    930 
    931     maxTileTotalTileSize *= maxTileSize * maxTileSize;
    932     smallTotalTileSize *= kBmpSmallTileSize * kBmpSmallTileSize;
    933 
    934     if (maxTileTotalTileSize > 2 * smallTotalTileSize) {
    935         return kBmpSmallTileSize;
    936     } else {
    937         return maxTileSize;
    938     }
    939 }
    940 
    941 // Given a bitmap, an optional src rect, and a context with a clip and matrix determine what
    942 // pixels from the bitmap are necessary.
    943 static void determine_clipped_src_rect(const GrContext* context,
    944                                        const GrRenderTarget* rt,
    945                                        const GrClip& clip,
    946                                        const SkMatrix& viewMatrix,
    947                                        const SkBitmap& bitmap,
    948                                        const SkRect* srcRectPtr,
    949                                        SkIRect* clippedSrcIRect) {
    950     clip.getConservativeBounds(rt, clippedSrcIRect, NULL);
    951     SkMatrix inv;
    952     if (!viewMatrix.invert(&inv)) {
    953         clippedSrcIRect->setEmpty();
    954         return;
    955     }
    956     SkRect clippedSrcRect = SkRect::Make(*clippedSrcIRect);
    957     inv.mapRect(&clippedSrcRect);
    958     if (srcRectPtr) {
    959         // we've setup src space 0,0 to map to the top left of the src rect.
    960         clippedSrcRect.offset(srcRectPtr->fLeft, srcRectPtr->fTop);
    961         if (!clippedSrcRect.intersect(*srcRectPtr)) {
    962             clippedSrcIRect->setEmpty();
    963             return;
    964         }
    965     }
    966     clippedSrcRect.roundOut(clippedSrcIRect);
    967     SkIRect bmpBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
    968     if (!clippedSrcIRect->intersect(bmpBounds)) {
    969         clippedSrcIRect->setEmpty();
    970     }
    971 }
    972 
    973 bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
    974                                    const SkMatrix& viewMatrix,
    975                                    const GrTextureParams& params,
    976                                    const SkRect* srcRectPtr,
    977                                    int maxTileSize,
    978                                    int* tileSize,
    979                                    SkIRect* clippedSrcRect) const {
    980     // if bitmap is explictly texture backed then just use the texture
    981     if (bitmap.getTexture()) {
    982         return false;
    983     }
    984 
    985     // if it's larger than the max tile size, then we have no choice but tiling.
    986     if (bitmap.width() > maxTileSize || bitmap.height() > maxTileSize) {
    987         determine_clipped_src_rect(fContext, fRenderTarget, fClip, viewMatrix, bitmap,
    988                                    srcRectPtr, clippedSrcRect);
    989         *tileSize = determine_tile_size(bitmap, *clippedSrcRect, maxTileSize);
    990         return true;
    991     }
    992 
    993     if (bitmap.width() * bitmap.height() < 4 * kBmpSmallTileSize * kBmpSmallTileSize) {
    994         return false;
    995     }
    996 
    997     // if the entire texture is already in our cache then no reason to tile it
    998     if (GrIsBitmapInCache(fContext, bitmap, &params)) {
    999         return false;
   1000     }
   1001 
   1002     // At this point we know we could do the draw by uploading the entire bitmap
   1003     // as a texture. However, if the texture would be large compared to the
   1004     // cache size and we don't require most of it for this draw then tile to
   1005     // reduce the amount of upload and cache spill.
   1006 
   1007     // assumption here is that sw bitmap size is a good proxy for its size as
   1008     // a texture
   1009     size_t bmpSize = bitmap.getSize();
   1010     size_t cacheSize;
   1011     fContext->getResourceCacheLimits(NULL, &cacheSize);
   1012     if (bmpSize < cacheSize / 2) {
   1013         return false;
   1014     }
   1015 
   1016     // Figure out how much of the src we will need based on the src rect and clipping.
   1017     determine_clipped_src_rect(fContext, fRenderTarget, fClip, viewMatrix, bitmap, srcRectPtr,
   1018                                clippedSrcRect);
   1019     *tileSize = kBmpSmallTileSize; // already know whole bitmap fits in one max sized tile.
   1020     size_t usedTileBytes = get_tile_count(*clippedSrcRect, kBmpSmallTileSize) *
   1021                            kBmpSmallTileSize * kBmpSmallTileSize;
   1022 
   1023     return usedTileBytes < 2 * bmpSize;
   1024 }
   1025 
   1026 void SkGpuDevice::drawBitmap(const SkDraw& origDraw,
   1027                              const SkBitmap& bitmap,
   1028                              const SkMatrix& m,
   1029                              const SkPaint& paint) {
   1030     SkMatrix concat;
   1031     SkTCopyOnFirstWrite<SkDraw> draw(origDraw);
   1032     if (!m.isIdentity()) {
   1033         concat.setConcat(*draw->fMatrix, m);
   1034         draw.writable()->fMatrix = &concat;
   1035     }
   1036     this->drawBitmapCommon(*draw, bitmap, NULL, NULL, paint, SkCanvas::kNone_DrawBitmapRectFlag);
   1037 }
   1038 
   1039 // This method outsets 'iRect' by 'outset' all around and then clamps its extents to
   1040 // 'clamp'. 'offset' is adjusted to remain positioned over the top-left corner
   1041 // of 'iRect' for all possible outsets/clamps.
   1042 static inline void clamped_outset_with_offset(SkIRect* iRect,
   1043                                               int outset,
   1044                                               SkPoint* offset,
   1045                                               const SkIRect& clamp) {
   1046     iRect->outset(outset, outset);
   1047 
   1048     int leftClampDelta = clamp.fLeft - iRect->fLeft;
   1049     if (leftClampDelta > 0) {
   1050         offset->fX -= outset - leftClampDelta;
   1051         iRect->fLeft = clamp.fLeft;
   1052     } else {
   1053         offset->fX -= outset;
   1054     }
   1055 
   1056     int topClampDelta = clamp.fTop - iRect->fTop;
   1057     if (topClampDelta > 0) {
   1058         offset->fY -= outset - topClampDelta;
   1059         iRect->fTop = clamp.fTop;
   1060     } else {
   1061         offset->fY -= outset;
   1062     }
   1063 
   1064     if (iRect->fRight > clamp.fRight) {
   1065         iRect->fRight = clamp.fRight;
   1066     }
   1067     if (iRect->fBottom > clamp.fBottom) {
   1068         iRect->fBottom = clamp.fBottom;
   1069     }
   1070 }
   1071 
   1072 static bool has_aligned_samples(const SkRect& srcRect,
   1073                                 const SkRect& transformedRect) {
   1074     // detect pixel disalignment
   1075     if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) -
   1076             transformedRect.left()) < COLOR_BLEED_TOLERANCE &&
   1077         SkScalarAbs(SkScalarRoundToScalar(transformedRect.top()) -
   1078             transformedRect.top()) < COLOR_BLEED_TOLERANCE &&
   1079         SkScalarAbs(transformedRect.width() - srcRect.width()) <
   1080             COLOR_BLEED_TOLERANCE &&
   1081         SkScalarAbs(transformedRect.height() - srcRect.height()) <
   1082             COLOR_BLEED_TOLERANCE) {
   1083         return true;
   1084     }
   1085     return false;
   1086 }
   1087 
   1088 static bool may_color_bleed(const SkRect& srcRect,
   1089                             const SkRect& transformedRect,
   1090                             const SkMatrix& m) {
   1091     // Only gets called if has_aligned_samples returned false.
   1092     // So we can assume that sampling is axis aligned but not texel aligned.
   1093     SkASSERT(!has_aligned_samples(srcRect, transformedRect));
   1094     SkRect innerSrcRect(srcRect), innerTransformedRect,
   1095         outerTransformedRect(transformedRect);
   1096     innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf);
   1097     m.mapRect(&innerTransformedRect, innerSrcRect);
   1098 
   1099     // The gap between outerTransformedRect and innerTransformedRect
   1100     // represents the projection of the source border area, which is
   1101     // problematic for color bleeding.  We must check whether any
   1102     // destination pixels sample the border area.
   1103     outerTransformedRect.inset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
   1104     innerTransformedRect.outset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
   1105     SkIRect outer, inner;
   1106     outerTransformedRect.round(&outer);
   1107     innerTransformedRect.round(&inner);
   1108     // If the inner and outer rects round to the same result, it means the
   1109     // border does not overlap any pixel centers. Yay!
   1110     return inner != outer;
   1111 }
   1112 
   1113 static bool needs_texture_domain(const SkBitmap& bitmap,
   1114                                  const SkRect& srcRect,
   1115                                  GrTextureParams &params,
   1116                                  const SkMatrix& contextMatrix,
   1117                                  bool bicubic) {
   1118     bool needsTextureDomain = false;
   1119     GrTexture* tex = bitmap.getTexture();
   1120     int width = tex ? tex->width() : bitmap.width();
   1121     int height = tex ? tex->height() : bitmap.height();
   1122 
   1123     if (bicubic || params.filterMode() != GrTextureParams::kNone_FilterMode) {
   1124         // Need texture domain if drawing a sub rect
   1125         needsTextureDomain = srcRect.width() < width ||
   1126                              srcRect.height() < height;
   1127         if (!bicubic && needsTextureDomain && contextMatrix.rectStaysRect()) {
   1128             // sampling is axis-aligned
   1129             SkRect transformedRect;
   1130             contextMatrix.mapRect(&transformedRect, srcRect);
   1131 
   1132             if (has_aligned_samples(srcRect, transformedRect)) {
   1133                 params.setFilterMode(GrTextureParams::kNone_FilterMode);
   1134                 needsTextureDomain = false;
   1135             } else {
   1136                 needsTextureDomain = may_color_bleed(srcRect, transformedRect, contextMatrix);
   1137             }
   1138         }
   1139     }
   1140     return needsTextureDomain;
   1141 }
   1142 
   1143 void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
   1144                                    const SkBitmap& bitmap,
   1145                                    const SkRect* srcRectPtr,
   1146                                    const SkSize* dstSizePtr,
   1147                                    const SkPaint& paint,
   1148                                    SkCanvas::DrawBitmapRectFlags flags) {
   1149     CHECK_SHOULD_DRAW(draw);
   1150 
   1151     SkRect srcRect;
   1152     SkSize dstSize;
   1153     // If there is no src rect, or the src rect contains the entire bitmap then we're effectively
   1154     // in the (easier) bleed case, so update flags.
   1155     if (NULL == srcRectPtr) {
   1156         SkScalar w = SkIntToScalar(bitmap.width());
   1157         SkScalar h = SkIntToScalar(bitmap.height());
   1158         dstSize.fWidth = w;
   1159         dstSize.fHeight = h;
   1160         srcRect.set(0, 0, w, h);
   1161     } else {
   1162         SkASSERT(dstSizePtr);
   1163         srcRect = *srcRectPtr;
   1164         dstSize = *dstSizePtr;
   1165     }
   1166     GrTexture* tex = bitmap.getTexture();
   1167     int width = tex ? tex->width() : bitmap.width();
   1168     int height = tex ? tex->height() : bitmap.height();
   1169     if (srcRect.fLeft <= 0 && srcRect.fTop <= 0 &&
   1170         srcRect.fRight >= width && srcRect.fBottom >= height) {
   1171         flags = (SkCanvas::DrawBitmapRectFlags) (flags | SkCanvas::kBleed_DrawBitmapRectFlag);
   1172     }
   1173 
   1174     // If the render target is not msaa and draw is antialiased, we call
   1175     // drawRect instead of drawing on the render target directly.
   1176     // FIXME: the tiled bitmap code path doesn't currently support
   1177     // anti-aliased edges, we work around that for now by drawing directly
   1178     // if the image size exceeds maximum texture size.
   1179     int maxTextureSize = fContext->getMaxTextureSize();
   1180     bool directDraw = fRenderTarget->isMultisampled() ||
   1181                       !paint.isAntiAlias() ||
   1182                       bitmap.width() > maxTextureSize ||
   1183                       bitmap.height() > maxTextureSize;
   1184 
   1185     // we check whether dst rect are pixel aligned
   1186     if (!directDraw) {
   1187         bool staysRect = draw.fMatrix->rectStaysRect();
   1188 
   1189         if (staysRect) {
   1190             SkRect rect;
   1191             SkRect dstRect = SkRect::MakeXYWH(0, 0, dstSize.fWidth, dstSize.fHeight);
   1192             draw.fMatrix->mapRect(&rect, dstRect);
   1193             const SkScalar *scalars = rect.asScalars();
   1194             bool isDstPixelAligned = true;
   1195             for (int i = 0; i < 4; i++) {
   1196                 if (!SkScalarIsInt(scalars[i])) {
   1197                     isDstPixelAligned = false;
   1198                     break;
   1199                 }
   1200             }
   1201 
   1202             if (isDstPixelAligned)
   1203                 directDraw = true;
   1204         }
   1205     }
   1206 
   1207     if (paint.getMaskFilter() || !directDraw) {
   1208         // Convert the bitmap to a shader so that the rect can be drawn
   1209         // through drawRect, which supports mask filters.
   1210         SkBitmap        tmp;    // subset of bitmap, if necessary
   1211         const SkBitmap* bitmapPtr = &bitmap;
   1212         SkMatrix localM;
   1213         if (srcRectPtr) {
   1214             localM.setTranslate(-srcRectPtr->fLeft, -srcRectPtr->fTop);
   1215             localM.postScale(dstSize.fWidth / srcRectPtr->width(),
   1216                              dstSize.fHeight / srcRectPtr->height());
   1217             // In bleed mode we position and trim the bitmap based on the src rect which is
   1218             // already accounted for in 'm' and 'srcRect'. In clamp mode we need to chop out
   1219             // the desired portion of the bitmap and then update 'm' and 'srcRect' to
   1220             // compensate.
   1221             if (!(SkCanvas::kBleed_DrawBitmapRectFlag & flags)) {
   1222                 SkIRect iSrc;
   1223                 srcRect.roundOut(&iSrc);
   1224 
   1225                 SkPoint offset = SkPoint::Make(SkIntToScalar(iSrc.fLeft),
   1226                                                SkIntToScalar(iSrc.fTop));
   1227 
   1228                 if (!bitmap.extractSubset(&tmp, iSrc)) {
   1229                     return;     // extraction failed
   1230                 }
   1231                 bitmapPtr = &tmp;
   1232                 srcRect.offset(-offset.fX, -offset.fY);
   1233 
   1234                 // The source rect has changed so update the matrix
   1235                 localM.preTranslate(offset.fX, offset.fY);
   1236             }
   1237         } else {
   1238             localM.reset();
   1239         }
   1240 
   1241         SkPaint paintWithShader(paint);
   1242         paintWithShader.setShader(SkShader::CreateBitmapShader(*bitmapPtr,
   1243             SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &localM))->unref();
   1244         SkRect dstRect = {0, 0, dstSize.fWidth, dstSize.fHeight};
   1245         this->drawRect(draw, dstRect, paintWithShader);
   1246 
   1247         return;
   1248     }
   1249 
   1250     // If there is no mask filter than it is OK to handle the src rect -> dst rect scaling using
   1251     // the view matrix rather than a local matrix.
   1252     SkMatrix m;
   1253     m.setScale(dstSize.fWidth / srcRect.width(),
   1254                dstSize.fHeight / srcRect.height());
   1255     SkMatrix viewM = *draw.fMatrix;
   1256     viewM.preConcat(m);
   1257 
   1258     GrTextureParams params;
   1259     SkFilterQuality paintFilterQuality = paint.getFilterQuality();
   1260     GrTextureParams::FilterMode textureFilterMode;
   1261 
   1262     bool doBicubic = false;
   1263 
   1264     switch(paintFilterQuality) {
   1265         case kNone_SkFilterQuality:
   1266             textureFilterMode = GrTextureParams::kNone_FilterMode;
   1267             break;
   1268         case kLow_SkFilterQuality:
   1269             textureFilterMode = GrTextureParams::kBilerp_FilterMode;
   1270             break;
   1271         case kMedium_SkFilterQuality:
   1272             if (viewM.getMinScale() < SK_Scalar1) {
   1273                 textureFilterMode = GrTextureParams::kMipMap_FilterMode;
   1274             } else {
   1275                 // Don't trigger MIP level generation unnecessarily.
   1276                 textureFilterMode = GrTextureParams::kBilerp_FilterMode;
   1277             }
   1278             break;
   1279         case kHigh_SkFilterQuality:
   1280             // Minification can look bad with the bicubic effect.
   1281             doBicubic =
   1282                 GrBicubicEffect::ShouldUseBicubic(viewM, &textureFilterMode);
   1283             break;
   1284         default:
   1285             SkErrorInternals::SetError( kInvalidPaint_SkError,
   1286                                         "Sorry, I don't understand the filtering "
   1287                                         "mode you asked for.  Falling back to "
   1288                                         "MIPMaps.");
   1289             textureFilterMode = GrTextureParams::kMipMap_FilterMode;
   1290             break;
   1291     }
   1292 
   1293     int tileFilterPad;
   1294     if (doBicubic) {
   1295         tileFilterPad = GrBicubicEffect::kFilterTexelPad;
   1296     } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) {
   1297         tileFilterPad = 0;
   1298     } else {
   1299         tileFilterPad = 1;
   1300     }
   1301     params.setFilterMode(textureFilterMode);
   1302 
   1303     int maxTileSize = fContext->getMaxTextureSize() - 2 * tileFilterPad;
   1304     int tileSize;
   1305 
   1306     SkIRect clippedSrcRect;
   1307     if (this->shouldTileBitmap(bitmap, viewM, params, srcRectPtr, maxTileSize, &tileSize,
   1308                                &clippedSrcRect)) {
   1309         this->drawTiledBitmap(bitmap, viewM, srcRect, clippedSrcRect, params, paint, flags,
   1310                               tileSize, doBicubic);
   1311     } else {
   1312         // take the simple case
   1313         bool needsTextureDomain = needs_texture_domain(bitmap,
   1314                                                        srcRect,
   1315                                                        params,
   1316                                                        viewM,
   1317                                                        doBicubic);
   1318         this->internalDrawBitmap(bitmap,
   1319                                  viewM,
   1320                                  srcRect,
   1321                                  params,
   1322                                  paint,
   1323                                  flags,
   1324                                  doBicubic,
   1325                                  needsTextureDomain);
   1326     }
   1327 }
   1328 
   1329 // Break 'bitmap' into several tiles to draw it since it has already
   1330 // been determined to be too large to fit in VRAM
   1331 void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
   1332                                   const SkMatrix& viewMatrix,
   1333                                   const SkRect& srcRect,
   1334                                   const SkIRect& clippedSrcIRect,
   1335                                   const GrTextureParams& params,
   1336                                   const SkPaint& paint,
   1337                                   SkCanvas::DrawBitmapRectFlags flags,
   1338                                   int tileSize,
   1339                                   bool bicubic) {
   1340     // The following pixel lock is technically redundant, but it is desirable
   1341     // to lock outside of the tile loop to prevent redecoding the whole image
   1342     // at each tile in cases where 'bitmap' holds an SkDiscardablePixelRef that
   1343     // is larger than the limit of the discardable memory pool.
   1344     SkAutoLockPixels alp(bitmap);
   1345     SkRect clippedSrcRect = SkRect::Make(clippedSrcIRect);
   1346 
   1347     int nx = bitmap.width() / tileSize;
   1348     int ny = bitmap.height() / tileSize;
   1349     for (int x = 0; x <= nx; x++) {
   1350         for (int y = 0; y <= ny; y++) {
   1351             SkRect tileR;
   1352             tileR.set(SkIntToScalar(x * tileSize),
   1353                       SkIntToScalar(y * tileSize),
   1354                       SkIntToScalar((x + 1) * tileSize),
   1355                       SkIntToScalar((y + 1) * tileSize));
   1356 
   1357             if (!SkRect::Intersects(tileR, clippedSrcRect)) {
   1358                 continue;
   1359             }
   1360 
   1361             if (!tileR.intersect(srcRect)) {
   1362                 continue;
   1363             }
   1364 
   1365             SkBitmap tmpB;
   1366             SkIRect iTileR;
   1367             tileR.roundOut(&iTileR);
   1368             SkPoint offset = SkPoint::Make(SkIntToScalar(iTileR.fLeft),
   1369                                            SkIntToScalar(iTileR.fTop));
   1370 
   1371             // Adjust the context matrix to draw at the right x,y in device space
   1372             SkMatrix viewM = viewMatrix;
   1373             SkMatrix tmpM;
   1374             tmpM.setTranslate(offset.fX - srcRect.fLeft, offset.fY - srcRect.fTop);
   1375             viewM.preConcat(tmpM);
   1376 
   1377             if (GrTextureParams::kNone_FilterMode != params.filterMode() || bicubic) {
   1378                 SkIRect iClampRect;
   1379 
   1380                 if (SkCanvas::kBleed_DrawBitmapRectFlag & flags) {
   1381                     // In bleed mode we want to always expand the tile on all edges
   1382                     // but stay within the bitmap bounds
   1383                     iClampRect = SkIRect::MakeWH(bitmap.width(), bitmap.height());
   1384                 } else {
   1385                     // In texture-domain/clamp mode we only want to expand the
   1386                     // tile on edges interior to "srcRect" (i.e., we want to
   1387                     // not bleed across the original clamped edges)
   1388                     srcRect.roundOut(&iClampRect);
   1389                 }
   1390                 int outset = bicubic ? GrBicubicEffect::kFilterTexelPad : 1;
   1391                 clamped_outset_with_offset(&iTileR, outset, &offset, iClampRect);
   1392             }
   1393 
   1394             if (bitmap.extractSubset(&tmpB, iTileR)) {
   1395                 // now offset it to make it "local" to our tmp bitmap
   1396                 tileR.offset(-offset.fX, -offset.fY);
   1397                 GrTextureParams paramsTemp = params;
   1398                 bool needsTextureDomain = needs_texture_domain(bitmap,
   1399                                                                srcRect,
   1400                                                                paramsTemp,
   1401                                                                viewM,
   1402                                                                bicubic);
   1403                 this->internalDrawBitmap(tmpB,
   1404                                          viewM,
   1405                                          tileR,
   1406                                          paramsTemp,
   1407                                          paint,
   1408                                          flags,
   1409                                          bicubic,
   1410                                          needsTextureDomain);
   1411             }
   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 SkBitmap& bitmap,
   1425                                      const SkMatrix& viewMatrix,
   1426                                      const SkRect& srcRect,
   1427                                      const GrTextureParams& params,
   1428                                      const SkPaint& paint,
   1429                                      SkCanvas::DrawBitmapRectFlags flags,
   1430                                      bool bicubic,
   1431                                      bool needsTextureDomain) {
   1432     SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() &&
   1433              bitmap.height() <= fContext->getMaxTextureSize());
   1434 
   1435     GrTexture* texture;
   1436     AutoBitmapTexture abt(fContext, bitmap, &params, &texture);
   1437     if (NULL == texture) {
   1438         return;
   1439     }
   1440 
   1441     SkRect dstRect = {0, 0, srcRect.width(), srcRect.height() };
   1442     SkRect paintRect;
   1443     SkScalar wInv = SkScalarInvert(SkIntToScalar(texture->width()));
   1444     SkScalar hInv = SkScalarInvert(SkIntToScalar(texture->height()));
   1445     paintRect.setLTRB(SkScalarMul(srcRect.fLeft,   wInv),
   1446                       SkScalarMul(srcRect.fTop,    hInv),
   1447                       SkScalarMul(srcRect.fRight,  wInv),
   1448                       SkScalarMul(srcRect.fBottom, hInv));
   1449 
   1450     SkRect textureDomain = SkRect::MakeEmpty();
   1451     SkAutoTUnref<GrFragmentProcessor> fp;
   1452     if (needsTextureDomain && !(flags & SkCanvas::kBleed_DrawBitmapRectFlag)) {
   1453         // Use a constrained texture domain to avoid color bleeding
   1454         SkScalar left, top, right, bottom;
   1455         if (srcRect.width() > SK_Scalar1) {
   1456             SkScalar border = SK_ScalarHalf / texture->width();
   1457             left = paintRect.left() + border;
   1458             right = paintRect.right() - border;
   1459         } else {
   1460             left = right = SkScalarHalf(paintRect.left() + paintRect.right());
   1461         }
   1462         if (srcRect.height() > SK_Scalar1) {
   1463             SkScalar border = SK_ScalarHalf / texture->height();
   1464             top = paintRect.top() + border;
   1465             bottom = paintRect.bottom() - border;
   1466         } else {
   1467             top = bottom = SkScalarHalf(paintRect.top() + paintRect.bottom());
   1468         }
   1469         textureDomain.setLTRB(left, top, right, bottom);
   1470         if (bicubic) {
   1471             fp.reset(GrBicubicEffect::Create(texture, SkMatrix::I(), textureDomain));
   1472         } else {
   1473             fp.reset(GrTextureDomainEffect::Create(texture,
   1474                                                    SkMatrix::I(),
   1475                                                    textureDomain,
   1476                                                    GrTextureDomain::kClamp_Mode,
   1477                                                    params.filterMode()));
   1478         }
   1479     } else if (bicubic) {
   1480         SkASSERT(GrTextureParams::kNone_FilterMode == params.filterMode());
   1481         SkShader::TileMode tileModes[2] = { params.getTileModeX(), params.getTileModeY() };
   1482         fp.reset(GrBicubicEffect::Create(texture, SkMatrix::I(), tileModes));
   1483     } else {
   1484         fp.reset(GrSimpleTextureEffect::Create(texture, SkMatrix::I(), params));
   1485     }
   1486 
   1487     // Construct a GrPaint by setting the bitmap texture as the first effect and then configuring
   1488     // the rest from the SkPaint.
   1489     GrPaint grPaint;
   1490     grPaint.addColorProcessor(fp);
   1491     bool alphaOnly = !(kAlpha_8_SkColorType == bitmap.colorType());
   1492     GrColor paintColor = (alphaOnly) ? SkColor2GrColorJustAlpha(paint.getColor()) :
   1493                                        SkColor2GrColor(paint.getColor());
   1494     if (!SkPaint2GrPaintNoShader(this->context(), fRenderTarget, paint, paintColor, false,
   1495                                  &grPaint)) {
   1496         return;
   1497     }
   1498 
   1499     fContext->drawNonAARectToRect(fRenderTarget, fClip, grPaint, viewMatrix, dstRect,
   1500                                   paintRect);
   1501 }
   1502 
   1503 bool SkGpuDevice::filterTexture(GrContext* context, GrTexture* texture,
   1504                                 int width, int height,
   1505                                 const SkImageFilter* filter,
   1506                                 const SkImageFilter::Context& ctx,
   1507                                 SkBitmap* result, SkIPoint* offset) {
   1508     SkASSERT(filter);
   1509 
   1510     // FIXME: plumb actual surface props such that we don't have to lie about the flags here
   1511     //        (https://code.google.com/p/skia/issues/detail?id=3148).
   1512     SkDeviceImageFilterProxy proxy(this, SkSurfaceProps(0, getLeakyProperties().pixelGeometry()));
   1513 
   1514     if (filter->canFilterImageGPU()) {
   1515         return filter->filterImageGPU(&proxy, wrap_texture(texture, width, height),
   1516                                       ctx, result, offset);
   1517     } else {
   1518         return false;
   1519     }
   1520 }
   1521 
   1522 void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
   1523                              int left, int top, const SkPaint& paint) {
   1524     // drawSprite is defined to be in device coords.
   1525     CHECK_SHOULD_DRAW(draw);
   1526 
   1527     SkAutoLockPixels alp(bitmap, !bitmap.getTexture());
   1528     if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
   1529         return;
   1530     }
   1531 
   1532     int w = bitmap.width();
   1533     int h = bitmap.height();
   1534 
   1535     GrTexture* texture;
   1536     // draw sprite uses the default texture params
   1537     AutoBitmapTexture abt(fContext, bitmap, NULL, &texture);
   1538     if (!texture) {
   1539         return;
   1540     }
   1541 
   1542     SkImageFilter* filter = paint.getImageFilter();
   1543     // This bitmap will own the filtered result as a texture.
   1544     SkBitmap filteredBitmap;
   1545 
   1546     if (filter) {
   1547         SkIPoint offset = SkIPoint::Make(0, 0);
   1548         SkMatrix matrix(*draw.fMatrix);
   1549         matrix.postTranslate(SkIntToScalar(-left), SkIntToScalar(-top));
   1550         SkIRect clipBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
   1551         SkAutoTUnref<SkImageFilter::Cache> cache(getImageFilterCache());
   1552         // This cache is transient, and is freed (along with all its contained
   1553         // textures) when it goes out of scope.
   1554         SkImageFilter::Context ctx(matrix, clipBounds, cache);
   1555         if (this->filterTexture(fContext, texture, w, h, filter, ctx, &filteredBitmap,
   1556                                 &offset)) {
   1557             texture = (GrTexture*) filteredBitmap.getTexture();
   1558             w = filteredBitmap.width();
   1559             h = filteredBitmap.height();
   1560             left += offset.x();
   1561             top += offset.y();
   1562         } else {
   1563             return;
   1564         }
   1565     }
   1566 
   1567     GrPaint grPaint;
   1568     grPaint.addColorTextureProcessor(texture, SkMatrix::I());
   1569 
   1570     if (!SkPaint2GrPaintNoShader(this->context(), fRenderTarget, paint,
   1571                                  SkColor2GrColorJustAlpha(paint.getColor()), false, &grPaint)) {
   1572         return;
   1573     }
   1574 
   1575     fContext->drawNonAARectToRect(fRenderTarget,
   1576                                   fClip,
   1577                                   grPaint,
   1578                                   SkMatrix::I(),
   1579                                   SkRect::MakeXYWH(SkIntToScalar(left),
   1580                                                    SkIntToScalar(top),
   1581                                                    SkIntToScalar(w),
   1582                                                    SkIntToScalar(h)),
   1583                                   SkRect::MakeXYWH(0,
   1584                                                    0,
   1585                                                    SK_Scalar1 * w / texture->width(),
   1586                                                    SK_Scalar1 * h / texture->height()));
   1587 }
   1588 
   1589 void SkGpuDevice::drawBitmapRect(const SkDraw& origDraw, const SkBitmap& bitmap,
   1590                                  const SkRect* src, const SkRect& dst,
   1591                                  const SkPaint& paint,
   1592                                  SkCanvas::DrawBitmapRectFlags flags) {
   1593     SkMatrix    matrix;
   1594     SkRect      bitmapBounds, tmpSrc;
   1595 
   1596     bitmapBounds.set(0, 0,
   1597                      SkIntToScalar(bitmap.width()),
   1598                      SkIntToScalar(bitmap.height()));
   1599 
   1600     // Compute matrix from the two rectangles
   1601     if (src) {
   1602         tmpSrc = *src;
   1603     } else {
   1604         tmpSrc = bitmapBounds;
   1605     }
   1606 
   1607     matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
   1608 
   1609     // clip the tmpSrc to the bounds of the bitmap. No check needed if src==null.
   1610     if (src) {
   1611         if (!bitmapBounds.contains(tmpSrc)) {
   1612             if (!tmpSrc.intersect(bitmapBounds)) {
   1613                 return; // nothing to draw
   1614             }
   1615         }
   1616     }
   1617 
   1618     SkRect tmpDst;
   1619     matrix.mapRect(&tmpDst, tmpSrc);
   1620 
   1621     SkTCopyOnFirstWrite<SkDraw> draw(origDraw);
   1622     if (0 != tmpDst.fLeft || 0 != tmpDst.fTop) {
   1623         // Translate so that tempDst's top left is at the origin.
   1624         matrix = *origDraw.fMatrix;
   1625         matrix.preTranslate(tmpDst.fLeft, tmpDst.fTop);
   1626         draw.writable()->fMatrix = &matrix;
   1627     }
   1628     SkSize dstSize;
   1629     dstSize.fWidth = tmpDst.width();
   1630     dstSize.fHeight = tmpDst.height();
   1631 
   1632     this->drawBitmapCommon(*draw, bitmap, &tmpSrc, &dstSize, paint, flags);
   1633 }
   1634 
   1635 void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
   1636                              int x, int y, const SkPaint& paint) {
   1637     // clear of the source device must occur before CHECK_SHOULD_DRAW
   1638     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawDevice", fContext);
   1639     SkGpuDevice* dev = static_cast<SkGpuDevice*>(device);
   1640 
   1641     // TODO: If the source device covers the whole of this device, we could
   1642     // omit fNeedsClear -related flushing.
   1643     // TODO: if source needs clear, we could maybe omit the draw fully.
   1644 
   1645     // drawDevice is defined to be in device coords.
   1646     CHECK_SHOULD_DRAW(draw);
   1647 
   1648     GrRenderTarget* devRT = dev->accessRenderTarget();
   1649     GrTexture* devTex;
   1650     if (NULL == (devTex = devRT->asTexture())) {
   1651         return;
   1652     }
   1653 
   1654     const SkImageInfo ii = dev->imageInfo();
   1655     int w = ii.width();
   1656     int h = ii.height();
   1657 
   1658     SkImageFilter* filter = paint.getImageFilter();
   1659     // This bitmap will own the filtered result as a texture.
   1660     SkBitmap filteredBitmap;
   1661 
   1662     if (filter) {
   1663         SkIPoint offset = SkIPoint::Make(0, 0);
   1664         SkMatrix matrix(*draw.fMatrix);
   1665         matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
   1666         SkIRect clipBounds = SkIRect::MakeWH(devTex->width(), devTex->height());
   1667         // This cache is transient, and is freed (along with all its contained
   1668         // textures) when it goes out of scope.
   1669         SkAutoTUnref<SkImageFilter::Cache> cache(getImageFilterCache());
   1670         SkImageFilter::Context ctx(matrix, clipBounds, cache);
   1671         if (this->filterTexture(fContext, devTex, device->width(), device->height(),
   1672                                 filter, ctx, &filteredBitmap, &offset)) {
   1673             devTex = filteredBitmap.getTexture();
   1674             w = filteredBitmap.width();
   1675             h = filteredBitmap.height();
   1676             x += offset.fX;
   1677             y += offset.fY;
   1678         } else {
   1679             return;
   1680         }
   1681     }
   1682 
   1683     GrPaint grPaint;
   1684     grPaint.addColorTextureProcessor(devTex, SkMatrix::I());
   1685 
   1686     if (!SkPaint2GrPaintNoShader(this->context(), fRenderTarget, paint,
   1687                                  SkColor2GrColorJustAlpha(paint.getColor()), false, &grPaint)) {
   1688         return;
   1689     }
   1690 
   1691     SkRect dstRect = SkRect::MakeXYWH(SkIntToScalar(x),
   1692                                       SkIntToScalar(y),
   1693                                       SkIntToScalar(w),
   1694                                       SkIntToScalar(h));
   1695 
   1696     // The device being drawn may not fill up its texture (e.g. saveLayer uses approximate
   1697     // scratch texture).
   1698     SkRect srcRect = SkRect::MakeWH(SK_Scalar1 * w / devTex->width(),
   1699                                     SK_Scalar1 * h / devTex->height());
   1700 
   1701     fContext->drawNonAARectToRect(fRenderTarget, fClip, grPaint, SkMatrix::I(), dstRect,
   1702                                   srcRect);
   1703 }
   1704 
   1705 bool SkGpuDevice::canHandleImageFilter(const SkImageFilter* filter) {
   1706     return filter->canFilterImageGPU();
   1707 }
   1708 
   1709 bool SkGpuDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src,
   1710                               const SkImageFilter::Context& ctx,
   1711                               SkBitmap* result, SkIPoint* offset) {
   1712     // want explicitly our impl, so guard against a subclass of us overriding it
   1713     if (!this->SkGpuDevice::canHandleImageFilter(filter)) {
   1714         return false;
   1715     }
   1716 
   1717     SkAutoLockPixels alp(src, !src.getTexture());
   1718     if (!src.getTexture() && !src.readyToDraw()) {
   1719         return false;
   1720     }
   1721 
   1722     GrTexture* texture;
   1723     // We assume here that the filter will not attempt to tile the src. Otherwise, this cache lookup
   1724     // must be pushed upstack.
   1725     AutoBitmapTexture abt(fContext, src, NULL, &texture);
   1726     if (!texture) {
   1727         return false;
   1728     }
   1729 
   1730     return this->filterTexture(fContext, texture, src.width(), src.height(),
   1731                                filter, ctx, result, offset);
   1732 }
   1733 
   1734 static bool wrap_as_bm(const SkImage* image, SkBitmap* bm) {
   1735     GrTexture* tex = image->getTexture();
   1736     if (tex) {
   1737         GrWrapTextureInBitmap(tex, image->width(), image->height(), image->isOpaque(), bm);
   1738         return true;
   1739     } else {
   1740         return as_IB(image)->getROPixels(bm);
   1741     }
   1742 }
   1743 
   1744 void SkGpuDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x, SkScalar y,
   1745                             const SkPaint& paint) {
   1746     SkBitmap bm;
   1747     if (wrap_as_bm(image, &bm)) {
   1748         this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
   1749     }
   1750 }
   1751 
   1752 void SkGpuDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const SkRect* src,
   1753                                 const SkRect& dst, const SkPaint& paint) {
   1754     SkBitmap bm;
   1755     if (wrap_as_bm(image, &bm)) {
   1756         this->drawBitmapRect(draw, bm, src, dst, paint, SkCanvas::kNone_DrawBitmapRectFlag);
   1757     }
   1758 }
   1759 
   1760 ///////////////////////////////////////////////////////////////////////////////
   1761 
   1762 // must be in SkCanvas::VertexMode order
   1763 static const GrPrimitiveType gVertexMode2PrimitiveType[] = {
   1764     kTriangles_GrPrimitiveType,
   1765     kTriangleStrip_GrPrimitiveType,
   1766     kTriangleFan_GrPrimitiveType,
   1767 };
   1768 
   1769 void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
   1770                               int vertexCount, const SkPoint vertices[],
   1771                               const SkPoint texs[], const SkColor colors[],
   1772                               SkXfermode* xmode,
   1773                               const uint16_t indices[], int indexCount,
   1774                               const SkPaint& paint) {
   1775     CHECK_SHOULD_DRAW(draw);
   1776     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawVertices", fContext);
   1777 
   1778     const uint16_t* outIndices;
   1779     SkAutoTDeleteArray<uint16_t> outAlloc(NULL);
   1780     GrPrimitiveType primType;
   1781     GrPaint grPaint;
   1782 
   1783     // If both textures and vertex-colors are NULL, strokes hairlines with the paint's color.
   1784     if ((NULL == texs || NULL == paint.getShader()) && NULL == colors) {
   1785 
   1786         texs = NULL;
   1787 
   1788         SkPaint copy(paint);
   1789         copy.setStyle(SkPaint::kStroke_Style);
   1790         copy.setStrokeWidth(0);
   1791 
   1792         // we ignore the shader if texs is null.
   1793         if (!SkPaint2GrPaintNoShader(this->context(), fRenderTarget, copy,
   1794                                      SkColor2GrColor(copy.getColor()), NULL == colors, &grPaint)) {
   1795             return;
   1796         }
   1797 
   1798         primType = kLines_GrPrimitiveType;
   1799         int triangleCount = 0;
   1800         int n = (NULL == indices) ? vertexCount : indexCount;
   1801         switch (vmode) {
   1802             case SkCanvas::kTriangles_VertexMode:
   1803                 triangleCount = n / 3;
   1804                 break;
   1805             case SkCanvas::kTriangleStrip_VertexMode:
   1806             case SkCanvas::kTriangleFan_VertexMode:
   1807                 triangleCount = n - 2;
   1808                 break;
   1809         }
   1810 
   1811         VertState       state(vertexCount, indices, indexCount);
   1812         VertState::Proc vertProc = state.chooseProc(vmode);
   1813 
   1814         //number of indices for lines per triangle with kLines
   1815         indexCount = triangleCount * 6;
   1816 
   1817         outAlloc.reset(SkNEW_ARRAY(uint16_t, indexCount));
   1818         outIndices = outAlloc.get();
   1819         uint16_t* auxIndices = outAlloc.get();
   1820         int i = 0;
   1821         while (vertProc(&state)) {
   1822             auxIndices[i]     = state.f0;
   1823             auxIndices[i + 1] = state.f1;
   1824             auxIndices[i + 2] = state.f1;
   1825             auxIndices[i + 3] = state.f2;
   1826             auxIndices[i + 4] = state.f2;
   1827             auxIndices[i + 5] = state.f0;
   1828             i += 6;
   1829         }
   1830     } else {
   1831         outIndices = indices;
   1832         primType = gVertexMode2PrimitiveType[vmode];
   1833 
   1834         if (NULL == texs || NULL == paint.getShader()) {
   1835             if (!SkPaint2GrPaintNoShader(this->context(), fRenderTarget, paint,
   1836                                          SkColor2GrColor(paint.getColor()),
   1837                                          NULL == colors, &grPaint)) {
   1838                 return;
   1839             }
   1840         } else {
   1841             if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix,
   1842                                  NULL == colors, &grPaint)) {
   1843                 return;
   1844             }
   1845         }
   1846     }
   1847 
   1848 #if 0
   1849     if (xmode && texs && colors) {
   1850         if (!SkXfermode::IsMode(xmode, SkXfermode::kModulate_Mode)) {
   1851             SkDebugf("Unsupported vertex-color/texture xfer mode.\n");
   1852             return;
   1853         }
   1854     }
   1855 #endif
   1856 
   1857     SkAutoSTMalloc<128, GrColor> convertedColors(0);
   1858     if (colors) {
   1859         // need to convert byte order and from non-PM to PM
   1860         convertedColors.reset(vertexCount);
   1861         SkColor color;
   1862         for (int i = 0; i < vertexCount; ++i) {
   1863             color = colors[i];
   1864             if (paint.getAlpha() != 255) {
   1865                 color = SkColorSetA(color, SkMulDiv255Round(SkColorGetA(color), paint.getAlpha()));
   1866             }
   1867             convertedColors[i] = SkColor2GrColor(color);
   1868         }
   1869         colors = convertedColors.get();
   1870     }
   1871     fContext->drawVertices(fRenderTarget,
   1872                            fClip,
   1873                            grPaint,
   1874                            *draw.fMatrix,
   1875                            primType,
   1876                            vertexCount,
   1877                            vertices,
   1878                            texs,
   1879                            colors,
   1880                            outIndices,
   1881                            indexCount);
   1882 }
   1883 
   1884 ///////////////////////////////////////////////////////////////////////////////
   1885 
   1886 void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
   1887                            size_t byteLength, SkScalar x, SkScalar y,
   1888                            const SkPaint& paint) {
   1889     CHECK_SHOULD_DRAW(draw);
   1890     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawText", fContext);
   1891 
   1892     GrPaint grPaint;
   1893     if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
   1894         return;
   1895     }
   1896 
   1897     SkDEBUGCODE(this->validate();)
   1898 
   1899     fTextContext->drawText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix,
   1900                            (const char *)text, byteLength, x, y, draw.fClip->getBounds());
   1901 }
   1902 
   1903 void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, size_t byteLength,
   1904                               const SkScalar pos[], int scalarsPerPos,
   1905                               const SkPoint& offset, const SkPaint& paint) {
   1906     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPosText", fContext);
   1907     CHECK_SHOULD_DRAW(draw);
   1908 
   1909     GrPaint grPaint;
   1910     if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
   1911         return;
   1912     }
   1913 
   1914     SkDEBUGCODE(this->validate();)
   1915 
   1916     fTextContext->drawPosText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix,
   1917                               (const char *)text, byteLength, pos, scalarsPerPos, offset,
   1918                               draw.fClip->getBounds());
   1919 }
   1920 
   1921 void SkGpuDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkScalar x, SkScalar y,
   1922                                const SkPaint& paint, SkDrawFilter* drawFilter) {
   1923     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawTextBlob", fContext);
   1924     CHECK_SHOULD_DRAW(draw);
   1925 
   1926     SkDEBUGCODE(this->validate();)
   1927 
   1928     fTextContext->drawTextBlob(fRenderTarget, fClip, paint, *draw.fMatrix, blob, x, y, drawFilter,
   1929                                draw.fClip->getBounds());
   1930 }
   1931 
   1932 ///////////////////////////////////////////////////////////////////////////////
   1933 
   1934 bool SkGpuDevice::onShouldDisableLCD(const SkPaint& paint) const {
   1935     if (paint.getShader() ||
   1936         !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode) ||
   1937         paint.getMaskFilter() ||
   1938         paint.getRasterizer() ||
   1939         paint.getColorFilter() ||
   1940         paint.getPathEffect() ||
   1941         paint.isFakeBoldText() ||
   1942         paint.getStyle() != SkPaint::kFill_Style)
   1943     {
   1944         return true;
   1945     }
   1946     return false;
   1947 }
   1948 
   1949 void SkGpuDevice::flush() {
   1950     DO_DEFERRED_CLEAR();
   1951     fRenderTarget->prepareForExternalRead();
   1952 }
   1953 
   1954 ///////////////////////////////////////////////////////////////////////////////
   1955 
   1956 SkBaseDevice* SkGpuDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) {
   1957     GrSurfaceDesc desc;
   1958     desc.fConfig = fRenderTarget->config();
   1959     desc.fFlags = kRenderTarget_GrSurfaceFlag;
   1960     desc.fWidth = cinfo.fInfo.width();
   1961     desc.fHeight = cinfo.fInfo.height();
   1962     desc.fSampleCnt = fRenderTarget->numSamples();
   1963 
   1964     SkAutoTUnref<GrTexture> texture;
   1965     // Skia's convention is to only clear a device if it is non-opaque.
   1966     unsigned flags = cinfo.fInfo.isOpaque() ? 0 : kNeedClear_Flag;
   1967 
   1968     // layers are never draw in repeat modes, so we can request an approx
   1969     // match and ignore any padding.
   1970     const GrTextureProvider::ScratchTexMatch match = (kNever_TileUsage == cinfo.fTileUsage) ?
   1971                                                   GrTextureProvider::kApprox_ScratchTexMatch :
   1972                                                   GrTextureProvider::kExact_ScratchTexMatch;
   1973     texture.reset(fContext->textureProvider()->refScratchTexture(desc, match));
   1974 
   1975     if (texture) {
   1976         SkSurfaceProps props(fSurfaceProps.flags(), cinfo.fPixelGeometry);
   1977         return SkGpuDevice::Create(
   1978             texture->asRenderTarget(), cinfo.fInfo.width(), cinfo.fInfo.height(), &props, flags);
   1979     } else {
   1980         SkErrorInternals::SetError( kInternalError_SkError,
   1981                                     "---- failed to create gpu device texture [%d %d]\n",
   1982                                     cinfo.fInfo.width(), cinfo.fInfo.height());
   1983         return NULL;
   1984     }
   1985 }
   1986 
   1987 SkSurface* SkGpuDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
   1988     // TODO: Change the signature of newSurface to take a budgeted parameter.
   1989     static const SkSurface::Budgeted kBudgeted = SkSurface::kNo_Budgeted;
   1990     return SkSurface::NewRenderTarget(fContext, kBudgeted, info, fRenderTarget->numSamples(),
   1991                                       &props);
   1992 }
   1993 
   1994 bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture* mainPicture,
   1995                                            const SkMatrix* matrix, const SkPaint* paint) {
   1996 #ifndef SK_IGNORE_GPU_LAYER_HOISTING
   1997     // todo: should handle this natively
   1998     if (paint) {
   1999         return false;
   2000     }
   2001 
   2002     SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
   2003 
   2004     const SkPicture::AccelData* data = mainPicture->EXPERIMENTAL_getAccelData(key);
   2005     if (!data) {
   2006         return false;
   2007     }
   2008 
   2009     const SkLayerInfo *gpuData = static_cast<const SkLayerInfo*>(data);
   2010     if (0 == gpuData->numBlocks()) {
   2011         return false;
   2012     }
   2013 
   2014     SkTDArray<GrHoistedLayer> atlasedNeedRendering, atlasedRecycled;
   2015 
   2016     SkIRect iBounds;
   2017     if (!mainCanvas->getClipDeviceBounds(&iBounds)) {
   2018         return false;
   2019     }
   2020 
   2021     SkRect clipBounds = SkRect::Make(iBounds);
   2022 
   2023     SkMatrix initialMatrix = mainCanvas->getTotalMatrix();
   2024 
   2025     GrLayerHoister::FindLayersToAtlas(fContext, mainPicture,
   2026                                       initialMatrix,
   2027                                       clipBounds,
   2028                                       &atlasedNeedRendering, &atlasedRecycled,
   2029                                       fRenderTarget->numSamples());
   2030 
   2031     GrLayerHoister::DrawLayersToAtlas(fContext, atlasedNeedRendering);
   2032 
   2033     SkTDArray<GrHoistedLayer> needRendering, recycled;
   2034 
   2035     SkAutoCanvasMatrixPaint acmp(mainCanvas, matrix, paint, mainPicture->cullRect());
   2036 
   2037     GrLayerHoister::FindLayersToHoist(fContext, mainPicture,
   2038                                       initialMatrix,
   2039                                       clipBounds,
   2040                                       &needRendering, &recycled,
   2041                                       fRenderTarget->numSamples());
   2042 
   2043     GrLayerHoister::DrawLayers(fContext, needRendering);
   2044 
   2045     // Render the entire picture using new layers
   2046     GrRecordReplaceDraw(mainPicture, mainCanvas, fContext->getLayerCache(),
   2047                         initialMatrix, NULL);
   2048 
   2049     GrLayerHoister::UnlockLayers(fContext, needRendering);
   2050     GrLayerHoister::UnlockLayers(fContext, recycled);
   2051     GrLayerHoister::UnlockLayers(fContext, atlasedNeedRendering);
   2052     GrLayerHoister::UnlockLayers(fContext, atlasedRecycled);
   2053 
   2054     return true;
   2055 #else
   2056     return false;
   2057 #endif
   2058 }
   2059 
   2060 SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() {
   2061     // We always return a transient cache, so it is freed after each
   2062     // filter traversal.
   2063     return SkImageFilter::Cache::Create(kDefaultImageFilterCacheSize);
   2064 }
   2065 
   2066 #endif
   2067