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