diff options
-rw-r--r-- | dm/DM.cpp | 61 | ||||
-rwxr-xr-x | src/gpu/GrContextFactory.cpp | 23 | ||||
-rw-r--r-- | src/gpu/GrContextFactory.h | 48 | ||||
-rw-r--r-- | tests/ImageTest.cpp | 70 | ||||
-rw-r--r-- | tests/SurfaceTest.cpp | 658 | ||||
-rw-r--r-- | tests/Test.h | 42 | ||||
-rw-r--r-- | tests/TestTest.cpp | 75 |
7 files changed, 573 insertions, 404 deletions
@@ -1144,6 +1144,67 @@ int dm_main() { return 0; } +// TODO: currently many GPU tests are declared outside SK_SUPPORT_GPU guards. +// Thus we export the empty RunWithGPUTestContexts when SK_SUPPORT_GPU=0. +namespace skiatest { +namespace { +typedef void(*TestWithGrContext)(skiatest::Reporter*, GrContext*); +typedef void(*TestWithGrContextAndGLContext)(skiatest::Reporter*, GrContext*, SkGLContext*); +#if SK_SUPPORT_GPU +template<typename T> +void call_test(T test, skiatest::Reporter* reporter, GrContextFactory::ContextInfo* context); +template<> +void call_test(TestWithGrContext test, skiatest::Reporter* reporter, + GrContextFactory::ContextInfo* context) { + test(reporter, context->fGrContext); +} +template<> +void call_test(TestWithGrContextAndGLContext test, skiatest::Reporter* reporter, + GrContextFactory::ContextInfo* context) { + test(reporter, context->fGrContext, context->fGLContext); +} +#endif +} // namespace + + +template<typename T> +void RunWithGPUTestContexts(T test, GPUTestContexts testContexts, Reporter* reporter, + GrContextFactory* factory) { +#if SK_SUPPORT_GPU + for (int i = 0; i < GrContextFactory::kGLContextTypeCnt; ++i) { + GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i; + int contextSelector = kNone_GPUTestContexts; + if (GrContextFactory::IsRenderingGLContext(glCtxType)) { + contextSelector |= kAllRendering_GPUTestContexts; + } + if (glCtxType == GrContextFactory::kNative_GLContextType) { + contextSelector |= kNative_GPUTestContexts; + } + if (glCtxType == GrContextFactory::kNull_GLContextType) { + contextSelector |= kNull_GPUTestContexts; + } + if ((testContexts & contextSelector) == 0) { + continue; + } + if (GrContextFactory::ContextInfo* context = factory->getContextInfo(glCtxType)) { + call_test(test, reporter, context); + } + } +#endif +} + +template +void RunWithGPUTestContexts<TestWithGrContext>(TestWithGrContext test, + GPUTestContexts testContexts, + Reporter* reporter, + GrContextFactory* factory); +template +void RunWithGPUTestContexts<TestWithGrContextAndGLContext>(TestWithGrContextAndGLContext test, + GPUTestContexts testContexts, + Reporter* reporter, + GrContextFactory* factory); +} // namespace skiatest + #if !defined(SK_BUILD_FOR_IOS) int main(int argc, char** argv) { SkCommandLineFlags::Parse(argc, argv); diff --git a/src/gpu/GrContextFactory.cpp b/src/gpu/GrContextFactory.cpp index acd5d93a04..424b3fda3a 100755 --- a/src/gpu/GrContextFactory.cpp +++ b/src/gpu/GrContextFactory.cpp @@ -23,15 +23,16 @@ #include "gl/GrGLGpu.h" #include "GrCaps.h" -GrContext* GrContextFactory::get(GLContextType type, GrGLStandard forcedGpuAPI) { +GrContextFactory::ContextInfo* GrContextFactory::getContextInfo(GLContextType type, + GrGLStandard forcedGpuAPI) { for (int i = 0; i < fContexts.count(); ++i) { if (forcedGpuAPI != kNone_GrGLStandard && - forcedGpuAPI != fContexts[i].fGLContext->gl()->fStandard) + forcedGpuAPI != fContexts[i]->fGLContext->gl()->fStandard) continue; - if (fContexts[i].fType == type) { - fContexts[i].fGLContext->makeCurrent(); - return fContexts[i].fGrContext; + if (fContexts[i]->fType == type) { + fContexts[i]->fGLContext->makeCurrent(); + return fContexts[i]; } } SkAutoTUnref<SkGLContext> glCtx; @@ -114,11 +115,9 @@ GrContext* GrContextFactory::get(GLContextType type, GrGLStandard forcedGpuAPI) } } - GPUContext& ctx = fContexts.push_back(); - ctx.fGLContext = glCtx.get(); - ctx.fGLContext->ref(); - ctx.fGrContext = grCtx.get(); - ctx.fGrContext->ref(); - ctx.fType = type; - return ctx.fGrContext; + ContextInfo* ctx = fContexts.emplace_back(new ContextInfo); + ctx->fGLContext = SkRef(glCtx.get()); + ctx->fGrContext = SkRef(grCtx.get()); + ctx->fType = type; + return ctx; } diff --git a/src/gpu/GrContextFactory.h b/src/gpu/GrContextFactory.h index 130c333dd0..6d17432318 100644 --- a/src/gpu/GrContextFactory.h +++ b/src/gpu/GrContextFactory.h @@ -98,39 +98,52 @@ public: void destroyContexts() { for (int i = 0; i < fContexts.count(); ++i) { - if (fContexts[i].fGLContext) { // could be abandoned. - fContexts[i].fGLContext->makeCurrent(); - } - fContexts[i].fGrContext->unref(); - if (fContexts[i].fGLContext) { - fContexts[i].fGLContext->unref(); + if (fContexts[i]->fGLContext) { // could be abandoned. + fContexts[i]->fGLContext->makeCurrent(); } + fContexts[i]->fGrContext->unref(); + SkSafeUnref(fContexts[i]->fGLContext); } fContexts.reset(); } void abandonContexts() { for (int i = 0; i < fContexts.count(); ++i) { - if (fContexts[i].fGLContext) { - fContexts[i].fGLContext->testAbandon(); - SkSafeSetNull(fContexts[i].fGLContext); + if (fContexts[i]->fGLContext) { + fContexts[i]->fGLContext->testAbandon(); + SkSafeSetNull(fContexts[i]->fGLContext); } - fContexts[i].fGrContext->abandonContext(); + fContexts[i]->fGrContext->abandonContext(); } } + struct ContextInfo { + GLContextType fType; + SkGLContext* fGLContext; + GrContext* fGrContext; + }; /** - * Get a GrContext initialized with a type of GL context. It also makes the GL context current. + * Get a context initialized with a type of GL context. It also makes the GL context current. + * Pointer is valid until destroyContexts() is called. */ - GrContext* get(GLContextType type, GrGLStandard forcedGpuAPI = kNone_GrGLStandard); + ContextInfo* getContextInfo(GLContextType type, GrGLStandard forcedGpuAPI = kNone_GrGLStandard); + /** + * Get a GrContext initialized with a type of GL context. It also makes the GL context current. + */ + GrContext* get(GLContextType type, GrGLStandard forcedGpuAPI = kNone_GrGLStandard) { + if (ContextInfo* info = this->getContextInfo(type, forcedGpuAPI)) { + return info->fGrContext; + } + return nullptr; + } // Returns the GLContext of the given type. If it has not been created yet, // nullptr is returned instead. SkGLContext* getGLContext(GLContextType type) { for (int i = 0; i < fContexts.count(); ++i) { - if (fContexts[i].fType == type) { - return fContexts[i].fGLContext; + if (fContexts[i]->fType == type) { + return fContexts[i]->fGLContext; } } @@ -140,12 +153,7 @@ public: const GrContextOptions& getGlobalOptions() const { return fGlobalOptions; } private: - struct GPUContext { - GLContextType fType; - SkGLContext* fGLContext; - GrContext* fGrContext; - }; - SkTArray<GPUContext, true> fContexts; + SkTArray<SkAutoTDelete<ContextInfo>, true> fContexts; const GrContextOptions fGlobalOptions; }; diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp index d139ca7075..7bce8e5a5d 100644 --- a/tests/ImageTest.cpp +++ b/tests/ImageTest.cpp @@ -415,60 +415,6 @@ struct ReleaseDataContext { } }; -// May we (soon) eliminate the need to keep testing this, by hiding the bloody device! -#include "SkDevice.h" -static uint32_t get_legacy_gen_id(SkSurface* surf) { - SkBaseDevice* device = surf->getCanvas()->getDevice_just_for_deprecated_compatibility_testing(); - return device->accessBitmap(false).getGenerationID(); -} - -/* - * Test legacy behavor of bumping the surface's device's bitmap's genID when we access its - * texture handle for writing. - * - * Note: this needs to be tested separately from checking newImageSnapshot, as calling that - * can also incidentally bump the genID (when a new backing surface is created). - */ -template <class F> -static void test_texture_handle_genID(skiatest::Reporter* reporter, SkSurface* surf, F f) { - const uint32_t gen0 = get_legacy_gen_id(surf); - f(surf, SkSurface::kFlushRead_BackendHandleAccess); - const uint32_t gen1 = get_legacy_gen_id(surf); - REPORTER_ASSERT(reporter, gen0 == gen1); - - f(surf, SkSurface::kFlushWrite_BackendHandleAccess); - const uint32_t gen2 = get_legacy_gen_id(surf); - REPORTER_ASSERT(reporter, gen0 != gen2); - - f(surf, SkSurface::kDiscardWrite_BackendHandleAccess); - const uint32_t gen3 = get_legacy_gen_id(surf); - REPORTER_ASSERT(reporter, gen0 != gen3); - REPORTER_ASSERT(reporter, gen2 != gen3); -} - -template <class F> -static void test_backend_handle(skiatest::Reporter* reporter, SkSurface* surf, F f) { - SkAutoTUnref<SkImage> image0(surf->newImageSnapshot()); - GrBackendObject obj = f(surf, SkSurface::kFlushRead_BackendHandleAccess); - REPORTER_ASSERT(reporter, obj != 0); - SkAutoTUnref<SkImage> image1(surf->newImageSnapshot()); - // just read access should not affect the snapshot - REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID()); - - obj = f(surf, SkSurface::kFlushWrite_BackendHandleAccess); - REPORTER_ASSERT(reporter, obj != 0); - SkAutoTUnref<SkImage> image2(surf->newImageSnapshot()); - // expect a new image, since we claimed we would write - REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID()); - - obj = f(surf, SkSurface::kDiscardWrite_BackendHandleAccess); - REPORTER_ASSERT(reporter, obj != 0); - SkAutoTUnref<SkImage> image3(surf->newImageSnapshot()); - // expect a new(er) image, since we claimed we would write - REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID()); - REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID()); -} - static SkImage* create_image(skiatest::Reporter* reporter, ImageType imageType, GrContext* context, SkColor color, ReleaseDataContext* releaseContext) { @@ -495,22 +441,6 @@ static SkImage* create_image(skiatest::Reporter* reporter, SkAutoTUnref<SkSurface> surf( SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0)); surf->getCanvas()->clear(color); - // test our backing texture / rendertarget while were here... - auto textureAccessorFunc = - [](SkSurface* surf, SkSurface::BackendHandleAccess access) -> GrBackendObject { - return surf->getTextureHandle(access); }; - auto renderTargetAccessorFunc = - [](SkSurface* surf, SkSurface::BackendHandleAccess access) -> GrBackendObject { - GrBackendObject obj; - SkAssertResult(surf->getRenderTargetHandle(&obj, access)); - return obj; }; - test_backend_handle(reporter, surf, textureAccessorFunc); - test_backend_handle(reporter, surf, renderTargetAccessorFunc); - test_texture_handle_genID(reporter, surf, textureAccessorFunc); - test_texture_handle_genID(reporter, surf, renderTargetAccessorFunc); - - // redraw so our returned image looks as expected. - surf->getCanvas()->clear(color); return surf->newImageSnapshot(); } case kCodec_ImageType: { diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp index 7e07e17f89..6859bce6bc 100644 --- a/tests/SurfaceTest.cpp +++ b/tests/SurfaceTest.cpp @@ -8,7 +8,6 @@ #include "SkCanvas.h" #include "SkData.h" #include "SkDevice.h" -#include "SkImageEncoder.h" #include "SkImage_Base.h" #include "SkPath.h" #include "SkRRect.h" @@ -17,72 +16,73 @@ #include "Test.h" #if SK_SUPPORT_GPU -#include "GrContextFactory.h" -#include "GrTest.h" -#else -class GrContextFactory; -class GrContext; +#include "GrContext.h" +#include "GrGpu.h" #endif -enum SurfaceType { - kRaster_SurfaceType, - kRasterDirect_SurfaceType, - kGpu_SurfaceType, - kGpuScratch_SurfaceType, +#include <initializer_list> - kLastSurfaceType = kGpuScratch_SurfaceType -}; -static const int kSurfaceTypeCnt = kLastSurfaceType + 1; - -static void release_storage(void* pixels, void* context) { +static void release_direct_surface_storage(void* pixels, void* context) { SkASSERT(pixels == context); sk_free(pixels); } - -static SkSurface* create_surface(SurfaceType surfaceType, GrContext* context, - SkAlphaType at = kPremul_SkAlphaType, +static SkSurface* create_surface(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 SkSurface::NewRaster(info); +} +static SkSurface* create_direct_surface(SkAlphaType at = kPremul_SkAlphaType, + SkImageInfo* requestedInfo = nullptr) { + const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at); + if (requestedInfo) { + *requestedInfo = info; + } + const size_t rowBytes = info.minRowBytes(); + void* storage = sk_malloc_throw(info.getSafeSize(rowBytes)); + return SkSurface::NewRasterDirectReleaseProc(info, storage, rowBytes, + release_direct_surface_storage, + storage); +} +#if SK_SUPPORT_GPU +static SkSurface* create_gpu_surface(GrContext* context, SkAlphaType at = kPremul_SkAlphaType, + SkImageInfo* requestedInfo = nullptr) { + const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at); + if (requestedInfo) { + *requestedInfo = info; + } + return SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0, nullptr); +} +static SkSurface* create_gpu_scratch_surface(GrContext* context, + SkAlphaType at = kPremul_SkAlphaType, + SkImageInfo* requestedInfo = nullptr) { + const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at); + if (requestedInfo) { + *requestedInfo = info; } - return nullptr; + return SkSurface::NewRenderTarget(context, SkSurface::kYes_Budgeted, info, 0, nullptr); } +#endif -static void test_empty_surface(skiatest::Reporter* reporter, GrContext* ctx) { +DEF_TEST(SurfaceEmpty, reporter) { 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; - } +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceEmpty_Gpu, reporter, context) { + const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType); + REPORTER_ASSERT(reporter, nullptr == + SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0, nullptr)); +} +#endif - const GrGpu* gpu = ctx->getGpu(); +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWrappedTexture, reporter, context) { + const GrGpu* gpu = context->getGpu(); if (!gpu) { return; } @@ -106,7 +106,8 @@ static void test_wrapped_texture_surface(skiatest::Reporter* reporter, GrContext wrappedDesc.fFlags = kRenderTarget_GrBackendTextureFlag; wrappedDesc.fTextureHandle = texHandle; - SkAutoTUnref<SkSurface> surface(SkSurface::NewWrappedRenderTarget(ctx, wrappedDesc, nullptr)); + SkAutoTUnref<SkSurface> surface( + SkSurface::NewWrappedRenderTarget(context, wrappedDesc, nullptr)); REPORTER_ASSERT(reporter, surface); if (surface) { // Validate that we can draw to the canvas and that the original texture color is preserved @@ -146,165 +147,136 @@ static void test_wrapped_texture_surface(skiatest::Reporter* reporter, GrContext } } 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 - }; - +static void test_canvas_peek(skiatest::Reporter* reporter, + SkSurface* surface, + const SkImageInfo& requestInfo, + bool expectPeekSuccess) { 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; + SkImageInfo info; + size_t rowBytes; + surface->getCanvas()->clear(color); + + const void* addr = surface->getCanvas()->peekPixels(&info, &rowBytes); + bool success = SkToBool(addr); + REPORTER_ASSERT(reporter, expectPeekSuccess == 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); + } +} +DEF_TEST(SurfaceCanvasPeek, reporter) { + for (auto& surface_func : { &create_surface, &create_direct_surface }) { + SkImageInfo requestInfo; + SkAutoTUnref<SkSurface> surface(surface_func(kPremul_SkAlphaType, &requestInfo)); + test_canvas_peek(reporter, surface, requestInfo, true); + } +} #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); - } - } +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCanvasPeek_Gpu, reporter, context) { + for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { + SkImageInfo requestInfo; + SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType, &requestInfo)); + test_canvas_peek(reporter, surface, requestInfo, false); } } +#endif // 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; +void test_access_pixels(skiatest::Reporter* reporter, SkSurface* surface) { + 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); +} +DEF_TEST(SurfaceAccessPixels, reporter) { + for (auto& surface_func : { &create_surface, &create_direct_surface }) { + SkAutoTUnref<SkSurface> surface(surface_func(kPremul_SkAlphaType, nullptr)); + test_access_pixels(reporter, surface); + } +} #if SK_SUPPORT_GPU - cnt = GrContextFactory::kGLContextTypeCnt; -#else - cnt = 1; +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceAccessPixels_Gpu, reporter, context) { + for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { + SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType, nullptr)); + test_access_pixels(reporter, surface); + } +} #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; + +static void test_snapshot_alphatype(skiatest::Reporter* reporter, SkSurface* surface, + bool expectOpaque) { + REPORTER_ASSERT(reporter, surface); + if (surface) { + SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); + REPORTER_ASSERT(reporter, image); + if (image) { + REPORTER_ASSERT(reporter, image->isOpaque() == SkToBool(expectOpaque)); } -#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); + } +} +DEF_TEST(SurfaceSnapshotAlphaType, reporter) { + for (auto& surface_func : { &create_surface, &create_direct_surface }) { + for (auto& isOpaque : { true, false }) { + SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; + SkAutoTUnref<SkSurface> surface(surface_func(alphaType, nullptr)); + test_snapshot_alphatype(reporter, surface, isOpaque); } } } - -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; +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceSnapshotAlphaType_Gpu, reporter, context) { + for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { + for (auto& isOpaque : { true, false }) { + SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; + SkAutoTUnref<SkSurface> surface(surface_func(context, alphaType, nullptr)); + test_snapshot_alphatype(reporter, surface, isOpaque); + } } +} #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 GrBackendObject get_surface_backend_texture_handle( + SkSurface* s, SkSurface::BackendHandleAccess a) { + return s->getTextureHandle(a); +} +static GrBackendObject get_surface_backend_render_target_handle( + SkSurface* s, SkSurface::BackendHandleAccess a) { + GrBackendObject result; + if (!s->getRenderTargetHandle(&result, a)) { + return 0; } + return result; } -static void test_backend_cow(skiatest::Reporter* reporter, SkSurface* surface, - SkSurface::BackendHandleAccess mode, - GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) { +static void test_backend_handle_access_copy_on_write( + skiatest::Reporter* reporter, SkSurface* surface, SkSurface::BackendHandleAccess mode, + GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) { GrBackendObject obj1 = func(surface, mode); SkAutoTUnref<SkImage> snap1(surface->newImageSnapshot()); @@ -314,12 +286,113 @@ static void test_backend_cow(skiatest::Reporter* reporter, SkSurface* surface, // If the access mode triggers CoW, then the backend objects should reflect it. REPORTER_ASSERT(reporter, (obj1 == obj2) == (snap1 == snap2)); } +DEF_TEST(SurfaceBackendHandleAccessCopyOnWrite, reporter) { + const SkSurface::BackendHandleAccess accessModes[] = { + SkSurface::kFlushRead_BackendHandleAccess, + SkSurface::kFlushWrite_BackendHandleAccess, + SkSurface::kDiscardWrite_BackendHandleAccess, + }; + for (auto& handle_access_func : + { &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle }) { + for (auto& accessMode : accessModes) { + SkAutoTUnref<SkSurface> surface(create_surface()); + test_backend_handle_access_copy_on_write(reporter, surface, accessMode, + handle_access_func); + } + } +} +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessCopyOnWrite_Gpu, reporter, context) { + const SkSurface::BackendHandleAccess accessModes[] = { + SkSurface::kFlushRead_BackendHandleAccess, + SkSurface::kFlushWrite_BackendHandleAccess, + SkSurface::kDiscardWrite_BackendHandleAccess, + }; + for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { + for (auto& handle_access_func : + { &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle }) { + for (auto& accessMode : accessModes) { + SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType, + nullptr)); + test_backend_handle_access_copy_on_write(reporter, surface, accessMode, + handle_access_func); + } + } + } +} +#endif -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); +#if SK_SUPPORT_GPU +// May we (soon) eliminate the need to keep testing this, by hiding the bloody device! +static uint32_t get_legacy_gen_id(SkSurface* surface) { + SkBaseDevice* device = + surface->getCanvas()->getDevice_just_for_deprecated_compatibility_testing(); + return device->accessBitmap(false).getGenerationID(); +} +/* + * Test legacy behavor of bumping the surface's device's bitmap's genID when we access its + * texture handle for writing. + * + * Note: this needs to be tested separately from checking newImageSnapshot, as calling that + * can also incidentally bump the genID (when a new backing surface is created). + */ +static void test_backend_handle_gen_id( + skiatest::Reporter* reporter, SkSurface* surface, + GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) { + const uint32_t gen0 = get_legacy_gen_id(surface); + func(surface, SkSurface::kFlushRead_BackendHandleAccess); + const uint32_t gen1 = get_legacy_gen_id(surface); + REPORTER_ASSERT(reporter, gen0 == gen1); + + func(surface, SkSurface::kFlushWrite_BackendHandleAccess); + const uint32_t gen2 = get_legacy_gen_id(surface); + REPORTER_ASSERT(reporter, gen0 != gen2); + + func(surface, SkSurface::kDiscardWrite_BackendHandleAccess); + const uint32_t gen3 = get_legacy_gen_id(surface); + REPORTER_ASSERT(reporter, gen0 != gen3); + REPORTER_ASSERT(reporter, gen2 != gen3); +} +static void test_backend_handle_unique_id( + skiatest::Reporter* reporter, SkSurface* surface, + GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) { + SkAutoTUnref<SkImage> image0(surface->newImageSnapshot()); + GrBackendObject obj = func(surface, SkSurface::kFlushRead_BackendHandleAccess); + REPORTER_ASSERT(reporter, obj != 0); + SkAutoTUnref<SkImage> image1(surface->newImageSnapshot()); + // just read access should not affect the snapshot + REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID()); + + obj = func(surface, SkSurface::kFlushWrite_BackendHandleAccess); + REPORTER_ASSERT(reporter, obj != 0); + SkAutoTUnref<SkImage> image2(surface->newImageSnapshot()); + // expect a new image, since we claimed we would write + REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID()); + + obj = func(surface, SkSurface::kDiscardWrite_BackendHandleAccess); + REPORTER_ASSERT(reporter, obj != 0); + SkAutoTUnref<SkImage> image3(surface->newImageSnapshot()); + // expect a new(er) image, since we claimed we would write + REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID()); + REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID()); +} +// No CPU test. +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessIDs_Gpu, reporter, context) { + for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { + for (auto& test_func : { &test_backend_handle_unique_id, &test_backend_handle_gen_id }) { + for (auto& handle_access_func : + { &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle}) { + SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType, + nullptr)); + test_func(reporter, surface, handle_access_func); + } + } + } +} +#endif + +// Verify that the right canvas commands trigger a copy on write. +static void test_copy_on_write(skiatest::Reporter* reporter, SkSurface* surface) { SkCanvas* canvas = surface->getCanvas(); const SkRect testRect = @@ -393,53 +466,51 @@ static void TestSurfaceCopyOnWrite(skiatest::Reporter* reporter, SurfaceType sur 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; - }); +} +DEF_TEST(SurfaceCopyOnWrite, reporter) { + SkAutoTUnref<SkSurface> surface(create_surface()); + test_copy_on_write(reporter, surface); +} +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCopyOnWrite_Gpu, reporter, context) { + for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { + SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType, nullptr)); + test_copy_on_write(reporter, surface); } } +#endif -static void TestSurfaceWritableAfterSnapshotRelease(skiatest::Reporter* reporter, - SurfaceType surfaceType, - GrContext* context) { +static void test_writable_after_snapshot_release(skiatest::Reporter* reporter, + SkSurface* surface) { // 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 } +DEF_TEST(SurfaceWriteableAfterSnapshotRelease, reporter) { + SkAutoTUnref<SkSurface> surface(create_surface()); + test_writable_after_snapshot_release(reporter, surface); +} +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWriteableAfterSnapshotRelease_Gpu, reporter, context) { + for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { + SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType, nullptr)); + test_writable_after_snapshot_release(reporter, surface); + } +} +#endif #if SK_SUPPORT_GPU -static void Test_crbug263329(skiatest::Reporter* reporter, - SurfaceType surfaceType, - GrContext* context) { +static void test_crbug263329(skiatest::Reporter* reporter, + SkSurface* surface1, + SkSurface* surface2) { // 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); @@ -465,39 +536,53 @@ static void Test_crbug263329(skiatest::Reporter* reporter, REPORTER_ASSERT(reporter, as_IB(image3)->getTexture() != as_IB(image1)->getTexture()); REPORTER_ASSERT(reporter, as_IB(image2)->getTexture() != as_IB(image1)->getTexture()); } +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCRBug263329_Gpu, reporter, context) { + for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { + SkAutoTUnref<SkSurface> surface1(surface_func(context, kPremul_SkAlphaType, nullptr)); + SkAutoTUnref<SkSurface> surface2(surface_func(context, kPremul_SkAlphaType, nullptr)); + test_crbug263329(reporter, surface1, surface2); + } +} +#endif -static void TestGetTexture(skiatest::Reporter* reporter, - SurfaceType surfaceType, - GrContext* context) { - SkAutoTUnref<SkSurface> surface(create_surface(surfaceType, context)); +DEF_TEST(SurfaceGetTexture, reporter) { + SkAutoTUnref<SkSurface> surface(create_surface()); SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); - GrTexture* texture = as_IB(image)->getTexture(); - if (surfaceType == kGpu_SurfaceType || surfaceType == kGpuScratch_SurfaceType) { + REPORTER_ASSERT(reporter, as_IB(image)->getTexture() == nullptr); + surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode); + REPORTER_ASSERT(reporter, as_IB(image)->getTexture() == nullptr); +} +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceGetTexture_Gpu, reporter, context) { + for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { + SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType, nullptr)); + SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); + GrTexture* texture = as_IB(image)->getTexture(); 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); } - surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode); - REPORTER_ASSERT(reporter, as_IB(image)->getTexture() == texture); } +#endif +#if SK_SUPPORT_GPU #include "GrGpuResourcePriv.h" #include "SkGpuDevice.h" #include "SkImage_Gpu.h" #include "SkSurface_Gpu.h" -SkSurface::Budgeted is_budgeted(SkSurface* surf) { +static 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) { +static 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) { +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBudget, reporter, context) { SkImageInfo info = SkImageInfo::MakeN32Premul(8,8); for (int i = 0; i < 2; ++i) { SkSurface::Budgeted sbudgeted = i ? SkSurface::kYes_Budgeted : SkSurface::kNo_Budgeted; @@ -525,86 +610,55 @@ static void test_surface_budget(skiatest::Reporter* reporter, GrContext* context } } } - #endif -static void TestSurfaceNoCanvas(skiatest::Reporter* reporter, - SurfaceType surfaceType, - GrContext* context, - SkSurface::ContentChangeMode mode) { +static void test_no_canvas1(skiatest::Reporter* reporter, + SkSurface* surface, + SkSurface::ContentChangeMode mode) { + // Test passes by not asserting + surface->notifyContentWillChange(mode); + SkDEBUGCODE(surface->validate();) +} +static void test_no_canvas2(skiatest::Reporter* reporter, + SkSurface* surface, + 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); + 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_TEST(SurfaceNoCanvas, reporter) { + SkSurface::ContentChangeMode modes[] = + { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode}; + for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) { + for (auto& mode : modes) { + SkAutoTUnref<SkSurface> surface(create_surface()); + test_func(reporter, surface, mode); + } } - } - -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); +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceNoCanvas_Gpu, reporter, context) { + SkSurface::ContentChangeMode modes[] = + { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode}; + for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { + for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) { + for (auto& mode : modes) { + SkAutoTUnref<SkSurface> surface( + surface_func(context, kPremul_SkAlphaType, nullptr)); + test_func(reporter, surface, mode); } } } -#endif } - - +#endif diff --git a/tests/Test.h b/tests/Test.h index c1e0c528fb..be2ef1f788 100644 --- a/tests/Test.h +++ b/tests/Test.h @@ -13,6 +13,8 @@ #include "SkTypes.h" class GrContextFactory; +class GrContext; +class SkGLContext; namespace skiatest { @@ -69,6 +71,17 @@ typedef SkTRegistry<Test> TestRegistry; ... } */ +enum GPUTestContexts { + kNone_GPUTestContexts = 0, + kNull_GPUTestContexts = 1, + kNative_GPUTestContexts = 1 << 1, + kOther_GPUTestContexts = 1 << 2, // Other than native, used only for below. + kAllRendering_GPUTestContexts = kNative_GPUTestContexts | kOther_GPUTestContexts, + kAll_GPUTestContexts = kAllRendering_GPUTestContexts | kNull_GPUTestContexts +}; +template<typename T> +void RunWithGPUTestContexts(T testFunction, GPUTestContexts contexts, Reporter* reporter, + GrContextFactory* factory); } // namespace skiatest #define REPORTER_ASSERT(r, cond) \ @@ -96,12 +109,41 @@ typedef SkTRegistry<Test> TestRegistry; skiatest::Test(#name, false, test_##name)); \ void test_##name(skiatest::Reporter* reporter, GrContextFactory*) +#define GPUTEST_EXPAND_MSVC(x) x +#define GPUTEST_APPLY(C, ...) GPUTEST_EXPAND_MSVC(C(__VA_ARGS__)) +#define GPUTEST_SELECT(a1, a2, N, ...) N + +#define GPUTEST_CONTEXT_ARGS1(a1) GrContext* a1 +#define GPUTEST_CONTEXT_ARGS2(a1, a2) GrContext* a1, SkGLContext* a2 +#define GPUTEST_CONTEXT_ARGS(...) \ + GPUTEST_APPLY(GPUTEST_SELECT(__VA_ARGS__, GPUTEST_CONTEXT_ARGS2, GPUTEST_CONTEXT_ARGS1), \ + __VA_ARGS__) + #define DEF_GPUTEST(name, reporter, factory) \ static void test_##name(skiatest::Reporter*, GrContextFactory*); \ skiatest::TestRegistry name##TestRegistry( \ skiatest::Test(#name, true, test_##name)); \ void test_##name(skiatest::Reporter* reporter, GrContextFactory* factory) +#define DEF_GPUTEST_FOR_CONTEXTS(name, contexts, reporter, ...) \ + static void test_##name(skiatest::Reporter*, GPUTEST_CONTEXT_ARGS(__VA_ARGS__)); \ + static void test_gpu_contexts_##name(skiatest::Reporter* reporter, \ + GrContextFactory* factory) { \ + skiatest::RunWithGPUTestContexts(test_##name, contexts, reporter, factory); \ + } \ + skiatest::TestRegistry name##TestRegistry( \ + skiatest::Test(#name, true, test_gpu_contexts_##name)); \ + void test_##name(skiatest::Reporter* reporter, GPUTEST_CONTEXT_ARGS(__VA_ARGS__)) + +#define DEF_GPUTEST_FOR_ALL_CONTEXTS(name, reporter, ...) \ + DEF_GPUTEST_FOR_CONTEXTS(name, skiatest::kAll_GPUTestContexts, reporter, __VA_ARGS__) +#define DEF_GPUTEST_FOR_RENDERING_CONTEXTS(name, reporter, ...) \ + DEF_GPUTEST_FOR_CONTEXTS(name, skiatest::kAllRendering_GPUTestContexts, reporter, __VA_ARGS__) +#define DEF_GPUTEST_FOR_NULL_CONTEXT(name, reporter, ...) \ + DEF_GPUTEST_FOR_CONTEXTS(name, skiatest::kNull_GPUTestContexts, reporter, __VA_ARGS__) +#define DEF_GPUTEST_FOR_NATIVE_CONTEXT(name, reporter, ...) \ + DEF_GPUTEST_FOR_CONTEXTS(name, skiatest::kNative_GPUTestContexts, reporter, __VA_ARGS__) + #define REQUIRE_PDF_DOCUMENT(TEST_NAME, REPORTER) \ do { \ SkDynamicMemoryWStream testStream; \ diff --git a/tests/TestTest.cpp b/tests/TestTest.cpp new file mode 100644 index 0000000000..2c303a74ce --- /dev/null +++ b/tests/TestTest.cpp @@ -0,0 +1,75 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "Test.h" + +#if SK_SUPPORT_GPU +#include "GrContext.h" +#include "gl/SkGLContext.h" +#endif + + +// This is an example of a normal test. +DEF_TEST(TestNormal, reporter) { + REPORTER_ASSERT(reporter, reporter); +} + +// This is an example of a GPU test that uses common GrContextFactory factory to do the test. +#if SK_SUPPORT_GPU +DEF_GPUTEST(TestGpuFactory, reporter, factory) { + REPORTER_ASSERT(reporter, reporter); + REPORTER_ASSERT(reporter, factory); +} +#endif + +// This is an example of a GPU test that tests a property that should work for all GPU contexts. +// Note: Some of the contexts might not produce a rendering output. +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_ALL_CONTEXTS(TestGpuAllContexts, reporter, context) { + REPORTER_ASSERT(reporter, reporter); + REPORTER_ASSERT(reporter, context); +} +#endif + +// This is an example of a GPU test that tests a property that should work for all GPU contexts that +// produce a rendering output. +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TestGpuRenderingContexts, reporter, context) { + REPORTER_ASSERT(reporter, reporter); + REPORTER_ASSERT(reporter, context); +} +#endif + +// This is an example of a GPU test that tests a property that should work at least for the native +// GPU context. If the test takes a long time to run, it may be appropriate to test only the native +// context. +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_NATIVE_CONTEXT(TestGpuNativeContext, reporter, context) { + REPORTER_ASSERT(reporter, reporter); + REPORTER_ASSERT(reporter, context); +} +#endif + +// This is an example of a GPU test that tests a property that uses the null GPU context. It should +// be used if the test tests some behavior that is mocked with the null context. +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_NULL_CONTEXT(TestGpuNullContext, reporter, context) { + REPORTER_ASSERT(reporter, reporter); + REPORTER_ASSERT(reporter, context); +} +#endif + +// This is an example of a GPU test that tests a property that should work for all GPU contexts. +// It uses the additional SkGLContext* glContext to implement the test. +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_ALL_CONTEXTS(TestGpuGrContextAndGLContext, reporter, context, glContext) { + REPORTER_ASSERT(reporter, reporter); + REPORTER_ASSERT(reporter, context); + REPORTER_ASSERT(reporter, glContext); +} +#endif + |