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