gfx/skia/trunk/src/utils/SkDeferredCanvas.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial