180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2012 Google Inc.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "Test.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkBitmap.h"
100a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#include "SkBitmapDevice.h"
11363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkBitmapProcShader.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkDeferredCanvas.h"
13096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "SkGradientShader.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkShader.h"
15e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#include "../src/image/SkSurface_Base.h"
16e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#include "../src/image/SkImagePriv.h"
177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#if SK_SUPPORT_GPU
187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "GrContextFactory.h"
197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#else
207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerclass GrContextFactory;
217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const int gWidth = 2;
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const int gHeight = 2;
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void create(SkBitmap* bm, SkBitmap::Config config, SkColor color) {
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bm->setConfig(config, gWidth, gHeight);
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bm->allocPixels();
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bm->eraseColor(color);
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void TestDeferredCanvasBitmapAccess(skiatest::Reporter* reporter) {
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmap store;
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    create(&store, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkBitmapDevice device(store);
37e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(&device));
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->clear(0x00000000);
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoLockPixels alp(store);
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, store.getColor(0,0) == 0xFFFFFFFF); //verify that clear was deferred
4358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkBitmap accessed = canvas->getDevice()->accessBitmap(false);
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, store.getColor(0,0) == 0x00000000); //verify that clear was executed
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, accessed.pixelRef() == store.pixelRef());
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerclass MockSurface : public SkSurface_Base {
49e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerpublic:
50e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    MockSurface(int width, int height) : SkSurface_Base(width, height) {
51e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        clearCounts();
52e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        fBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
53e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        fBitmap.allocPixels();
54e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
55e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
56e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    virtual SkCanvas* onNewCanvas() SK_OVERRIDE {
57e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        return SkNEW_ARGS(SkCanvas, (fBitmap));
58e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
59e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
600a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE {
61e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        return NULL;
62e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
63e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
64e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    virtual SkImage* onNewImageSnapshot() SK_OVERRIDE {
65e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        return SkNewImageFromBitmap(fBitmap, true);
66e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
67e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
68e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    virtual void onCopyOnWrite(ContentChangeMode mode) SK_OVERRIDE {
69e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        if (mode == SkSurface::kDiscard_ContentChangeMode) {
70e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            fDiscardCount++;
71e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        } else {
72e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            fRetainCount++;
73e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        }
74e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
75e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
76e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    void clearCounts() {
77e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        fDiscardCount = 0;
78e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        fRetainCount = 0;
79e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
80e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
81e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    int fDiscardCount, fRetainCount;
82e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkBitmap fBitmap;
83e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger};
84e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
85e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void TestDeferredCanvasWritePixelsToSurface(skiatest::Reporter* reporter) {
86e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<MockSurface> surface(SkNEW_ARGS(MockSurface, (10, 10)));
87e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
88e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
89e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkBitmap srcBitmap;
90e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    srcBitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
91e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    srcBitmap.allocPixels();
92e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    srcBitmap.eraseColor(SK_ColorGREEN);
93e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // Tests below depend on this bitmap being recognized as opaque
94e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
95e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // Preliminary sanity check: no copy on write if no active snapshot
96e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
97e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->clear(SK_ColorWHITE);
98e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
99e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
100e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
101e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
102e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->flush();
103e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
104e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
105e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
106e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // Case 1: Discard notification happens upon flushing
107e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // with an Image attached.
108e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
109e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkImage> image1(canvas->newImageSnapshot());
110e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
111e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
112e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
113e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
114e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->clear(SK_ColorWHITE);
115e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
116e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
117e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
118e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
119e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->flush();
120e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount);
121e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
122e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
123e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // Case 2: Opaque writePixels
124e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
125e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkImage> image2(canvas->newImageSnapshot());
126e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
127e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
128e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
129e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
130e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->writePixels(srcBitmap, 0, 0);
131e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
132e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
133e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
134e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
135e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->flush();
136e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount);
137e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
138e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
139e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // Case 3: writePixels that partially covers the canvas
140e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
141e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkImage> image3(canvas->newImageSnapshot());
142e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
143e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
144e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
145e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
146e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->writePixels(srcBitmap, 5, 0);
147e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
148e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
149e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
150e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
151e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->flush();
152e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
153e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 1 == surface->fRetainCount);
154e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
155e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // Case 4: unpremultiplied opaque writePixels that entirely
156e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // covers the canvas
157e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
158e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkImage> image4(canvas->newImageSnapshot());
159e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
160e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
161e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
162e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
163e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->writePixels(srcBitmap, 0, 0, SkCanvas::kRGBA_Unpremul_Config8888);
164e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount);
165e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
166e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
167e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
168e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->flush();
169e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
170e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
171e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
172e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // Case 5: unpremultiplied opaque writePixels that partially
173e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // covers the canvas
174e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
175e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkImage> image5(canvas->newImageSnapshot());
176e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
177e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
178e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
179e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
180e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->writePixels(srcBitmap, 5, 0, SkCanvas::kRGBA_Unpremul_Config8888);
181e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
182e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 1 == surface->fRetainCount);
183e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
184e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
185e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->flush();
186e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
187e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
188e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
189e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // Case 6: unpremultiplied opaque writePixels that entirely
190e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // covers the canvas, preceded by clear
191e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
192e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkImage> image6(canvas->newImageSnapshot());
193e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
194e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
195e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
196e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
197e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->clear(SK_ColorWHITE);
198e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
199e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
200e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
201e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
202e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->writePixels(srcBitmap, 0, 0, SkCanvas::kRGBA_Unpremul_Config8888);
203e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount);
204e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
205e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
206e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
207e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->flush();
208e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
209e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
210e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
211e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // Case 7: unpremultiplied opaque writePixels that partially
212e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // covers the canvas, preceeded by a clear
213e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
214e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkImage> image7(canvas->newImageSnapshot());
215e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
216e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
217e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
218e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
219e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->clear(SK_ColorWHITE);
220e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
221e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
222e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
223e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
224e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->writePixels(srcBitmap, 5, 0, SkCanvas::kRGBA_Unpremul_Config8888);
225e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount); // because of the clear
226e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
227e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
228e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
229e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->flush();
230e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
231e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
232e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
233e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // Case 8: unpremultiplied opaque writePixels that partially
234e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // covers the canvas, preceeded by a drawREct that partially
235e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // covers the canvas
236e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
237e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkImage> image8(canvas->newImageSnapshot());
238e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
239e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
240e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
241e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
242e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkPaint paint;
243e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->drawRect(SkRect::MakeLTRB(0, 0, 5, 5), paint);
244e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
245e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
246e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
247e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
248e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->writePixels(srcBitmap, 5, 0, SkCanvas::kRGBA_Unpremul_Config8888);
249e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
250e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 1 == surface->fRetainCount);
251e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
252e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    surface->clearCounts();
253e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    canvas->flush();
254e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount);
255e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == surface->fRetainCount);
256e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger}
257e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void TestDeferredCanvasFlush(skiatest::Reporter* reporter) {
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmap store;
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    create(&store, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
2620a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkBitmapDevice device(store);
263e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(&device));
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->clear(0x00000000);
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoLockPixels alp(store);
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, store.getColor(0,0) == 0xFFFFFFFF); //verify that clear was deferred
26958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->flush();
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, store.getColor(0,0) == 0x00000000); //verify that clear was executed
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void TestDeferredCanvasFreshFrame(skiatest::Reporter* reporter) {
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmap store;
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect fullRect;
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fullRect.setXYWH(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(gWidth),
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkIntToScalar(gHeight));
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect partialRect;
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    partialRect.setXYWH(SkIntToScalar(0), SkIntToScalar(0),
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkIntToScalar(1), SkIntToScalar(1));
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    create(&store, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
2820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkBitmapDevice device(store);
283e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(&device));
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // verify that frame is intially fresh
28658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, canvas->isFreshFrame());
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // no clearing op since last call to isFreshFrame -> not fresh
28858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify that clear triggers a fresh frame
29158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->clear(0x00000000);
29258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, canvas->isFreshFrame());
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify that clear with saved state triggers a fresh frame
29558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->save(SkCanvas::kMatrixClip_SaveFlag);
29658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->clear(0x00000000);
29758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->restore();
29858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, canvas->isFreshFrame());
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify that clear within a layer does NOT trigger a fresh frame
30158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->saveLayer(NULL, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag);
30258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->clear(0x00000000);
30358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->restore();
30458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify that a clear with clipping triggers a fresh frame
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // (clear is not affected by clipping)
30858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->save(SkCanvas::kMatrixClip_SaveFlag);
30958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->clipRect(partialRect, SkRegion::kIntersect_Op, false);
31058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->clear(0x00000000);
31158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->restore();
31258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, canvas->isFreshFrame());
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify that full frame rects with different forms of opaque paint
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // trigger frames to be marked as fresh
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPaint paint;
318096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setStyle(SkPaint::kFill_Style);
319096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setAlpha(255);
32058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawRect(fullRect, paint);
32158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, canvas->isFreshFrame());
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPaint paint;
325096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setStyle(SkPaint::kFill_Style);
326096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setAlpha(255);
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.setXfermodeMode(SkXfermode::kSrcIn_Mode);
32858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawRect(fullRect, paint);
32958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPaint paint;
333096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setStyle(SkPaint::kFill_Style);
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkBitmap bmp;
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        create(&bmp, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
3360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        bmp.setAlphaType(kOpaque_SkAlphaType);
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkShader* shader = SkShader::CreateBitmapShader(bmp,
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.setShader(shader)->unref();
34058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawRect(fullRect, paint);
34158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, canvas->isFreshFrame());
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify that full frame rects with different forms of non-opaque paint
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // do not trigger frames to be marked as fresh
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPaint paint;
348096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setStyle(SkPaint::kFill_Style);
349096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setAlpha(254);
35058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawRect(fullRect, paint);
35158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPaint paint;
355096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setStyle(SkPaint::kFill_Style);
356096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        // Defining a cone that partially overlaps the canvas
357096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        const SkPoint pt1 = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(0));
358096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        const SkScalar r1 = SkIntToScalar(1);
359096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        const SkPoint pt2 = SkPoint::Make(SkIntToScalar(10), SkIntToScalar(0));
360096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        const SkScalar r2 = SkIntToScalar(5);
361096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        const SkColor colors[2] = {SK_ColorWHITE, SK_ColorWHITE};
362096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        const SkScalar pos[2] = {0, SK_Scalar1};
363096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SkShader* shader = SkGradientShader::CreateTwoPointConical(
364096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            pt1, r1, pt2, r2, colors, pos, 2, SkShader::kClamp_TileMode, NULL);
365096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setShader(shader)->unref();
36658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawRect(fullRect, paint);
36758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
368096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
369096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    {
370096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SkPaint paint;
371096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setStyle(SkPaint::kFill_Style);
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkBitmap bmp;
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        create(&bmp, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
3740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        bmp.setAlphaType(kPremul_SkAlphaType);
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkShader* shader = SkShader::CreateBitmapShader(bmp,
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.setShader(shader)->unref();
37858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawRect(fullRect, paint);
37958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify that incomplete coverage does not trigger a fresh frame
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPaint paint;
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.setStyle(SkPaint::kFill_Style);
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.setAlpha(255);
38758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawRect(partialRect, paint);
38858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify that incomplete coverage due to clipping does not trigger a fresh
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // frame
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
39458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->save(SkCanvas::kMatrixClip_SaveFlag);
39558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->clipRect(partialRect, SkRegion::kIntersect_Op, false);
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPaint paint;
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.setStyle(SkPaint::kFill_Style);
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.setAlpha(255);
39958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawRect(fullRect, paint);
40058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->restore();
40158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
402363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
403363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    {
40458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->save(SkCanvas::kMatrixClip_SaveFlag);
405363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkPaint paint;
406096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setStyle(SkPaint::kFill_Style);
407096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setAlpha(255);
408363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkPath path;
409363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        path.addCircle(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(2));
41058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->clipPath(path, SkRegion::kIntersect_Op, false);
41158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawRect(fullRect, paint);
41258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->restore();
41358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify that stroked rect does not trigger a fresh frame
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPaint paint;
419096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setStyle(SkPaint::kStroke_Style);
420096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setAlpha(255);
42158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawRect(fullRect, paint);
42258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify kSrcMode triggers a fresh frame even with transparent color
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPaint paint;
428096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setStyle(SkPaint::kFill_Style);
429096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        paint.setAlpha(100);
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
43158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawRect(fullRect, paint);
43258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        REPORTER_ASSERT(reporter, canvas->isFreshFrame());
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerclass MockDevice : public SkBitmapDevice {
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
4380a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    MockDevice(const SkBitmap& bm) : SkBitmapDevice(bm) {
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDrawBitmapCallCount = 0;
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void drawBitmap(const SkDraw&, const SkBitmap&,
44258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                            const SkMatrix&, const SkPaint&) SK_OVERRIDE {
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDrawBitmapCallCount++;
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int fDrawBitmapCallCount;
44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Verifies that the deferred canvas triggers a flush when its memory
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// limit is exceeded
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void TestDeferredCanvasMemoryLimit(skiatest::Reporter* reporter) {
45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmap store;
45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    store.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    store.allocPixels();
45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    MockDevice mockDevice(store);
456e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(&mockDevice));
45758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->setMaxRecordingStorage(160000);
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmap sourceImage;
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // 100 by 100 image, takes 40,000 bytes in memory
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sourceImage.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sourceImage.allocPixels();
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < 5; i++) {
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sourceImage.notifyPixelsChanged(); // to force re-serialization
46658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawBitmap(sourceImage, 0, 0, NULL);
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, mockDevice.fDrawBitmapCallCount == 4);
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass NotificationCounter : public SkDeferredCanvas::NotificationClient {
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    NotificationCounter() {
47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fPrepareForDrawCount = fStorageAllocatedChangedCount =
47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fFlushedDrawCommandsCount = fSkippedPendingDrawCommandsCount = 0;
47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void prepareForDraw() SK_OVERRIDE {
48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fPrepareForDrawCount++;
48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
482096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    virtual void storageAllocatedForRecordingChanged(size_t) SK_OVERRIDE {
48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fStorageAllocatedChangedCount++;
48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void flushedDrawCommands() SK_OVERRIDE {
48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fFlushedDrawCommandsCount++;
48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void skippedPendingDrawCommands() SK_OVERRIDE {
48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fSkippedPendingDrawCommandsCount++;
49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int fPrepareForDrawCount;
49380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int fStorageAllocatedChangedCount;
49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int fFlushedDrawCommandsCount;
49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int fSkippedPendingDrawCommandsCount;
496096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
497096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerprivate:
498096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    typedef SkDeferredCanvas::NotificationClient INHERITED;
49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void TestDeferredCanvasBitmapCaching(skiatest::Reporter* reporter) {
50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmap store;
50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    store.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    store.allocPixels();
5050a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkBitmapDevice device(store);
50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    NotificationCounter notificationCounter;
507e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(&device));
50858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->setNotificationClient(&notificationCounter);
50980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const int imageCount = 2;
51180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmap sourceImages[imageCount];
51280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < imageCount; i++)
51380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sourceImages[i].setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
51580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sourceImages[i].allocPixels();
51680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
51780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t bitmapSize = sourceImages[0].getSize();
51980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->drawBitmap(sourceImages[0], 0, 0, NULL);
52180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 1 == notificationCounter.fStorageAllocatedChangedCount);
52280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // stored bitmap + drawBitmap command
52358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, canvas->storageAllocatedForRecording() > bitmapSize);
52480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // verify that nothing can be freed at this point
52658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == canvas->freeMemoryIfPossible(~0U));
52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // verify that flush leaves image in cache
52980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 0 == notificationCounter.fFlushedDrawCommandsCount);
53080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 0 == notificationCounter.fPrepareForDrawCount);
53158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->flush();
53280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 1 == notificationCounter.fFlushedDrawCommandsCount);
53380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 1 == notificationCounter.fPrepareForDrawCount);
53458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, canvas->storageAllocatedForRecording() >= bitmapSize);
53580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // verify that after a flush, cached image can be freed
53758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, canvas->freeMemoryIfPossible(~0U) >= bitmapSize);
53880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify that caching works for avoiding multiple copies of the same bitmap
54058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->drawBitmap(sourceImages[0], 0, 0, NULL);
54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 2 == notificationCounter.fStorageAllocatedChangedCount);
54258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->drawBitmap(sourceImages[0], 0, 0, NULL);
54380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 2 == notificationCounter.fStorageAllocatedChangedCount);
54480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 1 == notificationCounter.fFlushedDrawCommandsCount);
54558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, canvas->storageAllocatedForRecording() < 2 * bitmapSize);
54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify partial eviction based on bytesToFree
54858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->drawBitmap(sourceImages[1], 0, 0, NULL);
54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 1 == notificationCounter.fFlushedDrawCommandsCount);
55058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->flush();
55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 2 == notificationCounter.fFlushedDrawCommandsCount);
55258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, canvas->storageAllocatedForRecording() > 2 * bitmapSize);
55358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    size_t bytesFreed = canvas->freeMemoryIfPossible(1);
55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 2 == notificationCounter.fFlushedDrawCommandsCount);
55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter,  bytesFreed >= bitmapSize);
55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter,  bytesFreed < 2*bitmapSize);
55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verifiy that partial purge works, image zero is in cache but not reffed by
55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // a pending draw, while image 1 is locked-in.
56058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->freeMemoryIfPossible(~0U);
56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 2 == notificationCounter.fFlushedDrawCommandsCount);
56258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->drawBitmap(sourceImages[0], 0, 0, NULL);
56358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->flush();
56458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->drawBitmap(sourceImages[1], 0, 0, NULL);
56558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    bytesFreed = canvas->freeMemoryIfPossible(~0U);
56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // only one bitmap should have been freed.
56780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter,  bytesFreed >= bitmapSize);
56880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter,  bytesFreed < 2*bitmapSize);
56980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Clear for next test
57058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->flush();
57158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->freeMemoryIfPossible(~0U);
57258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, canvas->storageAllocatedForRecording() < bitmapSize);
57380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify the image cache is sensitive to genID bumps
57558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->drawBitmap(sourceImages[1], 0, 0, NULL);
57680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sourceImages[1].notifyPixelsChanged();
57758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->drawBitmap(sourceImages[1], 0, 0, NULL);
57858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, canvas->storageAllocatedForRecording() > 2*bitmapSize);
57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Verify that nothing in this test caused commands to be skipped
58180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 0 == notificationCounter.fSkippedPendingDrawCommandsCount);
58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
58380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void TestDeferredCanvasSkip(skiatest::Reporter* reporter) {
58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmap store;
58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    store.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
58780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    store.allocPixels();
5880a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkBitmapDevice device(store);
58980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    NotificationCounter notificationCounter;
590e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(&device));
59158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->setNotificationClient(&notificationCounter);
59258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->clear(0x0);
59380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 1 == notificationCounter.fSkippedPendingDrawCommandsCount);
59480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 0 == notificationCounter.fFlushedDrawCommandsCount);
59558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->flush();
59680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 1 == notificationCounter.fSkippedPendingDrawCommandsCount);
59780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    REPORTER_ASSERT(reporter, 1 == notificationCounter.fFlushedDrawCommandsCount);
59880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
59980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
60080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
601363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void TestDeferredCanvasBitmapShaderNoLeak(skiatest::Reporter* reporter) {
602363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // This is a regression test for crbug.com/155875
603363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // This test covers a code path that inserts bitmaps into the bitmap heap through the
604363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // flattening of SkBitmapProcShaders. The refcount in the bitmap heap is maintained through
605363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // the flattening and unflattening of the shader.
606363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkBitmap store;
607363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    store.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
608363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    store.allocPixels();
6090a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkBitmapDevice device(store);
610e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(&device));
611363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // test will fail if nbIterations is not in sync with
612363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // BITMAPS_TO_KEEP in SkGPipeWrite.cpp
613363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const int nbIterations = 5;
614363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    size_t bytesAllocated = 0;
615363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for(int pass = 0; pass < 2; ++pass) {
616363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        for(int i = 0; i < nbIterations; ++i) {
617363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkPaint paint;
618363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkBitmap paintPattern;
619363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            paintPattern.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
620363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            paintPattern.allocPixels();
621363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            paint.setShader(SkNEW_ARGS(SkBitmapProcShader,
622363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                (paintPattern, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode)))->unref();
62358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            canvas->drawPaint(paint);
62458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            canvas->flush();
625363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
626363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // In the first pass, memory allocation should be monotonically increasing as
627363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // the bitmap heap slots fill up.  In the second pass memory allocation should be
628363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // stable as bitmap heap slots get recycled.
62958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            size_t newBytesAllocated = canvas->storageAllocatedForRecording();
630363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            if (pass == 0) {
631363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                REPORTER_ASSERT(reporter, newBytesAllocated > bytesAllocated);
632363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                bytesAllocated = newBytesAllocated;
633363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            } else {
634363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                REPORTER_ASSERT(reporter, newBytesAllocated == bytesAllocated);
635363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
636363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
637363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
638363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // All cached resources should be evictable since last canvas call was flush()
63958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->freeMemoryIfPossible(~0U);
64058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == canvas->storageAllocatedForRecording());
641363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
642363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
643363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void TestDeferredCanvasBitmapSizeThreshold(skiatest::Reporter* reporter) {
644363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkBitmap store;
645363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    store.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
646363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    store.allocPixels();
647363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
648363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkBitmap sourceImage;
649363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // 100 by 100 image, takes 40,000 bytes in memory
650363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    sourceImage.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
651363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    sourceImage.allocPixels();
652363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
653363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // 1 under : should not store the image
654363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    {
6550a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkBitmapDevice device(store);
656e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(&device));
65758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->setBitmapSizeThreshold(39999);
65858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawBitmap(sourceImage, 0, 0, NULL);
65958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        size_t newBytesAllocated = canvas->storageAllocatedForRecording();
660363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        REPORTER_ASSERT(reporter, newBytesAllocated == 0);
661363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
662363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
663363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // exact value : should store the image
664363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    {
6650a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkBitmapDevice device(store);
666e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(&device));
66758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->setBitmapSizeThreshold(40000);
66858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawBitmap(sourceImage, 0, 0, NULL);
66958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        size_t newBytesAllocated = canvas->storageAllocatedForRecording();
670363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        REPORTER_ASSERT(reporter, newBytesAllocated > 0);
671363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
672363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
673363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // 1 over : should still store the image
674363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    {
6750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkBitmapDevice device(store);
676e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(&device));
67758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->setBitmapSizeThreshold(40001);
67858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canvas->drawBitmap(sourceImage, 0, 0, NULL);
67958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        size_t newBytesAllocated = canvas->storageAllocatedForRecording();
680363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        REPORTER_ASSERT(reporter, newBytesAllocated > 0);
681363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
682363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
683363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
6847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
6857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergertypedef void* PixelPtr;
6867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// Returns an opaque pointer which, either points to a GrTexture or RAM pixel
6877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// buffer. Used to test pointer equality do determine whether a surface points
6887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// to the same pixel data storage as before.
6897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic PixelPtr getSurfacePixelPtr(SkSurface* surface, bool useGpu) {
6907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return useGpu ? surface->getCanvas()->getDevice()->accessBitmap(false).getTexture() :
6917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        surface->getCanvas()->getDevice()->accessBitmap(false).getPixels();
6927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
6937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
6947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void TestDeferredCanvasSurface(skiatest::Reporter* reporter, GrContextFactory* factory) {
6950a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkImageInfo imageSpec = {
6967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        10,  // width
6977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        10,  // height
6980a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        kPMColor_SkColorType,
6990a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        kPremul_SkAlphaType
7007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    };
7017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkSurface* surface;
7027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    bool useGpu = NULL != factory;
7037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#if SK_SUPPORT_GPU
7047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (useGpu) {
7057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        GrContext* context = factory->get(GrContextFactory::kNative_GLContextType);
706910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        if (NULL == context) {
707910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            return;
708910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        }
709910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
7107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        surface = SkSurface::NewRenderTarget(context, imageSpec);
7117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } else {
7127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        surface = SkSurface::NewRaster(imageSpec);
7137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
7147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#else
7157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkASSERT(!useGpu);
7167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    surface = SkSurface::NewRaster(imageSpec);
7177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif
7187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkASSERT(NULL != surface);
7197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkAutoTUnref<SkSurface> aur(surface);
720e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface));
7217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
72258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkImage* image1 = canvas->newImageSnapshot();
7237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkAutoTUnref<SkImage> aur_i1(image1);
7247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    PixelPtr pixels1 = getSurfacePixelPtr(surface, useGpu);
7257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // The following clear would normally trigger a copy on write, but
7267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // it won't because rendering is deferred.
72758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->clear(SK_ColorBLACK);
7287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Obtaining a snapshot directly from the surface (as opposed to the
7297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // SkDeferredCanvas) will not trigger a flush of deferred draw operations
7307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // and will therefore return the same image as the previous snapshot.
7317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkImage* image2 = surface->newImageSnapshot();
7327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkAutoTUnref<SkImage> aur_i2(image2);
7337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Images identical because of deferral
7347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    REPORTER_ASSERT(reporter, image1->uniqueID() == image2->uniqueID());
7357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Now we obtain a snpshot via the deferred canvas, which triggers a flush.
7367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Because there is a pending clear, this will generate a different image.
73758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkImage* image3 = canvas->newImageSnapshot();
7387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkAutoTUnref<SkImage> aur_i3(image3);
7397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    REPORTER_ASSERT(reporter, image1->uniqueID() != image3->uniqueID());
7407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Verify that backing store is now a different buffer because of copy on
7417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // write
7427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    PixelPtr pixels2 = getSurfacePixelPtr(surface, useGpu);
7437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    REPORTER_ASSERT(reporter, pixels1 != pixels2);
7447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Verify copy-on write with a draw operation that gets deferred by
7457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // the in order draw buffer.
7467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkPaint paint;
74758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->drawPaint(paint);
74858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkImage* image4 = canvas->newImageSnapshot();  // implicit flush
7497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkAutoTUnref<SkImage> aur_i4(image4);
7507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    REPORTER_ASSERT(reporter, image4->uniqueID() != image3->uniqueID());
7517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    PixelPtr pixels3 = getSurfacePixelPtr(surface, useGpu);
7527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    REPORTER_ASSERT(reporter, pixels2 != pixels3);
7537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Verify that a direct canvas flush with a pending draw does not trigger
7547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // a copy on write when the surface is not sharing its buffer with an
7557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // SkImage.
75658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->clear(SK_ColorWHITE);
75758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->flush();
7587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    PixelPtr pixels4 = getSurfacePixelPtr(surface, useGpu);
75958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->drawPaint(paint);
76058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->flush();
7617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    PixelPtr pixels5 = getSurfacePixelPtr(surface, useGpu);
7627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    REPORTER_ASSERT(reporter, pixels4 == pixels5);
7637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
7647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
765779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenbergerstatic void TestDeferredCanvasSetSurface(skiatest::Reporter* reporter, GrContextFactory* factory) {
7660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkImageInfo imageSpec = {
767779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        10,  // width
768779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        10,  // height
7690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        kPMColor_SkColorType,
7700a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        kPremul_SkAlphaType
771779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    };
772779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    SkSurface* surface;
773779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    SkSurface* alternateSurface;
774779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    bool useGpu = NULL != factory;
775779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger#if SK_SUPPORT_GPU
776779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    if (useGpu) {
777779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        GrContext* context = factory->get(GrContextFactory::kNative_GLContextType);
778910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        if (NULL == context) {
779910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            return;
780910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        }
781779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        surface = SkSurface::NewRenderTarget(context, imageSpec);
782779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        alternateSurface = SkSurface::NewRenderTarget(context, imageSpec);
783779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    } else {
784779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        surface = SkSurface::NewRaster(imageSpec);
785779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        alternateSurface = SkSurface::NewRaster(imageSpec);
786779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    }
787779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger#else
788779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    SkASSERT(!useGpu);
789779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    surface = SkSurface::NewRaster(imageSpec);
790779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    alternateSurface = SkSurface::NewRaster(imageSpec);
791779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger#endif
792779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    SkASSERT(NULL != surface);
793779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    SkASSERT(NULL != alternateSurface);
794779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    SkAutoTUnref<SkSurface> aur1(surface);
795779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    SkAutoTUnref<SkSurface> aur2(alternateSurface);
796779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    PixelPtr pixels1 = getSurfacePixelPtr(surface, useGpu);
797779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    PixelPtr pixels2 = getSurfacePixelPtr(alternateSurface, useGpu);
798e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface));
79958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkAutoTUnref<SkImage> image1(canvas->newImageSnapshot());
80058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->setSurface(alternateSurface);
80158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkAutoTUnref<SkImage> image2(canvas->newImageSnapshot());
802779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    REPORTER_ASSERT(reporter, image1->uniqueID() != image2->uniqueID());
803779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    // Verify that none of the above operations triggered a surface copy on write.
804779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    REPORTER_ASSERT(reporter, getSurfacePixelPtr(surface, useGpu) == pixels1);
805779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    REPORTER_ASSERT(reporter, getSurfacePixelPtr(alternateSurface, useGpu) == pixels2);
806779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    // Verify that a flushed draw command will trigger a copy on write on alternateSurface.
80758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->clear(SK_ColorWHITE);
80858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->flush();
809779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    REPORTER_ASSERT(reporter, getSurfacePixelPtr(surface, useGpu) == pixels1);
810779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    REPORTER_ASSERT(reporter, getSurfacePixelPtr(alternateSurface, useGpu) != pixels2);
811779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger}
812779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
8137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void TestDeferredCanvasCreateCompatibleDevice(skiatest::Reporter* reporter) {
8147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkBitmap store;
8157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    store.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
8167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    store.allocPixels();
8170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkBitmapDevice device(store);
8187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    NotificationCounter notificationCounter;
819e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(&device));
82058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->setNotificationClient(&notificationCounter);
8210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkAutoTUnref<SkBaseDevice> secondaryDevice(canvas->createCompatibleDevice(
8227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkBitmap::kARGB_8888_Config, 10, 10, device.isOpaque()));
8237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkCanvas secondaryCanvas(secondaryDevice.get());
8247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkRect rect = SkRect::MakeWH(5, 5);
8257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkPaint paint;
8267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // After spawning a compatible canvas:
8277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // 1) Verify that secondary canvas is usable and does not report to the notification client.
8287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    secondaryCanvas.drawRect(rect, paint);
8297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    REPORTER_ASSERT(reporter, notificationCounter.fStorageAllocatedChangedCount == 0);
8307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // 2) Verify that original canvas is usable and still reports to the notification client.
83158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    canvas->drawRect(rect, paint);
8327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    REPORTER_ASSERT(reporter, notificationCounter.fStorageAllocatedChangedCount == 1);
8337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
8347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
8357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void TestDeferredCanvas(skiatest::Reporter* reporter, GrContextFactory* factory) {
83680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    TestDeferredCanvasBitmapAccess(reporter);
83780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    TestDeferredCanvasFlush(reporter);
83880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    TestDeferredCanvasFreshFrame(reporter);
83980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    TestDeferredCanvasMemoryLimit(reporter);
84080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    TestDeferredCanvasBitmapCaching(reporter);
84180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    TestDeferredCanvasSkip(reporter);
842363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    TestDeferredCanvasBitmapShaderNoLeak(reporter);
843363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    TestDeferredCanvasBitmapSizeThreshold(reporter);
8447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    TestDeferredCanvasCreateCompatibleDevice(reporter);
845e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    TestDeferredCanvasWritePixelsToSurface(reporter);
8467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    TestDeferredCanvasSurface(reporter, NULL);
847779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    TestDeferredCanvasSetSurface(reporter, NULL);
8487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (NULL != factory) {
8497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        TestDeferredCanvasSurface(reporter, factory);
850779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        TestDeferredCanvasSetSurface(reporter, factory);
8517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
85280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
85380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
85480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "TestClassDef.h"
8557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerDEFINE_GPUTESTCLASS("DeferredCanvas", TestDeferredCanvasClass, TestDeferredCanvas)
856