1
2/*
3 * Copyright 2012 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "Test.h"
9#include "SkBitmap.h"
10#include "SkDeferredCanvas.h"
11#include "SkShader.h"
12
13
14static const int gWidth = 2;
15static const int gHeight = 2;
16
17static void create(SkBitmap* bm, SkBitmap::Config config, SkColor color) {
18    bm->setConfig(config, gWidth, gHeight);
19    bm->allocPixels();
20    bm->eraseColor(color);
21}
22
23static void TestDeferredCanvasBitmapAccess(skiatest::Reporter* reporter) {
24    SkBitmap store;
25
26    create(&store, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
27    SkDevice device(store);
28    SkDeferredCanvas canvas(&device);
29
30    canvas.clear(0x00000000);
31
32    SkAutoLockPixels alp(store);
33    REPORTER_ASSERT(reporter, store.getColor(0,0) == 0xFFFFFFFF); //verify that clear was deferred
34    SkBitmap accessed = canvas.getDevice()->accessBitmap(false);
35    REPORTER_ASSERT(reporter, store.getColor(0,0) == 0x00000000); //verify that clear was executed
36    REPORTER_ASSERT(reporter, accessed.pixelRef() == store.pixelRef());
37}
38
39static void TestDeferredCanvasFlush(skiatest::Reporter* reporter) {
40    SkBitmap store;
41
42    create(&store, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
43    SkDevice device(store);
44    SkDeferredCanvas canvas(&device);
45
46    canvas.clear(0x00000000);
47
48    SkAutoLockPixels alp(store);
49    REPORTER_ASSERT(reporter, store.getColor(0,0) == 0xFFFFFFFF); //verify that clear was deferred
50    canvas.flush();
51    REPORTER_ASSERT(reporter, store.getColor(0,0) == 0x00000000); //verify that clear was executed
52}
53
54static void TestDeferredCanvasFreshFrame(skiatest::Reporter* reporter) {
55    SkBitmap store;
56    SkRect fullRect;
57    fullRect.setXYWH(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(gWidth),
58        SkIntToScalar(gHeight));
59    SkRect partialRect;
60    partialRect.setXYWH(SkIntToScalar(0), SkIntToScalar(0),
61        SkIntToScalar(1), SkIntToScalar(1));
62    create(&store, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
63    SkDevice device(store);
64    SkDeferredCanvas canvas(&device);
65
66    // verify that frame is intially fresh
67    REPORTER_ASSERT(reporter, canvas.getDeferredDevice()->isFreshFrame());
68    // no clearing op since last call to isFreshFrame -> not fresh
69    REPORTER_ASSERT(reporter, !canvas.getDeferredDevice()->isFreshFrame());
70
71    // Verify that clear triggers a fresh frame
72    canvas.clear(0x00000000);
73    REPORTER_ASSERT(reporter, canvas.getDeferredDevice()->isFreshFrame());
74
75    // Verify that clear with saved state triggers a fresh frame
76    canvas.save(SkCanvas::kMatrixClip_SaveFlag);
77    canvas.clear(0x00000000);
78    canvas.restore();
79    REPORTER_ASSERT(reporter, canvas.getDeferredDevice()->isFreshFrame());
80
81    // Verify that clear within a layer does NOT trigger a fresh frame
82    canvas.saveLayer(NULL, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag);
83    canvas.clear(0x00000000);
84    canvas.restore();
85    REPORTER_ASSERT(reporter, !canvas.getDeferredDevice()->isFreshFrame());
86
87    // Verify that a clear with clipping triggers a fresh frame
88    // (clear is not affected by clipping)
89    canvas.save(SkCanvas::kMatrixClip_SaveFlag);
90    canvas.clipRect(partialRect, SkRegion::kIntersect_Op, false);
91    canvas.clear(0x00000000);
92    canvas.restore();
93    REPORTER_ASSERT(reporter, canvas.getDeferredDevice()->isFreshFrame());
94
95    // Verify that full frame rects with different forms of opaque paint
96    // trigger frames to be marked as fresh
97    {
98        SkPaint paint;
99        paint.setStyle( SkPaint::kFill_Style );
100        paint.setAlpha( 255 );
101        canvas.drawRect(fullRect, paint);
102        REPORTER_ASSERT(reporter, canvas.getDeferredDevice()->isFreshFrame());
103    }
104    {
105        SkPaint paint;
106        paint.setStyle( SkPaint::kFill_Style );
107        SkBitmap bmp;
108        create(&bmp, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
109        bmp.setIsOpaque(true);
110        SkShader* shader = SkShader::CreateBitmapShader(bmp,
111            SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
112        paint.setShader(shader)->unref();
113        canvas.drawRect(fullRect, paint);
114        REPORTER_ASSERT(reporter, canvas.getDeferredDevice()->isFreshFrame());
115    }
116
117    // Verify that full frame rects with different forms of non-opaque paint
118    // do not trigger frames to be marked as fresh
119    {
120        SkPaint paint;
121        paint.setStyle( SkPaint::kFill_Style );
122        paint.setAlpha( 254 );
123        canvas.drawRect(fullRect, paint);
124        REPORTER_ASSERT(reporter, !canvas.getDeferredDevice()->isFreshFrame());
125    }
126    {
127        SkPaint paint;
128        paint.setStyle( SkPaint::kFill_Style );
129        SkBitmap bmp;
130        create(&bmp, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
131        bmp.setIsOpaque(false);
132        SkShader* shader = SkShader::CreateBitmapShader(bmp,
133            SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
134        paint.setShader(shader)->unref();
135        canvas.drawRect(fullRect, paint);
136        REPORTER_ASSERT(reporter, !canvas.getDeferredDevice()->isFreshFrame());
137    }
138
139    // Verify that incomplete coverage does not trigger a fresh frame
140    {
141        SkPaint paint;
142        paint.setStyle(SkPaint::kFill_Style);
143        paint.setAlpha(255);
144        canvas.drawRect(partialRect, paint);
145        REPORTER_ASSERT(reporter, !canvas.getDeferredDevice()->isFreshFrame());
146    }
147
148    // Verify that incomplete coverage due to clipping does not trigger a fresh
149    // frame
150    {
151        canvas.save(SkCanvas::kMatrixClip_SaveFlag);
152        canvas.clipRect(partialRect, SkRegion::kIntersect_Op, false);
153        SkPaint paint;
154        paint.setStyle(SkPaint::kFill_Style);
155        paint.setAlpha(255);
156        canvas.drawRect(fullRect, paint);
157        REPORTER_ASSERT(reporter, !canvas.getDeferredDevice()->isFreshFrame());
158    }
159
160    // Verify that stroked rect does not trigger a fresh frame
161    {
162        SkPaint paint;
163        paint.setStyle( SkPaint::kStroke_Style );
164        paint.setAlpha( 255 );
165        canvas.drawRect(fullRect, paint);
166        REPORTER_ASSERT(reporter, !canvas.getDeferredDevice()->isFreshFrame());
167    }
168
169    // Verify kSrcMode triggers a fresh frame even with transparent color
170    {
171        SkPaint paint;
172        paint.setStyle( SkPaint::kFill_Style );
173        paint.setAlpha( 100 );
174        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
175        canvas.drawRect(fullRect, paint);
176        REPORTER_ASSERT(reporter, !canvas.getDeferredDevice()->isFreshFrame());
177    }
178}
179
180static void TestDeferredCanvas(skiatest::Reporter* reporter) {
181    TestDeferredCanvasBitmapAccess(reporter);
182    TestDeferredCanvasFlush(reporter);
183    TestDeferredCanvasFreshFrame(reporter);
184}
185
186#include "TestClassDef.h"
187DEFINE_TESTCLASS("DeferredCanvas", TestDeferredCanvasClass, TestDeferredCanvas)
188