SurfaceTest.cpp revision 5965c8ae4ee960275da4bc40189bdba85aab8b5e
1/* 2 * Copyright 2013 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 "SkCanvas.h" 9#include "SkData.h" 10#include "SkImageEncoder.h" 11#include "SkRRect.h" 12#include "SkSurface.h" 13#include "SkUtils.h" 14#include "Test.h" 15 16#if SK_SUPPORT_GPU 17#include "GrContextFactory.h" 18#else 19class GrContextFactory; 20class GrContext; 21#endif 22 23enum SurfaceType { 24 kRaster_SurfaceType, 25 kRasterDirect_SurfaceType, 26 kGpu_SurfaceType, 27 kGpuScratch_SurfaceType, 28}; 29 30static void release_storage(void* pixels, void* context) { 31 SkASSERT(pixels == context); 32 sk_free(pixels); 33} 34 35static SkSurface* createSurface(SurfaceType surfaceType, GrContext* context, 36 SkImageInfo* requestedInfo = NULL) { 37 static const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); 38 39 if (requestedInfo) { 40 *requestedInfo = info; 41 } 42 43 switch (surfaceType) { 44 case kRaster_SurfaceType: 45 return SkSurface::NewRaster(info); 46 case kRasterDirect_SurfaceType: { 47 const size_t rowBytes = info.minRowBytes(); 48 void* storage = sk_malloc_throw(info.getSafeSize(rowBytes)); 49 return SkSurface::NewRasterDirectReleaseProc(info, storage, rowBytes, 50 release_storage, storage); 51 } 52 case kGpu_SurfaceType: 53#if SK_SUPPORT_GPU 54 return context ? SkSurface::NewRenderTarget(context, info, 0, NULL) : NULL; 55#endif 56 break; 57 case kGpuScratch_SurfaceType: 58#if SK_SUPPORT_GPU 59 return context ? SkSurface::NewScratchRenderTarget(context, info) : NULL; 60#endif 61 break; 62 } 63 return NULL; 64} 65 66enum ImageType { 67 kRasterCopy_ImageType, 68 kRasterData_ImageType, 69 kGpu_ImageType, 70 kCodec_ImageType, 71}; 72 73#include "SkImageGenerator.h" 74 75class EmptyGenerator : public SkImageGenerator { 76protected: 77 bool onGetInfo(SkImageInfo* info) SK_OVERRIDE { 78 *info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType); 79 return true; 80 } 81}; 82 83static void test_empty_image(skiatest::Reporter* reporter) { 84 const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType); 85 86 REPORTER_ASSERT(reporter, NULL == SkImage::NewRasterCopy(info, NULL, 0)); 87 REPORTER_ASSERT(reporter, NULL == SkImage::NewRasterData(info, NULL, 0)); 88 REPORTER_ASSERT(reporter, NULL == SkImage::NewFromGenerator(SkNEW(EmptyGenerator))); 89} 90 91static void test_empty_surface(skiatest::Reporter* reporter, GrContext* ctx) { 92 const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType); 93 94 REPORTER_ASSERT(reporter, NULL == SkSurface::NewRaster(info)); 95 REPORTER_ASSERT(reporter, NULL == SkSurface::NewRasterDirect(info, NULL, 0)); 96 if (ctx) { 97 REPORTER_ASSERT(reporter, NULL == SkSurface::NewRenderTarget(ctx, info, 0, NULL)); 98 REPORTER_ASSERT(reporter, NULL == SkSurface::NewScratchRenderTarget(ctx, info, 0, NULL)); 99 } 100} 101 102static void test_image(skiatest::Reporter* reporter) { 103 SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1); 104 size_t rowBytes = info.minRowBytes(); 105 size_t size = info.getSafeSize(rowBytes); 106 SkData* data = SkData::NewUninitialized(size); 107 108 REPORTER_ASSERT(reporter, data->unique()); 109 SkImage* image = SkImage::NewRasterData(info, data, rowBytes); 110 REPORTER_ASSERT(reporter, !data->unique()); 111 image->unref(); 112 REPORTER_ASSERT(reporter, data->unique()); 113 data->unref(); 114} 115 116static SkImage* createImage(ImageType imageType, GrContext* context, SkColor color) { 117 const SkPMColor pmcolor = SkPreMultiplyColor(color); 118 const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); 119 const size_t rowBytes = info.minRowBytes(); 120 const size_t size = rowBytes * info.height(); 121 122 SkAutoTUnref<SkData> data(SkData::NewUninitialized(size)); 123 void* addr = data->writable_data(); 124 sk_memset32((SkPMColor*)addr, pmcolor, SkToInt(size >> 2)); 125 126 switch (imageType) { 127 case kRasterCopy_ImageType: 128 return SkImage::NewRasterCopy(info, addr, rowBytes); 129 case kRasterData_ImageType: 130 return SkImage::NewRasterData(info, data, rowBytes); 131 case kGpu_ImageType: { 132 SkAutoTUnref<SkSurface> surf(SkSurface::NewRenderTarget(context, info, 0)); 133 surf->getCanvas()->clear(color); 134 return surf->newImageSnapshot(); 135 } 136 case kCodec_ImageType: { 137 SkBitmap bitmap; 138 bitmap.installPixels(info, addr, rowBytes); 139 SkAutoTUnref<SkData> src( 140 SkImageEncoder::EncodeData(bitmap, SkImageEncoder::kPNG_Type, 100)); 141 return SkImage::NewFromData(src); 142 } 143 } 144 SkASSERT(false); 145 return NULL; 146} 147 148static void set_pixels(SkPMColor pixels[], int count, SkPMColor color) { 149 sk_memset32(pixels, color, count); 150} 151static bool has_pixels(const SkPMColor pixels[], int count, SkPMColor expected) { 152 for (int i = 0; i < count; ++i) { 153 if (pixels[i] != expected) { 154 return false; 155 } 156 } 157 return true; 158} 159 160static void test_image_readpixels(skiatest::Reporter* reporter, SkImage* image, 161 SkPMColor expected) { 162 const SkPMColor notExpected = ~expected; 163 164 const int w = 2, h = 2; 165 const size_t rowBytes = w * sizeof(SkPMColor); 166 SkPMColor pixels[w*h]; 167 168 SkImageInfo info; 169 170 info = SkImageInfo::MakeUnknown(w, h); 171 REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, 0)); 172 173 // out-of-bounds should fail 174 info = SkImageInfo::MakeN32Premul(w, h); 175 REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, -w, 0)); 176 REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, -h)); 177 REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, image->width(), 0)); 178 REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, image->height())); 179 180 // top-left should succeed 181 set_pixels(pixels, w*h, notExpected); 182 REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, 0, 0)); 183 REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected)); 184 185 // bottom-right should succeed 186 set_pixels(pixels, w*h, notExpected); 187 REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, 188 image->width() - w, image->height() - h)); 189 REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected)); 190 191 // partial top-left should succeed 192 set_pixels(pixels, w*h, notExpected); 193 REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, -1, -1)); 194 REPORTER_ASSERT(reporter, pixels[3] == expected); 195 REPORTER_ASSERT(reporter, has_pixels(pixels, w*h - 1, notExpected)); 196 197 // partial bottom-right should succeed 198 set_pixels(pixels, w*h, notExpected); 199 REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, 200 image->width() - 1, image->height() - 1)); 201 REPORTER_ASSERT(reporter, pixels[0] == expected); 202 REPORTER_ASSERT(reporter, has_pixels(&pixels[1], w*h - 1, notExpected)); 203} 204 205static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* factory) { 206 static const struct { 207 ImageType fType; 208 bool fPeekShouldSucceed; 209 const char* fName; 210 } gRec[] = { 211 { kRasterCopy_ImageType, true, "RasterCopy" }, 212 { kRasterData_ImageType, true, "RasterData" }, 213 { kGpu_ImageType, false, "Gpu" }, 214 { kCodec_ImageType, false, "Codec" }, 215 }; 216 217 const SkColor color = SK_ColorRED; 218 const SkPMColor pmcolor = SkPreMultiplyColor(color); 219 220 GrContext* ctx = NULL; 221#if SK_SUPPORT_GPU 222 ctx = factory->get(GrContextFactory::kNative_GLContextType); 223#endif 224 225 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { 226 SkImageInfo info; 227 size_t rowBytes; 228 229 SkAutoTUnref<SkImage> image(createImage(gRec[i].fType, ctx, color)); 230 if (!image.get()) { 231 SkDebugf("failed to createImage[%d] %s\n", i, gRec[i].fName); 232 continue; // gpu may not be enabled 233 } 234 const void* addr = image->peekPixels(&info, &rowBytes); 235 bool success = SkToBool(addr); 236 REPORTER_ASSERT(reporter, gRec[i].fPeekShouldSucceed == success); 237 if (success) { 238 REPORTER_ASSERT(reporter, 10 == info.width()); 239 REPORTER_ASSERT(reporter, 10 == info.height()); 240 REPORTER_ASSERT(reporter, kN32_SkColorType == info.colorType()); 241 REPORTER_ASSERT(reporter, kPremul_SkAlphaType == info.alphaType() || 242 kOpaque_SkAlphaType == info.alphaType()); 243 REPORTER_ASSERT(reporter, info.minRowBytes() <= rowBytes); 244 REPORTER_ASSERT(reporter, pmcolor == *(const SkPMColor*)addr); 245 } 246 247 test_image_readpixels(reporter, image, pmcolor); 248 } 249} 250 251static void test_canvaspeek(skiatest::Reporter* reporter, 252 GrContextFactory* factory) { 253 static const struct { 254 SurfaceType fType; 255 bool fPeekShouldSucceed; 256 } gRec[] = { 257 { kRaster_SurfaceType, true }, 258 { kRasterDirect_SurfaceType, true }, 259#if SK_SUPPORT_GPU 260 { kGpu_SurfaceType, false }, 261 { kGpuScratch_SurfaceType, false }, 262#endif 263 }; 264 265 const SkColor color = SK_ColorRED; 266 const SkPMColor pmcolor = SkPreMultiplyColor(color); 267 268 int cnt; 269#if SK_SUPPORT_GPU 270 cnt = GrContextFactory::kGLContextTypeCnt; 271#else 272 cnt = 1; 273#endif 274 275 for (int i= 0; i < cnt; ++i) { 276 GrContext* context = NULL; 277#if SK_SUPPORT_GPU 278 GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i; 279 if (!GrContextFactory::IsRenderingGLContext(glCtxType)) { 280 continue; 281 } 282 context = factory->get(glCtxType); 283 284 if (NULL == context) { 285 continue; 286 } 287#endif 288 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { 289 SkImageInfo info, requestInfo; 290 size_t rowBytes; 291 292 SkAutoTUnref<SkSurface> surface(createSurface(gRec[i].fType, context, 293 &requestInfo)); 294 surface->getCanvas()->clear(color); 295 296 const void* addr = surface->getCanvas()->peekPixels(&info, &rowBytes); 297 bool success = SkToBool(addr); 298 REPORTER_ASSERT(reporter, gRec[i].fPeekShouldSucceed == success); 299 300 SkImageInfo info2; 301 size_t rb2; 302 const void* addr2 = surface->peekPixels(&info2, &rb2); 303 304 if (success) { 305 REPORTER_ASSERT(reporter, requestInfo == info); 306 REPORTER_ASSERT(reporter, requestInfo.minRowBytes() <= rowBytes); 307 REPORTER_ASSERT(reporter, pmcolor == *(const SkPMColor*)addr); 308 309 REPORTER_ASSERT(reporter, addr2 == addr); 310 REPORTER_ASSERT(reporter, info2 == info); 311 REPORTER_ASSERT(reporter, rb2 == rowBytes); 312 } else { 313 REPORTER_ASSERT(reporter, NULL == addr2); 314 } 315 } 316 } 317} 318 319static void TestSurfaceCopyOnWrite(skiatest::Reporter* reporter, SurfaceType surfaceType, 320 GrContext* context) { 321 // Verify that the right canvas commands trigger a copy on write 322 SkSurface* surface = createSurface(surfaceType, context); 323 SkAutoTUnref<SkSurface> aur_surface(surface); 324 SkCanvas* canvas = surface->getCanvas(); 325 326 const SkRect testRect = 327 SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), 328 SkIntToScalar(4), SkIntToScalar(5)); 329 SkPath testPath; 330 testPath.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), 331 SkIntToScalar(2), SkIntToScalar(1))); 332 333 const SkIRect testIRect = SkIRect::MakeXYWH(0, 0, 2, 1); 334 335 SkRegion testRegion; 336 testRegion.setRect(testIRect); 337 338 339 const SkColor testColor = 0x01020304; 340 const SkPaint testPaint; 341 const SkPoint testPoints[3] = { 342 {SkIntToScalar(0), SkIntToScalar(0)}, 343 {SkIntToScalar(2), SkIntToScalar(1)}, 344 {SkIntToScalar(0), SkIntToScalar(2)} 345 }; 346 const size_t testPointCount = 3; 347 348 SkBitmap testBitmap; 349 testBitmap.allocN32Pixels(10, 10); 350 testBitmap.eraseColor(0); 351 352 SkRRect testRRect; 353 testRRect.setRectXY(testRect, SK_Scalar1, SK_Scalar1); 354 355 SkString testText("Hello World"); 356 const SkPoint testPoints2[] = { 357 { SkIntToScalar(0), SkIntToScalar(1) }, 358 { SkIntToScalar(1), SkIntToScalar(1) }, 359 { SkIntToScalar(2), SkIntToScalar(1) }, 360 { SkIntToScalar(3), SkIntToScalar(1) }, 361 { SkIntToScalar(4), SkIntToScalar(1) }, 362 { SkIntToScalar(5), SkIntToScalar(1) }, 363 { SkIntToScalar(6), SkIntToScalar(1) }, 364 { SkIntToScalar(7), SkIntToScalar(1) }, 365 { SkIntToScalar(8), SkIntToScalar(1) }, 366 { SkIntToScalar(9), SkIntToScalar(1) }, 367 { SkIntToScalar(10), SkIntToScalar(1) }, 368 }; 369 370#define EXPECT_COPY_ON_WRITE(command) \ 371 { \ 372 SkImage* imageBefore = surface->newImageSnapshot(); \ 373 SkAutoTUnref<SkImage> aur_before(imageBefore); \ 374 canvas-> command ; \ 375 SkImage* imageAfter = surface->newImageSnapshot(); \ 376 SkAutoTUnref<SkImage> aur_after(imageAfter); \ 377 REPORTER_ASSERT(reporter, imageBefore != imageAfter); \ 378 } 379 380 EXPECT_COPY_ON_WRITE(clear(testColor)) 381 EXPECT_COPY_ON_WRITE(drawPaint(testPaint)) 382 EXPECT_COPY_ON_WRITE(drawPoints(SkCanvas::kPoints_PointMode, testPointCount, testPoints, \ 383 testPaint)) 384 EXPECT_COPY_ON_WRITE(drawOval(testRect, testPaint)) 385 EXPECT_COPY_ON_WRITE(drawRect(testRect, testPaint)) 386 EXPECT_COPY_ON_WRITE(drawRRect(testRRect, testPaint)) 387 EXPECT_COPY_ON_WRITE(drawPath(testPath, testPaint)) 388 EXPECT_COPY_ON_WRITE(drawBitmap(testBitmap, 0, 0)) 389 EXPECT_COPY_ON_WRITE(drawBitmapRect(testBitmap, NULL, testRect)) 390 EXPECT_COPY_ON_WRITE(drawBitmapNine(testBitmap, testIRect, testRect, NULL)) 391 EXPECT_COPY_ON_WRITE(drawSprite(testBitmap, 0, 0, NULL)) 392 EXPECT_COPY_ON_WRITE(drawText(testText.c_str(), testText.size(), 0, 1, testPaint)) 393 EXPECT_COPY_ON_WRITE(drawPosText(testText.c_str(), testText.size(), testPoints2, \ 394 testPaint)) 395 EXPECT_COPY_ON_WRITE(drawTextOnPath(testText.c_str(), testText.size(), testPath, NULL, \ 396 testPaint)) 397} 398 399static void TestSurfaceWritableAfterSnapshotRelease(skiatest::Reporter* reporter, 400 SurfaceType surfaceType, 401 GrContext* context) { 402 // This test succeeds by not triggering an assertion. 403 // The test verifies that the surface remains writable (usable) after 404 // acquiring and releasing a snapshot without triggering a copy on write. 405 SkAutoTUnref<SkSurface> surface(createSurface(surfaceType, context)); 406 SkCanvas* canvas = surface->getCanvas(); 407 canvas->clear(1); 408 surface->newImageSnapshot()->unref(); // Create and destroy SkImage 409 canvas->clear(2); // Must not assert internally 410} 411 412#if SK_SUPPORT_GPU 413static void Test_crbug263329(skiatest::Reporter* reporter, 414 SurfaceType surfaceType, 415 GrContext* context) { 416 // This is a regression test for crbug.com/263329 417 // Bug was caused by onCopyOnWrite releasing the old surface texture 418 // back to the scratch texture pool even though the texture is used 419 // by and active SkImage_Gpu. 420 SkAutoTUnref<SkSurface> surface1(createSurface(surfaceType, context)); 421 SkAutoTUnref<SkSurface> surface2(createSurface(surfaceType, context)); 422 SkCanvas* canvas1 = surface1->getCanvas(); 423 SkCanvas* canvas2 = surface2->getCanvas(); 424 canvas1->clear(1); 425 SkAutoTUnref<SkImage> image1(surface1->newImageSnapshot()); 426 // Trigger copy on write, new backing is a scratch texture 427 canvas1->clear(2); 428 SkAutoTUnref<SkImage> image2(surface1->newImageSnapshot()); 429 // Trigger copy on write, old backing should not be returned to scratch 430 // pool because it is held by image2 431 canvas1->clear(3); 432 433 canvas2->clear(4); 434 SkAutoTUnref<SkImage> image3(surface2->newImageSnapshot()); 435 // Trigger copy on write on surface2. The new backing store should not 436 // be recycling a texture that is held by an existing image. 437 canvas2->clear(5); 438 SkAutoTUnref<SkImage> image4(surface2->newImageSnapshot()); 439 REPORTER_ASSERT(reporter, image4->getTexture() != image3->getTexture()); 440 // The following assertion checks crbug.com/263329 441 REPORTER_ASSERT(reporter, image4->getTexture() != image2->getTexture()); 442 REPORTER_ASSERT(reporter, image4->getTexture() != image1->getTexture()); 443 REPORTER_ASSERT(reporter, image3->getTexture() != image2->getTexture()); 444 REPORTER_ASSERT(reporter, image3->getTexture() != image1->getTexture()); 445 REPORTER_ASSERT(reporter, image2->getTexture() != image1->getTexture()); 446} 447 448static void TestGetTexture(skiatest::Reporter* reporter, 449 SurfaceType surfaceType, 450 GrContext* context) { 451 SkAutoTUnref<SkSurface> surface(createSurface(surfaceType, context)); 452 SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); 453 GrTexture* texture = image->getTexture(); 454 if (surfaceType == kGpu_SurfaceType || surfaceType == kGpuScratch_SurfaceType) { 455 REPORTER_ASSERT(reporter, texture); 456 REPORTER_ASSERT(reporter, 0 != texture->getTextureHandle()); 457 } else { 458 REPORTER_ASSERT(reporter, NULL == texture); 459 } 460 surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode); 461 REPORTER_ASSERT(reporter, image->getTexture() == texture); 462} 463#endif 464 465static void TestSurfaceNoCanvas(skiatest::Reporter* reporter, 466 SurfaceType surfaceType, 467 GrContext* context, 468 SkSurface::ContentChangeMode mode) { 469 // Verifies the robustness of SkSurface for handling use cases where calls 470 // are made before a canvas is created. 471 { 472 // Test passes by not asserting 473 SkSurface* surface = createSurface(surfaceType, context); 474 SkAutoTUnref<SkSurface> aur_surface(surface); 475 surface->notifyContentWillChange(mode); 476 SkDEBUGCODE(surface->validate();) 477 } 478 { 479 SkSurface* surface = createSurface(surfaceType, context); 480 SkAutoTUnref<SkSurface> aur_surface(surface); 481 SkImage* image1 = surface->newImageSnapshot(); 482 SkAutoTUnref<SkImage> aur_image1(image1); 483 SkDEBUGCODE(image1->validate();) 484 SkDEBUGCODE(surface->validate();) 485 surface->notifyContentWillChange(mode); 486 SkDEBUGCODE(image1->validate();) 487 SkDEBUGCODE(surface->validate();) 488 SkImage* image2 = surface->newImageSnapshot(); 489 SkAutoTUnref<SkImage> aur_image2(image2); 490 SkDEBUGCODE(image2->validate();) 491 SkDEBUGCODE(surface->validate();) 492 REPORTER_ASSERT(reporter, image1 != image2); 493 } 494 495} 496 497DEF_GPUTEST(Surface, reporter, factory) { 498 test_image(reporter); 499 500 TestSurfaceCopyOnWrite(reporter, kRaster_SurfaceType, NULL); 501 TestSurfaceWritableAfterSnapshotRelease(reporter, kRaster_SurfaceType, NULL); 502 TestSurfaceNoCanvas(reporter, kRaster_SurfaceType, NULL, SkSurface::kDiscard_ContentChangeMode); 503 TestSurfaceNoCanvas(reporter, kRaster_SurfaceType, NULL, SkSurface::kRetain_ContentChangeMode); 504 505 test_empty_image(reporter); 506 test_empty_surface(reporter, NULL); 507 508 test_imagepeek(reporter, factory); 509 test_canvaspeek(reporter, factory); 510 511#if SK_SUPPORT_GPU 512 TestGetTexture(reporter, kRaster_SurfaceType, NULL); 513 if (factory) { 514 for (int i= 0; i < GrContextFactory::kGLContextTypeCnt; ++i) { 515 GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i; 516 if (!GrContextFactory::IsRenderingGLContext(glCtxType)) { 517 continue; 518 } 519 GrContext* context = factory->get(glCtxType); 520 if (context) { 521 Test_crbug263329(reporter, kGpu_SurfaceType, context); 522 Test_crbug263329(reporter, kGpuScratch_SurfaceType, context); 523 TestSurfaceCopyOnWrite(reporter, kGpu_SurfaceType, context); 524 TestSurfaceCopyOnWrite(reporter, kGpuScratch_SurfaceType, context); 525 TestSurfaceWritableAfterSnapshotRelease(reporter, kGpu_SurfaceType, context); 526 TestSurfaceWritableAfterSnapshotRelease(reporter, kGpuScratch_SurfaceType, context); 527 TestSurfaceNoCanvas(reporter, kGpu_SurfaceType, context, SkSurface::kDiscard_ContentChangeMode); 528 TestSurfaceNoCanvas(reporter, kGpuScratch_SurfaceType, context, SkSurface::kDiscard_ContentChangeMode); 529 TestSurfaceNoCanvas(reporter, kGpu_SurfaceType, context, SkSurface::kRetain_ContentChangeMode); 530 TestSurfaceNoCanvas(reporter, kGpuScratch_SurfaceType, context, SkSurface::kRetain_ContentChangeMode); 531 TestGetTexture(reporter, kGpu_SurfaceType, context); 532 TestGetTexture(reporter, kGpuScratch_SurfaceType, context); 533 test_empty_surface(reporter, context); 534 } 535 } 536 } 537#endif 538} 539