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
23class GrContextFactory;
24#endif
25
26static const int gWidth = 2;
27static const int gHeight = 2;
28
29static void create(SkBitmap* bm, SkColor color) {
30    bm->allocN32Pixels(gWidth, gHeight);
31    bm->eraseColor(color);
32}
33
34static SkSurface* createSurface(SkColor color) {
35    SkSurface* surface = SkSurface::NewRasterPMColor(gWidth, gHeight);
36    surface->getCanvas()->clear(color);
37    return surface;
38}
39
40static 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
52static 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
69class MockSurface : public SkSurface_Base {
70public:
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
105static 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
257static 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
272static 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
434class MockDevice : public SkBitmapDevice {
435public:
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
447class NotificationCounter : public SkDeferredCanvas::NotificationClient {
448public:
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
472private:
473    typedef SkDeferredCanvas::NotificationClient INHERITED;
474};
475
476// Verifies that the deferred canvas triggers a flush when its memory
477// limit is exceeded
478static 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
499static 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
512static 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
591static 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
606static 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
644static 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
680typedef 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.
684static PixelPtr getSurfacePixelPtr(SkSurface* surface, bool useGpu) {
685    return useGpu ? surface->getCanvas()->getDevice()->accessBitmap(false).getTexture() :
686        surface->getCanvas()->getDevice()->accessBitmap(false).getPixels();
687}
688
689static 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
755static 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
798static 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
819DEF_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
835DEF_GPUTEST(DeferredCanvas_GPU, reporter, factory) {
836    if (factory != NULL) {
837        TestDeferredCanvasSurface(reporter, factory);
838        TestDeferredCanvasSetSurface(reporter, factory);
839    }
840}
841