OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "../src/image/SkImagePriv.h" | 8 #include "../src/image/SkImagePriv.h" |
9 #include "../src/image/SkSurface_Base.h" | 9 #include "../src/image/SkSurface_Base.h" |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 SkPMColor pixel = 0; | 41 SkPMColor pixel = 0; |
42 SkBitmap bitmap; | 42 SkBitmap bitmap; |
43 bitmap.installPixels(SkImageInfo::MakeN32Premul(1, 1), &pixel, 4); | 43 bitmap.installPixels(SkImageInfo::MakeN32Premul(1, 1), &pixel, 4); |
44 SkCanvas canvas(bitmap); | 44 SkCanvas canvas(bitmap); |
45 | 45 |
46 SkPaint paint; | 46 SkPaint paint; |
47 paint.setXfermodeMode(SkXfermode::kSrc_Mode); | 47 paint.setXfermodeMode(SkXfermode::kSrc_Mode); |
48 surface->draw(&canvas, -SkIntToScalar(x), -SkIntToScalar(y), &paint); | 48 surface->draw(&canvas, -SkIntToScalar(x), -SkIntToScalar(y), &paint); |
49 return pixel; | 49 return pixel; |
50 } | 50 } |
| 51 class MockSurface; |
| 52 class MockDevice : public SkBitmapDevice { |
| 53 public: |
| 54 MockDevice(MockSurface* surface, const SkBitmap& bm) : SkBitmapDevice(bm), f
Surface(surface) { |
| 55 } |
| 56 void discard() SK_OVERRIDE; |
| 57 private: |
| 58 MockSurface* fSurface; |
| 59 typedef SkBitmapDevice INHERITED; |
| 60 }; |
51 | 61 |
52 class MockSurface : public SkSurface_Base { | 62 class MockSurface : public SkSurface_Base { |
53 public: | 63 public: |
54 MockSurface(int width, int height) : SkSurface_Base(width, height, NULL) { | 64 MockSurface(int width, int height) : SkSurface_Base(width, height, NULL) { |
55 clearCounts(); | 65 clearCounts(); |
56 fBitmap.allocN32Pixels(width, height); | 66 |
| 67 SkBitmap bitmap; |
| 68 bitmap.allocN32Pixels(width, height); |
| 69 fDevice.reset(SkNEW_ARGS(MockDevice, (this, bitmap))); |
| 70 fDeviceGenerationID = fDevice->accessBitmap(false).getGenerationID(); |
| 71 fGenerationID = this->newGenerationID(); |
57 } | 72 } |
58 | 73 |
59 SkCanvas* onNewCanvas() SK_OVERRIDE { | 74 SkCanvas* onNewCanvas() SK_OVERRIDE { |
60 return SkNEW_ARGS(SkCanvas, (fBitmap)); | 75 return SkNEW_ARGS(SkCanvas, (fDevice)); |
61 } | 76 } |
62 | 77 |
63 SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE { | 78 SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE { |
64 return NULL; | 79 return NULL; |
65 } | 80 } |
66 | 81 |
67 SkImage* onNewImageSnapshot(Budgeted) SK_OVERRIDE { | 82 SkImage* onNewImageSnapshot(Budgeted) SK_OVERRIDE { |
68 return SkNewImageFromBitmap(fBitmap, &this->props()); | 83 return fDevice->newImageSnapshot(); |
69 } | 84 } |
70 | 85 |
71 void onCopyOnWrite(ContentChangeMode mode) SK_OVERRIDE { | 86 uint32_t generationID() SK_OVERRIDE { |
72 if (mode == SkSurface::kDiscard_ContentChangeMode) { | 87 uint32_t deviceGenerationID = fDevice->accessBitmap(false).getGeneration
ID(); |
73 fCOWDiscardCount++; | 88 if (fDeviceGenerationID != deviceGenerationID) { |
74 } else { | 89 fDeviceGenerationID = deviceGenerationID; |
75 fCOWRetainCount++; | 90 fGenerationID = this->newGenerationID(); |
76 } | 91 } |
| 92 return fGenerationID; |
77 } | 93 } |
78 | 94 |
79 void onDiscard() SK_OVERRIDE { | 95 void incDiscardCount() { |
80 fDiscardCount++; | 96 fDiscardCount++; |
81 } | 97 } |
82 | 98 |
83 void clearCounts() { | 99 void clearCounts() { |
84 fCOWDiscardCount = 0; | |
85 fCOWRetainCount = 0; | |
86 fDiscardCount = 0; | 100 fDiscardCount = 0; |
87 } | 101 } |
88 | 102 |
89 int fCOWDiscardCount; | 103 SkAutoTUnref<MockDevice> fDevice; |
90 int fCOWRetainCount; | 104 uint32_t fDeviceGenerationID; |
| 105 uint32_t fGenerationID; |
| 106 |
91 int fDiscardCount; | 107 int fDiscardCount; |
92 SkBitmap fBitmap; | |
93 }; | 108 }; |
94 | 109 |
| 110 void MockDevice::discard() { |
| 111 if (fSurface) { |
| 112 fSurface->incDiscardCount(); |
| 113 } |
| 114 this->INHERITED::discard(); |
| 115 } |
| 116 |
95 static void TestDeferredCanvasWritePixelsToSurface(skiatest::Reporter* reporter)
{ | 117 static void TestDeferredCanvasWritePixelsToSurface(skiatest::Reporter* reporter)
{ |
96 SkAutoTUnref<MockSurface> surface(SkNEW_ARGS(MockSurface, (10, 10))); | 118 SkAutoTUnref<MockSurface> surface(SkNEW_ARGS(MockSurface, (10, 10))); |
97 SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()
)); | 119 SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()
)); |
98 | 120 |
99 SkBitmap srcBitmap; | 121 SkBitmap srcBitmap; |
100 srcBitmap.allocPixels(SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kUnp
remul_SkAlphaType)); | 122 srcBitmap.allocPixels(SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kUnp
remul_SkAlphaType)); |
101 srcBitmap.eraseColor(SK_ColorGREEN); | 123 srcBitmap.eraseColor(SK_ColorGREEN); |
102 // Tests below depend on this bitmap being recognized as opaque | 124 // Tests below depend on this bitmap being recognized as opaque |
103 | 125 |
104 // Preliminary sanity check: no copy on write if no active snapshot | 126 |
105 // Discard notification happens on SkSurface::onDiscard, since no | 127 // Case 0: SkBaseDevice::discard is called even when clear is the first comm
and. |
106 // active snapshot. | 128 // The call is made only after flush. |
| 129 uint32_t surfaceID = surface->generationID(); |
107 surface->clearCounts(); | 130 surface->clearCounts(); |
108 canvas->clear(SK_ColorWHITE); | 131 canvas->clear(SK_ColorWHITE); |
109 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
110 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
111 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 132 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 133 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
112 | 134 |
| 135 surfaceID = surface->generationID(); |
113 surface->clearCounts(); | 136 surface->clearCounts(); |
114 canvas->flush(); | 137 canvas->flush(); |
115 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
116 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
117 REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount); | 138 REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount); |
| 139 REPORTER_ASSERT(reporter, surfaceID != surface->generationID()); |
118 | 140 |
119 // Case 1: Discard notification happens upon flushing | 141 // Case 1: SkBaseDevice::discard is called upon flushing |
120 // with an Image attached. | 142 // with an Image attached. |
| 143 surfaceID = surface->generationID(); |
121 surface->clearCounts(); | 144 surface->clearCounts(); |
122 SkAutoTUnref<SkImage> image1(canvas->newImageSnapshot()); | 145 SkAutoTUnref<SkImage> image1(canvas->newImageSnapshot()); |
123 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
124 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
125 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 146 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 147 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
126 | 148 |
| 149 surfaceID = surface->generationID(); |
127 surface->clearCounts(); | 150 surface->clearCounts(); |
128 canvas->clear(SK_ColorWHITE); | 151 canvas->clear(SK_ColorWHITE); |
129 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
130 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
131 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 152 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 153 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
132 | 154 |
| 155 surfaceID = surface->generationID(); |
133 surface->clearCounts(); | 156 surface->clearCounts(); |
134 canvas->flush(); | 157 canvas->flush(); |
135 REPORTER_ASSERT(reporter, 1 == surface->fCOWDiscardCount); | 158 REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount); |
136 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | 159 REPORTER_ASSERT(reporter, surfaceID != surface->generationID()); |
137 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | |
138 | 160 |
139 // Case 2: Opaque writePixels | 161 // Case 2: Opaque writePixels |
| 162 surfaceID = surface->generationID(); |
140 surface->clearCounts(); | 163 surface->clearCounts(); |
141 SkAutoTUnref<SkImage> image2(canvas->newImageSnapshot()); | 164 SkAutoTUnref<SkImage> image2(canvas->newImageSnapshot()); |
142 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
143 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
144 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 165 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 166 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
145 | 167 |
146 // Case 3: writePixels that partially covers the canvas | 168 // Case 3: writePixels that partially covers the canvas |
| 169 surfaceID = surface->generationID(); |
147 surface->clearCounts(); | 170 surface->clearCounts(); |
148 SkAutoTUnref<SkImage> image3(canvas->newImageSnapshot()); | 171 SkAutoTUnref<SkImage> image3(canvas->newImageSnapshot()); |
149 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
150 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
151 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 172 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 173 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
152 | 174 |
153 // Case 4: unpremultiplied opaque writePixels that entirely | 175 // Case 4: unpremultiplied opaque writePixels that entirely |
154 // covers the canvas | 176 // covers the canvas |
| 177 surfaceID = surface->generationID(); |
155 surface->clearCounts(); | 178 surface->clearCounts(); |
156 SkAutoTUnref<SkImage> image4(canvas->newImageSnapshot()); | 179 SkAutoTUnref<SkImage> image4(canvas->newImageSnapshot()); |
157 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
158 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
159 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 180 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 181 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
160 | 182 |
| 183 surfaceID = surface->generationID(); |
161 surface->clearCounts(); | 184 surface->clearCounts(); |
162 canvas->writePixels(srcBitmap, 0, 0); | 185 canvas->writePixels(srcBitmap, 0, 0); |
163 REPORTER_ASSERT(reporter, 1 == surface->fCOWDiscardCount); | 186 REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount); |
164 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | 187 REPORTER_ASSERT(reporter, surfaceID != surface->generationID()); |
165 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | |
166 | 188 |
| 189 surfaceID = surface->generationID(); |
167 surface->clearCounts(); | 190 surface->clearCounts(); |
168 canvas->flush(); | 191 canvas->flush(); |
169 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
170 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
171 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 192 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 193 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
172 | 194 |
173 // Case 5: unpremultiplied opaque writePixels that partially | 195 // Case 5: unpremultiplied opaque writePixels that partially |
174 // covers the canvas | 196 // covers the canvas. The surface changes immediately. |
| 197 surfaceID = surface->generationID(); |
175 surface->clearCounts(); | 198 surface->clearCounts(); |
176 SkAutoTUnref<SkImage> image5(canvas->newImageSnapshot()); | 199 SkAutoTUnref<SkImage> image5(canvas->newImageSnapshot()); |
177 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
178 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
179 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 200 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 201 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
180 | 202 |
| 203 surfaceID = surface->generationID(); |
181 surface->clearCounts(); | 204 surface->clearCounts(); |
182 canvas->writePixels(srcBitmap, 5, 0); | 205 canvas->writePixels(srcBitmap, 5, 0); |
183 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
184 REPORTER_ASSERT(reporter, 1 == surface->fCOWRetainCount); | |
185 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 206 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 207 REPORTER_ASSERT(reporter, surfaceID != surface->generationID()); |
186 | 208 |
| 209 surfaceID = surface->generationID(); |
187 surface->clearCounts(); | 210 surface->clearCounts(); |
188 canvas->flush(); | 211 canvas->flush(); |
189 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
190 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
191 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 212 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 213 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
192 | 214 |
193 // Case 6: unpremultiplied opaque writePixels that entirely | 215 // Case 6: unpremultiplied opaque writePixels that entirely |
194 // covers the canvas, preceded by clear | 216 // covers the canvas, preceded by clear. |
| 217 surfaceID = surface->generationID(); |
195 surface->clearCounts(); | 218 surface->clearCounts(); |
196 SkAutoTUnref<SkImage> image6(canvas->newImageSnapshot()); | 219 SkAutoTUnref<SkImage> image6(canvas->newImageSnapshot()); |
197 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
198 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
199 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 220 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 221 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
200 | 222 |
| 223 surfaceID = surface->generationID(); |
201 surface->clearCounts(); | 224 surface->clearCounts(); |
202 canvas->clear(SK_ColorWHITE); | 225 canvas->clear(SK_ColorWHITE); |
203 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
204 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
205 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 226 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 227 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
206 | 228 |
| 229 surfaceID = surface->generationID(); |
207 surface->clearCounts(); | 230 surface->clearCounts(); |
208 canvas->writePixels(srcBitmap, 0, 0); | 231 canvas->writePixels(srcBitmap, 0, 0); |
209 REPORTER_ASSERT(reporter, 1 == surface->fCOWDiscardCount); | 232 REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount); |
210 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | 233 REPORTER_ASSERT(reporter, surfaceID != surface->generationID()); |
211 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | |
212 | 234 |
| 235 surfaceID = surface->generationID(); |
213 surface->clearCounts(); | 236 surface->clearCounts(); |
214 canvas->flush(); | 237 canvas->flush(); |
215 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
216 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
217 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 238 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 239 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
218 | 240 |
219 // Case 7: unpremultiplied opaque writePixels that partially | 241 // Case 7: unpremultiplied opaque writePixels that partially |
220 // covers the canvas, preceeded by a clear | 242 // covers the canvas, preceeded by a clear |
| 243 surfaceID = surface->generationID(); |
221 surface->clearCounts(); | 244 surface->clearCounts(); |
222 SkAutoTUnref<SkImage> image7(canvas->newImageSnapshot()); | 245 SkAutoTUnref<SkImage> image7(canvas->newImageSnapshot()); |
223 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
224 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
225 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 246 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 247 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
226 | 248 |
| 249 surfaceID = surface->generationID(); |
227 surface->clearCounts(); | 250 surface->clearCounts(); |
228 canvas->clear(SK_ColorWHITE); | 251 canvas->clear(SK_ColorWHITE); |
229 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
230 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
231 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 252 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 253 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
232 | 254 |
| 255 surfaceID = surface->generationID(); |
233 surface->clearCounts(); | 256 surface->clearCounts(); |
234 canvas->writePixels(srcBitmap, 5, 0); | 257 canvas->writePixels(srcBitmap, 5, 0); |
235 REPORTER_ASSERT(reporter, 1 == surface->fCOWDiscardCount); // because of the
clear | 258 REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount); // because of the cl
ear |
236 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | 259 REPORTER_ASSERT(reporter, surfaceID != surface->generationID()); |
237 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | |
238 | 260 |
| 261 surfaceID = surface->generationID(); |
239 surface->clearCounts(); | 262 surface->clearCounts(); |
240 canvas->flush(); | 263 canvas->flush(); |
241 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
242 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
243 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 264 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 265 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
244 | 266 |
245 // Case 8: unpremultiplied opaque writePixels that partially | 267 // Case 8: unpremultiplied opaque writePixels that partially |
246 // covers the canvas, preceeded by a drawREct that partially | 268 // covers the canvas, preceeded by a drawREct that partially |
247 // covers the canvas | 269 // covers the canvas |
| 270 surfaceID = surface->generationID(); |
248 surface->clearCounts(); | 271 surface->clearCounts(); |
249 SkAutoTUnref<SkImage> image8(canvas->newImageSnapshot()); | 272 SkAutoTUnref<SkImage> image8(canvas->newImageSnapshot()); |
250 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
251 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
252 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 273 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 274 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
253 | 275 |
| 276 surfaceID = surface->generationID(); |
254 surface->clearCounts(); | 277 surface->clearCounts(); |
255 SkPaint paint; | 278 SkPaint paint; |
256 canvas->drawRect(SkRect::MakeLTRB(0, 0, 5, 5), paint); | 279 canvas->drawRect(SkRect::MakeLTRB(0, 0, 5, 5), paint); |
257 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
258 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
259 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 280 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 281 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
260 | 282 |
| 283 surfaceID = surface->generationID(); |
261 surface->clearCounts(); | 284 surface->clearCounts(); |
262 canvas->writePixels(srcBitmap, 5, 0); | 285 canvas->writePixels(srcBitmap, 5, 0); |
263 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
264 REPORTER_ASSERT(reporter, 1 == surface->fCOWRetainCount); | |
265 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 286 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 287 REPORTER_ASSERT(reporter, surfaceID != surface->generationID()); |
266 | 288 |
| 289 surfaceID = surface->generationID(); |
267 surface->clearCounts(); | 290 surface->clearCounts(); |
268 canvas->flush(); | 291 canvas->flush(); |
269 REPORTER_ASSERT(reporter, 0 == surface->fCOWDiscardCount); | |
270 REPORTER_ASSERT(reporter, 0 == surface->fCOWRetainCount); | |
271 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); | 292 REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); |
| 293 REPORTER_ASSERT(reporter, surfaceID == surface->generationID()); |
272 } | 294 } |
273 | 295 |
274 static void TestDeferredCanvasFlush(skiatest::Reporter* reporter) { | 296 static void TestDeferredCanvasFlush(skiatest::Reporter* reporter) { |
275 SkAutoTUnref<SkSurface> surface(createSurface(0xFFFFFFFF)); | 297 SkAutoTUnref<SkSurface> surface(createSurface(0xFFFFFFFF)); |
276 SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()
)); | 298 SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()
)); |
277 | 299 |
278 canvas->clear(0x00000000); | 300 canvas->clear(0x00000000); |
279 | 301 |
280 // verify that clear was deferred | 302 // verify that clear was deferred |
281 REPORTER_ASSERT(reporter, 0xFFFFFFFF == read_pixel(surface, 0, 0)); | 303 REPORTER_ASSERT(reporter, 0xFFFFFFFF == read_pixel(surface, 0, 0)); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 { | 455 { |
434 SkPaint paint; | 456 SkPaint paint; |
435 paint.setStyle(SkPaint::kFill_Style); | 457 paint.setStyle(SkPaint::kFill_Style); |
436 paint.setAlpha(100); | 458 paint.setAlpha(100); |
437 paint.setXfermodeMode(SkXfermode::kSrc_Mode); | 459 paint.setXfermodeMode(SkXfermode::kSrc_Mode); |
438 canvas->drawRect(fullRect, paint); | 460 canvas->drawRect(fullRect, paint); |
439 REPORTER_ASSERT(reporter, canvas->isFreshFrame()); | 461 REPORTER_ASSERT(reporter, canvas->isFreshFrame()); |
440 } | 462 } |
441 } | 463 } |
442 | 464 |
443 class MockDevice : public SkBitmapDevice { | |
444 public: | |
445 MockDevice(const SkBitmap& bm) : SkBitmapDevice(bm) { | |
446 fDrawBitmapCallCount = 0; | |
447 } | |
448 virtual void drawBitmap(const SkDraw&, const SkBitmap&, | |
449 const SkMatrix&, const SkPaint&) SK_OVERRIDE { | |
450 fDrawBitmapCallCount++; | |
451 } | |
452 | |
453 int fDrawBitmapCallCount; | |
454 }; | |
455 | |
456 class NotificationCounter : public SkDeferredCanvas::NotificationClient { | 465 class NotificationCounter : public SkDeferredCanvas::NotificationClient { |
457 public: | 466 public: |
458 NotificationCounter() { | 467 NotificationCounter() { |
459 fPrepareForDrawCount = fStorageAllocatedChangedCount = | 468 fPrepareForDrawCount = fStorageAllocatedChangedCount = |
460 fFlushedDrawCommandsCount = fSkippedPendingDrawCommandsCount = 0; | 469 fFlushedDrawCommandsCount = fSkippedPendingDrawCommandsCount = 0; |
461 } | 470 } |
462 | 471 |
463 void prepareForDraw() SK_OVERRIDE { | 472 void prepareForDraw() SK_OVERRIDE { |
464 fPrepareForDrawCount++; | 473 fPrepareForDrawCount++; |
465 } | 474 } |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
682 // 1 over : should still store the image | 691 // 1 over : should still store the image |
683 { | 692 { |
684 SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.g
et())); | 693 SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.g
et())); |
685 canvas->setBitmapSizeThreshold(40001); | 694 canvas->setBitmapSizeThreshold(40001); |
686 canvas->drawBitmap(sourceImage, 0, 0, NULL); | 695 canvas->drawBitmap(sourceImage, 0, 0, NULL); |
687 size_t newBytesAllocated = canvas->storageAllocatedForRecording(); | 696 size_t newBytesAllocated = canvas->storageAllocatedForRecording(); |
688 REPORTER_ASSERT(reporter, newBytesAllocated > 0); | 697 REPORTER_ASSERT(reporter, newBytesAllocated > 0); |
689 } | 698 } |
690 } | 699 } |
691 | 700 |
692 | |
693 typedef const void* PixelPtr; | |
694 // Returns an opaque pointer which, either points to a GrTexture or RAM pixel | |
695 // buffer. Used to test pointer equality do determine whether a surface points | |
696 // to the same pixel data storage as before. | |
697 static PixelPtr get_surface_ptr(SkSurface* surface, bool useGpu) { | |
698 #if SK_SUPPORT_GPU | |
699 if (useGpu) { | |
700 return surface->getCanvas()->internal_private_accessTopLayerRenderTarget
()->asTexture(); | |
701 } else | |
702 #endif | |
703 { | |
704 return surface->peekPixels(NULL, NULL); | |
705 } | |
706 } | |
707 | |
708 static void TestDeferredCanvasSurface(skiatest::Reporter* reporter, GrContextFac
tory* factory) { | 701 static void TestDeferredCanvasSurface(skiatest::Reporter* reporter, GrContextFac
tory* factory) { |
709 SkImageInfo imageSpec = SkImageInfo::MakeN32Premul(10, 10); | 702 SkImageInfo imageSpec = SkImageInfo::MakeN32Premul(10, 10); |
710 bool useGpu = SkToBool(factory); | 703 bool useGpu = SkToBool(factory); |
711 int cnt; | 704 int cnt; |
712 #if SK_SUPPORT_GPU | 705 #if SK_SUPPORT_GPU |
713 if (useGpu) { | 706 if (useGpu) { |
714 cnt = GrContextFactory::kGLContextTypeCnt; | 707 cnt = GrContextFactory::kGLContextTypeCnt; |
715 } else { | 708 } else { |
716 cnt = 1; | 709 cnt = 1; |
717 } | 710 } |
(...skipping 20 matching lines...) Expand all Loading... |
738 #endif | 731 #endif |
739 { | 732 { |
740 surface = SkSurface::NewRaster(imageSpec); | 733 surface = SkSurface::NewRaster(imageSpec); |
741 } | 734 } |
742 SkASSERT(surface); | 735 SkASSERT(surface); |
743 SkAutoTUnref<SkSurface> aur(surface); | 736 SkAutoTUnref<SkSurface> aur(surface); |
744 SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface))
; | 737 SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface))
; |
745 | 738 |
746 SkImage* image1 = canvas->newImageSnapshot(); | 739 SkImage* image1 = canvas->newImageSnapshot(); |
747 SkAutoTUnref<SkImage> aur_i1(image1); | 740 SkAutoTUnref<SkImage> aur_i1(image1); |
748 PixelPtr pixels1 = get_surface_ptr(surface, useGpu); | 741 // The following clear would normally trigger a surface modification, bu
t |
749 // The following clear would normally trigger a copy on write, but | |
750 // it won't because rendering is deferred. | 742 // it won't because rendering is deferred. |
751 canvas->clear(SK_ColorBLACK); | 743 canvas->clear(SK_ColorBLACK); |
| 744 uint32_t genid1 = surface->generationID(); |
752 // Obtaining a snapshot directly from the surface (as opposed to the | 745 // Obtaining a snapshot directly from the surface (as opposed to the |
753 // SkDeferredCanvas) will not trigger a flush of deferred draw operation
s | 746 // SkDeferredCanvas) will not trigger a flush of deferred draw operation
s |
754 // and will therefore return the same image as the previous snapshot. | 747 // and will therefore return the same image as the previous snapshot. |
755 SkImage* image2 = surface->newImageSnapshot(); | 748 SkImage* image2 = surface->newImageSnapshot(); |
756 SkAutoTUnref<SkImage> aur_i2(image2); | 749 SkAutoTUnref<SkImage> aur_i2(image2); |
757 // Images identical because of deferral | 750 // Images identical because of deferral |
758 REPORTER_ASSERT(reporter, image1->uniqueID() == image2->uniqueID()); | 751 REPORTER_ASSERT(reporter, image1->uniqueID() == image2->uniqueID()); |
| 752 uint32_t genid2 = surface->generationID(); |
759 // Now we obtain a snpshot via the deferred canvas, which triggers a flu
sh. | 753 // Now we obtain a snpshot via the deferred canvas, which triggers a flu
sh. |
760 // Because there is a pending clear, this will generate a different imag
e. | 754 // Because there is a pending clear, this will generate a different imag
e. |
761 SkImage* image3 = canvas->newImageSnapshot(); | 755 SkImage* image3 = canvas->newImageSnapshot(); |
762 SkAutoTUnref<SkImage> aur_i3(image3); | 756 SkAutoTUnref<SkImage> aur_i3(image3); |
763 REPORTER_ASSERT(reporter, image1->uniqueID() != image3->uniqueID()); | 757 REPORTER_ASSERT(reporter, image1->uniqueID() != image3->uniqueID()); |
764 // Verify that backing store is now a different buffer because of copy o
n | 758 // Verify that backing store is now a different buffer because of change
d |
765 // write | 759 // surface generation id. |
766 PixelPtr pixels2 = get_surface_ptr(surface, useGpu); | 760 uint32_t genid3 = surface->generationID(); |
767 REPORTER_ASSERT(reporter, pixels1 != pixels2); | 761 REPORTER_ASSERT(reporter, genid1 == genid2); |
768 // Verify copy-on write with a draw operation that gets deferred by | 762 REPORTER_ASSERT(reporter, genid1 != genid3); |
| 763 // Verify surface modification with a draw operation that gets deferred
by |
769 // the in order draw buffer. | 764 // the in order draw buffer. |
770 SkPaint paint; | 765 SkPaint paint; |
771 canvas->drawPaint(paint); | 766 canvas->drawPaint(paint); |
772 SkImage* image4 = canvas->newImageSnapshot(); // implicit flush | 767 SkImage* image4 = canvas->newImageSnapshot(); // implicit flush |
773 SkAutoTUnref<SkImage> aur_i4(image4); | 768 SkAutoTUnref<SkImage> aur_i4(image4); |
774 REPORTER_ASSERT(reporter, image4->uniqueID() != image3->uniqueID()); | 769 REPORTER_ASSERT(reporter, image3->uniqueID() != image4->uniqueID()); |
775 PixelPtr pixels3 = get_surface_ptr(surface, useGpu); | 770 uint32_t genid4 = surface->generationID(); |
776 REPORTER_ASSERT(reporter, pixels2 != pixels3); | 771 REPORTER_ASSERT(reporter, genid3 != genid4); |
777 // Verify that a direct canvas flush with a pending draw does not trigge
r | |
778 // a copy on write when the surface is not sharing its buffer with an | |
779 // SkImage. | |
780 canvas->clear(SK_ColorWHITE); | |
781 canvas->flush(); | |
782 PixelPtr pixels4 = get_surface_ptr(surface, useGpu); | |
783 canvas->drawPaint(paint); | |
784 canvas->flush(); | |
785 PixelPtr pixels5 = get_surface_ptr(surface, useGpu); | |
786 REPORTER_ASSERT(reporter, pixels4 == pixels5); | |
787 } | 772 } |
788 } | 773 } |
789 | 774 |
790 static void TestDeferredCanvasSetSurface(skiatest::Reporter* reporter, GrContext
Factory* factory) { | 775 static void TestDeferredCanvasSetSurface(skiatest::Reporter* reporter, GrContext
Factory* factory) { |
791 SkImageInfo imageSpec = SkImageInfo::MakeN32Premul(10, 10); | 776 SkImageInfo imageSpec = SkImageInfo::MakeN32Premul(10, 10); |
792 SkSurface* surface; | 777 SkSurface* surface; |
793 SkSurface* alternateSurface; | 778 SkSurface* alternateSurface; |
794 bool useGpu = SkToBool(factory); | 779 bool useGpu = SkToBool(factory); |
795 int cnt; | 780 int cnt; |
796 #if SK_SUPPORT_GPU | 781 #if SK_SUPPORT_GPU |
(...skipping 25 matching lines...) Expand all Loading... |
822 } else | 807 } else |
823 #endif | 808 #endif |
824 { | 809 { |
825 surface = SkSurface::NewRaster(imageSpec); | 810 surface = SkSurface::NewRaster(imageSpec); |
826 alternateSurface = SkSurface::NewRaster(imageSpec); | 811 alternateSurface = SkSurface::NewRaster(imageSpec); |
827 } | 812 } |
828 SkASSERT(surface); | 813 SkASSERT(surface); |
829 SkASSERT(alternateSurface); | 814 SkASSERT(alternateSurface); |
830 SkAutoTUnref<SkSurface> aur1(surface); | 815 SkAutoTUnref<SkSurface> aur1(surface); |
831 SkAutoTUnref<SkSurface> aur2(alternateSurface); | 816 SkAutoTUnref<SkSurface> aur2(alternateSurface); |
832 PixelPtr pixels1 = get_surface_ptr(surface, useGpu); | 817 uint32_t genid1 = surface->generationID(); |
833 PixelPtr pixels2 = get_surface_ptr(alternateSurface, useGpu); | 818 uint32_t genid2 = alternateSurface->generationID(); |
834 SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface))
; | 819 SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface))
; |
835 SkAutoTUnref<SkImage> image1(canvas->newImageSnapshot()); | 820 SkAutoTUnref<SkImage> image1(canvas->newImageSnapshot()); |
836 canvas->setSurface(alternateSurface); | 821 canvas->setSurface(alternateSurface); |
837 SkAutoTUnref<SkImage> image2(canvas->newImageSnapshot()); | 822 SkAutoTUnref<SkImage> image2(canvas->newImageSnapshot()); |
838 REPORTER_ASSERT(reporter, image1->uniqueID() != image2->uniqueID()); | 823 REPORTER_ASSERT(reporter, image1->uniqueID() != image2->uniqueID()); |
839 // Verify that none of the above operations triggered a surface copy on
write. | 824 // Verify that none of the above operations triggered a surface modifica
tion. |
840 REPORTER_ASSERT(reporter, get_surface_ptr(surface, useGpu) == pixels1); | 825 REPORTER_ASSERT(reporter, surface->generationID() == genid1); |
841 REPORTER_ASSERT(reporter, get_surface_ptr(alternateSurface, useGpu) == p
ixels2); | 826 REPORTER_ASSERT(reporter, alternateSurface->generationID() == genid2); |
842 // Verify that a flushed draw command will trigger a copy on write on al
ternateSurface. | 827 // Verify that a flushed draw command will trigger a modification on alt
ernateSurface. |
843 canvas->clear(SK_ColorWHITE); | 828 canvas->clear(SK_ColorWHITE); |
844 canvas->flush(); | 829 canvas->flush(); |
845 REPORTER_ASSERT(reporter, get_surface_ptr(surface, useGpu) == pixels1); | 830 REPORTER_ASSERT(reporter, surface->generationID() == genid1); |
846 REPORTER_ASSERT(reporter, get_surface_ptr(alternateSurface, useGpu) != p
ixels2); | 831 REPORTER_ASSERT(reporter, alternateSurface->generationID() != genid2); |
847 } | 832 } |
848 } | 833 } |
849 | 834 |
850 static void TestDeferredCanvasCreateCompatibleDevice(skiatest::Reporter* reporte
r) { | 835 static void TestDeferredCanvasCreateCompatibleDevice(skiatest::Reporter* reporte
r) { |
851 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(100, 100)); | 836 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(100, 100)); |
852 SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()
)); | 837 SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()
)); |
853 | 838 |
854 NotificationCounter notificationCounter; | 839 NotificationCounter notificationCounter; |
855 canvas->setNotificationClient(¬ificationCounter); | 840 canvas->setNotificationClient(¬ificationCounter); |
856 | 841 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
936 TestDeferredCanvasSurface(reporter, NULL); | 921 TestDeferredCanvasSurface(reporter, NULL); |
937 TestDeferredCanvasSetSurface(reporter, NULL); | 922 TestDeferredCanvasSetSurface(reporter, NULL); |
938 } | 923 } |
939 | 924 |
940 DEF_GPUTEST(DeferredCanvas_GPU, reporter, factory) { | 925 DEF_GPUTEST(DeferredCanvas_GPU, reporter, factory) { |
941 if (factory != NULL) { | 926 if (factory != NULL) { |
942 TestDeferredCanvasSurface(reporter, factory); | 927 TestDeferredCanvasSurface(reporter, factory); |
943 TestDeferredCanvasSetSurface(reporter, factory); | 928 TestDeferredCanvasSetSurface(reporter, factory); |
944 } | 929 } |
945 } | 930 } |
OLD | NEW |