Home | History | Annotate | Download | only in utils
      1 
      2 /*
      3  * Copyright 2013 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "SkDeferredCanvas.h"
     10 
     11 #include "SkChunkAlloc.h"
     12 #include "SkColorFilter.h"
     13 #include "SkDevice.h"
     14 #include "SkDrawFilter.h"
     15 #include "SkGPipe.h"
     16 #include "SkPaint.h"
     17 #include "SkPaintPriv.h"
     18 #include "SkRRect.h"
     19 #include "SkShader.h"
     20 #include "SkSurface.h"
     21 
     22 enum {
     23     // Deferred canvas will auto-flush when recording reaches this limit
     24     kDefaultMaxRecordingStorageBytes = 64*1024*1024,
     25     kDeferredCanvasBitmapSizeThreshold = ~0U, // Disables this feature
     26 };
     27 
     28 enum PlaybackMode {
     29     kNormal_PlaybackMode,
     30     kSilent_PlaybackMode,
     31 };
     32 
     33 namespace {
     34 bool shouldDrawImmediately(const SkBitmap* bitmap, const SkPaint* paint,
     35                            size_t bitmapSizeThreshold) {
     36     if (bitmap && ((bitmap->getTexture() && !bitmap->isImmutable()) ||
     37         (bitmap->getSize() > bitmapSizeThreshold))) {
     38         return true;
     39     }
     40     if (paint) {
     41         SkShader* shader = paint->getShader();
     42         // Here we detect the case where the shader is an SkBitmapProcShader
     43         // with a gpu texture attached.  Checking this without RTTI
     44         // requires making the assumption that only gradient shaders
     45         // and SkBitmapProcShader implement asABitmap().  The following
     46         // code may need to be revised if that assumption is ever broken.
     47         if (shader && !shader->asAGradient(NULL)) {
     48             SkBitmap bm;
     49             if (shader->asABitmap(&bm, NULL, NULL) &&
     50                 NULL != bm.getTexture()) {
     51                 return true;
     52             }
     53         }
     54     }
     55     return false;
     56 }
     57 }
     58 
     59 //-----------------------------------------------------------------------------
     60 // DeferredPipeController
     61 //-----------------------------------------------------------------------------
     62 
     63 class DeferredPipeController : public SkGPipeController {
     64 public:
     65     DeferredPipeController();
     66     void setPlaybackCanvas(SkCanvas*);
     67     virtual ~DeferredPipeController();
     68     virtual void* requestBlock(size_t minRequest, size_t* actual) SK_OVERRIDE;
     69     virtual void notifyWritten(size_t bytes) SK_OVERRIDE;
     70     void playback(bool silent);
     71     bool hasPendingCommands() const { return fAllocator.blockCount() != 0; }
     72     size_t storageAllocatedForRecording() const { return fAllocator.totalCapacity(); }
     73 private:
     74     enum {
     75         kMinBlockSize = 4096
     76     };
     77     struct PipeBlock {
     78         PipeBlock(void* block, size_t size) { fBlock = block, fSize = size; }
     79         void* fBlock;
     80         size_t fSize;
     81     };
     82     void* fBlock;
     83     size_t fBytesWritten;
     84     SkChunkAlloc fAllocator;
     85     SkTDArray<PipeBlock> fBlockList;
     86     SkGPipeReader fReader;
     87 };
     88 
     89 DeferredPipeController::DeferredPipeController() :
     90     fAllocator(kMinBlockSize) {
     91     fBlock = NULL;
     92     fBytesWritten = 0;
     93 }
     94 
     95 DeferredPipeController::~DeferredPipeController() {
     96     fAllocator.reset();
     97 }
     98 
     99 void DeferredPipeController::setPlaybackCanvas(SkCanvas* canvas) {
    100     fReader.setCanvas(canvas);
    101 }
    102 
    103 void* DeferredPipeController::requestBlock(size_t minRequest, size_t *actual) {
    104     if (fBlock) {
    105         // Save the previous block for later
    106         PipeBlock previousBloc(fBlock, fBytesWritten);
    107         fBlockList.push(previousBloc);
    108     }
    109     int32_t blockSize = SkMax32(minRequest, kMinBlockSize);
    110     fBlock = fAllocator.allocThrow(blockSize);
    111     fBytesWritten = 0;
    112     *actual = blockSize;
    113     return fBlock;
    114 }
    115 
    116 void DeferredPipeController::notifyWritten(size_t bytes) {
    117     fBytesWritten += bytes;
    118 }
    119 
    120 void DeferredPipeController::playback(bool silent) {
    121     uint32_t flags = silent ? SkGPipeReader::kSilent_PlaybackFlag : 0;
    122     for (int currentBlock = 0; currentBlock < fBlockList.count(); currentBlock++ ) {
    123         fReader.playback(fBlockList[currentBlock].fBlock, fBlockList[currentBlock].fSize,
    124                          flags);
    125     }
    126     fBlockList.reset();
    127 
    128     if (fBlock) {
    129         fReader.playback(fBlock, fBytesWritten, flags);
    130         fBlock = NULL;
    131     }
    132 
    133     // Release all allocated blocks
    134     fAllocator.reset();
    135 }
    136 
    137 //-----------------------------------------------------------------------------
    138 // DeferredDevice
    139 //-----------------------------------------------------------------------------
    140 // FIXME: Derive from SkBaseDevice.
    141 class DeferredDevice : public SkDevice {
    142 public:
    143     explicit DeferredDevice(SkDevice* immediateDevice);
    144     explicit DeferredDevice(SkSurface* surface);
    145     ~DeferredDevice();
    146 
    147     void setNotificationClient(SkDeferredCanvas::NotificationClient* notificationClient);
    148     SkCanvas* recordingCanvas();
    149     SkCanvas* immediateCanvas() const {return fImmediateCanvas;}
    150     SkDevice* immediateDevice() const {return fImmediateCanvas->getTopDevice();}
    151     SkImage* newImageSnapshot();
    152     void setSurface(SkSurface* surface);
    153     bool isFreshFrame();
    154     bool hasPendingCommands();
    155     size_t storageAllocatedForRecording() const;
    156     size_t freeMemoryIfPossible(size_t bytesToFree);
    157     size_t getBitmapSizeThreshold() const;
    158     void setBitmapSizeThreshold(size_t sizeThreshold);
    159     void flushPendingCommands(PlaybackMode);
    160     void skipPendingCommands();
    161     void setMaxRecordingStorage(size_t);
    162     void recordedDrawCommand();
    163 
    164     virtual uint32_t getDeviceCapabilities() SK_OVERRIDE;
    165     virtual int width() const SK_OVERRIDE;
    166     virtual int height() const SK_OVERRIDE;
    167     virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE;
    168 
    169     virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
    170                                                int width, int height,
    171                                                bool isOpaque,
    172                                                Usage usage) SK_OVERRIDE;
    173 
    174     virtual void writePixels(const SkBitmap& bitmap, int x, int y,
    175                                 SkCanvas::Config8888 config8888) SK_OVERRIDE;
    176 
    177 protected:
    178     virtual const SkBitmap& onAccessBitmap(SkBitmap*) SK_OVERRIDE;
    179     virtual bool onReadPixels(const SkBitmap& bitmap,
    180                                 int x, int y,
    181                                 SkCanvas::Config8888 config8888) SK_OVERRIDE;
    182 
    183     // The following methods are no-ops on a deferred device
    184     virtual bool filterTextFlags(const SkPaint& paint, TextFlags*)
    185         SK_OVERRIDE
    186         {return false;}
    187 
    188     // None of the following drawing methods should ever get called on the
    189     // deferred device
    190     virtual void clear(SkColor color) SK_OVERRIDE
    191         {SkASSERT(0);}
    192     virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE
    193         {SkASSERT(0);}
    194     virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
    195                             size_t count, const SkPoint[],
    196                             const SkPaint& paint) SK_OVERRIDE
    197         {SkASSERT(0);}
    198     virtual void drawRect(const SkDraw&, const SkRect& r,
    199                             const SkPaint& paint) SK_OVERRIDE
    200         {SkASSERT(0);}
    201     virtual void drawRRect(const SkDraw&, const SkRRect& rr,
    202                            const SkPaint& paint) SK_OVERRIDE
    203         {SkASSERT(0);}
    204     virtual void drawPath(const SkDraw&, const SkPath& path,
    205                             const SkPaint& paint,
    206                             const SkMatrix* prePathMatrix = NULL,
    207                             bool pathIsMutable = false) SK_OVERRIDE
    208         {SkASSERT(0);}
    209     virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
    210                             const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE
    211         {SkASSERT(0);}
    212     virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
    213                             int x, int y, const SkPaint& paint) SK_OVERRIDE
    214         {SkASSERT(0);}
    215     virtual void drawText(const SkDraw&, const void* text, size_t len,
    216                             SkScalar x, SkScalar y, const SkPaint& paint) SK_OVERRIDE
    217         {SkASSERT(0);}
    218     virtual void drawPosText(const SkDraw&, const void* text, size_t len,
    219                                 const SkScalar pos[], SkScalar constY,
    220                                 int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE
    221         {SkASSERT(0);}
    222     virtual void drawTextOnPath(const SkDraw&, const void* text,
    223                                 size_t len, const SkPath& path,
    224                                 const SkMatrix* matrix,
    225                                 const SkPaint& paint) SK_OVERRIDE
    226         {SkASSERT(0);}
    227 #ifdef SK_BUILD_FOR_ANDROID
    228     virtual void drawPosTextOnPath(const SkDraw& draw, const void* text,
    229                                     size_t len, const SkPoint pos[],
    230                                     const SkPaint& paint,
    231                                     const SkPath& path,
    232                                     const SkMatrix* matrix) SK_OVERRIDE
    233         {SkASSERT(0);}
    234 #endif
    235     virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode,
    236                                 int vertexCount, const SkPoint verts[],
    237                                 const SkPoint texs[], const SkColor colors[],
    238                                 SkXfermode* xmode, const uint16_t indices[],
    239                                 int indexCount, const SkPaint& paint) SK_OVERRIDE
    240         {SkASSERT(0);}
    241     virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
    242                             const SkPaint&) SK_OVERRIDE
    243         {SkASSERT(0);}
    244 private:
    245     virtual void flush() SK_OVERRIDE;
    246 
    247     void beginRecording();
    248     void init();
    249     void aboutToDraw();
    250     void prepareForImmediatePixelWrite();
    251 
    252     DeferredPipeController fPipeController;
    253     SkGPipeWriter  fPipeWriter;
    254     SkCanvas* fImmediateCanvas;
    255     SkCanvas* fRecordingCanvas;
    256     SkSurface* fSurface;
    257     SkDeferredCanvas::NotificationClient* fNotificationClient;
    258     bool fFreshFrame;
    259     bool fCanDiscardCanvasContents;
    260     size_t fMaxRecordingStorageBytes;
    261     size_t fPreviousStorageAllocated;
    262     size_t fBitmapSizeThreshold;
    263 };
    264 
    265 DeferredDevice::DeferredDevice(SkDevice* immediateDevice)
    266     : SkDevice(SkBitmap::kNo_Config,
    267                immediateDevice->width(), immediateDevice->height(),
    268                immediateDevice->isOpaque(),
    269                immediateDevice->getDeviceProperties()) {
    270     fSurface = NULL;
    271     fImmediateCanvas = SkNEW_ARGS(SkCanvas, (immediateDevice));
    272     fPipeController.setPlaybackCanvas(fImmediateCanvas);
    273     this->init();
    274 }
    275 
    276 DeferredDevice::DeferredDevice(SkSurface* surface)
    277     : SkDevice(SkBitmap::kNo_Config,
    278                surface->getCanvas()->getDevice()->width(),
    279                surface->getCanvas()->getDevice()->height(),
    280                surface->getCanvas()->getDevice()->isOpaque(),
    281                surface->getCanvas()->getDevice()->getDeviceProperties()) {
    282     fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes;
    283     fNotificationClient = NULL;
    284     fImmediateCanvas = NULL;
    285     fSurface = NULL;
    286     this->setSurface(surface);
    287     this->init();
    288 }
    289 
    290 void DeferredDevice::setSurface(SkSurface* surface) {
    291     SkRefCnt_SafeAssign(fImmediateCanvas, surface->getCanvas());
    292     SkRefCnt_SafeAssign(fSurface, surface);
    293     fPipeController.setPlaybackCanvas(fImmediateCanvas);
    294 }
    295 
    296 void DeferredDevice::init() {
    297     fRecordingCanvas = NULL;
    298     fFreshFrame = true;
    299     fCanDiscardCanvasContents = false;
    300     fPreviousStorageAllocated = 0;
    301     fBitmapSizeThreshold = kDeferredCanvasBitmapSizeThreshold;
    302     fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes;
    303     fNotificationClient = NULL;
    304     this->beginRecording();
    305 }
    306 
    307 DeferredDevice::~DeferredDevice() {
    308     this->flushPendingCommands(kSilent_PlaybackMode);
    309     SkSafeUnref(fImmediateCanvas);
    310     SkSafeUnref(fSurface);
    311 }
    312 
    313 void DeferredDevice::setMaxRecordingStorage(size_t maxStorage) {
    314     fMaxRecordingStorageBytes = maxStorage;
    315     this->recordingCanvas(); // Accessing the recording canvas applies the new limit.
    316 }
    317 
    318 void DeferredDevice::beginRecording() {
    319     SkASSERT(NULL == fRecordingCanvas);
    320     fRecordingCanvas = fPipeWriter.startRecording(&fPipeController, 0,
    321         immediateDevice()->width(), immediateDevice()->height());
    322 }
    323 
    324 void DeferredDevice::setNotificationClient(
    325     SkDeferredCanvas::NotificationClient* notificationClient) {
    326     fNotificationClient = notificationClient;
    327 }
    328 
    329 void DeferredDevice::skipPendingCommands() {
    330     if (!fRecordingCanvas->isDrawingToLayer()) {
    331         fCanDiscardCanvasContents = true;
    332         if (fPipeController.hasPendingCommands()) {
    333             fFreshFrame = true;
    334             flushPendingCommands(kSilent_PlaybackMode);
    335             if (fNotificationClient) {
    336                 fNotificationClient->skippedPendingDrawCommands();
    337             }
    338         }
    339     }
    340 }
    341 
    342 bool DeferredDevice::isFreshFrame() {
    343     bool ret = fFreshFrame;
    344     fFreshFrame = false;
    345     return ret;
    346 }
    347 
    348 bool DeferredDevice::hasPendingCommands() {
    349     return fPipeController.hasPendingCommands();
    350 }
    351 
    352 void DeferredDevice::aboutToDraw()
    353 {
    354     if (NULL != fNotificationClient) {
    355         fNotificationClient->prepareForDraw();
    356     }
    357     if (fCanDiscardCanvasContents) {
    358         if (NULL != fSurface) {
    359             fSurface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
    360         }
    361         fCanDiscardCanvasContents = false;
    362     }
    363 }
    364 
    365 void DeferredDevice::flushPendingCommands(PlaybackMode playbackMode) {
    366     if (!fPipeController.hasPendingCommands()) {
    367         return;
    368     }
    369     if (playbackMode == kNormal_PlaybackMode) {
    370         aboutToDraw();
    371     }
    372     fPipeWriter.flushRecording(true);
    373     fPipeController.playback(kSilent_PlaybackMode == playbackMode);
    374     if (playbackMode == kNormal_PlaybackMode && fNotificationClient) {
    375         fNotificationClient->flushedDrawCommands();
    376     }
    377     fPreviousStorageAllocated = storageAllocatedForRecording();
    378 }
    379 
    380 void DeferredDevice::flush() {
    381     this->flushPendingCommands(kNormal_PlaybackMode);
    382     fImmediateCanvas->flush();
    383 }
    384 
    385 size_t DeferredDevice::freeMemoryIfPossible(size_t bytesToFree) {
    386     size_t val = fPipeWriter.freeMemoryIfPossible(bytesToFree);
    387     fPreviousStorageAllocated = storageAllocatedForRecording();
    388     return val;
    389 }
    390 
    391 size_t DeferredDevice::getBitmapSizeThreshold() const {
    392     return fBitmapSizeThreshold;
    393 }
    394 
    395 void DeferredDevice::setBitmapSizeThreshold(size_t sizeThreshold) {
    396     fBitmapSizeThreshold = sizeThreshold;
    397 }
    398 
    399 size_t DeferredDevice::storageAllocatedForRecording() const {
    400     return (fPipeController.storageAllocatedForRecording()
    401             + fPipeWriter.storageAllocatedForRecording());
    402 }
    403 
    404 void DeferredDevice::recordedDrawCommand() {
    405     size_t storageAllocated = this->storageAllocatedForRecording();
    406 
    407     if (storageAllocated > fMaxRecordingStorageBytes) {
    408         // First, attempt to reduce cache without flushing
    409         size_t tryFree = storageAllocated - fMaxRecordingStorageBytes;
    410         if (this->freeMemoryIfPossible(tryFree) < tryFree) {
    411             // Flush is necessary to free more space.
    412             this->flushPendingCommands(kNormal_PlaybackMode);
    413             // Free as much as possible to avoid oscillating around fMaxRecordingStorageBytes
    414             // which could cause a high flushing frequency.
    415             this->freeMemoryIfPossible(~0U);
    416         }
    417         storageAllocated = this->storageAllocatedForRecording();
    418     }
    419 
    420     if (fNotificationClient &&
    421         storageAllocated != fPreviousStorageAllocated) {
    422         fPreviousStorageAllocated = storageAllocated;
    423         fNotificationClient->storageAllocatedForRecordingChanged(storageAllocated);
    424     }
    425 }
    426 
    427 SkCanvas* DeferredDevice::recordingCanvas() {
    428     return fRecordingCanvas;
    429 }
    430 
    431 SkImage* DeferredDevice::newImageSnapshot() {
    432     this->flush();
    433     return fSurface ? fSurface->newImageSnapshot() : NULL;
    434 }
    435 
    436 uint32_t DeferredDevice::getDeviceCapabilities() {
    437     return immediateDevice()->getDeviceCapabilities();
    438 }
    439 
    440 int DeferredDevice::width() const {
    441     return immediateDevice()->width();
    442 }
    443 
    444 int DeferredDevice::height() const {
    445     return immediateDevice()->height();
    446 }
    447 
    448 GrRenderTarget* DeferredDevice::accessRenderTarget() {
    449     this->flushPendingCommands(kNormal_PlaybackMode);
    450     return immediateDevice()->accessRenderTarget();
    451 }
    452 
    453 void DeferredDevice::prepareForImmediatePixelWrite() {
    454     // The purpose of the following code is to make sure commands are flushed, that
    455     // aboutToDraw() is called and that notifyContentWillChange is called, without
    456     // calling anything redundantly.
    457     if (fPipeController.hasPendingCommands()) {
    458         this->flushPendingCommands(kNormal_PlaybackMode);
    459     } else {
    460         bool mustNotifyDirectly = !fCanDiscardCanvasContents;
    461         this->aboutToDraw();
    462         if (mustNotifyDirectly) {
    463             fSurface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode);
    464         }
    465     }
    466 
    467     fImmediateCanvas->flush();
    468 }
    469 
    470 void DeferredDevice::writePixels(const SkBitmap& bitmap,
    471     int x, int y, SkCanvas::Config8888 config8888) {
    472 
    473     if (x <= 0 && y <= 0 && (x + bitmap.width()) >= width() &&
    474         (y + bitmap.height()) >= height()) {
    475         this->skipPendingCommands();
    476     }
    477 
    478     if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
    479         SkCanvas::kNative_Premul_Config8888 != config8888 &&
    480         kPMColorAlias != config8888) {
    481         //Special case config: no deferral
    482         prepareForImmediatePixelWrite();
    483         immediateDevice()->writePixels(bitmap, x, y, config8888);
    484         return;
    485     }
    486 
    487     SkPaint paint;
    488     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
    489     if (shouldDrawImmediately(&bitmap, NULL, getBitmapSizeThreshold())) {
    490         prepareForImmediatePixelWrite();
    491         fImmediateCanvas->drawSprite(bitmap, x, y, &paint);
    492     } else {
    493         this->recordingCanvas()->drawSprite(bitmap, x, y, &paint);
    494         this->recordedDrawCommand();
    495 
    496     }
    497 }
    498 
    499 const SkBitmap& DeferredDevice::onAccessBitmap(SkBitmap*) {
    500     this->flushPendingCommands(kNormal_PlaybackMode);
    501     return immediateDevice()->accessBitmap(false);
    502 }
    503 
    504 SkDevice* DeferredDevice::onCreateCompatibleDevice(
    505     SkBitmap::Config config, int width, int height, bool isOpaque,
    506     Usage usage) {
    507 
    508     // Save layer usage not supported, and not required by SkDeferredCanvas.
    509     SkASSERT(usage != kSaveLayer_Usage);
    510     // Create a compatible non-deferred device.
    511     // We do not create a deferred device because we know the new device
    512     // will not be used with a deferred canvas (there is no API for that).
    513     // And connecting a DeferredDevice to non-deferred canvas can result
    514     // in unpredictable behavior.
    515     return immediateDevice()->createCompatibleDevice(config, width, height, isOpaque);
    516 }
    517 
    518 bool DeferredDevice::onReadPixels(
    519     const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) {
    520     this->flushPendingCommands(kNormal_PlaybackMode);
    521     return fImmediateCanvas->readPixels(const_cast<SkBitmap*>(&bitmap),
    522                                                    x, y, config8888);
    523 }
    524 
    525 class AutoImmediateDrawIfNeeded {
    526 public:
    527     AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkBitmap* bitmap,
    528                               const SkPaint* paint) {
    529         this->init(canvas, bitmap, paint);
    530     }
    531 
    532     AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkPaint* paint) {
    533         this->init(canvas, NULL, paint);
    534     }
    535 
    536     ~AutoImmediateDrawIfNeeded() {
    537         if (fCanvas) {
    538             fCanvas->setDeferredDrawing(true);
    539         }
    540     }
    541 private:
    542     void init(SkDeferredCanvas& canvas, const SkBitmap* bitmap, const SkPaint* paint)
    543     {
    544         DeferredDevice* device = static_cast<DeferredDevice*>(canvas.getDevice());
    545         if (canvas.isDeferredDrawing() && (NULL != device) &&
    546             shouldDrawImmediately(bitmap, paint, device->getBitmapSizeThreshold())) {
    547             canvas.setDeferredDrawing(false);
    548             fCanvas = &canvas;
    549         } else {
    550             fCanvas = NULL;
    551         }
    552     }
    553 
    554     SkDeferredCanvas* fCanvas;
    555 };
    556 
    557 SkDeferredCanvas* SkDeferredCanvas::Create(SkSurface* surface) {
    558     SkAutoTUnref<DeferredDevice> deferredDevice(SkNEW_ARGS(DeferredDevice, (surface)));
    559     return SkNEW_ARGS(SkDeferredCanvas, (deferredDevice));
    560 }
    561 
    562 SkDeferredCanvas* SkDeferredCanvas::Create(SkDevice* device) {
    563     SkAutoTUnref<DeferredDevice> deferredDevice(SkNEW_ARGS(DeferredDevice, (device)));
    564     return SkNEW_ARGS(SkDeferredCanvas, (deferredDevice));
    565 }
    566 
    567 SkDeferredCanvas::SkDeferredCanvas(DeferredDevice* device) : SkCanvas (device) {
    568     this->init();
    569 }
    570 
    571 void SkDeferredCanvas::init() {
    572     fDeferredDrawing = true; // On by default
    573 }
    574 
    575 void SkDeferredCanvas::setMaxRecordingStorage(size_t maxStorage) {
    576     this->validate();
    577     this->getDeferredDevice()->setMaxRecordingStorage(maxStorage);
    578 }
    579 
    580 size_t SkDeferredCanvas::storageAllocatedForRecording() const {
    581     return this->getDeferredDevice()->storageAllocatedForRecording();
    582 }
    583 
    584 size_t SkDeferredCanvas::freeMemoryIfPossible(size_t bytesToFree) {
    585     return this->getDeferredDevice()->freeMemoryIfPossible(bytesToFree);
    586 }
    587 
    588 void SkDeferredCanvas::setBitmapSizeThreshold(size_t sizeThreshold) {
    589     DeferredDevice* deferredDevice = this->getDeferredDevice();
    590     SkASSERT(deferredDevice);
    591     deferredDevice->setBitmapSizeThreshold(sizeThreshold);
    592 }
    593 
    594 void SkDeferredCanvas::recordedDrawCommand() {
    595     if (fDeferredDrawing) {
    596         this->getDeferredDevice()->recordedDrawCommand();
    597     }
    598 }
    599 
    600 void SkDeferredCanvas::validate() const {
    601     SkASSERT(this->getDevice());
    602 }
    603 
    604 SkCanvas* SkDeferredCanvas::drawingCanvas() const {
    605     this->validate();
    606     return fDeferredDrawing ? this->getDeferredDevice()->recordingCanvas() :
    607         this->getDeferredDevice()->immediateCanvas();
    608 }
    609 
    610 SkCanvas* SkDeferredCanvas::immediateCanvas() const {
    611     this->validate();
    612     return this->getDeferredDevice()->immediateCanvas();
    613 }
    614 
    615 DeferredDevice* SkDeferredCanvas::getDeferredDevice() const {
    616     return static_cast<DeferredDevice*>(this->getDevice());
    617 }
    618 
    619 void SkDeferredCanvas::setDeferredDrawing(bool val) {
    620     this->validate(); // Must set device before calling this method
    621     if (val != fDeferredDrawing) {
    622         if (fDeferredDrawing) {
    623             // Going live.
    624             this->getDeferredDevice()->flushPendingCommands(kNormal_PlaybackMode);
    625         }
    626         fDeferredDrawing = val;
    627     }
    628 }
    629 
    630 bool SkDeferredCanvas::isDeferredDrawing() const {
    631     return fDeferredDrawing;
    632 }
    633 
    634 bool SkDeferredCanvas::isFreshFrame() const {
    635     return this->getDeferredDevice()->isFreshFrame();
    636 }
    637 
    638 bool SkDeferredCanvas::hasPendingCommands() const {
    639     return this->getDeferredDevice()->hasPendingCommands();
    640 }
    641 
    642 void SkDeferredCanvas::silentFlush() {
    643     if (fDeferredDrawing) {
    644         this->getDeferredDevice()->flushPendingCommands(kSilent_PlaybackMode);
    645     }
    646 }
    647 
    648 SkDeferredCanvas::~SkDeferredCanvas() {
    649 }
    650 
    651 SkSurface* SkDeferredCanvas::setSurface(SkSurface* surface) {
    652     DeferredDevice* deferredDevice = this->getDeferredDevice();
    653     SkASSERT(NULL != deferredDevice);
    654     // By swapping the surface into the existing device, we preserve
    655     // all pending commands, which can help to seamlessly recover from
    656     // a lost accelerated graphics context.
    657     deferredDevice->setSurface(surface);
    658     return surface;
    659 }
    660 
    661 SkDeferredCanvas::NotificationClient* SkDeferredCanvas::setNotificationClient(
    662     NotificationClient* notificationClient) {
    663 
    664     DeferredDevice* deferredDevice = this->getDeferredDevice();
    665     SkASSERT(deferredDevice);
    666     if (deferredDevice) {
    667         deferredDevice->setNotificationClient(notificationClient);
    668     }
    669     return notificationClient;
    670 }
    671 
    672 SkImage* SkDeferredCanvas::newImageSnapshot() {
    673     DeferredDevice* deferredDevice = this->getDeferredDevice();
    674     SkASSERT(deferredDevice);
    675     return deferredDevice ? deferredDevice->newImageSnapshot() : NULL;
    676 }
    677 
    678 bool SkDeferredCanvas::isFullFrame(const SkRect* rect,
    679                                    const SkPaint* paint) const {
    680     SkCanvas* canvas = this->drawingCanvas();
    681     SkISize canvasSize = this->getDeviceSize();
    682     if (rect) {
    683         if (!canvas->getTotalMatrix().rectStaysRect()) {
    684             return false; // conservative
    685         }
    686 
    687         SkRect transformedRect;
    688         canvas->getTotalMatrix().mapRect(&transformedRect, *rect);
    689 
    690         if (paint) {
    691             SkPaint::Style paintStyle = paint->getStyle();
    692             if (!(paintStyle == SkPaint::kFill_Style ||
    693                 paintStyle == SkPaint::kStrokeAndFill_Style)) {
    694                 return false;
    695             }
    696             if (paint->getMaskFilter() || paint->getLooper()
    697                 || paint->getPathEffect() || paint->getImageFilter()) {
    698                 return false; // conservative
    699             }
    700         }
    701 
    702         // The following test holds with AA enabled, and is conservative
    703         // by a 0.5 pixel margin with AA disabled
    704         if (transformedRect.fLeft > SkIntToScalar(0) ||
    705             transformedRect.fTop > SkIntToScalar(0) ||
    706             transformedRect.fRight < SkIntToScalar(canvasSize.fWidth) ||
    707             transformedRect.fBottom < SkIntToScalar(canvasSize.fHeight)) {
    708             return false;
    709         }
    710     }
    711 
    712     return this->getClipStack()->quickContains(SkRect::MakeXYWH(0, 0,
    713         SkIntToScalar(canvasSize.fWidth), SkIntToScalar(canvasSize.fHeight)));
    714 }
    715 
    716 int SkDeferredCanvas::save(SaveFlags flags) {
    717     this->drawingCanvas()->save(flags);
    718     int val = this->INHERITED::save(flags);
    719     this->recordedDrawCommand();
    720 
    721     return val;
    722 }
    723 
    724 int SkDeferredCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
    725                                 SaveFlags flags) {
    726     this->drawingCanvas()->saveLayer(bounds, paint, flags);
    727     int count = this->INHERITED::save(flags);
    728     this->clipRectBounds(bounds, flags, NULL);
    729     this->recordedDrawCommand();
    730 
    731     return count;
    732 }
    733 
    734 void SkDeferredCanvas::restore() {
    735     this->drawingCanvas()->restore();
    736     this->INHERITED::restore();
    737     this->recordedDrawCommand();
    738 }
    739 
    740 bool SkDeferredCanvas::isDrawingToLayer() const {
    741     return this->drawingCanvas()->isDrawingToLayer();
    742 }
    743 
    744 bool SkDeferredCanvas::translate(SkScalar dx, SkScalar dy) {
    745     this->drawingCanvas()->translate(dx, dy);
    746     bool val = this->INHERITED::translate(dx, dy);
    747     this->recordedDrawCommand();
    748     return val;
    749 }
    750 
    751 bool SkDeferredCanvas::scale(SkScalar sx, SkScalar sy) {
    752     this->drawingCanvas()->scale(sx, sy);
    753     bool val = this->INHERITED::scale(sx, sy);
    754     this->recordedDrawCommand();
    755     return val;
    756 }
    757 
    758 bool SkDeferredCanvas::rotate(SkScalar degrees) {
    759     this->drawingCanvas()->rotate(degrees);
    760     bool val = this->INHERITED::rotate(degrees);
    761     this->recordedDrawCommand();
    762     return val;
    763 }
    764 
    765 bool SkDeferredCanvas::skew(SkScalar sx, SkScalar sy) {
    766     this->drawingCanvas()->skew(sx, sy);
    767     bool val = this->INHERITED::skew(sx, sy);
    768     this->recordedDrawCommand();
    769     return val;
    770 }
    771 
    772 bool SkDeferredCanvas::concat(const SkMatrix& matrix) {
    773     this->drawingCanvas()->concat(matrix);
    774     bool val = this->INHERITED::concat(matrix);
    775     this->recordedDrawCommand();
    776     return val;
    777 }
    778 
    779 void SkDeferredCanvas::setMatrix(const SkMatrix& matrix) {
    780     this->drawingCanvas()->setMatrix(matrix);
    781     this->INHERITED::setMatrix(matrix);
    782     this->recordedDrawCommand();
    783 }
    784 
    785 bool SkDeferredCanvas::clipRect(const SkRect& rect,
    786                                 SkRegion::Op op,
    787                                 bool doAntiAlias) {
    788     this->drawingCanvas()->clipRect(rect, op, doAntiAlias);
    789     bool val = this->INHERITED::clipRect(rect, op, doAntiAlias);
    790     this->recordedDrawCommand();
    791     return val;
    792 }
    793 
    794 bool SkDeferredCanvas::clipRRect(const SkRRect& rrect,
    795                                  SkRegion::Op op,
    796                                  bool doAntiAlias) {
    797     this->drawingCanvas()->clipRRect(rrect, op, doAntiAlias);
    798     bool val = this->INHERITED::clipRRect(rrect, op, doAntiAlias);
    799     this->recordedDrawCommand();
    800     return val;
    801 }
    802 
    803 bool SkDeferredCanvas::clipPath(const SkPath& path,
    804                                 SkRegion::Op op,
    805                                 bool doAntiAlias) {
    806     this->drawingCanvas()->clipPath(path, op, doAntiAlias);
    807     bool val = this->INHERITED::clipPath(path, op, doAntiAlias);
    808     this->recordedDrawCommand();
    809     return val;
    810 }
    811 
    812 bool SkDeferredCanvas::clipRegion(const SkRegion& deviceRgn,
    813                                   SkRegion::Op op) {
    814     this->drawingCanvas()->clipRegion(deviceRgn, op);
    815     bool val = this->INHERITED::clipRegion(deviceRgn, op);
    816     this->recordedDrawCommand();
    817     return val;
    818 }
    819 
    820 void SkDeferredCanvas::clear(SkColor color) {
    821     // purge pending commands
    822     if (fDeferredDrawing) {
    823         this->getDeferredDevice()->skipPendingCommands();
    824     }
    825 
    826     this->drawingCanvas()->clear(color);
    827     this->recordedDrawCommand();
    828 }
    829 
    830 void SkDeferredCanvas::drawPaint(const SkPaint& paint) {
    831     if (fDeferredDrawing && this->isFullFrame(NULL, &paint) &&
    832         isPaintOpaque(&paint)) {
    833         this->getDeferredDevice()->skipPendingCommands();
    834     }
    835     AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
    836     this->drawingCanvas()->drawPaint(paint);
    837     this->recordedDrawCommand();
    838 }
    839 
    840 void SkDeferredCanvas::drawPoints(PointMode mode, size_t count,
    841                                   const SkPoint pts[], const SkPaint& paint) {
    842     AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
    843     this->drawingCanvas()->drawPoints(mode, count, pts, paint);
    844     this->recordedDrawCommand();
    845 }
    846 
    847 void SkDeferredCanvas::drawOval(const SkRect& rect, const SkPaint& paint) {
    848     AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
    849     this->drawingCanvas()->drawOval(rect, paint);
    850     this->recordedDrawCommand();
    851 }
    852 
    853 void SkDeferredCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
    854     if (fDeferredDrawing && this->isFullFrame(&rect, &paint) &&
    855         isPaintOpaque(&paint)) {
    856         this->getDeferredDevice()->skipPendingCommands();
    857     }
    858 
    859     AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
    860     this->drawingCanvas()->drawRect(rect, paint);
    861     this->recordedDrawCommand();
    862 }
    863 
    864 void SkDeferredCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
    865     if (rrect.isRect()) {
    866         this->SkDeferredCanvas::drawRect(rrect.getBounds(), paint);
    867     } else if (rrect.isOval()) {
    868         this->SkDeferredCanvas::drawOval(rrect.getBounds(), paint);
    869     } else {
    870         AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
    871         this->drawingCanvas()->drawRRect(rrect, paint);
    872         this->recordedDrawCommand();
    873     }
    874 }
    875 
    876 void SkDeferredCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
    877     AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
    878     this->drawingCanvas()->drawPath(path, paint);
    879     this->recordedDrawCommand();
    880 }
    881 
    882 void SkDeferredCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left,
    883                                   SkScalar top, const SkPaint* paint) {
    884     SkRect bitmapRect = SkRect::MakeXYWH(left, top,
    885         SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
    886     if (fDeferredDrawing &&
    887         this->isFullFrame(&bitmapRect, paint) &&
    888         isPaintOpaque(paint, &bitmap)) {
    889         this->getDeferredDevice()->skipPendingCommands();
    890     }
    891 
    892     AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
    893     this->drawingCanvas()->drawBitmap(bitmap, left, top, paint);
    894     this->recordedDrawCommand();
    895 }
    896 
    897 void SkDeferredCanvas::drawBitmapRectToRect(const SkBitmap& bitmap,
    898                                             const SkRect* src,
    899                                             const SkRect& dst,
    900                                             const SkPaint* paint) {
    901     if (fDeferredDrawing &&
    902         this->isFullFrame(&dst, paint) &&
    903         isPaintOpaque(paint, &bitmap)) {
    904         this->getDeferredDevice()->skipPendingCommands();
    905     }
    906 
    907     AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
    908     this->drawingCanvas()->drawBitmapRectToRect(bitmap, src, dst, paint);
    909     this->recordedDrawCommand();
    910 }
    911 
    912 
    913 void SkDeferredCanvas::drawBitmapMatrix(const SkBitmap& bitmap,
    914                                         const SkMatrix& m,
    915                                         const SkPaint* paint) {
    916     // TODO: reset recording canvas if paint+bitmap is opaque and clip rect
    917     // covers canvas entirely and transformed bitmap covers canvas entirely
    918     AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
    919     this->drawingCanvas()->drawBitmapMatrix(bitmap, m, paint);
    920     this->recordedDrawCommand();
    921 }
    922 
    923 void SkDeferredCanvas::drawBitmapNine(const SkBitmap& bitmap,
    924                                       const SkIRect& center, const SkRect& dst,
    925                                       const SkPaint* paint) {
    926     // TODO: reset recording canvas if paint+bitmap is opaque and clip rect
    927     // covers canvas entirely and dst covers canvas entirely
    928     AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
    929     this->drawingCanvas()->drawBitmapNine(bitmap, center, dst, paint);
    930     this->recordedDrawCommand();
    931 }
    932 
    933 void SkDeferredCanvas::drawSprite(const SkBitmap& bitmap, int left, int top,
    934                                   const SkPaint* paint) {
    935     SkRect bitmapRect = SkRect::MakeXYWH(
    936         SkIntToScalar(left),
    937         SkIntToScalar(top),
    938         SkIntToScalar(bitmap.width()),
    939         SkIntToScalar(bitmap.height()));
    940     if (fDeferredDrawing &&
    941         this->isFullFrame(&bitmapRect, paint) &&
    942         isPaintOpaque(paint, &bitmap)) {
    943         this->getDeferredDevice()->skipPendingCommands();
    944     }
    945 
    946     AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
    947     this->drawingCanvas()->drawSprite(bitmap, left, top, paint);
    948     this->recordedDrawCommand();
    949 }
    950 
    951 void SkDeferredCanvas::drawText(const void* text, size_t byteLength,
    952                                 SkScalar x, SkScalar y, const SkPaint& paint) {
    953     AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
    954     this->drawingCanvas()->drawText(text, byteLength, x, y, paint);
    955     this->recordedDrawCommand();
    956 }
    957 
    958 void SkDeferredCanvas::drawPosText(const void* text, size_t byteLength,
    959                                    const SkPoint pos[], const SkPaint& paint) {
    960     AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
    961     this->drawingCanvas()->drawPosText(text, byteLength, pos, paint);
    962     this->recordedDrawCommand();
    963 }
    964 
    965 void SkDeferredCanvas::drawPosTextH(const void* text, size_t byteLength,
    966                                     const SkScalar xpos[], SkScalar constY,
    967                                     const SkPaint& paint) {
    968     AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
    969     this->drawingCanvas()->drawPosTextH(text, byteLength, xpos, constY, paint);
    970     this->recordedDrawCommand();
    971 }
    972 
    973 void SkDeferredCanvas::drawTextOnPath(const void* text, size_t byteLength,
    974                                       const SkPath& path,
    975                                       const SkMatrix* matrix,
    976                                       const SkPaint& paint) {
    977     AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
    978     this->drawingCanvas()->drawTextOnPath(text, byteLength, path, matrix, paint);
    979     this->recordedDrawCommand();
    980 }
    981 
    982 void SkDeferredCanvas::drawPicture(SkPicture& picture) {
    983     this->drawingCanvas()->drawPicture(picture);
    984     this->recordedDrawCommand();
    985 }
    986 
    987 void SkDeferredCanvas::drawVertices(VertexMode vmode, int vertexCount,
    988                                     const SkPoint vertices[],
    989                                     const SkPoint texs[],
    990                                     const SkColor colors[], SkXfermode* xmode,
    991                                     const uint16_t indices[], int indexCount,
    992                                     const SkPaint& paint) {
    993     AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
    994     this->drawingCanvas()->drawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
    995                                         indices, indexCount, paint);
    996     this->recordedDrawCommand();
    997 }
    998 
    999 SkBounder* SkDeferredCanvas::setBounder(SkBounder* bounder) {
   1000     this->drawingCanvas()->setBounder(bounder);
   1001     this->INHERITED::setBounder(bounder);
   1002     this->recordedDrawCommand();
   1003     return bounder;
   1004 }
   1005 
   1006 SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) {
   1007     this->drawingCanvas()->setDrawFilter(filter);
   1008     this->INHERITED::setDrawFilter(filter);
   1009     this->recordedDrawCommand();
   1010     return filter;
   1011 }
   1012 
   1013 SkCanvas* SkDeferredCanvas::canvasForDrawIter() {
   1014     return this->drawingCanvas();
   1015 }
   1016