skia2/tests/SurfaceTest.cpp
kkinnunen 4e18413b78 Move SkImage tests from SurfaceTest to ImageTest
The general SkImage features seem to be tested in
ImageTest instead of SurfaceTest.

Helps in reviewing further reformatting of SurfaceTest.

BUG=skia:2992

Review URL: https://codereview.chromium.org/1452123002
2015-11-17 22:53:28 -08:00

611 lines
24 KiB
C++

/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkCanvas.h"
#include "SkData.h"
#include "SkDevice.h"
#include "SkImageEncoder.h"
#include "SkImage_Base.h"
#include "SkPath.h"
#include "SkRRect.h"
#include "SkSurface.h"
#include "SkUtils.h"
#include "Test.h"
#if SK_SUPPORT_GPU
#include "GrContextFactory.h"
#include "GrTest.h"
#else
class GrContextFactory;
class GrContext;
#endif
enum SurfaceType {
kRaster_SurfaceType,
kRasterDirect_SurfaceType,
kGpu_SurfaceType,
kGpuScratch_SurfaceType,
kLastSurfaceType = kGpuScratch_SurfaceType
};
static const int kSurfaceTypeCnt = kLastSurfaceType + 1;
static void release_storage(void* pixels, void* context) {
SkASSERT(pixels == context);
sk_free(pixels);
}
static SkSurface* create_surface(SurfaceType surfaceType, GrContext* context,
SkAlphaType at = kPremul_SkAlphaType,
SkImageInfo* requestedInfo = nullptr) {
const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
if (requestedInfo) {
*requestedInfo = info;
}
switch (surfaceType) {
case kRaster_SurfaceType:
return SkSurface::NewRaster(info);
case kRasterDirect_SurfaceType: {
const size_t rowBytes = info.minRowBytes();
void* storage = sk_malloc_throw(info.getSafeSize(rowBytes));
return SkSurface::NewRasterDirectReleaseProc(info, storage, rowBytes,
release_storage, storage);
}
case kGpu_SurfaceType:
return SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0, nullptr);
case kGpuScratch_SurfaceType:
return SkSurface::NewRenderTarget(context, SkSurface::kYes_Budgeted, info, 0, nullptr);
}
return nullptr;
}
static void test_empty_surface(skiatest::Reporter* reporter, GrContext* ctx) {
const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
REPORTER_ASSERT(reporter, nullptr == SkSurface::NewRaster(info));
REPORTER_ASSERT(reporter, nullptr == SkSurface::NewRasterDirect(info, nullptr, 0));
if (ctx) {
REPORTER_ASSERT(reporter, nullptr ==
SkSurface::NewRenderTarget(ctx, SkSurface::kNo_Budgeted, info, 0, nullptr));
}
}
#if SK_SUPPORT_GPU
static void test_wrapped_texture_surface(skiatest::Reporter* reporter, GrContext* ctx) {
if (nullptr == ctx) {
return;
}
const GrGpu* gpu = ctx->getGpu();
if (!gpu) {
return;
}
// Test the wrapped factory for SkSurface by creating a backend texture and then wrap it in
// a SkSurface.
static const int kW = 100;
static const int kH = 100;
static const uint32_t kOrigColor = 0xFFAABBCC;
SkAutoTArray<uint32_t> pixels(kW * kH);
sk_memset32(pixels.get(), kOrigColor, kW * kH);
GrBackendObject texHandle = gpu->createTestingOnlyBackendTexture(pixels.get(), kW, kH,
kRGBA_8888_GrPixelConfig);
GrBackendTextureDesc wrappedDesc;
wrappedDesc.fConfig = kRGBA_8888_GrPixelConfig;
wrappedDesc.fWidth = kW;
wrappedDesc.fHeight = kH;
wrappedDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
wrappedDesc.fSampleCnt = 0;
wrappedDesc.fFlags = kRenderTarget_GrBackendTextureFlag;
wrappedDesc.fTextureHandle = texHandle;
SkAutoTUnref<SkSurface> surface(SkSurface::NewWrappedRenderTarget(ctx, wrappedDesc, nullptr));
REPORTER_ASSERT(reporter, surface);
if (surface) {
// Validate that we can draw to the canvas and that the original texture color is preserved
// in pixels that aren't rendered to via the surface.
SkPaint paint;
static const SkColor kRectColor = ~kOrigColor | 0xFF000000;
paint.setColor(kRectColor);
surface->getCanvas()->drawRect(SkRect::MakeWH(SkIntToScalar(kW), SkIntToScalar(kH)/2),
paint);
SkImageInfo readInfo = SkImageInfo::MakeN32Premul(kW, kH);
surface->readPixels(readInfo, pixels.get(), kW * sizeof(uint32_t), 0, 0);
bool stop = false;
SkPMColor origColorPM = SkPackARGB32((kOrigColor >> 24 & 0xFF),
(kOrigColor >> 0 & 0xFF),
(kOrigColor >> 8 & 0xFF),
(kOrigColor >> 16 & 0xFF));
SkPMColor rectColorPM = SkPackARGB32((kRectColor >> 24 & 0xFF),
(kRectColor >> 16 & 0xFF),
(kRectColor >> 8 & 0xFF),
(kRectColor >> 0 & 0xFF));
for (int y = 0; y < kH/2 && !stop; ++y) {
for (int x = 0; x < kW && !stop; ++x) {
REPORTER_ASSERT(reporter, rectColorPM == pixels[x + y * kW]);
if (rectColorPM != pixels[x + y * kW]) {
stop = true;
}
}
}
stop = false;
for (int y = kH/2; y < kH && !stop; ++y) {
for (int x = 0; x < kW && !stop; ++x) {
REPORTER_ASSERT(reporter, origColorPM == pixels[x + y * kW]);
if (origColorPM != pixels[x + y * kW]) {
stop = true;
}
}
}
}
gpu->deleteTestingOnlyBackendTexture(texHandle);
}
#endif
static void test_canvaspeek(skiatest::Reporter* reporter,
GrContextFactory* factory) {
static const struct {
SurfaceType fType;
bool fPeekShouldSucceed;
} gRec[] = {
{ kRaster_SurfaceType, true },
{ kRasterDirect_SurfaceType, true },
#if SK_SUPPORT_GPU
{ kGpu_SurfaceType, false },
{ kGpuScratch_SurfaceType, false },
#endif
};
const SkColor color = SK_ColorRED;
const SkPMColor pmcolor = SkPreMultiplyColor(color);
int cnt;
#if SK_SUPPORT_GPU
cnt = GrContextFactory::kGLContextTypeCnt;
#else
cnt = 1;
#endif
for (int i= 0; i < cnt; ++i) {
GrContext* context = nullptr;
#if SK_SUPPORT_GPU
GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
continue;
}
context = factory->get(glCtxType);
if (nullptr == context) {
continue;
}
#endif
for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
SkImageInfo info, requestInfo;
size_t rowBytes;
SkAutoTUnref<SkSurface> surface(create_surface(gRec[i].fType, context,
kPremul_SkAlphaType, &requestInfo));
surface->getCanvas()->clear(color);
const void* addr = surface->getCanvas()->peekPixels(&info, &rowBytes);
bool success = SkToBool(addr);
REPORTER_ASSERT(reporter, gRec[i].fPeekShouldSucceed == success);
SkImageInfo info2;
size_t rb2;
const void* addr2 = surface->peekPixels(&info2, &rb2);
if (success) {
REPORTER_ASSERT(reporter, requestInfo == info);
REPORTER_ASSERT(reporter, requestInfo.minRowBytes() <= rowBytes);
REPORTER_ASSERT(reporter, pmcolor == *(const SkPMColor*)addr);
REPORTER_ASSERT(reporter, addr2 == addr);
REPORTER_ASSERT(reporter, info2 == info);
REPORTER_ASSERT(reporter, rb2 == rowBytes);
} else {
REPORTER_ASSERT(reporter, nullptr == addr2);
}
}
}
}
// For compatibility with clients that still call accessBitmap(), we need to ensure that we bump
// the bitmap's genID when we draw to it, else they won't know it has new values. When they are
// exclusively using surface/image, and we can hide accessBitmap from device, we can remove this
// test.
static void test_accessPixels(skiatest::Reporter* reporter, GrContextFactory* factory) {
static const struct {
SurfaceType fType;
bool fPeekShouldSucceed;
} gRec[] = {
{ kRaster_SurfaceType, true },
{ kRasterDirect_SurfaceType, true },
#if SK_SUPPORT_GPU
{ kGpu_SurfaceType, false },
{ kGpuScratch_SurfaceType, false },
#endif
};
int cnt;
#if SK_SUPPORT_GPU
cnt = GrContextFactory::kGLContextTypeCnt;
#else
cnt = 1;
#endif
for (int i= 0; i < cnt; ++i) {
GrContext* context = nullptr;
#if SK_SUPPORT_GPU
GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
continue;
}
context = factory->get(glCtxType);
if (nullptr == context) {
continue;
}
#endif
for (size_t j = 0; j < SK_ARRAY_COUNT(gRec); ++j) {
SkImageInfo info, requestInfo;
SkAutoTUnref<SkSurface> surface(create_surface(gRec[j].fType, context,
kPremul_SkAlphaType, &requestInfo));
SkCanvas* canvas = surface->getCanvas();
canvas->clear(0);
SkBaseDevice* device = canvas->getDevice_just_for_deprecated_compatibility_testing();
SkBitmap bm = device->accessBitmap(false);
uint32_t genID0 = bm.getGenerationID();
// Now we draw something, which needs to "dirty" the genID (sorta like copy-on-write)
canvas->drawColor(SK_ColorBLUE);
// Now check that we get a different genID
uint32_t genID1 = bm.getGenerationID();
REPORTER_ASSERT(reporter, genID0 != genID1);
}
}
}
static void test_snap_alphatype(skiatest::Reporter* reporter, GrContextFactory* factory) {
GrContext* context = nullptr;
#if SK_SUPPORT_GPU
context = factory->get(GrContextFactory::kNative_GLContextType);
if (nullptr == context) {
return;
}
#endif
for (int opaque = 0; opaque < 2; ++opaque) {
SkAlphaType atype = SkToBool(opaque) ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
for (int st = 0; st < kSurfaceTypeCnt; ++st) {
SurfaceType stype = (SurfaceType)st;
SkAutoTUnref<SkSurface> surface(create_surface(stype, context, atype));
REPORTER_ASSERT(reporter, surface);
if (surface) {
SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
REPORTER_ASSERT(reporter, image);
if (image) {
REPORTER_ASSERT(reporter, image->isOpaque() == SkToBool(opaque));
}
}
}
}
}
static void test_backend_cow(skiatest::Reporter* reporter, SkSurface* surface,
SkSurface::BackendHandleAccess mode,
GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) {
GrBackendObject obj1 = func(surface, mode);
SkAutoTUnref<SkImage> snap1(surface->newImageSnapshot());
GrBackendObject obj2 = func(surface, mode);
SkAutoTUnref<SkImage> snap2(surface->newImageSnapshot());
// If the access mode triggers CoW, then the backend objects should reflect it.
REPORTER_ASSERT(reporter, (obj1 == obj2) == (snap1 == snap2));
}
static void TestSurfaceCopyOnWrite(skiatest::Reporter* reporter, SurfaceType surfaceType,
GrContext* context) {
// Verify that the right canvas commands trigger a copy on write
SkSurface* surface = create_surface(surfaceType, context);
SkAutoTUnref<SkSurface> aur_surface(surface);
SkCanvas* canvas = surface->getCanvas();
const SkRect testRect =
SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
SkIntToScalar(4), SkIntToScalar(5));
SkPath testPath;
testPath.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
SkIntToScalar(2), SkIntToScalar(1)));
const SkIRect testIRect = SkIRect::MakeXYWH(0, 0, 2, 1);
SkRegion testRegion;
testRegion.setRect(testIRect);
const SkColor testColor = 0x01020304;
const SkPaint testPaint;
const SkPoint testPoints[3] = {
{SkIntToScalar(0), SkIntToScalar(0)},
{SkIntToScalar(2), SkIntToScalar(1)},
{SkIntToScalar(0), SkIntToScalar(2)}
};
const size_t testPointCount = 3;
SkBitmap testBitmap;
testBitmap.allocN32Pixels(10, 10);
testBitmap.eraseColor(0);
SkRRect testRRect;
testRRect.setRectXY(testRect, SK_Scalar1, SK_Scalar1);
SkString testText("Hello World");
const SkPoint testPoints2[] = {
{ SkIntToScalar(0), SkIntToScalar(1) },
{ SkIntToScalar(1), SkIntToScalar(1) },
{ SkIntToScalar(2), SkIntToScalar(1) },
{ SkIntToScalar(3), SkIntToScalar(1) },
{ SkIntToScalar(4), SkIntToScalar(1) },
{ SkIntToScalar(5), SkIntToScalar(1) },
{ SkIntToScalar(6), SkIntToScalar(1) },
{ SkIntToScalar(7), SkIntToScalar(1) },
{ SkIntToScalar(8), SkIntToScalar(1) },
{ SkIntToScalar(9), SkIntToScalar(1) },
{ SkIntToScalar(10), SkIntToScalar(1) },
};
#define EXPECT_COPY_ON_WRITE(command) \
{ \
SkImage* imageBefore = surface->newImageSnapshot(); \
SkAutoTUnref<SkImage> aur_before(imageBefore); \
canvas-> command ; \
SkImage* imageAfter = surface->newImageSnapshot(); \
SkAutoTUnref<SkImage> aur_after(imageAfter); \
REPORTER_ASSERT(reporter, imageBefore != imageAfter); \
}
EXPECT_COPY_ON_WRITE(clear(testColor))
EXPECT_COPY_ON_WRITE(drawPaint(testPaint))
EXPECT_COPY_ON_WRITE(drawPoints(SkCanvas::kPoints_PointMode, testPointCount, testPoints, \
testPaint))
EXPECT_COPY_ON_WRITE(drawOval(testRect, testPaint))
EXPECT_COPY_ON_WRITE(drawRect(testRect, testPaint))
EXPECT_COPY_ON_WRITE(drawRRect(testRRect, testPaint))
EXPECT_COPY_ON_WRITE(drawPath(testPath, testPaint))
EXPECT_COPY_ON_WRITE(drawBitmap(testBitmap, 0, 0))
EXPECT_COPY_ON_WRITE(drawBitmapRect(testBitmap, testRect, nullptr))
EXPECT_COPY_ON_WRITE(drawBitmapNine(testBitmap, testIRect, testRect, nullptr))
EXPECT_COPY_ON_WRITE(drawSprite(testBitmap, 0, 0, nullptr))
EXPECT_COPY_ON_WRITE(drawText(testText.c_str(), testText.size(), 0, 1, testPaint))
EXPECT_COPY_ON_WRITE(drawPosText(testText.c_str(), testText.size(), testPoints2, \
testPaint))
EXPECT_COPY_ON_WRITE(drawTextOnPath(testText.c_str(), testText.size(), testPath, nullptr, \
testPaint))
const SkSurface::BackendHandleAccess accessModes[] = {
SkSurface::kFlushRead_BackendHandleAccess,
SkSurface::kFlushWrite_BackendHandleAccess,
SkSurface::kDiscardWrite_BackendHandleAccess,
};
for (auto access : accessModes) {
test_backend_cow(reporter, surface, access,
[](SkSurface* s, SkSurface::BackendHandleAccess a) -> GrBackendObject {
return s->getTextureHandle(a);
});
test_backend_cow(reporter, surface, access,
[](SkSurface* s, SkSurface::BackendHandleAccess a) -> GrBackendObject {
GrBackendObject result;
if (!s->getRenderTargetHandle(&result, a)) {
return 0;
}
return result;
});
}
}
static void TestSurfaceWritableAfterSnapshotRelease(skiatest::Reporter* reporter,
SurfaceType surfaceType,
GrContext* context) {
// This test succeeds by not triggering an assertion.
// The test verifies that the surface remains writable (usable) after
// acquiring and releasing a snapshot without triggering a copy on write.
SkAutoTUnref<SkSurface> surface(create_surface(surfaceType, context));
SkCanvas* canvas = surface->getCanvas();
canvas->clear(1);
surface->newImageSnapshot()->unref(); // Create and destroy SkImage
canvas->clear(2); // Must not assert internally
}
#if SK_SUPPORT_GPU
static void Test_crbug263329(skiatest::Reporter* reporter,
SurfaceType surfaceType,
GrContext* context) {
// This is a regression test for crbug.com/263329
// Bug was caused by onCopyOnWrite releasing the old surface texture
// back to the scratch texture pool even though the texture is used
// by and active SkImage_Gpu.
SkAutoTUnref<SkSurface> surface1(create_surface(surfaceType, context));
SkAutoTUnref<SkSurface> surface2(create_surface(surfaceType, context));
SkCanvas* canvas1 = surface1->getCanvas();
SkCanvas* canvas2 = surface2->getCanvas();
canvas1->clear(1);
SkAutoTUnref<SkImage> image1(surface1->newImageSnapshot());
// Trigger copy on write, new backing is a scratch texture
canvas1->clear(2);
SkAutoTUnref<SkImage> image2(surface1->newImageSnapshot());
// Trigger copy on write, old backing should not be returned to scratch
// pool because it is held by image2
canvas1->clear(3);
canvas2->clear(4);
SkAutoTUnref<SkImage> image3(surface2->newImageSnapshot());
// Trigger copy on write on surface2. The new backing store should not
// be recycling a texture that is held by an existing image.
canvas2->clear(5);
SkAutoTUnref<SkImage> image4(surface2->newImageSnapshot());
REPORTER_ASSERT(reporter, as_IB(image4)->getTexture() != as_IB(image3)->getTexture());
// The following assertion checks crbug.com/263329
REPORTER_ASSERT(reporter, as_IB(image4)->getTexture() != as_IB(image2)->getTexture());
REPORTER_ASSERT(reporter, as_IB(image4)->getTexture() != as_IB(image1)->getTexture());
REPORTER_ASSERT(reporter, as_IB(image3)->getTexture() != as_IB(image2)->getTexture());
REPORTER_ASSERT(reporter, as_IB(image3)->getTexture() != as_IB(image1)->getTexture());
REPORTER_ASSERT(reporter, as_IB(image2)->getTexture() != as_IB(image1)->getTexture());
}
static void TestGetTexture(skiatest::Reporter* reporter,
SurfaceType surfaceType,
GrContext* context) {
SkAutoTUnref<SkSurface> surface(create_surface(surfaceType, context));
SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
GrTexture* texture = as_IB(image)->getTexture();
if (surfaceType == kGpu_SurfaceType || surfaceType == kGpuScratch_SurfaceType) {
REPORTER_ASSERT(reporter, texture);
REPORTER_ASSERT(reporter, 0 != texture->getTextureHandle());
} else {
REPORTER_ASSERT(reporter, nullptr == texture);
}
surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
REPORTER_ASSERT(reporter, as_IB(image)->getTexture() == texture);
}
#include "GrGpuResourcePriv.h"
#include "SkGpuDevice.h"
#include "SkImage_Gpu.h"
#include "SkSurface_Gpu.h"
SkSurface::Budgeted is_budgeted(SkSurface* surf) {
return ((SkSurface_Gpu*)surf)->getDevice()->accessRenderTarget()->resourcePriv().isBudgeted() ?
SkSurface::kYes_Budgeted : SkSurface::kNo_Budgeted;
}
SkSurface::Budgeted is_budgeted(SkImage* image) {
return ((SkImage_Gpu*)image)->getTexture()->resourcePriv().isBudgeted() ?
SkSurface::kYes_Budgeted : SkSurface::kNo_Budgeted;
}
static void test_surface_budget(skiatest::Reporter* reporter, GrContext* context) {
SkImageInfo info = SkImageInfo::MakeN32Premul(8,8);
for (int i = 0; i < 2; ++i) {
SkSurface::Budgeted sbudgeted = i ? SkSurface::kYes_Budgeted : SkSurface::kNo_Budgeted;
for (int j = 0; j < 2; ++j) {
SkSurface::Budgeted ibudgeted = j ? SkSurface::kYes_Budgeted : SkSurface::kNo_Budgeted;
SkAutoTUnref<SkSurface>
surface(SkSurface::NewRenderTarget(context, sbudgeted, info, 0));
SkASSERT(surface);
REPORTER_ASSERT(reporter, sbudgeted == is_budgeted(surface));
SkAutoTUnref<SkImage> image(surface->newImageSnapshot(ibudgeted));
// Initially the image shares a texture with the surface, and the surface decides
// whether it is budgeted or not.
REPORTER_ASSERT(reporter, sbudgeted == is_budgeted(surface));
REPORTER_ASSERT(reporter, sbudgeted == is_budgeted(image));
// Now trigger copy-on-write
surface->getCanvas()->clear(SK_ColorBLUE);
// They don't share a texture anymore. They should each have made their own budget
// decision.
REPORTER_ASSERT(reporter, sbudgeted == is_budgeted(surface));
REPORTER_ASSERT(reporter, ibudgeted == is_budgeted(image));
}
}
}
#endif
static void TestSurfaceNoCanvas(skiatest::Reporter* reporter,
SurfaceType surfaceType,
GrContext* context,
SkSurface::ContentChangeMode mode) {
// Verifies the robustness of SkSurface for handling use cases where calls
// are made before a canvas is created.
{
// Test passes by not asserting
SkSurface* surface = create_surface(surfaceType, context);
SkAutoTUnref<SkSurface> aur_surface(surface);
surface->notifyContentWillChange(mode);
SkDEBUGCODE(surface->validate();)
}
{
SkSurface* surface = create_surface(surfaceType, context);
SkAutoTUnref<SkSurface> aur_surface(surface);
SkImage* image1 = surface->newImageSnapshot();
SkAutoTUnref<SkImage> aur_image1(image1);
SkDEBUGCODE(image1->validate();)
SkDEBUGCODE(surface->validate();)
surface->notifyContentWillChange(mode);
SkDEBUGCODE(image1->validate();)
SkDEBUGCODE(surface->validate();)
SkImage* image2 = surface->newImageSnapshot();
SkAutoTUnref<SkImage> aur_image2(image2);
SkDEBUGCODE(image2->validate();)
SkDEBUGCODE(surface->validate();)
REPORTER_ASSERT(reporter, image1 != image2);
}
}
DEF_GPUTEST(Surface, reporter, factory) {
TestSurfaceCopyOnWrite(reporter, kRaster_SurfaceType, nullptr);
TestSurfaceWritableAfterSnapshotRelease(reporter, kRaster_SurfaceType, nullptr);
TestSurfaceNoCanvas(reporter, kRaster_SurfaceType, nullptr, SkSurface::kDiscard_ContentChangeMode);
TestSurfaceNoCanvas(reporter, kRaster_SurfaceType, nullptr, SkSurface::kRetain_ContentChangeMode);
test_empty_surface(reporter, nullptr);
test_canvaspeek(reporter, factory);
test_accessPixels(reporter, factory);
test_snap_alphatype(reporter, factory);
#if SK_SUPPORT_GPU
TestGetTexture(reporter, kRaster_SurfaceType, nullptr);
if (factory) {
for (int i= 0; i < GrContextFactory::kGLContextTypeCnt; ++i) {
GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
continue;
}
GrContext* context = factory->get(glCtxType);
if (context) {
Test_crbug263329(reporter, kGpu_SurfaceType, context);
Test_crbug263329(reporter, kGpuScratch_SurfaceType, context);
TestSurfaceCopyOnWrite(reporter, kGpu_SurfaceType, context);
TestSurfaceCopyOnWrite(reporter, kGpuScratch_SurfaceType, context);
TestSurfaceWritableAfterSnapshotRelease(reporter, kGpu_SurfaceType, context);
TestSurfaceWritableAfterSnapshotRelease(reporter, kGpuScratch_SurfaceType, context);
TestSurfaceNoCanvas(reporter, kGpu_SurfaceType, context, SkSurface::kDiscard_ContentChangeMode);
TestSurfaceNoCanvas(reporter, kGpuScratch_SurfaceType, context, SkSurface::kDiscard_ContentChangeMode);
TestSurfaceNoCanvas(reporter, kGpu_SurfaceType, context, SkSurface::kRetain_ContentChangeMode);
TestSurfaceNoCanvas(reporter, kGpuScratch_SurfaceType, context, SkSurface::kRetain_ContentChangeMode);
TestGetTexture(reporter, kGpu_SurfaceType, context);
TestGetTexture(reporter, kGpuScratch_SurfaceType, context);
test_empty_surface(reporter, context);
test_surface_budget(reporter, context);
test_wrapped_texture_surface(reporter, context);
}
}
}
#endif
}