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