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 "GrBlurUtils.h"
     11 #include "GrContext.h"
     12 #include "SkDraw.h"
     13 #include "GrGpu.h"
     14 #include "GrGpuResourcePriv.h"
     15 #include "GrImageIDTextureAdjuster.h"
     16 #include "GrLayerHoister.h"
     17 #include "GrRecordReplaceDraw.h"
     18 #include "GrStrokeInfo.h"
     19 #include "GrTracing.h"
     20 #include "SkCanvasPriv.h"
     21 #include "SkErrorInternals.h"
     22 #include "SkGlyphCache.h"
     23 #include "SkGrTexturePixelRef.h"
     24 #include "SkGr.h"
     25 #include "SkGrPriv.h"
     26 #include "SkImage_Base.h"
     27 #include "SkImageCacherator.h"
     28 #include "SkImageFilter.h"
     29 #include "SkLayerInfo.h"
     30 #include "SkMaskFilter.h"
     31 #include "SkNinePatchIter.h"
     32 #include "SkPathEffect.h"
     33 #include "SkPicture.h"
     34 #include "SkPictureData.h"
     35 #include "SkRRect.h"
     36 #include "SkRecord.h"
     37 #include "SkStroke.h"
     38 #include "SkSurface.h"
     39 #include "SkSurface_Gpu.h"
     40 #include "SkTLazy.h"
     41 #include "SkUtils.h"
     42 #include "SkVertState.h"
     43 #include "SkXfermode.h"
     44 #include "batches/GrRectBatchFactory.h"
     45 #include "effects/GrBicubicEffect.h"
     46 #include "effects/GrDashingEffect.h"
     47 #include "effects/GrRRectEffect.h"
     48 #include "effects/GrSimpleTextureEffect.h"
     49 #include "effects/GrTextureDomain.h"
     50 #include "text/GrTextUtils.h"
     51 
     52 #if SK_SUPPORT_GPU
     53 
     54 #define ASSERT_SINGLE_OWNER \
     55     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->debugSingleOwner());)
     56 
     57 enum { kDefaultImageFilterCacheSize = 32 * 1024 * 1024 };
     58 
     59 #if 0
     60     extern bool (*gShouldDrawProc)();
     61     #define CHECK_SHOULD_DRAW(draw)                             \
     62         do {                                                    \
     63             if (gShouldDrawProc && !gShouldDrawProc()) return;  \
     64             this->prepareDraw(draw);                            \
     65         } while (0)
     66 #else
     67     #define CHECK_SHOULD_DRAW(draw) this->prepareDraw(draw)
     68 #endif
     69 
     70 ///////////////////////////////////////////////////////////////////////////////
     71 
     72 #define CHECK_FOR_ANNOTATION(paint) \
     73     do { if (paint.getAnnotation()) { return; } } while (0)
     74 
     75 ///////////////////////////////////////////////////////////////////////////////
     76 
     77 // Helper for turning a bitmap into a texture. If the bitmap is GrTexture backed this
     78 // just accesses the backing GrTexture. Otherwise, it creates a cached texture
     79 // representation and releases it in the destructor.
     80 class AutoBitmapTexture : public SkNoncopyable {
     81 public:
     82     AutoBitmapTexture() {}
     83 
     84     AutoBitmapTexture(GrContext* context,
     85                       const SkBitmap& bitmap,
     86                       const GrTextureParams& params,
     87                       GrTexture** texture) {
     88         SkASSERT(texture);
     89         *texture = this->set(context, bitmap, params);
     90     }
     91 
     92     GrTexture* set(GrContext* context,
     93                    const SkBitmap& bitmap,
     94                    const GrTextureParams& params) {
     95         // Either get the texture directly from the bitmap, or else use the cache and
     96         // remember to unref it.
     97         if (GrTexture* bmpTexture = bitmap.getTexture()) {
     98             fTexture.reset(nullptr);
     99             return bmpTexture;
    100         } else {
    101             fTexture.reset(GrRefCachedBitmapTexture(context, bitmap, params));
    102             return fTexture.get();
    103         }
    104     }
    105 
    106 private:
    107     SkAutoTUnref<GrTexture> fTexture;
    108 };
    109 
    110 ///////////////////////////////////////////////////////////////////////////////
    111 
    112 /** Checks that the alpha type is legal and gets constructor flags. Returns false if device creation
    113     should fail. */
    114 bool SkGpuDevice::CheckAlphaTypeAndGetFlags(
    115                         const SkImageInfo* info, SkGpuDevice::InitContents init, unsigned* flags) {
    116     *flags = 0;
    117     if (info) {
    118         switch (info->alphaType()) {
    119             case kPremul_SkAlphaType:
    120                 break;
    121             case kOpaque_SkAlphaType:
    122                 *flags |= SkGpuDevice::kIsOpaque_Flag;
    123                 break;
    124             default: // If it is unpremul or unknown don't try to render
    125                 return false;
    126         }
    127     }
    128     if (kClear_InitContents == init) {
    129         *flags |= kNeedClear_Flag;
    130     }
    131     return true;
    132 }
    133 
    134 SkGpuDevice* SkGpuDevice::Create(GrRenderTarget* rt, const SkSurfaceProps* props,
    135                                  InitContents init) {
    136     return SkGpuDevice::Create(rt, rt->width(), rt->height(), props, init);
    137 }
    138 
    139 SkGpuDevice* SkGpuDevice::Create(GrRenderTarget* rt, int width, int height,
    140                                  const SkSurfaceProps* props, InitContents init) {
    141     if (!rt || rt->wasDestroyed()) {
    142         return nullptr;
    143     }
    144     unsigned flags;
    145     if (!CheckAlphaTypeAndGetFlags(nullptr, init, &flags)) {
    146         return nullptr;
    147     }
    148     return new SkGpuDevice(rt, width, height, props, flags);
    149 }
    150 
    151 SkGpuDevice* SkGpuDevice::Create(GrContext* context, SkBudgeted budgeted,
    152                                  const SkImageInfo& info, int sampleCount,
    153                                  const SkSurfaceProps* props, InitContents init,
    154                                  GrTextureStorageAllocator customAllocator) {
    155     unsigned flags;
    156     if (!CheckAlphaTypeAndGetFlags(&info, init, &flags)) {
    157         return nullptr;
    158     }
    159 
    160     SkAutoTUnref<GrRenderTarget> rt(CreateRenderTarget(
    161             context, budgeted, info, sampleCount, customAllocator));
    162     if (nullptr == rt) {
    163         return nullptr;
    164     }
    165 
    166     return new SkGpuDevice(rt, info.width(), info.height(), props, flags);
    167 }
    168 
    169 SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, int width, int height,
    170                          const SkSurfaceProps* props, unsigned flags)
    171     : INHERITED(SkSurfacePropsCopyOrDefault(props))
    172     , fContext(SkRef(rt->getContext()))
    173     , fRenderTarget(SkRef(rt)) {
    174     fOpaque = SkToBool(flags & kIsOpaque_Flag);
    175 
    176     SkAlphaType at = fOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
    177     SkImageInfo info = rt->surfacePriv().info(at).makeWH(width, height);
    178     SkPixelRef* pr = new SkGrPixelRef(info, rt);
    179     fLegacyBitmap.setInfo(info);
    180     fLegacyBitmap.setPixelRef(pr)->unref();
    181 
    182     fDrawContext.reset(this->context()->drawContext(rt, &this->surfaceProps()));
    183     if (flags & kNeedClear_Flag) {
    184         this->clearAll();
    185     }
    186 }
    187 
    188 GrRenderTarget* SkGpuDevice::CreateRenderTarget(
    189         GrContext* context, SkBudgeted budgeted, const SkImageInfo& origInfo,
    190         int sampleCount, GrTextureStorageAllocator textureStorageAllocator) {
    191     if (kUnknown_SkColorType == origInfo.colorType() ||
    192         origInfo.width() < 0 || origInfo.height() < 0) {
    193         return nullptr;
    194     }
    195 
    196     if (!context) {
    197         return nullptr;
    198     }
    199 
    200     SkColorType ct = origInfo.colorType();
    201     SkAlphaType at = origInfo.alphaType();
    202     if (kRGB_565_SkColorType == ct) {
    203         at = kOpaque_SkAlphaType;  // force this setting
    204     } else if (ct != kBGRA_8888_SkColorType && ct != kRGBA_8888_SkColorType) {
    205         // Fall back from whatever ct was to default of kRGBA or kBGRA which is aliased as kN32
    206         ct = kN32_SkColorType;
    207     }
    208     if (kOpaque_SkAlphaType != at) {
    209         at = kPremul_SkAlphaType;  // force this setting
    210     }
    211     const SkImageInfo info = SkImageInfo::Make(origInfo.width(), origInfo.height(), ct, at);
    212 
    213     GrSurfaceDesc desc;
    214     desc.fFlags = kRenderTarget_GrSurfaceFlag;
    215     desc.fWidth = info.width();
    216     desc.fHeight = info.height();
    217     desc.fConfig = SkImageInfo2GrPixelConfig(info);
    218     desc.fSampleCnt = sampleCount;
    219     desc.fTextureStorageAllocator = textureStorageAllocator;
    220     GrTexture* texture = context->textureProvider()->createTexture(desc, budgeted, nullptr, 0);
    221     if (nullptr == texture) {
    222         return nullptr;
    223     }
    224     SkASSERT(nullptr != texture->asRenderTarget());
    225     return texture->asRenderTarget();
    226 }
    227 
    228 ///////////////////////////////////////////////////////////////////////////////
    229 
    230 bool SkGpuDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
    231                                int x, int y) {
    232     ASSERT_SINGLE_OWNER
    233 
    234     // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
    235     GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo);
    236     if (kUnknown_GrPixelConfig == config) {
    237         return false;
    238     }
    239 
    240     uint32_t flags = 0;
    241     if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
    242         flags = GrContext::kUnpremul_PixelOpsFlag;
    243     }
    244     return fRenderTarget->readPixels(x, y, dstInfo.width(), dstInfo.height(), config, dstPixels,
    245                                      dstRowBytes, flags);
    246 }
    247 
    248 bool SkGpuDevice::onWritePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes,
    249                                 int x, int y) {
    250     ASSERT_SINGLE_OWNER
    251     // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
    252     GrPixelConfig config = SkImageInfo2GrPixelConfig(info);
    253     if (kUnknown_GrPixelConfig == config) {
    254         return false;
    255     }
    256     uint32_t flags = 0;
    257     if (kUnpremul_SkAlphaType == info.alphaType()) {
    258         flags = GrContext::kUnpremul_PixelOpsFlag;
    259     }
    260     fRenderTarget->writePixels(x, y, info.width(), info.height(), config, pixels, rowBytes, flags);
    261 
    262     // need to bump our genID for compatibility with clients that "know" we have a bitmap
    263     fLegacyBitmap.notifyPixelsChanged();
    264 
    265     return true;
    266 }
    267 
    268 const SkBitmap& SkGpuDevice::onAccessBitmap() {
    269     ASSERT_SINGLE_OWNER
    270     return fLegacyBitmap;
    271 }
    272 
    273 bool SkGpuDevice::onAccessPixels(SkPixmap* pmap) {
    274     ASSERT_SINGLE_OWNER
    275     // For compatibility with clients the know we're backed w/ a bitmap, and want to inspect its
    276     // genID. When we can hide/remove that fact, we can eliminate this call to notify.
    277     // ... ugh.
    278     fLegacyBitmap.notifyPixelsChanged();
    279     return false;
    280 }
    281 
    282 void SkGpuDevice::onAttachToCanvas(SkCanvas* canvas) {
    283     ASSERT_SINGLE_OWNER
    284     INHERITED::onAttachToCanvas(canvas);
    285 
    286     // Canvas promises that this ptr is valid until onDetachFromCanvas is called
    287     fClipStack.reset(SkRef(canvas->getClipStack()));
    288 }
    289 
    290 void SkGpuDevice::onDetachFromCanvas() {
    291     ASSERT_SINGLE_OWNER
    292     INHERITED::onDetachFromCanvas();
    293     fClip.reset();
    294     fClipStack.reset(nullptr);
    295 }
    296 
    297 // call this every draw call, to ensure that the context reflects our state,
    298 // and not the state from some other canvas/device
    299 void SkGpuDevice::prepareDraw(const SkDraw& draw) {
    300     ASSERT_SINGLE_OWNER
    301     SkASSERT(fClipStack.get());
    302 
    303     SkASSERT(draw.fClipStack && draw.fClipStack == fClipStack);
    304 
    305     fClip.setClipStack(fClipStack, &this->getOrigin());
    306 }
    307 
    308 GrRenderTarget* SkGpuDevice::accessRenderTarget() {
    309     ASSERT_SINGLE_OWNER
    310     return fRenderTarget;
    311 }
    312 
    313 void SkGpuDevice::clearAll() {
    314     ASSERT_SINGLE_OWNER
    315     GrColor color = 0;
    316     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "clearAll", fContext);
    317     SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
    318     fDrawContext->clear(&rect, color, true);
    319 }
    320 
    321 void SkGpuDevice::replaceRenderTarget(bool shouldRetainContent) {
    322     ASSERT_SINGLE_OWNER
    323 
    324     SkBudgeted budgeted = fRenderTarget->resourcePriv().isBudgeted();
    325 
    326     SkAutoTUnref<GrRenderTarget> newRT(CreateRenderTarget(
    327         this->context(), budgeted, this->imageInfo(), fRenderTarget->desc().fSampleCnt,
    328         fRenderTarget->desc().fTextureStorageAllocator));
    329 
    330     if (nullptr == newRT) {
    331         return;
    332     }
    333 
    334     if (shouldRetainContent) {
    335         if (fRenderTarget->wasDestroyed()) {
    336             return;
    337         }
    338         this->context()->copySurface(newRT, fRenderTarget);
    339     }
    340 
    341     SkASSERT(fRenderTarget != newRT);
    342 
    343     fRenderTarget.reset(newRT.detach());
    344 
    345 #ifdef SK_DEBUG
    346     SkImageInfo info = fRenderTarget->surfacePriv().info(fOpaque ? kOpaque_SkAlphaType :
    347                                                                    kPremul_SkAlphaType);
    348     SkASSERT(info == fLegacyBitmap.info());
    349 #endif
    350     SkPixelRef* pr = new SkGrPixelRef(fLegacyBitmap.info(), fRenderTarget);
    351     fLegacyBitmap.setPixelRef(pr)->unref();
    352 
    353     fDrawContext.reset(this->context()->drawContext(fRenderTarget, &this->surfaceProps()));
    354 }
    355 
    356 ///////////////////////////////////////////////////////////////////////////////
    357 
    358 void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
    359     ASSERT_SINGLE_OWNER
    360     CHECK_SHOULD_DRAW(draw);
    361     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPaint", fContext);
    362 
    363     GrPaint grPaint;
    364     if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
    365         return;
    366     }
    367 
    368     fDrawContext->drawPaint(fClip, grPaint, *draw.fMatrix);
    369 }
    370 
    371 // must be in SkCanvas::PointMode order
    372 static const GrPrimitiveType gPointMode2PrimtiveType[] = {
    373     kPoints_GrPrimitiveType,
    374     kLines_GrPrimitiveType,
    375     kLineStrip_GrPrimitiveType
    376 };
    377 
    378 // suppress antialiasing on axis-aligned integer-coordinate lines
    379 static bool needs_antialiasing(SkCanvas::PointMode mode, size_t count, const SkPoint pts[]) {
    380     if (mode == SkCanvas::PointMode::kPoints_PointMode) {
    381         return false;
    382     }
    383     if (count == 2) {
    384         // We do not antialias as long as the primary axis of the line is integer-aligned, even if
    385         // the other coordinates are not. This does mean the two end pixels of the line will be
    386         // sharp even when they shouldn't be, but turning antialiasing on (as things stand
    387         // currently) means that the line will turn into a two-pixel-wide blur. While obviously a
    388         // more complete fix is possible down the road, for the time being we accept the error on
    389         // the two end pixels as being the lesser of two evils.
    390         if (pts[0].fX == pts[1].fX) {
    391             return ((int) pts[0].fX) != pts[0].fX;
    392         }
    393         if (pts[0].fY == pts[1].fY) {
    394             return ((int) pts[0].fY) != pts[0].fY;
    395         }
    396     }
    397     return true;
    398 }
    399 
    400 void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
    401                              size_t count, const SkPoint pts[], const SkPaint& paint) {
    402     ASSERT_SINGLE_OWNER
    403     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPoints", fContext);
    404     CHECK_FOR_ANNOTATION(paint);
    405     CHECK_SHOULD_DRAW(draw);
    406 
    407     SkScalar width = paint.getStrokeWidth();
    408     if (width < 0) {
    409         return;
    410     }
    411 
    412     if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mode) {
    413         GrStrokeInfo strokeInfo(paint, SkPaint::kStroke_Style);
    414         GrPaint grPaint;
    415         if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
    416             return;
    417         }
    418         SkPath path;
    419         path.setIsVolatile(true);
    420         path.moveTo(pts[0]);
    421         path.lineTo(pts[1]);
    422         fDrawContext->drawPath(fClip, grPaint, *draw.fMatrix, path, strokeInfo);
    423         return;
    424     }
    425 
    426     // we only handle non-antialiased hairlines and paints without path effects or mask filters,
    427     // else we let the SkDraw call our drawPath()
    428     if (width > 0 || paint.getPathEffect() || paint.getMaskFilter() ||
    429         (paint.isAntiAlias() && needs_antialiasing(mode, count, pts))) {
    430         draw.drawPoints(mode, count, pts, paint, true);
    431         return;
    432     }
    433 
    434     GrPaint grPaint;
    435     if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
    436         return;
    437     }
    438 
    439     fDrawContext->drawVertices(fClip,
    440                                grPaint,
    441                                *draw.fMatrix,
    442                                gPointMode2PrimtiveType[mode],
    443                                SkToS32(count),
    444                                (SkPoint*)pts,
    445                                nullptr,
    446                                nullptr,
    447                                nullptr,
    448                                0);
    449 }
    450 
    451 ///////////////////////////////////////////////////////////////////////////////
    452 
    453 void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, const SkPaint& paint) {
    454     ASSERT_SINGLE_OWNER
    455     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawRect", fContext);
    456     CHECK_FOR_ANNOTATION(paint);
    457     CHECK_SHOULD_DRAW(draw);
    458 
    459     bool doStroke = paint.getStyle() != SkPaint::kFill_Style;
    460     SkScalar width = paint.getStrokeWidth();
    461 
    462     /*
    463         We have special code for hairline strokes, miter-strokes, bevel-stroke
    464         and fills. Anything else we just call our path code.
    465      */
    466     bool usePath = doStroke && width > 0 &&
    467                    (paint.getStrokeJoin() == SkPaint::kRound_Join ||
    468                     (paint.getStrokeJoin() == SkPaint::kBevel_Join && rect.isEmpty()));
    469 
    470     // a few other reasons we might need to call drawPath...
    471     if (paint.getMaskFilter() || paint.getPathEffect() ||
    472         paint.getStyle() == SkPaint::kStrokeAndFill_Style) { // we can't both stroke and fill rects
    473         usePath = true;
    474     }
    475 
    476     if (usePath) {
    477         SkPath path;
    478         path.setIsVolatile(true);
    479         path.addRect(rect);
    480         GrBlurUtils::drawPathWithMaskFilter(fContext, fDrawContext,
    481                                             fClip, path, paint,
    482                                             *draw.fMatrix, nullptr,
    483                                             draw.fClip->getBounds(), true);
    484         return;
    485     }
    486 
    487     GrPaint grPaint;
    488     if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
    489         return;
    490     }
    491 
    492     GrStrokeInfo strokeInfo(paint);
    493 
    494     fDrawContext->drawRect(fClip, grPaint, *draw.fMatrix, rect, &strokeInfo);
    495 }
    496 
    497 ///////////////////////////////////////////////////////////////////////////////
    498 
    499 void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rect,
    500                             const SkPaint& paint) {
    501     ASSERT_SINGLE_OWNER
    502     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawRRect", fContext);
    503     CHECK_FOR_ANNOTATION(paint);
    504     CHECK_SHOULD_DRAW(draw);
    505 
    506     GrPaint grPaint;
    507     if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
    508         return;
    509     }
    510 
    511     GrStrokeInfo strokeInfo(paint);
    512     if (paint.getMaskFilter()) {
    513         // try to hit the fast path for drawing filtered round rects
    514 
    515         SkRRect devRRect;
    516         if (rect.transform(*draw.fMatrix, &devRRect)) {
    517             if (devRRect.allCornersCircular()) {
    518                 SkRect maskRect;
    519                 if (paint.getMaskFilter()->canFilterMaskGPU(devRRect,
    520                                                             draw.fClip->getBounds(),
    521                                                             *draw.fMatrix,
    522                                                             &maskRect)) {
    523                     SkIRect finalIRect;
    524                     maskRect.roundOut(&finalIRect);
    525                     if (draw.fClip->quickReject(finalIRect)) {
    526                         // clipped out
    527                         return;
    528                     }
    529                     if (paint.getMaskFilter()->directFilterRRectMaskGPU(fContext->textureProvider(),
    530                                                                         fDrawContext,
    531                                                                         &grPaint,
    532                                                                         fClip,
    533                                                                         *draw.fMatrix,
    534                                                                         strokeInfo,
    535                                                                         devRRect)) {
    536                         return;
    537                     }
    538                 }
    539 
    540             }
    541         }
    542     }
    543 
    544     if (paint.getMaskFilter() || paint.getPathEffect()) {
    545         // The only mask filter the native rrect drawing code could've handle was taken
    546         // care of above.
    547         // A path effect will presumably transform this rrect into something else.
    548         SkPath path;
    549         path.setIsVolatile(true);
    550         path.addRRect(rect);
    551         GrBlurUtils::drawPathWithMaskFilter(fContext, fDrawContext,
    552                                             fClip, path, paint,
    553                                             *draw.fMatrix, nullptr,
    554                                             draw.fClip->getBounds(), true);
    555         return;
    556     }
    557 
    558     SkASSERT(!strokeInfo.isDashed());
    559 
    560     fDrawContext->drawRRect(fClip, grPaint, *draw.fMatrix, rect, strokeInfo);
    561 }
    562 
    563 bool SkGpuDevice::drawFilledDRRect(const SkMatrix& viewMatrix, const SkRRect& origOuter,
    564                                    const SkRRect& origInner, const SkPaint& paint) {
    565     SkASSERT(!origInner.isEmpty());
    566     SkASSERT(!origOuter.isEmpty());
    567 
    568     bool applyAA = paint.isAntiAlias() && !fRenderTarget->isUnifiedMultisampled();
    569 
    570     GrPrimitiveEdgeType innerEdgeType = applyAA ? kInverseFillAA_GrProcessorEdgeType :
    571                                                   kInverseFillBW_GrProcessorEdgeType;
    572     GrPrimitiveEdgeType outerEdgeType = applyAA ? kFillAA_GrProcessorEdgeType :
    573                                                   kFillBW_GrProcessorEdgeType;
    574 
    575     SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
    576     SkMatrix inverseVM;
    577     if (!viewMatrix.isIdentity()) {
    578         if (!origInner.transform(viewMatrix, inner.writable())) {
    579             return false;
    580         }
    581         if (!origOuter.transform(viewMatrix, outer.writable())) {
    582             return false;
    583         }
    584         if (!viewMatrix.invert(&inverseVM)) {
    585             return false;
    586         }
    587     } else {
    588         inverseVM.reset();
    589     }
    590 
    591     GrPaint grPaint;
    592 
    593     if (!SkPaintToGrPaint(this->context(), paint, viewMatrix, &grPaint)) {
    594         return false;
    595     }
    596 
    597     grPaint.setAntiAlias(false);
    598 
    599     // TODO these need to be a geometry processors
    600     SkAutoTUnref<GrFragmentProcessor> innerEffect(GrRRectEffect::Create(innerEdgeType, *inner));
    601     if (!innerEffect) {
    602         return false;
    603     }
    604 
    605     SkAutoTUnref<GrFragmentProcessor> outerEffect(GrRRectEffect::Create(outerEdgeType, *outer));
    606     if (!outerEffect) {
    607         return false;
    608     }
    609 
    610     grPaint.addCoverageFragmentProcessor(innerEffect);
    611     grPaint.addCoverageFragmentProcessor(outerEffect);
    612 
    613     SkRect bounds = outer->getBounds();
    614     if (applyAA) {
    615         bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
    616     }
    617 
    618     fDrawContext->fillRectWithLocalMatrix(fClip, grPaint, SkMatrix::I(), bounds, inverseVM);
    619     return true;
    620 }
    621 
    622 
    623 void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
    624                              const SkRRect& inner, const SkPaint& paint) {
    625     ASSERT_SINGLE_OWNER
    626     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawDRRect", fContext);
    627     CHECK_FOR_ANNOTATION(paint);
    628     CHECK_SHOULD_DRAW(draw);
    629 
    630     if (outer.isEmpty()) {
    631        return;
    632     }
    633 
    634     if (inner.isEmpty()) {
    635         return this->drawRRect(draw, outer, paint);
    636     }
    637 
    638     SkStrokeRec stroke(paint);
    639 
    640     if (stroke.isFillStyle() && !paint.getMaskFilter() && !paint.getPathEffect()) {
    641         if (this->drawFilledDRRect(*draw.fMatrix, outer, inner, paint)) {
    642             return;
    643         }
    644     }
    645 
    646     SkPath path;
    647     path.setIsVolatile(true);
    648     path.addRRect(outer);
    649     path.addRRect(inner);
    650     path.setFillType(SkPath::kEvenOdd_FillType);
    651 
    652     GrBlurUtils::drawPathWithMaskFilter(fContext, fDrawContext,
    653                                         fClip, path, paint,
    654                                         *draw.fMatrix, nullptr,
    655                                         draw.fClip->getBounds(), true);
    656 }
    657 
    658 
    659 /////////////////////////////////////////////////////////////////////////////
    660 
    661 void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) {
    662     ASSERT_SINGLE_OWNER
    663     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawOval", fContext);
    664     CHECK_FOR_ANNOTATION(paint);
    665     CHECK_SHOULD_DRAW(draw);
    666 
    667     // Presumably the path effect warps this to something other than an oval
    668     if (paint.getPathEffect()) {
    669         SkPath path;
    670         path.setIsVolatile(true);
    671         path.addOval(oval);
    672         this->drawPath(draw, path, paint, nullptr, true);
    673         return;
    674     }
    675 
    676     if (paint.getMaskFilter()) {
    677         // The RRect path can handle special case blurring
    678         SkRRect rr = SkRRect::MakeOval(oval);
    679         return this->drawRRect(draw, rr, paint);
    680     }
    681 
    682     GrPaint grPaint;
    683     if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
    684         return;
    685     }
    686 
    687     GrStrokeInfo strokeInfo(paint);
    688     SkASSERT(!strokeInfo.isDashed());
    689 
    690     fDrawContext->drawOval(fClip, grPaint, *draw.fMatrix, oval, strokeInfo);
    691 }
    692 
    693 #include "SkMaskFilter.h"
    694 
    695 ///////////////////////////////////////////////////////////////////////////////
    696 
    697 void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
    698                            const SkPaint& paint, const SkMatrix* prePathMatrix,
    699                            bool pathIsMutable) {
    700     ASSERT_SINGLE_OWNER
    701     if (!origSrcPath.isInverseFillType() && !paint.getPathEffect() && !prePathMatrix) {
    702         bool isClosed;
    703         SkRect rect;
    704         if (origSrcPath.isRect(&rect, &isClosed) && isClosed) {
    705             this->drawRect(draw, rect, paint);
    706             return;
    707         }
    708         if (origSrcPath.isOval(&rect)) {
    709             this->drawOval(draw, rect, paint);
    710             return;
    711         }
    712         SkRRect rrect;
    713         if (origSrcPath.isRRect(&rrect)) {
    714             this->drawRRect(draw, rrect, paint);
    715             return;
    716         }
    717     }
    718 
    719     CHECK_FOR_ANNOTATION(paint);
    720     CHECK_SHOULD_DRAW(draw);
    721     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPath", fContext);
    722 
    723     GrBlurUtils::drawPathWithMaskFilter(fContext, fDrawContext,
    724                                         fClip, origSrcPath, paint,
    725                                         *draw.fMatrix, prePathMatrix,
    726                                         draw.fClip->getBounds(), pathIsMutable);
    727 }
    728 
    729 static const int kBmpSmallTileSize = 1 << 10;
    730 
    731 static inline int get_tile_count(const SkIRect& srcRect, int tileSize)  {
    732     int tilesX = (srcRect.fRight / tileSize) - (srcRect.fLeft / tileSize) + 1;
    733     int tilesY = (srcRect.fBottom / tileSize) - (srcRect.fTop / tileSize) + 1;
    734     return tilesX * tilesY;
    735 }
    736 
    737 static int determine_tile_size(const SkIRect& src, int maxTileSize) {
    738     if (maxTileSize <= kBmpSmallTileSize) {
    739         return maxTileSize;
    740     }
    741 
    742     size_t maxTileTotalTileSize = get_tile_count(src, maxTileSize);
    743     size_t smallTotalTileSize = get_tile_count(src, kBmpSmallTileSize);
    744 
    745     maxTileTotalTileSize *= maxTileSize * maxTileSize;
    746     smallTotalTileSize *= kBmpSmallTileSize * kBmpSmallTileSize;
    747 
    748     if (maxTileTotalTileSize > 2 * smallTotalTileSize) {
    749         return kBmpSmallTileSize;
    750     } else {
    751         return maxTileSize;
    752     }
    753 }
    754 
    755 // Given a bitmap, an optional src rect, and a context with a clip and matrix determine what
    756 // pixels from the bitmap are necessary.
    757 static void determine_clipped_src_rect(const GrRenderTarget* rt,
    758                                        const GrClip& clip,
    759                                        const SkMatrix& viewMatrix,
    760                                        const SkISize& imageSize,
    761                                        const SkRect* srcRectPtr,
    762                                        SkIRect* clippedSrcIRect) {
    763     clip.getConservativeBounds(rt->width(), rt->height(), clippedSrcIRect, nullptr);
    764     SkMatrix inv;
    765     if (!viewMatrix.invert(&inv)) {
    766         clippedSrcIRect->setEmpty();
    767         return;
    768     }
    769     SkRect clippedSrcRect = SkRect::Make(*clippedSrcIRect);
    770     inv.mapRect(&clippedSrcRect);
    771     if (srcRectPtr) {
    772         // we've setup src space 0,0 to map to the top left of the src rect.
    773         clippedSrcRect.offset(srcRectPtr->fLeft, srcRectPtr->fTop);
    774         if (!clippedSrcRect.intersect(*srcRectPtr)) {
    775             clippedSrcIRect->setEmpty();
    776             return;
    777         }
    778     }
    779     clippedSrcRect.roundOut(clippedSrcIRect);
    780     SkIRect bmpBounds = SkIRect::MakeSize(imageSize);
    781     if (!clippedSrcIRect->intersect(bmpBounds)) {
    782         clippedSrcIRect->setEmpty();
    783     }
    784 }
    785 
    786 bool SkGpuDevice::shouldTileImageID(uint32_t imageID, const SkIRect& imageRect,
    787                                     const SkMatrix& viewMatrix,
    788                                     const GrTextureParams& params,
    789                                     const SkRect* srcRectPtr,
    790                                     int maxTileSize,
    791                                     int* tileSize,
    792                                     SkIRect* clippedSubset) const {
    793     ASSERT_SINGLE_OWNER
    794     // if it's larger than the max tile size, then we have no choice but tiling.
    795     if (imageRect.width() > maxTileSize || imageRect.height() > maxTileSize) {
    796         determine_clipped_src_rect(fRenderTarget, fClip, viewMatrix, imageRect.size(),
    797                                    srcRectPtr, clippedSubset);
    798         *tileSize = determine_tile_size(*clippedSubset, maxTileSize);
    799         return true;
    800     }
    801 
    802     // If the image would only produce 4 tiles of the smaller size, don't bother tiling it.
    803     const size_t area = imageRect.width() * imageRect.height();
    804     if (area < 4 * kBmpSmallTileSize * kBmpSmallTileSize) {
    805         return false;
    806     }
    807 
    808     // At this point we know we could do the draw by uploading the entire bitmap
    809     // as a texture. However, if the texture would be large compared to the
    810     // cache size and we don't require most of it for this draw then tile to
    811     // reduce the amount of upload and cache spill.
    812 
    813     // assumption here is that sw bitmap size is a good proxy for its size as
    814     // a texture
    815     size_t bmpSize = area * sizeof(SkPMColor);  // assume 32bit pixels
    816     size_t cacheSize;
    817     fContext->getResourceCacheLimits(nullptr, &cacheSize);
    818     if (bmpSize < cacheSize / 2) {
    819         return false;
    820     }
    821 
    822     // Figure out how much of the src we will need based on the src rect and clipping. Reject if
    823     // tiling memory savings would be < 50%.
    824     determine_clipped_src_rect(fRenderTarget, fClip, viewMatrix, imageRect.size(), srcRectPtr,
    825                                clippedSubset);
    826     *tileSize = kBmpSmallTileSize; // already know whole bitmap fits in one max sized tile.
    827     size_t usedTileBytes = get_tile_count(*clippedSubset, kBmpSmallTileSize) *
    828                            kBmpSmallTileSize * kBmpSmallTileSize;
    829 
    830     return usedTileBytes < 2 * bmpSize;
    831 }
    832 
    833 bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
    834                                    const SkMatrix& viewMatrix,
    835                                    const GrTextureParams& params,
    836                                    const SkRect* srcRectPtr,
    837                                    int maxTileSize,
    838                                    int* tileSize,
    839                                    SkIRect* clippedSrcRect) const {
    840     ASSERT_SINGLE_OWNER
    841     // if bitmap is explictly texture backed then just use the texture
    842     if (bitmap.getTexture()) {
    843         return false;
    844     }
    845 
    846     return this->shouldTileImageID(bitmap.getGenerationID(), bitmap.getSubset(), viewMatrix, params,
    847                                    srcRectPtr, maxTileSize, tileSize, clippedSrcRect);
    848 }
    849 
    850 bool SkGpuDevice::shouldTileImage(const SkImage* image, const SkRect* srcRectPtr,
    851                                   SkCanvas::SrcRectConstraint constraint, SkFilterQuality quality,
    852                                   const SkMatrix& viewMatrix) const {
    853     ASSERT_SINGLE_OWNER
    854     // if image is explictly texture backed then just use the texture
    855     if (as_IB(image)->peekTexture()) {
    856         return false;
    857     }
    858 
    859     GrTextureParams params;
    860     bool doBicubic;
    861     GrTextureParams::FilterMode textureFilterMode =
    862                     GrSkFilterQualityToGrFilterMode(quality, viewMatrix, SkMatrix::I(), &doBicubic);
    863 
    864     int tileFilterPad;
    865     if (doBicubic) {
    866         tileFilterPad = GrBicubicEffect::kFilterTexelPad;
    867     } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) {
    868         tileFilterPad = 0;
    869     } else {
    870         tileFilterPad = 1;
    871     }
    872     params.setFilterMode(textureFilterMode);
    873 
    874     int maxTileSize = fContext->caps()->maxTileSize() - 2 * tileFilterPad;
    875 
    876     // these are output, which we safely ignore, as we just want to know the predicate
    877     int outTileSize;
    878     SkIRect outClippedSrcRect;
    879 
    880     return this->shouldTileImageID(image->unique(), image->bounds(), viewMatrix, params, srcRectPtr,
    881                                    maxTileSize, &outTileSize, &outClippedSrcRect);
    882 }
    883 
    884 void SkGpuDevice::drawBitmap(const SkDraw& origDraw,
    885                              const SkBitmap& bitmap,
    886                              const SkMatrix& m,
    887                              const SkPaint& paint) {
    888     ASSERT_SINGLE_OWNER
    889     CHECK_SHOULD_DRAW(origDraw);
    890     SkMatrix viewMatrix;
    891     viewMatrix.setConcat(*origDraw.fMatrix, m);
    892     if (bitmap.getTexture()) {
    893         GrBitmapTextureAdjuster adjuster(&bitmap);
    894         // We can use kFast here because we know texture-backed bitmaps don't support extractSubset.
    895         this->drawTextureProducer(&adjuster, nullptr, nullptr, SkCanvas::kFast_SrcRectConstraint,
    896                                   viewMatrix, fClip, paint);
    897         return;
    898     }
    899     int maxTileSize = fContext->caps()->maxTileSize();
    900 
    901     // The tile code path doesn't currently support AA, so if the paint asked for aa and we could
    902     // draw untiled, then we bypass checking for tiling purely for optimization reasons.
    903     bool drawAA = !fRenderTarget->isUnifiedMultisampled() &&
    904                   paint.isAntiAlias() &&
    905                   bitmap.width() <= maxTileSize &&
    906                   bitmap.height() <= maxTileSize;
    907 
    908     bool skipTileCheck = drawAA || paint.getMaskFilter();
    909 
    910     if (!skipTileCheck) {
    911         SkRect srcRect = SkRect::MakeIWH(bitmap.width(), bitmap.height());
    912         int tileSize;
    913         SkIRect clippedSrcRect;
    914 
    915         GrTextureParams params;
    916         bool doBicubic;
    917         GrTextureParams::FilterMode textureFilterMode =
    918             GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), viewMatrix, SkMatrix::I(),
    919                                             &doBicubic);
    920 
    921         int tileFilterPad;
    922 
    923         if (doBicubic) {
    924             tileFilterPad = GrBicubicEffect::kFilterTexelPad;
    925         } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) {
    926             tileFilterPad = 0;
    927         } else {
    928             tileFilterPad = 1;
    929         }
    930         params.setFilterMode(textureFilterMode);
    931 
    932         int maxTileSizeForFilter = fContext->caps()->maxTileSize() - 2 * tileFilterPad;
    933         if (this->shouldTileBitmap(bitmap, viewMatrix, params, &srcRect,
    934                                    maxTileSizeForFilter, &tileSize, &clippedSrcRect)) {
    935             this->drawTiledBitmap(bitmap, viewMatrix, srcRect, clippedSrcRect, params, paint,
    936                                   SkCanvas::kStrict_SrcRectConstraint, tileSize, doBicubic);
    937             return;
    938         }
    939     }
    940     GrBitmapTextureMaker maker(fContext, bitmap);
    941     this->drawTextureProducer(&maker, nullptr, nullptr, SkCanvas::kStrict_SrcRectConstraint,
    942                               viewMatrix, fClip, paint);
    943 }
    944 
    945 // This method outsets 'iRect' by 'outset' all around and then clamps its extents to
    946 // 'clamp'. 'offset' is adjusted to remain positioned over the top-left corner
    947 // of 'iRect' for all possible outsets/clamps.
    948 static inline void clamped_outset_with_offset(SkIRect* iRect,
    949                                               int outset,
    950                                               SkPoint* offset,
    951                                               const SkIRect& clamp) {
    952     iRect->outset(outset, outset);
    953 
    954     int leftClampDelta = clamp.fLeft - iRect->fLeft;
    955     if (leftClampDelta > 0) {
    956         offset->fX -= outset - leftClampDelta;
    957         iRect->fLeft = clamp.fLeft;
    958     } else {
    959         offset->fX -= outset;
    960     }
    961 
    962     int topClampDelta = clamp.fTop - iRect->fTop;
    963     if (topClampDelta > 0) {
    964         offset->fY -= outset - topClampDelta;
    965         iRect->fTop = clamp.fTop;
    966     } else {
    967         offset->fY -= outset;
    968     }
    969 
    970     if (iRect->fRight > clamp.fRight) {
    971         iRect->fRight = clamp.fRight;
    972     }
    973     if (iRect->fBottom > clamp.fBottom) {
    974         iRect->fBottom = clamp.fBottom;
    975     }
    976 }
    977 
    978 // Break 'bitmap' into several tiles to draw it since it has already
    979 // been determined to be too large to fit in VRAM
    980 void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
    981                                   const SkMatrix& viewMatrix,
    982                                   const SkRect& srcRect,
    983                                   const SkIRect& clippedSrcIRect,
    984                                   const GrTextureParams& params,
    985                                   const SkPaint& origPaint,
    986                                   SkCanvas::SrcRectConstraint constraint,
    987                                   int tileSize,
    988                                   bool bicubic) {
    989     ASSERT_SINGLE_OWNER
    990 
    991     // This is the funnel for all paths that draw tiled bitmaps/images. Log histogram entry.
    992     SK_HISTOGRAM_BOOLEAN("DrawTiled", true);
    993 
    994     // The following pixel lock is technically redundant, but it is desirable
    995     // to lock outside of the tile loop to prevent redecoding the whole image
    996     // at each tile in cases where 'bitmap' holds an SkDiscardablePixelRef that
    997     // is larger than the limit of the discardable memory pool.
    998     SkAutoLockPixels alp(bitmap);
    999 
   1000     const SkPaint* paint = &origPaint;
   1001     SkPaint tempPaint;
   1002     if (origPaint.isAntiAlias() && !fRenderTarget->isUnifiedMultisampled()) {
   1003         // Drop antialiasing to avoid seams at tile boundaries.
   1004         tempPaint = origPaint;
   1005         tempPaint.setAntiAlias(false);
   1006         paint = &tempPaint;
   1007     }
   1008     SkRect clippedSrcRect = SkRect::Make(clippedSrcIRect);
   1009 
   1010     int nx = bitmap.width() / tileSize;
   1011     int ny = bitmap.height() / tileSize;
   1012     for (int x = 0; x <= nx; x++) {
   1013         for (int y = 0; y <= ny; y++) {
   1014             SkRect tileR;
   1015             tileR.set(SkIntToScalar(x * tileSize),
   1016                       SkIntToScalar(y * tileSize),
   1017                       SkIntToScalar((x + 1) * tileSize),
   1018                       SkIntToScalar((y + 1) * tileSize));
   1019 
   1020             if (!SkRect::Intersects(tileR, clippedSrcRect)) {
   1021                 continue;
   1022             }
   1023 
   1024             if (!tileR.intersect(srcRect)) {
   1025                 continue;
   1026             }
   1027 
   1028             SkBitmap tmpB;
   1029             SkIRect iTileR;
   1030             tileR.roundOut(&iTileR);
   1031             SkPoint offset = SkPoint::Make(SkIntToScalar(iTileR.fLeft),
   1032                                            SkIntToScalar(iTileR.fTop));
   1033 
   1034             // Adjust the context matrix to draw at the right x,y in device space
   1035             SkMatrix viewM = viewMatrix;
   1036             SkMatrix tmpM;
   1037             tmpM.setTranslate(offset.fX - srcRect.fLeft, offset.fY - srcRect.fTop);
   1038             viewM.preConcat(tmpM);
   1039 
   1040             if (GrTextureParams::kNone_FilterMode != params.filterMode() || bicubic) {
   1041                 SkIRect iClampRect;
   1042 
   1043                 if (SkCanvas::kFast_SrcRectConstraint == constraint) {
   1044                     // In bleed mode we want to always expand the tile on all edges
   1045                     // but stay within the bitmap bounds
   1046                     iClampRect = SkIRect::MakeWH(bitmap.width(), bitmap.height());
   1047                 } else {
   1048                     // In texture-domain/clamp mode we only want to expand the
   1049                     // tile on edges interior to "srcRect" (i.e., we want to
   1050                     // not bleed across the original clamped edges)
   1051                     srcRect.roundOut(&iClampRect);
   1052                 }
   1053                 int outset = bicubic ? GrBicubicEffect::kFilterTexelPad : 1;
   1054                 clamped_outset_with_offset(&iTileR, outset, &offset, iClampRect);
   1055             }
   1056 
   1057             if (bitmap.extractSubset(&tmpB, iTileR)) {
   1058                 // now offset it to make it "local" to our tmp bitmap
   1059                 tileR.offset(-offset.fX, -offset.fY);
   1060                 GrTextureParams paramsTemp = params;
   1061                 // de-optimized this determination
   1062                 bool needsTextureDomain = true;
   1063                 this->internalDrawBitmap(tmpB,
   1064                                          viewM,
   1065                                          tileR,
   1066                                          paramsTemp,
   1067                                          *paint,
   1068                                          constraint,
   1069                                          bicubic,
   1070                                          needsTextureDomain);
   1071             }
   1072         }
   1073     }
   1074 }
   1075 
   1076 /*
   1077  *  This is called by drawBitmap(), which has to handle images that may be too
   1078  *  large to be represented by a single texture.
   1079  *
   1080  *  internalDrawBitmap assumes that the specified bitmap will fit in a texture
   1081  *  and that non-texture portion of the GrPaint has already been setup.
   1082  */
   1083 void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
   1084                                      const SkMatrix& viewMatrix,
   1085                                      const SkRect& srcRect,
   1086                                      const GrTextureParams& params,
   1087                                      const SkPaint& paint,
   1088                                      SkCanvas::SrcRectConstraint constraint,
   1089                                      bool bicubic,
   1090                                      bool needsTextureDomain) {
   1091     // We should have already handled bitmaps larger than the max texture size.
   1092     SkASSERT(bitmap.width() <= fContext->caps()->maxTextureSize() &&
   1093              bitmap.height() <= fContext->caps()->maxTextureSize());
   1094     // Unless the bitmap is inherently texture-backed, we should be respecting the max tile size
   1095     // by the time we get here.
   1096     SkASSERT(bitmap.getTexture() ||
   1097              (bitmap.width() <= fContext->caps()->maxTileSize() &&
   1098               bitmap.height() <= fContext->caps()->maxTileSize()));
   1099 
   1100     GrTexture* texture;
   1101     AutoBitmapTexture abt(fContext, bitmap, params, &texture);
   1102     if (nullptr == texture) {
   1103         return;
   1104     }
   1105 
   1106     SkRect dstRect = {0, 0, srcRect.width(), srcRect.height() };
   1107     SkRect paintRect;
   1108     SkScalar wInv = SkScalarInvert(SkIntToScalar(texture->width()));
   1109     SkScalar hInv = SkScalarInvert(SkIntToScalar(texture->height()));
   1110     paintRect.setLTRB(SkScalarMul(srcRect.fLeft,   wInv),
   1111                       SkScalarMul(srcRect.fTop,    hInv),
   1112                       SkScalarMul(srcRect.fRight,  wInv),
   1113                       SkScalarMul(srcRect.fBottom, hInv));
   1114 
   1115     SkMatrix texMatrix;
   1116     texMatrix.reset();
   1117     if (kAlpha_8_SkColorType == bitmap.colorType() && paint.getShader()) {
   1118         // In cases where we are doing an A8 bitmap draw with a shader installed, we cannot use
   1119         // local coords with the bitmap draw since it may mess up texture look ups for the shader.
   1120         // Thus we need to pass in the transform matrix directly to the texture processor used for
   1121         // the bitmap draw.
   1122         texMatrix.setScale(wInv, hInv);
   1123     }
   1124 
   1125     SkRect textureDomain = SkRect::MakeEmpty();
   1126 
   1127     // Construct a GrPaint by setting the bitmap texture as the first effect and then configuring
   1128     // the rest from the SkPaint.
   1129     SkAutoTUnref<const GrFragmentProcessor> fp;
   1130 
   1131     if (needsTextureDomain && (SkCanvas::kStrict_SrcRectConstraint == constraint)) {
   1132         // Use a constrained texture domain to avoid color bleeding
   1133         SkScalar left, top, right, bottom;
   1134         if (srcRect.width() > SK_Scalar1) {
   1135             SkScalar border = SK_ScalarHalf / texture->width();
   1136             left = paintRect.left() + border;
   1137             right = paintRect.right() - border;
   1138         } else {
   1139             left = right = SkScalarHalf(paintRect.left() + paintRect.right());
   1140         }
   1141         if (srcRect.height() > SK_Scalar1) {
   1142             SkScalar border = SK_ScalarHalf / texture->height();
   1143             top = paintRect.top() + border;
   1144             bottom = paintRect.bottom() - border;
   1145         } else {
   1146             top = bottom = SkScalarHalf(paintRect.top() + paintRect.bottom());
   1147         }
   1148         textureDomain.setLTRB(left, top, right, bottom);
   1149         if (bicubic) {
   1150             fp.reset(GrBicubicEffect::Create(texture, texMatrix, textureDomain));
   1151         } else {
   1152             fp.reset(GrTextureDomainEffect::Create(texture,
   1153                                                    texMatrix,
   1154                                                    textureDomain,
   1155                                                    GrTextureDomain::kClamp_Mode,
   1156                                                    params.filterMode()));
   1157         }
   1158     } else if (bicubic) {
   1159         SkASSERT(GrTextureParams::kNone_FilterMode == params.filterMode());
   1160         SkShader::TileMode tileModes[2] = { params.getTileModeX(), params.getTileModeY() };
   1161         fp.reset(GrBicubicEffect::Create(texture, texMatrix, tileModes));
   1162     } else {
   1163         fp.reset(GrSimpleTextureEffect::Create(texture, texMatrix, params));
   1164     }
   1165 
   1166     GrPaint grPaint;
   1167     if (!SkPaintToGrPaintWithTexture(this->context(), paint, viewMatrix, fp,
   1168                                      kAlpha_8_SkColorType == bitmap.colorType(), &grPaint)) {
   1169         return;
   1170     }
   1171 
   1172     if (kAlpha_8_SkColorType == bitmap.colorType() && paint.getShader()) {
   1173         // We don't have local coords in this case and have previously set the transform
   1174         // matrices directly on the texture processor.
   1175         fDrawContext->drawRect(fClip, grPaint, viewMatrix, dstRect);
   1176     } else {
   1177         fDrawContext->fillRectToRect(fClip, grPaint, viewMatrix, dstRect, paintRect);
   1178     }
   1179 }
   1180 
   1181 bool SkGpuDevice::filterTexture(GrContext* context, GrTexture* texture,
   1182                                 int width, int height,
   1183                                 const SkImageFilter* filter,
   1184                                 const SkImageFilter::Context& ctx,
   1185                                 SkBitmap* result, SkIPoint* offset) {
   1186     ASSERT_SINGLE_OWNER
   1187     SkASSERT(filter);
   1188 
   1189     SkImageFilter::DeviceProxy proxy(this);
   1190 
   1191     if (filter->canFilterImageGPU()) {
   1192         SkBitmap bm;
   1193         GrWrapTextureInBitmap(texture, width, height, false, &bm);
   1194         return filter->filterImageGPUDeprecated(&proxy, bm, ctx, result, offset);
   1195     } else {
   1196         return false;
   1197     }
   1198 }
   1199 
   1200 void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
   1201                              int left, int top, const SkPaint& paint) {
   1202     ASSERT_SINGLE_OWNER
   1203     // drawSprite is defined to be in device coords.
   1204     CHECK_SHOULD_DRAW(draw);
   1205 
   1206     SkAutoLockPixels alp(bitmap, !bitmap.getTexture());
   1207     if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
   1208         return;
   1209     }
   1210 
   1211     int w = bitmap.width();
   1212     int h = bitmap.height();
   1213 
   1214     GrTexture* texture;
   1215     // draw sprite neither filters nor tiles.
   1216     AutoBitmapTexture abt(fContext, bitmap, GrTextureParams::ClampNoFilter(), &texture);
   1217     if (!texture) {
   1218         return;
   1219     }
   1220 
   1221     bool alphaOnly = kAlpha_8_SkColorType == bitmap.colorType();
   1222 
   1223     SkImageFilter* filter = paint.getImageFilter();
   1224     // This bitmap will own the filtered result as a texture.
   1225     SkBitmap filteredBitmap;
   1226 
   1227     if (filter) {
   1228         SkIPoint offset = SkIPoint::Make(0, 0);
   1229         SkMatrix matrix(*draw.fMatrix);
   1230         matrix.postTranslate(SkIntToScalar(-left), SkIntToScalar(-top));
   1231         SkIRect clipBounds = draw.fClip->getBounds().makeOffset(-left, -top);
   1232         SkAutoTUnref<SkImageFilter::Cache> cache(getImageFilterCache());
   1233         // This cache is transient, and is freed (along with all its contained
   1234         // textures) when it goes out of scope.
   1235         SkImageFilter::Context ctx(matrix, clipBounds, cache);
   1236         if (this->filterTexture(fContext, texture, w, h, filter, ctx, &filteredBitmap,
   1237                                 &offset)) {
   1238             texture = (GrTexture*) filteredBitmap.getTexture();
   1239             w = filteredBitmap.width();
   1240             h = filteredBitmap.height();
   1241             left += offset.x();
   1242             top += offset.y();
   1243         } else {
   1244             return;
   1245         }
   1246         SkASSERT(!GrPixelConfigIsAlphaOnly(texture->config()));
   1247         alphaOnly = false;
   1248     }
   1249 
   1250     GrPaint grPaint;
   1251     SkAutoTUnref<const GrFragmentProcessor> fp(
   1252         GrSimpleTextureEffect::Create(texture, SkMatrix::I()));
   1253     if (alphaOnly) {
   1254         fp.reset(GrFragmentProcessor::MulOutputByInputUnpremulColor(fp));
   1255     } else {
   1256         fp.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp));
   1257     }
   1258     if (!SkPaintToGrPaintReplaceShader(this->context(), paint, fp, &grPaint)) {
   1259         return;
   1260     }
   1261 
   1262     fDrawContext->fillRectToRect(fClip,
   1263                                  grPaint,
   1264                                  SkMatrix::I(),
   1265                                  SkRect::MakeXYWH(SkIntToScalar(left),
   1266                                                   SkIntToScalar(top),
   1267                                                   SkIntToScalar(w),
   1268                                                   SkIntToScalar(h)),
   1269                                  SkRect::MakeXYWH(0,
   1270                                                   0,
   1271                                                   SK_Scalar1 * w / texture->width(),
   1272                                                   SK_Scalar1 * h / texture->height()));
   1273 }
   1274 
   1275 void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
   1276                                  const SkRect* src, const SkRect& origDst,
   1277                                  const SkPaint& paint, SkCanvas::SrcRectConstraint constraint) {
   1278     ASSERT_SINGLE_OWNER
   1279     CHECK_SHOULD_DRAW(draw);
   1280     if (bitmap.getTexture()) {
   1281         GrBitmapTextureAdjuster adjuster(&bitmap);
   1282         this->drawTextureProducer(&adjuster, src, &origDst, constraint, *draw.fMatrix, fClip,
   1283                                   paint);
   1284         return;
   1285     }
   1286     // The src rect is inferred to be the bmp bounds if not provided. Otherwise, the src rect must
   1287     // be clipped to the bmp bounds. To determine tiling parameters we need the filter mode which
   1288     // in turn requires knowing the src-to-dst mapping. If the src was clipped to the bmp bounds
   1289     // then we use the src-to-dst mapping to compute a new clipped dst rect.
   1290     const SkRect* dst = &origDst;
   1291     const SkRect bmpBounds = SkRect::MakeIWH(bitmap.width(), bitmap.height());
   1292     // Compute matrix from the two rectangles
   1293     if (!src) {
   1294         src = &bmpBounds;
   1295     }
   1296 
   1297     SkMatrix srcToDstMatrix;
   1298     if (!srcToDstMatrix.setRectToRect(*src, *dst, SkMatrix::kFill_ScaleToFit)) {
   1299         return;
   1300     }
   1301     SkRect tmpSrc, tmpDst;
   1302     if (src != &bmpBounds) {
   1303         if (!bmpBounds.contains(*src)) {
   1304             tmpSrc = *src;
   1305             if (!tmpSrc.intersect(bmpBounds)) {
   1306                 return; // nothing to draw
   1307             }
   1308             src = &tmpSrc;
   1309             srcToDstMatrix.mapRect(&tmpDst, *src);
   1310             dst = &tmpDst;
   1311         }
   1312     }
   1313 
   1314     int maxTileSize = fContext->caps()->maxTileSize();
   1315 
   1316     // The tile code path doesn't currently support AA, so if the paint asked for aa and we could
   1317     // draw untiled, then we bypass checking for tiling purely for optimization reasons.
   1318     bool drawAA = !fRenderTarget->isUnifiedMultisampled() &&
   1319         paint.isAntiAlias() &&
   1320         bitmap.width() <= maxTileSize &&
   1321         bitmap.height() <= maxTileSize;
   1322 
   1323     bool skipTileCheck = drawAA || paint.getMaskFilter();
   1324 
   1325     if (!skipTileCheck) {
   1326         int tileSize;
   1327         SkIRect clippedSrcRect;
   1328 
   1329         GrTextureParams params;
   1330         bool doBicubic;
   1331         GrTextureParams::FilterMode textureFilterMode =
   1332             GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), *draw.fMatrix, srcToDstMatrix,
   1333                                             &doBicubic);
   1334 
   1335         int tileFilterPad;
   1336 
   1337         if (doBicubic) {
   1338             tileFilterPad = GrBicubicEffect::kFilterTexelPad;
   1339         } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) {
   1340             tileFilterPad = 0;
   1341         } else {
   1342             tileFilterPad = 1;
   1343         }
   1344         params.setFilterMode(textureFilterMode);
   1345 
   1346         int maxTileSizeForFilter = fContext->caps()->maxTileSize() - 2 * tileFilterPad;
   1347         // Fold the dst rect into the view matrix. This is only OK because we don't get here if
   1348         // we have a mask filter.
   1349         SkMatrix viewMatrix = *draw.fMatrix;
   1350         viewMatrix.preTranslate(dst->fLeft, dst->fTop);
   1351         viewMatrix.preScale(dst->width()/src->width(), dst->height()/src->height());
   1352         if (this->shouldTileBitmap(bitmap, viewMatrix, params, src,
   1353                                    maxTileSizeForFilter, &tileSize, &clippedSrcRect)) {
   1354             this->drawTiledBitmap(bitmap, viewMatrix, *src, clippedSrcRect, params, paint,
   1355                                   constraint, tileSize, doBicubic);
   1356             return;
   1357         }
   1358     }
   1359     GrBitmapTextureMaker maker(fContext, bitmap);
   1360     this->drawTextureProducer(&maker, src, dst, constraint, *draw.fMatrix, fClip, paint);
   1361 }
   1362 
   1363 void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
   1364                              int x, int y, const SkPaint& paint) {
   1365     ASSERT_SINGLE_OWNER
   1366     // clear of the source device must occur before CHECK_SHOULD_DRAW
   1367     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawDevice", fContext);
   1368     SkGpuDevice* dev = static_cast<SkGpuDevice*>(device);
   1369 
   1370     // drawDevice is defined to be in device coords.
   1371     CHECK_SHOULD_DRAW(draw);
   1372 
   1373     GrRenderTarget* devRT = dev->accessRenderTarget();
   1374     GrTexture* devTex;
   1375     if (nullptr == (devTex = devRT->asTexture())) {
   1376         return;
   1377     }
   1378 
   1379     const SkImageInfo ii = dev->imageInfo();
   1380     int w = ii.width();
   1381     int h = ii.height();
   1382 
   1383     SkImageFilter* filter = paint.getImageFilter();
   1384     // This bitmap will own the filtered result as a texture.
   1385     SkBitmap filteredBitmap;
   1386 
   1387     if (filter) {
   1388         SkIPoint offset = SkIPoint::Make(0, 0);
   1389         SkMatrix matrix(*draw.fMatrix);
   1390         matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
   1391         SkIRect clipBounds = draw.fClip->getBounds().makeOffset(-x, -y);
   1392         // This cache is transient, and is freed (along with all its contained
   1393         // textures) when it goes out of scope.
   1394         SkAutoTUnref<SkImageFilter::Cache> cache(getImageFilterCache());
   1395         SkImageFilter::Context ctx(matrix, clipBounds, cache);
   1396         if (this->filterTexture(fContext, devTex, device->width(), device->height(),
   1397                                 filter, ctx, &filteredBitmap, &offset)) {
   1398             devTex = filteredBitmap.getTexture();
   1399             w = filteredBitmap.width();
   1400             h = filteredBitmap.height();
   1401             x += offset.fX;
   1402             y += offset.fY;
   1403         } else {
   1404             return;
   1405         }
   1406     }
   1407 
   1408     GrPaint grPaint;
   1409     SkAutoTUnref<const GrFragmentProcessor> fp(
   1410         GrSimpleTextureEffect::Create(devTex, SkMatrix::I()));
   1411     if (GrPixelConfigIsAlphaOnly(devTex->config())) {
   1412         // Can this happen?
   1413         fp.reset(GrFragmentProcessor::MulOutputByInputUnpremulColor(fp));
   1414    } else {
   1415         fp.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp));
   1416     }
   1417 
   1418     if (!SkPaintToGrPaintReplaceShader(this->context(), paint, fp, &grPaint)) {
   1419         return;
   1420     }
   1421 
   1422     SkRect dstRect = SkRect::MakeXYWH(SkIntToScalar(x),
   1423                                       SkIntToScalar(y),
   1424                                       SkIntToScalar(w),
   1425                                       SkIntToScalar(h));
   1426 
   1427     // The device being drawn may not fill up its texture (e.g. saveLayer uses approximate
   1428     // scratch texture).
   1429     SkRect srcRect = SkRect::MakeWH(SK_Scalar1 * w / devTex->width(),
   1430                                     SK_Scalar1 * h / devTex->height());
   1431 
   1432     fDrawContext->fillRectToRect(fClip, grPaint, SkMatrix::I(), dstRect, srcRect);
   1433 }
   1434 
   1435 bool SkGpuDevice::canHandleImageFilter(const SkImageFilter* filter) {
   1436     ASSERT_SINGLE_OWNER
   1437     return filter->canFilterImageGPU();
   1438 }
   1439 
   1440 bool SkGpuDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src,
   1441                               const SkImageFilter::Context& ctx,
   1442                               SkBitmap* result, SkIPoint* offset) {
   1443     ASSERT_SINGLE_OWNER
   1444     // want explicitly our impl, so guard against a subclass of us overriding it
   1445     if (!this->SkGpuDevice::canHandleImageFilter(filter)) {
   1446         return false;
   1447     }
   1448 
   1449     SkAutoLockPixels alp(src, !src.getTexture());
   1450     if (!src.getTexture() && !src.readyToDraw()) {
   1451         return false;
   1452     }
   1453 
   1454     GrTexture* texture;
   1455     // We assume here that the filter will not attempt to tile the src. Otherwise, this cache lookup
   1456     // must be pushed upstack.
   1457     AutoBitmapTexture abt(fContext, src, GrTextureParams::ClampNoFilter(), &texture);
   1458     if (!texture) {
   1459         return false;
   1460     }
   1461 
   1462     return this->filterTexture(fContext, texture, src.width(), src.height(),
   1463                                filter, ctx, result, offset);
   1464 }
   1465 
   1466 void SkGpuDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x, SkScalar y,
   1467                             const SkPaint& paint) {
   1468     ASSERT_SINGLE_OWNER
   1469     SkMatrix viewMatrix = *draw.fMatrix;
   1470     viewMatrix.preTranslate(x, y);
   1471     if (as_IB(image)->peekTexture()) {
   1472         CHECK_SHOULD_DRAW(draw);
   1473         GrImageTextureAdjuster adjuster(as_IB(image));
   1474         this->drawTextureProducer(&adjuster, nullptr, nullptr, SkCanvas::kFast_SrcRectConstraint,
   1475                                   viewMatrix, fClip, paint);
   1476         return;
   1477     } else {
   1478         SkBitmap bm;
   1479         if (this->shouldTileImage(image, nullptr, SkCanvas::kFast_SrcRectConstraint,
   1480                                   paint.getFilterQuality(), *draw.fMatrix)) {
   1481             // only support tiling as bitmap at the moment, so force raster-version
   1482             if (!as_IB(image)->getROPixels(&bm)) {
   1483                 return;
   1484             }
   1485             this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
   1486         } else if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) {
   1487             CHECK_SHOULD_DRAW(draw);
   1488             GrImageTextureMaker maker(fContext, cacher, image, SkImage::kAllow_CachingHint);
   1489             this->drawTextureProducer(&maker, nullptr, nullptr, SkCanvas::kFast_SrcRectConstraint,
   1490                                       viewMatrix, fClip, paint);
   1491         } else if (as_IB(image)->getROPixels(&bm)) {
   1492             this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
   1493         }
   1494     }
   1495 }
   1496 
   1497 void SkGpuDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const SkRect* src,
   1498                                 const SkRect& dst, const SkPaint& paint,
   1499                                 SkCanvas::SrcRectConstraint constraint) {
   1500     ASSERT_SINGLE_OWNER
   1501     if (as_IB(image)->peekTexture()) {
   1502         CHECK_SHOULD_DRAW(draw);
   1503         GrImageTextureAdjuster adjuster(as_IB(image));
   1504         this->drawTextureProducer(&adjuster, src, &dst, constraint, *draw.fMatrix, fClip, paint);
   1505         return;
   1506     }
   1507     SkBitmap bm;
   1508     SkMatrix totalMatrix = *draw.fMatrix;
   1509     totalMatrix.preScale(dst.width() / (src ? src->width() : image->width()),
   1510                          dst.height() / (src ? src->height() : image->height()));
   1511     if (this->shouldTileImage(image, src, constraint, paint.getFilterQuality(), totalMatrix)) {
   1512         // only support tiling as bitmap at the moment, so force raster-version
   1513         if (!as_IB(image)->getROPixels(&bm)) {
   1514             return;
   1515         }
   1516         this->drawBitmapRect(draw, bm, src, dst, paint, constraint);
   1517     } else if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) {
   1518         CHECK_SHOULD_DRAW(draw);
   1519         GrImageTextureMaker maker(fContext, cacher, image, SkImage::kAllow_CachingHint);
   1520         this->drawTextureProducer(&maker, src, &dst, constraint, *draw.fMatrix, fClip, paint);
   1521     } else if (as_IB(image)->getROPixels(&bm)) {
   1522         this->drawBitmapRect(draw, bm, src, dst, paint, constraint);
   1523     }
   1524 }
   1525 
   1526 void SkGpuDevice::drawProducerNine(const SkDraw& draw, GrTextureProducer* producer,
   1527                                    const SkIRect& center, const SkRect& dst, const SkPaint& paint) {
   1528     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawProducerNine", fContext);
   1529 
   1530     CHECK_FOR_ANNOTATION(paint);
   1531     CHECK_SHOULD_DRAW(draw);
   1532 
   1533     bool useFallback = paint.getMaskFilter() || paint.isAntiAlias() ||
   1534                        fRenderTarget->isUnifiedMultisampled();
   1535     bool doBicubic;
   1536     GrTextureParams::FilterMode textureFilterMode =
   1537         GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), *draw.fMatrix, SkMatrix::I(),
   1538                                         &doBicubic);
   1539     if (useFallback || doBicubic || GrTextureParams::kNone_FilterMode != textureFilterMode) {
   1540         SkNinePatchIter iter(producer->width(), producer->height(), center, dst);
   1541 
   1542         SkRect srcR, dstR;
   1543         while (iter.next(&srcR, &dstR)) {
   1544             this->drawTextureProducer(producer, &srcR, &dstR, SkCanvas::kStrict_SrcRectConstraint,
   1545                                       *draw.fMatrix, fClip, paint);
   1546         }
   1547         return;
   1548     }
   1549 
   1550     static const GrTextureParams::FilterMode kMode = GrTextureParams::kNone_FilterMode;
   1551     SkAutoTUnref<const GrFragmentProcessor> fp(
   1552         producer->createFragmentProcessor(SkMatrix::I(),
   1553                                           SkRect::MakeIWH(producer->width(), producer->height()),
   1554                                           GrTextureProducer::kNo_FilterConstraint, true,
   1555                                           &kMode));
   1556     GrPaint grPaint;
   1557     if (!SkPaintToGrPaintWithTexture(this->context(), paint, *draw.fMatrix, fp,
   1558                                      producer->isAlphaOnly(), &grPaint)) {
   1559         return;
   1560     }
   1561 
   1562     fDrawContext->drawImageNine(fClip, grPaint, *draw.fMatrix, producer->width(),
   1563                                 producer->height(), center, dst);
   1564 }
   1565 
   1566 void SkGpuDevice::drawImageNine(const SkDraw& draw, const SkImage* image,
   1567                                 const SkIRect& center, const SkRect& dst, const SkPaint& paint) {
   1568     ASSERT_SINGLE_OWNER
   1569     if (as_IB(image)->peekTexture()) {
   1570         GrImageTextureAdjuster adjuster(as_IB(image));
   1571         this->drawProducerNine(draw, &adjuster, center, dst, paint);
   1572     } else {
   1573         SkBitmap bm;
   1574         if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) {
   1575             GrImageTextureMaker maker(fContext, cacher, image, SkImage::kAllow_CachingHint);
   1576             this->drawProducerNine(draw, &maker, center, dst, paint);
   1577         } else if (as_IB(image)->getROPixels(&bm)) {
   1578             this->drawBitmapNine(draw, bm, center, dst, paint);
   1579         }
   1580     }
   1581 }
   1582 
   1583 void SkGpuDevice::drawBitmapNine(const SkDraw& draw, const SkBitmap& bitmap, const SkIRect& center,
   1584                                  const SkRect& dst, const SkPaint& paint) {
   1585     ASSERT_SINGLE_OWNER
   1586     if (bitmap.getTexture()) {
   1587         GrBitmapTextureAdjuster adjuster(&bitmap);
   1588         this->drawProducerNine(draw, &adjuster, center, dst, paint);
   1589     } else {
   1590         GrBitmapTextureMaker maker(fContext, bitmap);
   1591         this->drawProducerNine(draw, &maker, center, dst, paint);
   1592     }
   1593 }
   1594 
   1595 ///////////////////////////////////////////////////////////////////////////////
   1596 
   1597 // must be in SkCanvas::VertexMode order
   1598 static const GrPrimitiveType gVertexMode2PrimitiveType[] = {
   1599     kTriangles_GrPrimitiveType,
   1600     kTriangleStrip_GrPrimitiveType,
   1601     kTriangleFan_GrPrimitiveType,
   1602 };
   1603 
   1604 void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
   1605                               int vertexCount, const SkPoint vertices[],
   1606                               const SkPoint texs[], const SkColor colors[],
   1607                               SkXfermode* xmode,
   1608                               const uint16_t indices[], int indexCount,
   1609                               const SkPaint& paint) {
   1610     ASSERT_SINGLE_OWNER
   1611     CHECK_SHOULD_DRAW(draw);
   1612     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawVertices", fContext);
   1613 
   1614     // If both textures and vertex-colors are nullptr, strokes hairlines with the paint's color.
   1615     if ((nullptr == texs || nullptr == paint.getShader()) && nullptr == colors) {
   1616 
   1617         texs = nullptr;
   1618 
   1619         SkPaint copy(paint);
   1620         copy.setStyle(SkPaint::kStroke_Style);
   1621         copy.setStrokeWidth(0);
   1622 
   1623         GrPaint grPaint;
   1624         // we ignore the shader if texs is null.
   1625         if (!SkPaintToGrPaintNoShader(this->context(), copy, &grPaint)) {
   1626             return;
   1627         }
   1628 
   1629         int triangleCount = 0;
   1630         int n = (nullptr == indices) ? vertexCount : indexCount;
   1631         switch (vmode) {
   1632             case SkCanvas::kTriangles_VertexMode:
   1633                 triangleCount = n / 3;
   1634                 break;
   1635             case SkCanvas::kTriangleStrip_VertexMode:
   1636             case SkCanvas::kTriangleFan_VertexMode:
   1637                 triangleCount = n - 2;
   1638                 break;
   1639         }
   1640 
   1641         VertState       state(vertexCount, indices, indexCount);
   1642         VertState::Proc vertProc = state.chooseProc(vmode);
   1643 
   1644         //number of indices for lines per triangle with kLines
   1645         indexCount = triangleCount * 6;
   1646 
   1647         SkAutoTDeleteArray<uint16_t> lineIndices(new uint16_t[indexCount]);
   1648         int i = 0;
   1649         while (vertProc(&state)) {
   1650             lineIndices[i]     = state.f0;
   1651             lineIndices[i + 1] = state.f1;
   1652             lineIndices[i + 2] = state.f1;
   1653             lineIndices[i + 3] = state.f2;
   1654             lineIndices[i + 4] = state.f2;
   1655             lineIndices[i + 5] = state.f0;
   1656             i += 6;
   1657         }
   1658         fDrawContext->drawVertices(fClip,
   1659                                    grPaint,
   1660                                    *draw.fMatrix,
   1661                                    kLines_GrPrimitiveType,
   1662                                    vertexCount,
   1663                                    vertices,
   1664                                    texs,
   1665                                    colors,
   1666                                    lineIndices.get(),
   1667                                    indexCount);
   1668         return;
   1669     }
   1670 
   1671     GrPrimitiveType primType = gVertexMode2PrimitiveType[vmode];
   1672 
   1673     SkAutoSTMalloc<128, GrColor> convertedColors(0);
   1674     if (colors) {
   1675         // need to convert byte order and from non-PM to PM. TODO: Keep unpremul until after
   1676         // interpolation.
   1677         convertedColors.reset(vertexCount);
   1678         for (int i = 0; i < vertexCount; ++i) {
   1679             convertedColors[i] = SkColorToPremulGrColor(colors[i]);
   1680         }
   1681         colors = convertedColors.get();
   1682     }
   1683     GrPaint grPaint;
   1684     if (texs && paint.getShader()) {
   1685         if (colors) {
   1686             // When there are texs and colors the shader and colors are combined using xmode. A null
   1687             // xmode is defined to mean modulate.
   1688             SkXfermode::Mode colorMode;
   1689             if (xmode) {
   1690                 if (!xmode->asMode(&colorMode)) {
   1691                     return;
   1692                 }
   1693             } else {
   1694                 colorMode = SkXfermode::kModulate_Mode;
   1695             }
   1696             if (!SkPaintToGrPaintWithXfermode(this->context(), paint, *draw.fMatrix, colorMode,
   1697                                               false, &grPaint)) {
   1698                 return;
   1699             }
   1700         } else {
   1701             // We have a shader, but no colors to blend it against.
   1702             if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
   1703                 return;
   1704             }
   1705         }
   1706     } else {
   1707         if (colors) {
   1708             // We have colors, but either have no shader or no texture coords (which implies that
   1709             // we should ignore the shader).
   1710             if (!SkPaintToGrPaintWithPrimitiveColor(this->context(), paint, &grPaint)) {
   1711                 return;
   1712             }
   1713         } else {
   1714             // No colors and no shaders. Just draw with the paint color.
   1715             if (!SkPaintToGrPaintNoShader(this->context(), paint, &grPaint)) {
   1716                 return;
   1717             }
   1718         }
   1719     }
   1720 
   1721     fDrawContext->drawVertices(fClip,
   1722                                grPaint,
   1723                                *draw.fMatrix,
   1724                                primType,
   1725                                vertexCount,
   1726                                vertices,
   1727                                texs,
   1728                                colors,
   1729                                indices,
   1730                                indexCount);
   1731 }
   1732 
   1733 ///////////////////////////////////////////////////////////////////////////////
   1734 
   1735 void SkGpuDevice::drawAtlas(const SkDraw& draw, const SkImage* atlas, const SkRSXform xform[],
   1736                             const SkRect texRect[], const SkColor colors[], int count,
   1737                             SkXfermode::Mode mode, const SkPaint& paint) {
   1738     ASSERT_SINGLE_OWNER
   1739     if (paint.isAntiAlias()) {
   1740         this->INHERITED::drawAtlas(draw, atlas, xform, texRect, colors, count, mode, paint);
   1741         return;
   1742     }
   1743 
   1744     CHECK_SHOULD_DRAW(draw);
   1745     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawText", fContext);
   1746 
   1747     SkPaint p(paint);
   1748     p.setShader(atlas->newShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode))->unref();
   1749 
   1750     GrPaint grPaint;
   1751     if (colors) {
   1752         if (!SkPaintToGrPaintWithXfermode(this->context(), p, *draw.fMatrix, mode, true,
   1753                                           &grPaint)) {
   1754             return;
   1755         }
   1756     } else {
   1757         if (!SkPaintToGrPaint(this->context(), p, *draw.fMatrix, &grPaint)) {
   1758             return;
   1759         }
   1760     }
   1761 
   1762     SkDEBUGCODE(this->validate();)
   1763     fDrawContext->drawAtlas(fClip, grPaint, *draw.fMatrix, count, xform, texRect, colors);
   1764 }
   1765 
   1766 ///////////////////////////////////////////////////////////////////////////////
   1767 
   1768 void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
   1769                            size_t byteLength, SkScalar x, SkScalar y,
   1770                            const SkPaint& paint) {
   1771     ASSERT_SINGLE_OWNER
   1772     CHECK_SHOULD_DRAW(draw);
   1773     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawText", fContext);
   1774 
   1775     GrPaint grPaint;
   1776     if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
   1777         return;
   1778     }
   1779 
   1780     SkDEBUGCODE(this->validate();)
   1781 
   1782     fDrawContext->drawText(fClip, grPaint, paint, *draw.fMatrix,
   1783                            (const char *)text, byteLength, x, y, draw.fClip->getBounds());
   1784 }
   1785 
   1786 void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, size_t byteLength,
   1787                               const SkScalar pos[], int scalarsPerPos,
   1788                               const SkPoint& offset, const SkPaint& paint) {
   1789     ASSERT_SINGLE_OWNER
   1790     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPosText", fContext);
   1791     CHECK_SHOULD_DRAW(draw);
   1792 
   1793     GrPaint grPaint;
   1794     if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
   1795         return;
   1796     }
   1797 
   1798     SkDEBUGCODE(this->validate();)
   1799 
   1800     fDrawContext->drawPosText(fClip, grPaint, paint, *draw.fMatrix,
   1801                               (const char *)text, byteLength, pos, scalarsPerPos, offset,
   1802                               draw.fClip->getBounds());
   1803 }
   1804 
   1805 void SkGpuDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkScalar x, SkScalar y,
   1806                                const SkPaint& paint, SkDrawFilter* drawFilter) {
   1807     ASSERT_SINGLE_OWNER
   1808     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawTextBlob", fContext);
   1809     CHECK_SHOULD_DRAW(draw);
   1810 
   1811     SkDEBUGCODE(this->validate();)
   1812 
   1813     fDrawContext->drawTextBlob(fClip, paint, *draw.fMatrix,
   1814                                blob, x, y, drawFilter, draw.fClip->getBounds());
   1815 }
   1816 
   1817 ///////////////////////////////////////////////////////////////////////////////
   1818 
   1819 bool SkGpuDevice::onShouldDisableLCD(const SkPaint& paint) const {
   1820     return GrTextUtils::ShouldDisableLCD(paint);
   1821 }
   1822 
   1823 void SkGpuDevice::flush() {
   1824     ASSERT_SINGLE_OWNER
   1825 
   1826     fRenderTarget->prepareForExternalIO();
   1827 }
   1828 
   1829 ///////////////////////////////////////////////////////////////////////////////
   1830 
   1831 SkBaseDevice* SkGpuDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) {
   1832     ASSERT_SINGLE_OWNER
   1833     GrSurfaceDesc desc;
   1834     desc.fConfig = fRenderTarget->config();
   1835     desc.fFlags = kRenderTarget_GrSurfaceFlag;
   1836     desc.fWidth = cinfo.fInfo.width();
   1837     desc.fHeight = cinfo.fInfo.height();
   1838     desc.fSampleCnt = fRenderTarget->desc().fSampleCnt;
   1839 
   1840     SkAutoTUnref<GrTexture> texture;
   1841     // Skia's convention is to only clear a device if it is non-opaque.
   1842     InitContents init = cinfo.fInfo.isOpaque() ? kUninit_InitContents : kClear_InitContents;
   1843 
   1844     // layers are never draw in repeat modes, so we can request an approx
   1845     // match and ignore any padding.
   1846     if (kNever_TileUsage == cinfo.fTileUsage) {
   1847         texture.reset(fContext->textureProvider()->createApproxTexture(desc));
   1848     } else {
   1849         texture.reset(fContext->textureProvider()->createTexture(desc, SkBudgeted::kYes));
   1850     }
   1851 
   1852     if (texture) {
   1853         SkSurfaceProps props(this->surfaceProps().flags(), cinfo.fPixelGeometry);
   1854         return SkGpuDevice::Create(
   1855             texture->asRenderTarget(), cinfo.fInfo.width(), cinfo.fInfo.height(), &props, init);
   1856     } else {
   1857         SkErrorInternals::SetError( kInternalError_SkError,
   1858                                     "---- failed to create gpu device texture [%d %d]\n",
   1859                                     cinfo.fInfo.width(), cinfo.fInfo.height());
   1860         return nullptr;
   1861     }
   1862 }
   1863 
   1864 SkSurface* SkGpuDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
   1865     ASSERT_SINGLE_OWNER
   1866     // TODO: Change the signature of newSurface to take a budgeted parameter.
   1867     static const SkBudgeted kBudgeted = SkBudgeted::kNo;
   1868     return SkSurface::NewRenderTarget(fContext, kBudgeted, info, fRenderTarget->desc().fSampleCnt,
   1869                                       &props);
   1870 }
   1871 
   1872 bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture* mainPicture,
   1873                                            const SkMatrix* matrix, const SkPaint* paint) {
   1874     ASSERT_SINGLE_OWNER
   1875 #ifndef SK_IGNORE_GPU_LAYER_HOISTING
   1876     // todo: should handle this natively
   1877     if (paint) {
   1878         return false;
   1879     }
   1880 
   1881     const SkBigPicture::AccelData* data = nullptr;
   1882     if (const SkBigPicture* bp = mainPicture->asSkBigPicture()) {
   1883         data = bp->accelData();
   1884     }
   1885     if (!data) {
   1886         return false;
   1887     }
   1888 
   1889     const SkLayerInfo *gpuData = static_cast<const SkLayerInfo*>(data);
   1890     if (0 == gpuData->numBlocks()) {
   1891         return false;
   1892     }
   1893 
   1894     SkTDArray<GrHoistedLayer> atlasedNeedRendering, atlasedRecycled;
   1895 
   1896     SkIRect iBounds;
   1897     if (!mainCanvas->getClipDeviceBounds(&iBounds)) {
   1898         return false;
   1899     }
   1900 
   1901     SkRect clipBounds = SkRect::Make(iBounds);
   1902 
   1903     SkMatrix initialMatrix = mainCanvas->getTotalMatrix();
   1904 
   1905     GrLayerHoister::Begin(fContext);
   1906 
   1907     GrLayerHoister::FindLayersToAtlas(fContext, mainPicture,
   1908                                       initialMatrix,
   1909                                       clipBounds,
   1910                                       &atlasedNeedRendering, &atlasedRecycled,
   1911                                       fRenderTarget->numColorSamples());
   1912 
   1913     GrLayerHoister::DrawLayersToAtlas(fContext, atlasedNeedRendering);
   1914 
   1915     SkTDArray<GrHoistedLayer> needRendering, recycled;
   1916 
   1917     SkAutoCanvasMatrixPaint acmp(mainCanvas, matrix, paint, mainPicture->cullRect());
   1918 
   1919     GrLayerHoister::FindLayersToHoist(fContext, mainPicture,
   1920                                       initialMatrix,
   1921                                       clipBounds,
   1922                                       &needRendering, &recycled,
   1923                                       fRenderTarget->numColorSamples());
   1924 
   1925     GrLayerHoister::DrawLayers(fContext, needRendering);
   1926 
   1927     // Render the entire picture using new layers
   1928     GrRecordReplaceDraw(mainPicture, mainCanvas, fContext->getLayerCache(),
   1929                         initialMatrix, nullptr);
   1930 
   1931     GrLayerHoister::UnlockLayers(fContext, needRendering);
   1932     GrLayerHoister::UnlockLayers(fContext, recycled);
   1933     GrLayerHoister::UnlockLayers(fContext, atlasedNeedRendering);
   1934     GrLayerHoister::UnlockLayers(fContext, atlasedRecycled);
   1935     GrLayerHoister::End(fContext);
   1936 
   1937     return true;
   1938 #else
   1939     return false;
   1940 #endif
   1941 }
   1942 
   1943 SkImageFilter::Cache* SkGpuDevice::NewImageFilterCache() {
   1944     return SkImageFilter::Cache::Create(kDefaultImageFilterCacheSize);
   1945 }
   1946 
   1947 SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() {
   1948     ASSERT_SINGLE_OWNER
   1949     // We always return a transient cache, so it is freed after each
   1950     // filter traversal.
   1951     return SkGpuDevice::NewImageFilterCache();
   1952 }
   1953 
   1954 #endif
   1955