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