b8b82b2e8329429c31a052f24af8871a74e4021a
[platform/framework/web/crosswalk.git] / src / third_party / skia / tests / DeferredCanvasTest.cpp
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) {
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 = NULL != 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);
710         } else
711 #endif
712         {
713            surface = SkSurface::NewRaster(imageSpec);
714         }
715         SkASSERT(NULL != 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 = NULL != 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);
792             alternateSurface = SkSurface::NewRenderTarget(context, imageSpec);
793         } else
794 #endif
795         {
796             surface = SkSurface::NewRaster(imageSpec);
797             alternateSurface = SkSurface::NewRaster(imageSpec);
798         }
799         SkASSERT(NULL != surface);
800         SkASSERT(NULL != 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 DEF_TEST(DeferredCanvas_CPU, reporter) {
843     TestDeferredCanvasFlush(reporter);
844     TestDeferredCanvasSilentFlush(reporter);
845     TestDeferredCanvasFreshFrame(reporter);
846     TestDeferredCanvasMemoryLimit(reporter);
847     TestDeferredCanvasBitmapCaching(reporter);
848     TestDeferredCanvasSkip(reporter);
849     TestDeferredCanvasBitmapShaderNoLeak(reporter);
850     TestDeferredCanvasBitmapSizeThreshold(reporter);
851     TestDeferredCanvasCreateCompatibleDevice(reporter);
852     TestDeferredCanvasWritePixelsToSurface(reporter);
853     TestDeferredCanvasSurface(reporter, NULL);
854     TestDeferredCanvasSetSurface(reporter, NULL);
855 }
856
857 DEF_GPUTEST(DeferredCanvas_GPU, reporter, factory) {
858     if (factory != NULL) {
859         TestDeferredCanvasSurface(reporter, factory);
860         TestDeferredCanvasSetSurface(reporter, factory);
861     }
862 }