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