Index: tests/SurfaceTest.cpp |
diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp |
index 878adeda3d957a86fe2805b429c2c8e5626c425f..a3e0f8f4e3f832b976c04ca10588dc3c2b37098e 100644 |
--- a/tests/SurfaceTest.cpp |
+++ b/tests/SurfaceTest.cpp |
@@ -83,75 +83,6 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceEmpty_Gpu, reporter, ctxInfo) { |
} |
#endif |
-#if SK_SUPPORT_GPU |
-DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceWrappedTexture, reporter, ctxInfo) { |
- GrGpu* gpu = ctxInfo.fGrContext->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; |
- |
- auto surface(SkSurface::MakeFromBackendTexture(ctxInfo.fGrContext, 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_canvas_peek(skiatest::Reporter* reporter, |
sk_sp<SkSurface>& surface, |
const SkImageInfo& requestInfo, |
@@ -820,10 +751,54 @@ DEF_TEST(surface_rowbytes, reporter) { |
} |
#if SK_SUPPORT_GPU |
+static sk_sp<SkSurface> create_gpu_surface_backend_texture( |
+ GrContext* context, int sampleCnt, uint32_t color, GrBackendObject* outTexture) { |
+ const int kWidth = 10; |
+ const int kHeight = 10; |
+ SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[kWidth * kHeight]); |
+ sk_memset32(pixels.get(), color, kWidth * kHeight); |
+ GrBackendTextureDesc desc; |
+ desc.fConfig = kRGBA_8888_GrPixelConfig; |
+ desc.fWidth = kWidth; |
+ desc.fHeight = kHeight; |
+ desc.fFlags = kRenderTarget_GrBackendTextureFlag; |
+ desc.fTextureHandle = context->getGpu()->createTestingOnlyBackendTexture( |
+ pixels.get(), kWidth, kHeight, kRGBA_8888_GrPixelConfig); |
+ sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(context, desc, nullptr); |
+ if (!surface) { |
+ context->getGpu()->deleteTestingOnlyBackendTexture(desc.fTextureHandle); |
+ return nullptr; |
+ } |
+ *outTexture = desc.fTextureHandle; |
+ return surface; |
+} |
+ |
+static sk_sp<SkSurface> create_gpu_surface_backend_texture_as_render_target( |
+ GrContext* context, int sampleCnt, uint32_t color, GrBackendObject* outTexture) { |
+ const int kWidth = 10; |
+ const int kHeight = 10; |
+ SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[kWidth * kHeight]); |
+ sk_memset32(pixels.get(), color, kWidth * kHeight); |
+ GrBackendTextureDesc desc; |
+ desc.fConfig = kRGBA_8888_GrPixelConfig; |
+ desc.fWidth = kWidth; |
+ desc.fHeight = kHeight; |
+ desc.fFlags = kRenderTarget_GrBackendTextureFlag; |
+ desc.fTextureHandle = context->getGpu()->createTestingOnlyBackendTexture( |
+ pixels.get(), kWidth, kHeight, kRGBA_8888_GrPixelConfig); |
+ sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTextureAsRenderTarget(context, desc, |
+ nullptr); |
+ if (!surface) { |
+ context->getGpu()->deleteTestingOnlyBackendTexture(desc.fTextureHandle); |
+ return nullptr; |
+ } |
+ *outTexture = desc.fTextureHandle; |
+ return surface; |
+} |
-void test_surface_clear(skiatest::Reporter* reporter, sk_sp<SkSurface> surface, |
- std::function<GrSurface*(SkSurface*)> grSurfaceGetter, |
- uint32_t expectedValue) { |
+static void test_surface_clear(skiatest::Reporter* reporter, sk_sp<SkSurface> surface, |
+ std::function<GrSurface*(SkSurface*)> grSurfaceGetter, |
+ uint32_t expectedValue) { |
if (!surface) { |
ERRORF(reporter, "Could not create GPU SkSurface."); |
return; |
@@ -831,7 +806,7 @@ void test_surface_clear(skiatest::Reporter* reporter, sk_sp<SkSurface> surface, |
int w = surface->width(); |
int h = surface->height(); |
SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[w * h]); |
- memset(pixels.get(), ~expectedValue, sizeof(uint32_t) * w * h); |
+ sk_memset32(pixels.get(), ~expectedValue, w * h); |
SkAutoTUnref<GrSurface> grSurface(SkSafeRef(grSurfaceGetter(surface.get()))); |
if (!grSurface) { |
@@ -872,31 +847,127 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceClear_Gpu, reporter, ctxInfo) { |
[] (SkSurface* s){ sk_sp<SkImage> i(s->makeImageSnapshot()); |
return as_IB(i)->peekTexture(); }, |
}; |
+ |
for (auto grSurfaceGetter : grSurfaceGetters) { |
+ // Test that non-wrapped RTs are created clear. |
for (auto& surface_func : {&create_gpu_surface, &create_gpu_scratch_surface}) { |
auto surface = surface_func(context, kPremul_SkAlphaType, nullptr); |
test_surface_clear(reporter, surface, grSurfaceGetter, 0x0); |
} |
// Wrapped RTs are *not* supposed to clear (to allow client to partially update a surface). |
- static const int kWidth = 10; |
- static const int kHeight = 10; |
- SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[kWidth * kHeight]); |
- memset(pixels.get(), 0xAB, sizeof(uint32_t) * kWidth * kHeight); |
+ // This is applicable only when sample count is 0. Otherwise contents are undefined. |
+ const uint32_t kOrigColor = 0xABABABAB; |
+ for (auto& surface_func : {&create_gpu_surface_backend_texture, |
+ &create_gpu_surface_backend_texture_as_render_target}) { |
+ GrBackendObject textureObject; |
+ int sampleCnt = 0; |
+ auto surface = surface_func(context, sampleCnt, kOrigColor, &textureObject); |
+ test_surface_clear(reporter, surface, grSurfaceGetter, kOrigColor); |
+ surface.reset(); |
+ context->getGpu()->deleteTestingOnlyBackendTexture(textureObject); |
+ } |
+ } |
+} |
+#endif |
- GrBackendObject textureObject = |
- context->getGpu()->createTestingOnlyBackendTexture(pixels.get(), kWidth, kHeight, |
- kRGBA_8888_GrPixelConfig); |
+#if SK_SUPPORT_GPU |
+static void test_surface_draw_path_triggering_stencil( |
+ skiatest::Reporter* reporter, int sampleCnt, sk_sp<SkSurface> surface, |
+ uint32_t origColor) { |
+ const int kW = surface->width(); |
+ const int kH = surface->height(); |
+ SkPaint paint; |
+ paint.setAntiAlias(true); |
+ paint.setColor(SK_ColorGREEN); |
+ SkPath clipPath; |
+ clipPath.quadTo(SkIntToScalar(kW), SkIntToScalar(0), SkIntToScalar(kW), SkIntToScalar(kH)); |
+ clipPath.lineTo(SkIntToScalar(0), SkIntToScalar(kH)); |
+ clipPath.lineTo(SkIntToScalar(0), SkIntToScalar(0)); |
+ clipPath.close(); |
+ SkPath path; |
+ path.quadTo(SkIntToScalar(0), SkIntToScalar(kH), SkIntToScalar(kW), SkIntToScalar(kH)); |
+ path.lineTo(SkIntToScalar(kW), SkIntToScalar(0)); |
+ path.lineTo(SkIntToScalar(0), SkIntToScalar(0)); |
+ path.close(); |
+ surface->getCanvas()->clipPath(clipPath, SkRegion::kIntersect_Op, true); |
+ surface->getCanvas()->drawPath(path, paint); |
+ // TODO: verify the drawing in a way that passes all platforms. |
+} |
+ |
+static void test_surface_draw_partially( |
+ skiatest::Reporter* reporter, sk_sp<SkSurface> surface, uint32_t origColor) { |
+ const int kW = surface->width(); |
+ const int kH = surface->height(); |
+ SkPaint paint; |
+ const SkColor kRectColor = ~origColor | 0xFF000000; |
+ paint.setColor(kRectColor); |
+ surface->getCanvas()->drawRect(SkRect::MakeWH(SkIntToScalar(kW), SkIntToScalar(kH)/2), |
+ paint); |
+ SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[kW * kH]); |
+ sk_memset32(pixels.get(), ~origColor, kW * kH); |
+ SkImageInfo readInfo = SkImageInfo::MakeN32Premul(kW, kH); |
+ SkAssertResult(surface->readPixels(readInfo, pixels.get(), kW * sizeof(uint32_t), 0, 0)); |
+ bool stop = false; |
+ SkPMColor origColorPM = SkPackARGB32((origColor >> 24 & 0xFF), |
+ (origColor >> 0 & 0xFF), |
+ (origColor >> 8 & 0xFF), |
+ (origColor >> 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; |
+ } |
+ } |
+ } |
+} |
- GrBackendTextureDesc desc; |
- desc.fConfig = kRGBA_8888_GrPixelConfig; |
- desc.fWidth = kWidth; |
- desc.fHeight = kHeight; |
- desc.fFlags = kRenderTarget_GrBackendTextureFlag; |
- desc.fTextureHandle = textureObject; |
+DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceWrappedTextureDrawTests, reporter, ctxInfo) { |
+ GrGpu* gpu = ctxInfo.fGrContext->getGpu(); |
+ if (!gpu) { |
+ return; |
+ } |
+ static const uint32_t kOrigColor = 0xFFAABBCC; |
- auto surface = SkSurface::MakeFromBackendTexture(context, desc, nullptr); |
- test_surface_clear(reporter, surface, grSurfaceGetter, 0xABABABAB); |
- context->getGpu()->deleteTestingOnlyBackendTexture(textureObject); |
+ for (auto& surface_func : {&create_gpu_surface_backend_texture, |
+ &create_gpu_surface_backend_texture_as_render_target}) { |
+ for (int sampleCnt : {0, 4, 8}) { |
+ GrBackendObject textureObject; |
+ auto surface = surface_func(ctxInfo.fGrContext, sampleCnt, kOrigColor, &textureObject); |
+ if (!surface) { |
+ continue; |
+ } |
+ // Validate that we can draw paths to a canvas of a surface created with |
+ // SkSurface::MakeFromBackendTextureAsRenderTarget. The code intends to enforce the use |
+ // of stencil buffer. The original bug prevented the creation of stencil buffer, causing |
+ // an assert while drawing paths. |
+ test_surface_draw_path_triggering_stencil(reporter, sampleCnt, surface, kOrigColor); |
+ surface.reset(); |
+ gpu->deleteTestingOnlyBackendTexture(textureObject); |
+ } |
+ // 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. |
+ // This works only for non-multisampled case. |
+ GrBackendObject textureObject; |
+ auto surface = surface_func(ctxInfo.fGrContext, 0, kOrigColor, &textureObject); |
+ if (surface) { |
+ test_surface_draw_partially(reporter, surface, kOrigColor); |
+ surface.reset(); |
+ gpu->deleteTestingOnlyBackendTexture(textureObject); |
+ } |
} |
} |
#endif |