Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "../src/image/SkImagePriv.h"
      9 #include "../src/image/SkSurface_Base.h"
     10 #include "SkBitmap.h"
     11 #include "SkBitmapDevice.h"
     12 #include "SkBitmapProcShader.h"
     13 #include "SkDeferredCanvas.h"
     14 #include "SkGradientShader.h"
     15 #include "SkShader.h"
     16 #include "SkSurface.h"
     17 #include "Test.h"
     18 #include "sk_tool_utils.h"
     19 
     20 #if SK_SUPPORT_GPU
     21 #include "GrContextFactory.h"
     22 #else
     23 class GrContextFactory;
     24 #endif
     25 
     26 static const int gWidth = 2;
     27 static const int gHeight = 2;
     28 
     29 static void create(SkBitmap* bm, SkColor color) {
     30     bm->allocN32Pixels(gWidth, gHeight);
     31     bm->eraseColor(color);
     32 }
     33 
     34 static SkSurface* createSurface(SkColor color) {
     35     SkSurface* surface = SkSurface::NewRasterPMColor(gWidth, gHeight);
     36     surface->getCanvas()->clear(color);
     37     return surface;
     38 }
     39 
     40 static SkPMColor read_pixel(SkSurface* surface, int x, int y) {
     41     SkPMColor pixel = 0;
     42     SkBitmap bitmap;
     43     bitmap.installPixels(SkImageInfo::MakeN32Premul(1, 1), &pixel, 4);
     44     SkCanvas canvas(bitmap);
     45 
     46     SkPaint paint;
     47     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
     48     surface->draw(&canvas, -SkIntToScalar(x), -SkIntToScalar(y), &paint);
     49     return pixel;
     50 }
     51 
     52 class MockSurface : public SkSurface_Base {
     53 public:
     54     MockSurface(int width, int height) : SkSurface_Base(width, height, NULL) {
     55         clearCounts();
     56         fBitmap.allocN32Pixels(width, height);
     57     }
     58 
     59     virtual SkCanvas* onNewCanvas() SK_OVERRIDE {
     60         return SkNEW_ARGS(SkCanvas, (fBitmap));
     61     }
     62 
     63     virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE {
     64         return NULL;
     65     }
     66 
     67     virtual SkImage* onNewImageSnapshot() SK_OVERRIDE {
     68         return SkNewImageFromBitmap(fBitmap, true);
     69     }
     70 
     71     virtual void onCopyOnWrite(ContentChangeMode mode) SK_OVERRIDE {
     72         if (mode == SkSurface::kDiscard_ContentChangeMode) {
     73             fDiscardCount++;
     74         } else {
     75             fRetainCount++;
     76         }
     77     }
     78 
     79     void clearCounts() {
     80         fDiscardCount = 0;
     81         fRetainCount = 0;
     82     }
     83 
     84     int fDiscardCount, fRetainCount;
     85     SkBitmap fBitmap;
     86 };
     87 
     88 static void TestDeferredCanvasWritePixelsToSurface(skiatest::Reporter* reporter) {
     89     SkAutoTUnref<MockSurface> surface(SkNEW_ARGS(MockSurface, (10, 10)));
     90     SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
     91 
     92     SkBitmap srcBitmap;
     93     srcBitmap.allocPixels(SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kUnpremul_SkAlphaType));
     94     srcBitmap.eraseColor(SK_ColorGREEN);
     95     // Tests below depend on this bitmap being recognized as opaque
     96 
     97     // Preliminary sanity check: no copy on write if no active snapshot
     98     surface->clearCounts();
     99     canvas->clear(SK_ColorWHITE);
    100     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    101     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    102 
    103     surface->clearCounts();
    104     canvas->flush();
    105     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    106     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    107 
    108     // Case 1: Discard notification happens upon flushing
    109     // with an Image attached.
    110     surface->clearCounts();
    111     SkAutoTUnref<SkImage> image1(canvas->newImageSnapshot());
    112     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    113     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    114 
    115     surface->clearCounts();
    116     canvas->clear(SK_ColorWHITE);
    117     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    118     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    119 
    120     surface->clearCounts();
    121     canvas->flush();
    122     REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount);
    123     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    124 
    125     // Case 2: Opaque writePixels
    126     surface->clearCounts();
    127     SkAutoTUnref<SkImage> image2(canvas->newImageSnapshot());
    128     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    129     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    130 
    131     // Case 3: writePixels that partially covers the canvas
    132     surface->clearCounts();
    133     SkAutoTUnref<SkImage> image3(canvas->newImageSnapshot());
    134     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    135     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    136 
    137     // Case 4: unpremultiplied opaque writePixels that entirely
    138     // covers the canvas
    139     surface->clearCounts();
    140     SkAutoTUnref<SkImage> image4(canvas->newImageSnapshot());
    141     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    142     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    143 
    144     surface->clearCounts();
    145     canvas->writePixels(srcBitmap, 0, 0);
    146     REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount);
    147     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    148 
    149     surface->clearCounts();
    150     canvas->flush();
    151     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    152     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    153 
    154     // Case 5: unpremultiplied opaque writePixels that partially
    155     // covers the canvas
    156     surface->clearCounts();
    157     SkAutoTUnref<SkImage> image5(canvas->newImageSnapshot());
    158     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    159     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    160 
    161     surface->clearCounts();
    162     canvas->writePixels(srcBitmap, 5, 0);
    163     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    164     REPORTER_ASSERT(reporter, 1 == surface->fRetainCount);
    165 
    166     surface->clearCounts();
    167     canvas->flush();
    168     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    169     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    170 
    171     // Case 6: unpremultiplied opaque writePixels that entirely
    172     // covers the canvas, preceded by clear
    173     surface->clearCounts();
    174     SkAutoTUnref<SkImage> image6(canvas->newImageSnapshot());
    175     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    176     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    177 
    178     surface->clearCounts();
    179     canvas->clear(SK_ColorWHITE);
    180     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    181     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    182 
    183     surface->clearCounts();
    184     canvas->writePixels(srcBitmap, 0, 0);
    185     REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount);
    186     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    187 
    188     surface->clearCounts();
    189     canvas->flush();
    190     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    191     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    192 
    193     // Case 7: unpremultiplied opaque writePixels that partially
    194     // covers the canvas, preceeded by a clear
    195     surface->clearCounts();
    196     SkAutoTUnref<SkImage> image7(canvas->newImageSnapshot());
    197     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    198     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    199 
    200     surface->clearCounts();
    201     canvas->clear(SK_ColorWHITE);
    202     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    203     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    204 
    205     surface->clearCounts();
    206     canvas->writePixels(srcBitmap, 5, 0);
    207     REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount); // because of the clear
    208     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    209 
    210     surface->clearCounts();
    211     canvas->flush();
    212     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    213     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    214 
    215     // Case 8: unpremultiplied opaque writePixels that partially
    216     // covers the canvas, preceeded by a drawREct that partially
    217     // covers the canvas
    218     surface->clearCounts();
    219     SkAutoTUnref<SkImage> image8(canvas->newImageSnapshot());
    220     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    221     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    222 
    223     surface->clearCounts();
    224     SkPaint paint;
    225     canvas->drawRect(SkRect::MakeLTRB(0, 0, 5, 5), paint);
    226     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    227     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    228 
    229     surface->clearCounts();
    230     canvas->writePixels(srcBitmap, 5, 0);
    231     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    232     REPORTER_ASSERT(reporter, 1 == surface->fRetainCount);
    233 
    234     surface->clearCounts();
    235     canvas->flush();
    236     REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
    237     REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
    238 }
    239 
    240 static void TestDeferredCanvasFlush(skiatest::Reporter* reporter) {
    241     SkAutoTUnref<SkSurface> surface(createSurface(0xFFFFFFFF));
    242     SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
    243 
    244     canvas->clear(0x00000000);
    245 
    246     // verify that clear was deferred
    247     REPORTER_ASSERT(reporter, 0xFFFFFFFF == read_pixel(surface, 0, 0));
    248 
    249     canvas->flush();
    250 
    251     // verify that clear was executed
    252     REPORTER_ASSERT(reporter, 0 == read_pixel(surface, 0, 0));
    253 }
    254 
    255 static void TestDeferredCanvasFreshFrame(skiatest::Reporter* reporter) {
    256     SkRect fullRect;
    257     fullRect.setXYWH(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(gWidth),
    258         SkIntToScalar(gHeight));
    259     SkRect partialRect;
    260     partialRect.setXYWH(SkIntToScalar(0), SkIntToScalar(0),
    261         SkIntToScalar(1), SkIntToScalar(1));
    262 
    263     SkAutoTUnref<SkSurface> surface(createSurface(0xFFFFFFFF));
    264     SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
    265 
    266     // verify that frame is intially fresh
    267     REPORTER_ASSERT(reporter, canvas->isFreshFrame());
    268     // no clearing op since last call to isFreshFrame -> not fresh
    269     REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
    270 
    271     // Verify that clear triggers a fresh frame
    272     canvas->clear(0x00000000);
    273     REPORTER_ASSERT(reporter, canvas->isFreshFrame());
    274 
    275     // Verify that clear with saved state triggers a fresh frame
    276     canvas->save();
    277     canvas->clear(0x00000000);
    278     canvas->restore();
    279     REPORTER_ASSERT(reporter, canvas->isFreshFrame());
    280 
    281     // Verify that clear within a layer does NOT trigger a fresh frame
    282     canvas->saveLayer(NULL, NULL);
    283     canvas->clear(0x00000000);
    284     canvas->restore();
    285     REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
    286 
    287     // Verify that a clear with clipping triggers a fresh frame
    288     // (clear is not affected by clipping)
    289     canvas->save();
    290     canvas->clipRect(partialRect, SkRegion::kIntersect_Op, false);
    291     canvas->clear(0x00000000);
    292     canvas->restore();
    293     REPORTER_ASSERT(reporter, canvas->isFreshFrame());
    294 
    295     // Verify that full frame rects with different forms of opaque paint
    296     // trigger frames to be marked as fresh
    297     {
    298         SkPaint paint;
    299         paint.setStyle(SkPaint::kFill_Style);
    300         paint.setAlpha(255);
    301         canvas->drawRect(fullRect, paint);
    302         REPORTER_ASSERT(reporter, canvas->isFreshFrame());
    303     }
    304     {
    305         SkPaint paint;
    306         paint.setStyle(SkPaint::kFill_Style);
    307         paint.setAlpha(255);
    308         paint.setXfermodeMode(SkXfermode::kSrcIn_Mode);
    309         canvas->drawRect(fullRect, paint);
    310         REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
    311     }
    312     {
    313         SkPaint paint;
    314         paint.setStyle(SkPaint::kFill_Style);
    315         SkBitmap bmp;
    316         create(&bmp, 0xFFFFFFFF);
    317         bmp.setAlphaType(kOpaque_SkAlphaType);
    318         SkShader* shader = SkShader::CreateBitmapShader(bmp,
    319             SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
    320         paint.setShader(shader)->unref();
    321         canvas->drawRect(fullRect, paint);
    322         REPORTER_ASSERT(reporter, canvas->isFreshFrame());
    323     }
    324 
    325     // Verify that full frame rects with different forms of non-opaque paint
    326     // do not trigger frames to be marked as fresh
    327     {
    328         SkPaint paint;
    329         paint.setStyle(SkPaint::kFill_Style);
    330         paint.setAlpha(254);
    331         canvas->drawRect(fullRect, paint);
    332         REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
    333     }
    334     {
    335         SkPaint paint;
    336         paint.setStyle(SkPaint::kFill_Style);
    337         // Defining a cone that partially overlaps the canvas
    338         const SkPoint pt1 = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(0));
    339         const SkScalar r1 = SkIntToScalar(1);
    340         const SkPoint pt2 = SkPoint::Make(SkIntToScalar(10), SkIntToScalar(0));
    341         const SkScalar r2 = SkIntToScalar(5);
    342         const SkColor colors[2] = {SK_ColorWHITE, SK_ColorWHITE};
    343         const SkScalar pos[2] = {0, SK_Scalar1};
    344         SkShader* shader = SkGradientShader::CreateTwoPointConical(
    345             pt1, r1, pt2, r2, colors, pos, 2, SkShader::kClamp_TileMode);
    346         paint.setShader(shader)->unref();
    347         canvas->drawRect(fullRect, paint);
    348         REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
    349     }
    350     {
    351         SkPaint paint;
    352         paint.setStyle(SkPaint::kFill_Style);
    353         SkBitmap bmp;
    354         create(&bmp, 0xFFFFFFFF);
    355         bmp.setAlphaType(kPremul_SkAlphaType);
    356         SkShader* shader = SkShader::CreateBitmapShader(bmp,
    357             SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
    358         paint.setShader(shader)->unref();
    359         canvas->drawRect(fullRect, paint);
    360         REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
    361     }
    362 
    363     // Verify that incomplete coverage does not trigger a fresh frame
    364     {
    365         SkPaint paint;
    366         paint.setStyle(SkPaint::kFill_Style);
    367         paint.setAlpha(255);
    368         canvas->drawRect(partialRect, paint);
    369         REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
    370     }
    371 
    372     // Verify that incomplete coverage due to clipping does not trigger a fresh
    373     // frame
    374     {
    375         canvas->save();
    376         canvas->clipRect(partialRect, SkRegion::kIntersect_Op, false);
    377         SkPaint paint;
    378         paint.setStyle(SkPaint::kFill_Style);
    379         paint.setAlpha(255);
    380         canvas->drawRect(fullRect, paint);
    381         canvas->restore();
    382         REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
    383     }
    384     {
    385         canvas->save();
    386         SkPaint paint;
    387         paint.setStyle(SkPaint::kFill_Style);
    388         paint.setAlpha(255);
    389         SkPath path;
    390         path.addCircle(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(2));
    391         canvas->clipPath(path, SkRegion::kIntersect_Op, false);
    392         canvas->drawRect(fullRect, paint);
    393         canvas->restore();
    394         REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
    395     }
    396 
    397     // Verify that stroked rect does not trigger a fresh frame
    398     {
    399         SkPaint paint;
    400         paint.setStyle(SkPaint::kStroke_Style);
    401         paint.setAlpha(255);
    402         canvas->drawRect(fullRect, paint);
    403         REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
    404     }
    405 
    406     // Verify kSrcMode triggers a fresh frame even with transparent color
    407     {
    408         SkPaint paint;
    409         paint.setStyle(SkPaint::kFill_Style);
    410         paint.setAlpha(100);
    411         paint.setXfermodeMode(SkXfermode::kSrc_Mode);
    412         canvas->drawRect(fullRect, paint);
    413         REPORTER_ASSERT(reporter, canvas->isFreshFrame());
    414     }
    415 }
    416 
    417 class MockDevice : public SkBitmapDevice {
    418 public:
    419     MockDevice(const SkBitmap& bm) : SkBitmapDevice(bm) {
    420         fDrawBitmapCallCount = 0;
    421     }
    422     virtual void drawBitmap(const SkDraw&, const SkBitmap&,
    423                             const SkMatrix&, const SkPaint&) SK_OVERRIDE {
    424         fDrawBitmapCallCount++;
    425     }
    426 
    427     int fDrawBitmapCallCount;
    428 };
    429 
    430 class NotificationCounter : public SkDeferredCanvas::NotificationClient {
    431 public:
    432     NotificationCounter() {
    433         fPrepareForDrawCount = fStorageAllocatedChangedCount =
    434             fFlushedDrawCommandsCount = fSkippedPendingDrawCommandsCount = 0;
    435     }
    436 
    437     virtual void prepareForDraw() SK_OVERRIDE {
    438         fPrepareForDrawCount++;
    439     }
    440     virtual void storageAllocatedForRecordingChanged(size_t) SK_OVERRIDE {
    441         fStorageAllocatedChangedCount++;
    442     }
    443     virtual void flushedDrawCommands() SK_OVERRIDE {
    444         fFlushedDrawCommandsCount++;
    445     }
    446     virtual void skippedPendingDrawCommands() SK_OVERRIDE {
    447         fSkippedPendingDrawCommandsCount++;
    448     }
    449 
    450     int fPrepareForDrawCount;
    451     int fStorageAllocatedChangedCount;
    452     int fFlushedDrawCommandsCount;
    453     int fSkippedPendingDrawCommandsCount;
    454 
    455 private:
    456     typedef SkDeferredCanvas::NotificationClient INHERITED;
    457 };
    458 
    459 // Verifies that the deferred canvas triggers a flush when its memory
    460 // limit is exceeded
    461 static void TestDeferredCanvasMemoryLimit(skiatest::Reporter* reporter) {
    462     SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterPMColor(100, 100));
    463     SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
    464 
    465     NotificationCounter notificationCounter;
    466     canvas->setNotificationClient(&notificationCounter);
    467 
    468     canvas->setMaxRecordingStorage(160000);
    469 
    470     SkBitmap sourceImage;
    471     // 100 by 100 image, takes 40,000 bytes in memory
    472     sourceImage.allocN32Pixels(100, 100);
    473     sourceImage.eraseColor(SK_ColorGREEN);
    474 
    475     for (int i = 0; i < 5; i++) {
    476         sourceImage.notifyPixelsChanged(); // to force re-serialization
    477         canvas->drawBitmap(sourceImage, 0, 0, NULL);
    478     }
    479 
    480     REPORTER_ASSERT(reporter, 1 == notificationCounter.fFlushedDrawCommandsCount);
    481 }
    482 
    483 static void TestDeferredCanvasSilentFlush(skiatest::Reporter* reporter) {
    484     SkAutoTUnref<SkSurface> surface(createSurface(0));
    485     SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
    486 
    487     NotificationCounter notificationCounter;
    488     canvas->setNotificationClient(&notificationCounter);
    489 
    490     canvas->silentFlush(); // will skip the initial clear that was recorded in createSurface
    491 
    492     REPORTER_ASSERT(reporter, 0 == notificationCounter.fFlushedDrawCommandsCount);
    493     REPORTER_ASSERT(reporter, 1 == notificationCounter.fSkippedPendingDrawCommandsCount);
    494 }
    495 
    496 static void TestDeferredCanvasBitmapCaching(skiatest::Reporter* reporter) {
    497     SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterPMColor(100, 100));
    498     SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
    499 
    500     NotificationCounter notificationCounter;
    501     canvas->setNotificationClient(&notificationCounter);
    502 
    503     const int imageCount = 2;
    504     SkBitmap sourceImages[imageCount];
    505     for (int i = 0; i < imageCount; i++) {
    506         sourceImages[i].allocN32Pixels(100, 100);
    507         sourceImages[i].eraseColor(SK_ColorGREEN);
    508     }
    509 
    510     size_t bitmapSize = sourceImages[0].getSize();
    511 
    512     canvas->drawBitmap(sourceImages[0], 0, 0, NULL);
    513     REPORTER_ASSERT(reporter, 1 == notificationCounter.fStorageAllocatedChangedCount);
    514     // stored bitmap + drawBitmap command
    515     REPORTER_ASSERT(reporter, canvas->storageAllocatedForRecording() > bitmapSize);
    516 
    517     // verify that nothing can be freed at this point
    518     REPORTER_ASSERT(reporter, 0 == canvas->freeMemoryIfPossible(~0U));
    519 
    520     // verify that flush leaves image in cache
    521     REPORTER_ASSERT(reporter, 0 == notificationCounter.fFlushedDrawCommandsCount);
    522     REPORTER_ASSERT(reporter, 0 == notificationCounter.fPrepareForDrawCount);
    523     canvas->flush();
    524     REPORTER_ASSERT(reporter, 1 == notificationCounter.fFlushedDrawCommandsCount);
    525     REPORTER_ASSERT(reporter, 1 == notificationCounter.fPrepareForDrawCount);
    526     REPORTER_ASSERT(reporter, canvas->storageAllocatedForRecording() >= bitmapSize);
    527 
    528     // verify that after a flush, cached image can be freed
    529     REPORTER_ASSERT(reporter, canvas->freeMemoryIfPossible(~0U) >= bitmapSize);
    530 
    531     // Verify that caching works for avoiding multiple copies of the same bitmap
    532     canvas->drawBitmap(sourceImages[0], 0, 0, NULL);
    533     REPORTER_ASSERT(reporter, 2 == notificationCounter.fStorageAllocatedChangedCount);
    534     canvas->drawBitmap(sourceImages[0], 0, 0, NULL);
    535     REPORTER_ASSERT(reporter, 2 == notificationCounter.fStorageAllocatedChangedCount);
    536     REPORTER_ASSERT(reporter, 1 == notificationCounter.fFlushedDrawCommandsCount);
    537     REPORTER_ASSERT(reporter, canvas->storageAllocatedForRecording() < 2 * bitmapSize);
    538 
    539     // Verify partial eviction based on bytesToFree
    540     canvas->drawBitmap(sourceImages[1], 0, 0, NULL);
    541     REPORTER_ASSERT(reporter, 1 == notificationCounter.fFlushedDrawCommandsCount);
    542     canvas->flush();
    543     REPORTER_ASSERT(reporter, 2 == notificationCounter.fFlushedDrawCommandsCount);
    544     REPORTER_ASSERT(reporter, canvas->storageAllocatedForRecording() > 2 * bitmapSize);
    545     size_t bytesFreed = canvas->freeMemoryIfPossible(1);
    546     REPORTER_ASSERT(reporter, 2 == notificationCounter.fFlushedDrawCommandsCount);
    547     REPORTER_ASSERT(reporter,  bytesFreed >= bitmapSize);
    548     REPORTER_ASSERT(reporter,  bytesFreed < 2*bitmapSize);
    549 
    550     // Verifiy that partial purge works, image zero is in cache but not reffed by
    551     // a pending draw, while image 1 is locked-in.
    552     canvas->freeMemoryIfPossible(~0U);
    553     REPORTER_ASSERT(reporter, 2 == notificationCounter.fFlushedDrawCommandsCount);
    554     canvas->drawBitmap(sourceImages[0], 0, 0, NULL);
    555     canvas->flush();
    556     canvas->drawBitmap(sourceImages[1], 0, 0, NULL);
    557     bytesFreed = canvas->freeMemoryIfPossible(~0U);
    558     // only one bitmap should have been freed.
    559     REPORTER_ASSERT(reporter,  bytesFreed >= bitmapSize);
    560     REPORTER_ASSERT(reporter,  bytesFreed < 2*bitmapSize);
    561     // Clear for next test
    562     canvas->flush();
    563     canvas->freeMemoryIfPossible(~0U);
    564     REPORTER_ASSERT(reporter, canvas->storageAllocatedForRecording() < bitmapSize);
    565 
    566     // Verify the image cache is sensitive to genID bumps
    567     canvas->drawBitmap(sourceImages[1], 0, 0, NULL);
    568     sourceImages[1].notifyPixelsChanged();
    569     canvas->drawBitmap(sourceImages[1], 0, 0, NULL);
    570     REPORTER_ASSERT(reporter, canvas->storageAllocatedForRecording() > 2*bitmapSize);
    571 
    572     // Verify that nothing in this test caused commands to be skipped
    573     REPORTER_ASSERT(reporter, 0 == notificationCounter.fSkippedPendingDrawCommandsCount);
    574 }
    575 
    576 static void TestDeferredCanvasSkip(skiatest::Reporter* reporter) {
    577     SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterPMColor(100, 100));
    578     SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
    579 
    580     NotificationCounter notificationCounter;
    581     canvas->setNotificationClient(&notificationCounter);
    582     canvas->clear(0x0);
    583     REPORTER_ASSERT(reporter, 1 == notificationCounter.fSkippedPendingDrawCommandsCount);
    584     REPORTER_ASSERT(reporter, 0 == notificationCounter.fFlushedDrawCommandsCount);
    585     canvas->flush();
    586     REPORTER_ASSERT(reporter, 1 == notificationCounter.fSkippedPendingDrawCommandsCount);
    587     REPORTER_ASSERT(reporter, 1 == notificationCounter.fFlushedDrawCommandsCount);
    588 
    589 }
    590 
    591 static void TestDeferredCanvasBitmapShaderNoLeak(skiatest::Reporter* reporter) {
    592     // This is a regression test for crbug.com/155875
    593     // This test covers a code path that inserts bitmaps into the bitmap heap through the
    594     // flattening of SkBitmapProcShaders. The refcount in the bitmap heap is maintained through
    595     // the flattening and unflattening of the shader.
    596     SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterPMColor(100, 100));
    597     SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
    598     // test will fail if nbIterations is not in sync with
    599     // BITMAPS_TO_KEEP in SkGPipeWrite.cpp
    600     const int nbIterations = 5;
    601     size_t bytesAllocated = 0;
    602     for(int pass = 0; pass < 2; ++pass) {
    603         for(int i = 0; i < nbIterations; ++i) {
    604             SkPaint paint;
    605             SkBitmap paintPattern;
    606             paintPattern.allocN32Pixels(10, 10);
    607             paintPattern.eraseColor(SK_ColorGREEN);
    608             paint.setShader(SkNEW_ARGS(SkBitmapProcShader,
    609                 (paintPattern, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode)))->unref();
    610             canvas->drawPaint(paint);
    611             canvas->flush();
    612 
    613             // In the first pass, memory allocation should be monotonically increasing as
    614             // the bitmap heap slots fill up.  In the second pass memory allocation should be
    615             // stable as bitmap heap slots get recycled.
    616             size_t newBytesAllocated = canvas->storageAllocatedForRecording();
    617             if (pass == 0) {
    618                 REPORTER_ASSERT(reporter, newBytesAllocated > bytesAllocated);
    619                 bytesAllocated = newBytesAllocated;
    620             } else {
    621                 REPORTER_ASSERT(reporter, newBytesAllocated == bytesAllocated);
    622             }
    623         }
    624     }
    625     // All cached resources should be evictable since last canvas call was flush()
    626     canvas->freeMemoryIfPossible(~0U);
    627     REPORTER_ASSERT(reporter, 0 == canvas->storageAllocatedForRecording());
    628 }
    629 
    630 static void TestDeferredCanvasBitmapSizeThreshold(skiatest::Reporter* reporter) {
    631     SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterPMColor(100, 100));
    632 
    633     SkBitmap sourceImage;
    634     // 100 by 100 image, takes 40,000 bytes in memory
    635     sourceImage.allocN32Pixels(100, 100);
    636     sourceImage.eraseColor(SK_ColorGREEN);
    637 
    638     // 1 under : should not store the image
    639     {
    640         SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
    641         canvas->setBitmapSizeThreshold(39999);
    642         canvas->drawBitmap(sourceImage, 0, 0, NULL);
    643         size_t newBytesAllocated = canvas->storageAllocatedForRecording();
    644         REPORTER_ASSERT(reporter, newBytesAllocated == 0);
    645     }
    646 
    647     // exact value : should store the image
    648     {
    649         SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
    650         canvas->setBitmapSizeThreshold(40000);
    651         canvas->drawBitmap(sourceImage, 0, 0, NULL);
    652         size_t newBytesAllocated = canvas->storageAllocatedForRecording();
    653         REPORTER_ASSERT(reporter, newBytesAllocated > 0);
    654     }
    655 
    656     // 1 over : should still store the image
    657     {
    658         SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
    659         canvas->setBitmapSizeThreshold(40001);
    660         canvas->drawBitmap(sourceImage, 0, 0, NULL);
    661         size_t newBytesAllocated = canvas->storageAllocatedForRecording();
    662         REPORTER_ASSERT(reporter, newBytesAllocated > 0);
    663     }
    664 }
    665 
    666 
    667 typedef const void* PixelPtr;
    668 // Returns an opaque pointer which, either points to a GrTexture or RAM pixel
    669 // buffer. Used to test pointer equality do determine whether a surface points
    670 // to the same pixel data storage as before.
    671 static PixelPtr get_surface_ptr(SkSurface* surface, bool useGpu) {
    672 #if SK_SUPPORT_GPU
    673     if (useGpu) {
    674         return surface->getCanvas()->internal_private_accessTopLayerRenderTarget()->asTexture();
    675     } else
    676 #endif
    677     {
    678         return surface->peekPixels(NULL, NULL);
    679     }
    680 }
    681 
    682 static void TestDeferredCanvasSurface(skiatest::Reporter* reporter, GrContextFactory* factory) {
    683     SkImageInfo imageSpec = SkImageInfo::MakeN32Premul(10, 10);
    684     bool useGpu = SkToBool(factory);
    685     int cnt;
    686 #if SK_SUPPORT_GPU
    687     if (useGpu) {
    688         cnt = GrContextFactory::kGLContextTypeCnt;
    689     } else {
    690         cnt = 1;
    691     }
    692 #else
    693     SkASSERT(!useGpu);
    694     cnt = 1;
    695 #endif
    696     for (int i = 0; i < cnt; ++i) {
    697         SkSurface* surface;
    698 #if SK_SUPPORT_GPU
    699         if (useGpu) {
    700             GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
    701             if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
    702                 continue;
    703             }
    704             GrContext* context = factory->get(glCtxType);
    705             if (NULL == context) {
    706                 return;
    707             }
    708 
    709             surface = SkSurface::NewRenderTarget(context, imageSpec, 0, NULL);
    710         } else
    711 #endif
    712         {
    713            surface = SkSurface::NewRaster(imageSpec);
    714         }
    715         SkASSERT(surface);
    716         SkAutoTUnref<SkSurface> aur(surface);
    717         SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface));
    718 
    719         SkImage* image1 = canvas->newImageSnapshot();
    720         SkAutoTUnref<SkImage> aur_i1(image1);
    721         PixelPtr pixels1 = get_surface_ptr(surface, useGpu);
    722         // The following clear would normally trigger a copy on write, but
    723         // it won't because rendering is deferred.
    724         canvas->clear(SK_ColorBLACK);
    725         // Obtaining a snapshot directly from the surface (as opposed to the
    726         // SkDeferredCanvas) will not trigger a flush of deferred draw operations
    727         // and will therefore return the same image as the previous snapshot.
    728         SkImage* image2 = surface->newImageSnapshot();
    729         SkAutoTUnref<SkImage> aur_i2(image2);
    730         // Images identical because of deferral
    731         REPORTER_ASSERT(reporter, image1->uniqueID() == image2->uniqueID());
    732         // Now we obtain a snpshot via the deferred canvas, which triggers a flush.
    733         // Because there is a pending clear, this will generate a different image.
    734         SkImage* image3 = canvas->newImageSnapshot();
    735         SkAutoTUnref<SkImage> aur_i3(image3);
    736         REPORTER_ASSERT(reporter, image1->uniqueID() != image3->uniqueID());
    737         // Verify that backing store is now a different buffer because of copy on
    738         // write
    739         PixelPtr pixels2 = get_surface_ptr(surface, useGpu);
    740         REPORTER_ASSERT(reporter, pixels1 != pixels2);
    741         // Verify copy-on write with a draw operation that gets deferred by
    742         // the in order draw buffer.
    743         SkPaint paint;
    744         canvas->drawPaint(paint);
    745         SkImage* image4 = canvas->newImageSnapshot();  // implicit flush
    746         SkAutoTUnref<SkImage> aur_i4(image4);
    747         REPORTER_ASSERT(reporter, image4->uniqueID() != image3->uniqueID());
    748         PixelPtr pixels3 = get_surface_ptr(surface, useGpu);
    749         REPORTER_ASSERT(reporter, pixels2 != pixels3);
    750         // Verify that a direct canvas flush with a pending draw does not trigger
    751         // a copy on write when the surface is not sharing its buffer with an
    752         // SkImage.
    753         canvas->clear(SK_ColorWHITE);
    754         canvas->flush();
    755         PixelPtr pixels4 = get_surface_ptr(surface, useGpu);
    756         canvas->drawPaint(paint);
    757         canvas->flush();
    758         PixelPtr pixels5 = get_surface_ptr(surface, useGpu);
    759         REPORTER_ASSERT(reporter, pixels4 == pixels5);
    760     }
    761 }
    762 
    763 static void TestDeferredCanvasSetSurface(skiatest::Reporter* reporter, GrContextFactory* factory) {
    764     SkImageInfo imageSpec = SkImageInfo::MakeN32Premul(10, 10);
    765     SkSurface* surface;
    766     SkSurface* alternateSurface;
    767     bool useGpu = SkToBool(factory);
    768     int cnt;
    769 #if SK_SUPPORT_GPU
    770     if (useGpu) {
    771         cnt = GrContextFactory::kGLContextTypeCnt;
    772     } else {
    773         cnt = 1;
    774     }
    775 #else
    776     SkASSERT(!useGpu);
    777     cnt = 1;
    778 #endif
    779 
    780     for (int i = 0; i < cnt; ++i) {
    781 #if SK_SUPPORT_GPU
    782         if (useGpu) {
    783             GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
    784             if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
    785                 continue;
    786             }
    787             GrContext* context = factory->get(glCtxType);
    788             if (NULL == context) {
    789                 continue;
    790             }
    791             surface = SkSurface::NewRenderTarget(context, imageSpec, 0, NULL);
    792             alternateSurface = SkSurface::NewRenderTarget(context, imageSpec, 0, NULL);
    793         } else
    794 #endif
    795         {
    796             surface = SkSurface::NewRaster(imageSpec);
    797             alternateSurface = SkSurface::NewRaster(imageSpec);
    798         }
    799         SkASSERT(surface);
    800         SkASSERT(alternateSurface);
    801         SkAutoTUnref<SkSurface> aur1(surface);
    802         SkAutoTUnref<SkSurface> aur2(alternateSurface);
    803         PixelPtr pixels1 = get_surface_ptr(surface, useGpu);
    804         PixelPtr pixels2 = get_surface_ptr(alternateSurface, useGpu);
    805         SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface));
    806         SkAutoTUnref<SkImage> image1(canvas->newImageSnapshot());
    807         canvas->setSurface(alternateSurface);
    808         SkAutoTUnref<SkImage> image2(canvas->newImageSnapshot());
    809         REPORTER_ASSERT(reporter, image1->uniqueID() != image2->uniqueID());
    810         // Verify that none of the above operations triggered a surface copy on write.
    811         REPORTER_ASSERT(reporter, get_surface_ptr(surface, useGpu) == pixels1);
    812         REPORTER_ASSERT(reporter, get_surface_ptr(alternateSurface, useGpu) == pixels2);
    813         // Verify that a flushed draw command will trigger a copy on write on alternateSurface.
    814         canvas->clear(SK_ColorWHITE);
    815         canvas->flush();
    816         REPORTER_ASSERT(reporter, get_surface_ptr(surface, useGpu) == pixels1);
    817         REPORTER_ASSERT(reporter, get_surface_ptr(alternateSurface, useGpu) != pixels2);
    818     }
    819 }
    820 
    821 static void TestDeferredCanvasCreateCompatibleDevice(skiatest::Reporter* reporter) {
    822     SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterPMColor(100, 100));
    823     SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
    824 
    825     NotificationCounter notificationCounter;
    826     canvas->setNotificationClient(&notificationCounter);
    827 
    828     SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
    829     SkAutoTUnref<SkSurface> secondarySurface(canvas->newSurface(info));
    830 
    831     SkRect rect = SkRect::MakeWH(5, 5);
    832     SkPaint paint;
    833     // After spawning a compatible canvas:
    834     // 1) Verify that secondary canvas is usable and does not report to the notification client.
    835     surface->getCanvas()->drawRect(rect, paint);
    836     REPORTER_ASSERT(reporter, notificationCounter.fStorageAllocatedChangedCount == 0);
    837     // 2) Verify that original canvas is usable and still reports to the notification client.
    838     canvas->drawRect(rect, paint);
    839     REPORTER_ASSERT(reporter, notificationCounter.fStorageAllocatedChangedCount == 1);
    840 }
    841 
    842 static void TestDeferredCanvasGetCanvasSize(skiatest::Reporter* reporter) {
    843     SkRect rect;
    844     rect.setXYWH(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(gWidth), SkIntToScalar(gHeight));
    845     SkRect clip;
    846     clip.setXYWH(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(1), SkIntToScalar(1));
    847 
    848     SkPaint paint;
    849     SkISize size = SkISize::Make(gWidth, gHeight);
    850 
    851     SkAutoTUnref<SkSurface> surface(createSurface(0xFFFFFFFF));
    852     SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
    853     SkSurface* newSurface = SkSurface::NewRasterPMColor(4, 4);
    854     SkAutoTUnref<SkSurface> aur(newSurface);
    855 
    856     for (int i = 0; i < 2; ++i) {
    857         if (i == 1) {
    858             canvas->setSurface(newSurface);
    859             size = SkISize::Make(4, 4);
    860         }
    861 
    862         // verify that canvas size is correctly initialized or set
    863         REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
    864 
    865         // Verify that clear, clip and draw the canvas will not change its size
    866         canvas->clear(0x00000000);
    867         canvas->clipRect(clip, SkRegion::kIntersect_Op, false);
    868         canvas->drawRect(rect, paint);
    869         REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
    870 
    871         // Verify that flush the canvas will not change its size
    872         canvas->flush();
    873         REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
    874 
    875         // Verify that clear canvas with saved state will not change its size
    876         canvas->save();
    877         canvas->clear(0xFFFFFFFF);
    878         REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
    879 
    880         // Verify that restore canvas state will not change its size
    881         canvas->restore();
    882         REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
    883 
    884         // Verify that clear within a layer will not change canvas size
    885         canvas->saveLayer(&clip, &paint);
    886         canvas->clear(0x00000000);
    887         REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
    888 
    889         // Verify that restore from a layer will not change canvas size
    890         canvas->restore();
    891         REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
    892     }
    893 }
    894 
    895 DEF_TEST(DeferredCanvas_CPU, reporter) {
    896     TestDeferredCanvasFlush(reporter);
    897     TestDeferredCanvasSilentFlush(reporter);
    898     TestDeferredCanvasFreshFrame(reporter);
    899     TestDeferredCanvasMemoryLimit(reporter);
    900     TestDeferredCanvasBitmapCaching(reporter);
    901     TestDeferredCanvasSkip(reporter);
    902     TestDeferredCanvasBitmapShaderNoLeak(reporter);
    903     TestDeferredCanvasBitmapSizeThreshold(reporter);
    904     TestDeferredCanvasCreateCompatibleDevice(reporter);
    905     TestDeferredCanvasWritePixelsToSurface(reporter);
    906     TestDeferredCanvasGetCanvasSize(reporter);
    907     TestDeferredCanvasSurface(reporter, NULL);
    908     TestDeferredCanvasSetSurface(reporter, NULL);
    909 }
    910 
    911 DEF_GPUTEST(DeferredCanvas_GPU, reporter, factory) {
    912     if (factory != NULL) {
    913         TestDeferredCanvasSurface(reporter, factory);
    914         TestDeferredCanvasSetSurface(reporter, factory);
    915     }
    916 }
    917