• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <functional>
9 #include "SkCanvas.h"
10 #include "SkColorSpace_Base.h"
11 #include "SkData.h"
12 #include "SkDevice.h"
13 #include "SkImage_Base.h"
14 #include "SkOverdrawCanvas.h"
15 #include "SkPath.h"
16 #include "SkRegion.h"
17 #include "SkRRect.h"
18 #include "SkSurface.h"
19 #include "SkUtils.h"
20 #include "Test.h"
21 
22 #if SK_SUPPORT_GPU
23 #include "GrContext.h"
24 #include "GrContextPriv.h"
25 #include "GrRenderTargetContext.h"
26 #include "GrGpu.h"
27 #include "GrResourceProvider.h"
28 #include <vector>
29 #endif
30 
31 #include <initializer_list>
32 
release_direct_surface_storage(void * pixels,void * context)33 static void release_direct_surface_storage(void* pixels, void* context) {
34     SkASSERT(pixels == context);
35     sk_free(pixels);
36 }
create_surface(SkAlphaType at=kPremul_SkAlphaType,SkImageInfo * requestedInfo=nullptr)37 static sk_sp<SkSurface> create_surface(SkAlphaType at = kPremul_SkAlphaType,
38                                        SkImageInfo* requestedInfo = nullptr) {
39     const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
40     if (requestedInfo) {
41         *requestedInfo = info;
42     }
43     return SkSurface::MakeRaster(info);
44 }
create_direct_surface(SkAlphaType at=kPremul_SkAlphaType,SkImageInfo * requestedInfo=nullptr)45 static sk_sp<SkSurface> create_direct_surface(SkAlphaType at = kPremul_SkAlphaType,
46                                               SkImageInfo* requestedInfo = nullptr) {
47     const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
48     if (requestedInfo) {
49         *requestedInfo = info;
50     }
51     const size_t rowBytes = info.minRowBytes();
52     void* storage = sk_malloc_throw(info.getSafeSize(rowBytes));
53     return SkSurface::MakeRasterDirectReleaseProc(info, storage, rowBytes,
54                                                   release_direct_surface_storage,
55                                                   storage);
56 }
57 #if SK_SUPPORT_GPU
create_gpu_surface(GrContext * context,SkAlphaType at=kPremul_SkAlphaType,SkImageInfo * requestedInfo=nullptr)58 static sk_sp<SkSurface> create_gpu_surface(GrContext* context, SkAlphaType at = kPremul_SkAlphaType,
59                                            SkImageInfo* requestedInfo = nullptr) {
60     const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
61     if (requestedInfo) {
62         *requestedInfo = info;
63     }
64     return SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
65 }
create_gpu_scratch_surface(GrContext * context,SkAlphaType at=kPremul_SkAlphaType,SkImageInfo * requestedInfo=nullptr)66 static sk_sp<SkSurface> create_gpu_scratch_surface(GrContext* context,
67                                                    SkAlphaType at = kPremul_SkAlphaType,
68                                                    SkImageInfo* requestedInfo = nullptr) {
69     const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
70     if (requestedInfo) {
71         *requestedInfo = info;
72     }
73     return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info);
74 }
75 #endif
76 
DEF_TEST(SurfaceEmpty,reporter)77 DEF_TEST(SurfaceEmpty, reporter) {
78     const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
79     REPORTER_ASSERT(reporter, nullptr == SkSurface::MakeRaster(info));
80     REPORTER_ASSERT(reporter, nullptr == SkSurface::MakeRasterDirect(info, nullptr, 0));
81 
82 }
83 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceEmpty_Gpu,reporter,ctxInfo)84 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceEmpty_Gpu, reporter, ctxInfo) {
85     const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
86     REPORTER_ASSERT(reporter, nullptr ==
87                     SkSurface::MakeRenderTarget(ctxInfo.grContext(), SkBudgeted::kNo, info));
88 }
89 #endif
90 
test_canvas_peek(skiatest::Reporter * reporter,sk_sp<SkSurface> & surface,const SkImageInfo & requestInfo,bool expectPeekSuccess)91 static void test_canvas_peek(skiatest::Reporter* reporter,
92                              sk_sp<SkSurface>& surface,
93                              const SkImageInfo& requestInfo,
94                              bool expectPeekSuccess) {
95     const SkColor color = SK_ColorRED;
96     const SkPMColor pmcolor = SkPreMultiplyColor(color);
97     surface->getCanvas()->clear(color);
98 
99     SkPixmap pmap;
100     bool success = surface->getCanvas()->peekPixels(&pmap);
101     REPORTER_ASSERT(reporter, expectPeekSuccess == success);
102 
103     SkPixmap pmap2;
104     const void* addr2 = surface->peekPixels(&pmap2) ? pmap2.addr() : nullptr;
105 
106     if (success) {
107         REPORTER_ASSERT(reporter, requestInfo == pmap.info());
108         REPORTER_ASSERT(reporter, requestInfo.minRowBytes() <= pmap.rowBytes());
109         REPORTER_ASSERT(reporter, pmcolor == *pmap.addr32());
110 
111         REPORTER_ASSERT(reporter, pmap.addr() == pmap2.addr());
112         REPORTER_ASSERT(reporter, pmap.info() == pmap2.info());
113         REPORTER_ASSERT(reporter, pmap.rowBytes() == pmap2.rowBytes());
114     } else {
115         REPORTER_ASSERT(reporter, nullptr == addr2);
116     }
117 }
DEF_TEST(SurfaceCanvasPeek,reporter)118 DEF_TEST(SurfaceCanvasPeek, reporter) {
119     for (auto& surface_func : { &create_surface, &create_direct_surface }) {
120         SkImageInfo requestInfo;
121         auto surface(surface_func(kPremul_SkAlphaType, &requestInfo));
122         test_canvas_peek(reporter, surface, requestInfo, true);
123     }
124 }
125 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCanvasPeek_Gpu,reporter,ctxInfo)126 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCanvasPeek_Gpu, reporter, ctxInfo) {
127     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
128         SkImageInfo requestInfo;
129         auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, &requestInfo));
130         test_canvas_peek(reporter, surface, requestInfo, false);
131     }
132 }
133 #endif
134 
test_snapshot_alphatype(skiatest::Reporter * reporter,const sk_sp<SkSurface> & surface,SkAlphaType expectedAlphaType)135 static void test_snapshot_alphatype(skiatest::Reporter* reporter, const sk_sp<SkSurface>& surface,
136                                     SkAlphaType expectedAlphaType) {
137     REPORTER_ASSERT(reporter, surface);
138     if (surface) {
139         sk_sp<SkImage> image(surface->makeImageSnapshot());
140         REPORTER_ASSERT(reporter, image);
141         if (image) {
142             REPORTER_ASSERT(reporter, image->alphaType() == expectedAlphaType);
143         }
144     }
145 }
DEF_TEST(SurfaceSnapshotAlphaType,reporter)146 DEF_TEST(SurfaceSnapshotAlphaType, reporter) {
147     for (auto& surface_func : { &create_surface, &create_direct_surface }) {
148         for (auto& at: { kOpaque_SkAlphaType, kPremul_SkAlphaType, kUnpremul_SkAlphaType }) {
149             auto surface(surface_func(at, nullptr));
150             test_snapshot_alphatype(reporter, surface, at);
151         }
152     }
153 }
154 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceSnapshotAlphaType_Gpu,reporter,ctxInfo)155 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceSnapshotAlphaType_Gpu, reporter, ctxInfo) {
156     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
157         // GPU doesn't support creating unpremul surfaces, so only test opaque + premul
158         for (auto& at : { kOpaque_SkAlphaType, kPremul_SkAlphaType }) {
159             auto surface(surface_func(ctxInfo.grContext(), at, nullptr));
160             test_snapshot_alphatype(reporter, surface, at);
161         }
162     }
163 }
164 #endif
165 
get_surface_backend_texture_handle(SkSurface * s,SkSurface::BackendHandleAccess a)166 static GrBackendObject get_surface_backend_texture_handle(
167     SkSurface* s, SkSurface::BackendHandleAccess a) {
168     return s->getTextureHandle(a);
169 }
get_surface_backend_render_target_handle(SkSurface * s,SkSurface::BackendHandleAccess a)170 static GrBackendObject get_surface_backend_render_target_handle(
171     SkSurface* s, SkSurface::BackendHandleAccess a) {
172     GrBackendObject result;
173     if (!s->getRenderTargetHandle(&result, a)) {
174         return 0;
175     }
176     return result;
177 }
178 
test_backend_handle_access_copy_on_write(skiatest::Reporter * reporter,SkSurface * surface,SkSurface::BackendHandleAccess mode,GrBackendObject (* func)(SkSurface *,SkSurface::BackendHandleAccess))179 static void test_backend_handle_access_copy_on_write(
180     skiatest::Reporter* reporter, SkSurface* surface, SkSurface::BackendHandleAccess mode,
181     GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) {
182     GrBackendObject obj1 = func(surface, mode);
183     sk_sp<SkImage> snap1(surface->makeImageSnapshot());
184 
185     GrBackendObject obj2 = func(surface, mode);
186     sk_sp<SkImage> snap2(surface->makeImageSnapshot());
187 
188     // If the access mode triggers CoW, then the backend objects should reflect it.
189     REPORTER_ASSERT(reporter, (obj1 == obj2) == (snap1 == snap2));
190 }
DEF_TEST(SurfaceBackendHandleAccessCopyOnWrite,reporter)191 DEF_TEST(SurfaceBackendHandleAccessCopyOnWrite, reporter) {
192     const SkSurface::BackendHandleAccess accessModes[] = {
193         SkSurface::kFlushRead_BackendHandleAccess,
194         SkSurface::kFlushWrite_BackendHandleAccess,
195         SkSurface::kDiscardWrite_BackendHandleAccess,
196     };
197     for (auto& handle_access_func :
198             { &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle }) {
199         for (auto& accessMode : accessModes) {
200             auto surface(create_surface());
201             test_backend_handle_access_copy_on_write(reporter, surface.get(), accessMode,
202                                                      handle_access_func);
203         }
204     }
205 }
206 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessCopyOnWrite_Gpu,reporter,ctxInfo)207 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessCopyOnWrite_Gpu, reporter, ctxInfo) {
208         const SkSurface::BackendHandleAccess accessModes[] = {
209         SkSurface::kFlushRead_BackendHandleAccess,
210         SkSurface::kFlushWrite_BackendHandleAccess,
211         SkSurface::kDiscardWrite_BackendHandleAccess,
212     };
213     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
214         for (auto& handle_access_func :
215                 { &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle }) {
216             for (auto& accessMode : accessModes) {
217                 auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
218                 test_backend_handle_access_copy_on_write(reporter, surface.get(), accessMode,
219                                                          handle_access_func);
220             }
221         }
222     }
223 }
224 #endif
225 
226 #if SK_SUPPORT_GPU
227 
test_backend_handle_unique_id(skiatest::Reporter * reporter,SkSurface * surface,GrBackendObject (* func)(SkSurface *,SkSurface::BackendHandleAccess))228 static void test_backend_handle_unique_id(
229     skiatest::Reporter* reporter, SkSurface* surface,
230     GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) {
231     sk_sp<SkImage> image0(surface->makeImageSnapshot());
232     GrBackendObject obj = func(surface, SkSurface::kFlushRead_BackendHandleAccess);
233     REPORTER_ASSERT(reporter, obj != 0);
234     sk_sp<SkImage> image1(surface->makeImageSnapshot());
235     // just read access should not affect the snapshot
236     REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID());
237 
238     obj = func(surface, SkSurface::kFlushWrite_BackendHandleAccess);
239     REPORTER_ASSERT(reporter, obj != 0);
240     sk_sp<SkImage> image2(surface->makeImageSnapshot());
241     // expect a new image, since we claimed we would write
242     REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID());
243 
244     obj = func(surface, SkSurface::kDiscardWrite_BackendHandleAccess);
245     REPORTER_ASSERT(reporter, obj != 0);
246     sk_sp<SkImage> image3(surface->makeImageSnapshot());
247     // expect a new(er) image, since we claimed we would write
248     REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID());
249     REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID());
250 }
251 // No CPU test.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessIDs_Gpu,reporter,ctxInfo)252 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessIDs_Gpu, reporter, ctxInfo) {
253     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
254         for (auto& test_func : { &test_backend_handle_unique_id }) {
255             for (auto& handle_access_func :
256                 { &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle}) {
257                 auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
258                 test_func(reporter, surface.get(), handle_access_func);
259             }
260         }
261     }
262 }
263 #endif
264 
265 // Verify that the right canvas commands trigger a copy on write.
test_copy_on_write(skiatest::Reporter * reporter,SkSurface * surface)266 static void test_copy_on_write(skiatest::Reporter* reporter, SkSurface* surface) {
267     SkCanvas* canvas = surface->getCanvas();
268 
269     const SkRect testRect =
270         SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
271                          SkIntToScalar(4), SkIntToScalar(5));
272     SkPath testPath;
273     testPath.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
274                                       SkIntToScalar(2), SkIntToScalar(1)));
275 
276     const SkIRect testIRect = SkIRect::MakeXYWH(0, 0, 2, 1);
277 
278     SkRegion testRegion;
279     testRegion.setRect(testIRect);
280 
281 
282     const SkColor testColor = 0x01020304;
283     const SkPaint testPaint;
284     const SkPoint testPoints[3] = {
285         {SkIntToScalar(0), SkIntToScalar(0)},
286         {SkIntToScalar(2), SkIntToScalar(1)},
287         {SkIntToScalar(0), SkIntToScalar(2)}
288     };
289     const size_t testPointCount = 3;
290 
291     SkBitmap testBitmap;
292     testBitmap.allocN32Pixels(10, 10);
293     testBitmap.eraseColor(0);
294 
295     SkRRect testRRect;
296     testRRect.setRectXY(testRect, SK_Scalar1, SK_Scalar1);
297 
298     SkString testText("Hello World");
299     const SkPoint testPoints2[] = {
300         { SkIntToScalar(0), SkIntToScalar(1) },
301         { SkIntToScalar(1), SkIntToScalar(1) },
302         { SkIntToScalar(2), SkIntToScalar(1) },
303         { SkIntToScalar(3), SkIntToScalar(1) },
304         { SkIntToScalar(4), SkIntToScalar(1) },
305         { SkIntToScalar(5), SkIntToScalar(1) },
306         { SkIntToScalar(6), SkIntToScalar(1) },
307         { SkIntToScalar(7), SkIntToScalar(1) },
308         { SkIntToScalar(8), SkIntToScalar(1) },
309         { SkIntToScalar(9), SkIntToScalar(1) },
310         { SkIntToScalar(10), SkIntToScalar(1) },
311     };
312 
313 #define EXPECT_COPY_ON_WRITE(command)                               \
314     {                                                               \
315         sk_sp<SkImage> imageBefore = surface->makeImageSnapshot();  \
316         sk_sp<SkImage> aur_before(imageBefore);                     \
317         canvas-> command ;                                          \
318         sk_sp<SkImage> imageAfter = surface->makeImageSnapshot();   \
319         sk_sp<SkImage> aur_after(imageAfter);                       \
320         REPORTER_ASSERT(reporter, imageBefore != imageAfter);       \
321     }
322 
323     EXPECT_COPY_ON_WRITE(clear(testColor))
324     EXPECT_COPY_ON_WRITE(drawPaint(testPaint))
325     EXPECT_COPY_ON_WRITE(drawPoints(SkCanvas::kPoints_PointMode, testPointCount, testPoints, \
326         testPaint))
327     EXPECT_COPY_ON_WRITE(drawOval(testRect, testPaint))
328     EXPECT_COPY_ON_WRITE(drawRect(testRect, testPaint))
329     EXPECT_COPY_ON_WRITE(drawRRect(testRRect, testPaint))
330     EXPECT_COPY_ON_WRITE(drawPath(testPath, testPaint))
331     EXPECT_COPY_ON_WRITE(drawBitmap(testBitmap, 0, 0))
332     EXPECT_COPY_ON_WRITE(drawBitmapRect(testBitmap, testRect, nullptr))
333     EXPECT_COPY_ON_WRITE(drawBitmapNine(testBitmap, testIRect, testRect, nullptr))
334     EXPECT_COPY_ON_WRITE(drawText(testText.c_str(), testText.size(), 0, 1, testPaint))
335     EXPECT_COPY_ON_WRITE(drawPosText(testText.c_str(), testText.size(), testPoints2, \
336         testPaint))
337     EXPECT_COPY_ON_WRITE(drawTextOnPath(testText.c_str(), testText.size(), testPath, nullptr, \
338         testPaint))
339 }
DEF_TEST(SurfaceCopyOnWrite,reporter)340 DEF_TEST(SurfaceCopyOnWrite, reporter) {
341     test_copy_on_write(reporter, create_surface().get());
342 }
343 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCopyOnWrite_Gpu,reporter,ctxInfo)344 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCopyOnWrite_Gpu, reporter, ctxInfo) {
345     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
346         auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
347         test_copy_on_write(reporter, surface.get());
348     }
349 }
350 #endif
351 
test_writable_after_snapshot_release(skiatest::Reporter * reporter,SkSurface * surface)352 static void test_writable_after_snapshot_release(skiatest::Reporter* reporter,
353                                                  SkSurface* surface) {
354     // This test succeeds by not triggering an assertion.
355     // The test verifies that the surface remains writable (usable) after
356     // acquiring and releasing a snapshot without triggering a copy on write.
357     SkCanvas* canvas = surface->getCanvas();
358     canvas->clear(1);
359     surface->makeImageSnapshot();  // Create and destroy SkImage
360     canvas->clear(2);  // Must not assert internally
361 }
DEF_TEST(SurfaceWriteableAfterSnapshotRelease,reporter)362 DEF_TEST(SurfaceWriteableAfterSnapshotRelease, reporter) {
363     test_writable_after_snapshot_release(reporter, create_surface().get());
364 }
365 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWriteableAfterSnapshotRelease_Gpu,reporter,ctxInfo)366 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWriteableAfterSnapshotRelease_Gpu, reporter, ctxInfo) {
367     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
368         auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
369         test_writable_after_snapshot_release(reporter, surface.get());
370     }
371 }
372 #endif
373 
374 #if SK_SUPPORT_GPU
test_crbug263329(skiatest::Reporter * reporter,SkSurface * surface1,SkSurface * surface2)375 static void test_crbug263329(skiatest::Reporter* reporter,
376                              SkSurface* surface1,
377                              SkSurface* surface2) {
378     // This is a regression test for crbug.com/263329
379     // Bug was caused by onCopyOnWrite releasing the old surface texture
380     // back to the scratch texture pool even though the texture is used
381     // by and active SkImage_Gpu.
382     SkCanvas* canvas1 = surface1->getCanvas();
383     SkCanvas* canvas2 = surface2->getCanvas();
384     canvas1->clear(1);
385     sk_sp<SkImage> image1(surface1->makeImageSnapshot());
386     // Trigger copy on write, new backing is a scratch texture
387     canvas1->clear(2);
388     sk_sp<SkImage> image2(surface1->makeImageSnapshot());
389     // Trigger copy on write, old backing should not be returned to scratch
390     // pool because it is held by image2
391     canvas1->clear(3);
392 
393     canvas2->clear(4);
394     sk_sp<SkImage> image3(surface2->makeImageSnapshot());
395     // Trigger copy on write on surface2. The new backing store should not
396     // be recycling a texture that is held by an existing image.
397     canvas2->clear(5);
398     sk_sp<SkImage> image4(surface2->makeImageSnapshot());
399     REPORTER_ASSERT(reporter, as_IB(image4)->peekTexture() != as_IB(image3)->peekTexture());
400     // The following assertion checks crbug.com/263329
401     REPORTER_ASSERT(reporter, as_IB(image4)->peekTexture() != as_IB(image2)->peekTexture());
402     REPORTER_ASSERT(reporter, as_IB(image4)->peekTexture() != as_IB(image1)->peekTexture());
403     REPORTER_ASSERT(reporter, as_IB(image3)->peekTexture() != as_IB(image2)->peekTexture());
404     REPORTER_ASSERT(reporter, as_IB(image3)->peekTexture() != as_IB(image1)->peekTexture());
405     REPORTER_ASSERT(reporter, as_IB(image2)->peekTexture() != as_IB(image1)->peekTexture());
406 }
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCRBug263329_Gpu,reporter,ctxInfo)407 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCRBug263329_Gpu, reporter, ctxInfo) {
408     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
409         auto surface1(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
410         auto surface2(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
411         test_crbug263329(reporter, surface1.get(), surface2.get());
412     }
413 }
414 #endif
415 
DEF_TEST(SurfaceGetTexture,reporter)416 DEF_TEST(SurfaceGetTexture, reporter) {
417     auto surface(create_surface());
418     sk_sp<SkImage> image(surface->makeImageSnapshot());
419     REPORTER_ASSERT(reporter, !as_IB(image)->isTextureBacked());
420     surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
421     REPORTER_ASSERT(reporter, !as_IB(image)->isTextureBacked());
422 }
423 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfacepeekTexture_Gpu,reporter,ctxInfo)424 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfacepeekTexture_Gpu, reporter, ctxInfo) {
425     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
426         auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
427         sk_sp<SkImage> image(surface->makeImageSnapshot());
428 
429         REPORTER_ASSERT(reporter, as_IB(image)->isTextureBacked());
430         GrBackendObject textureHandle = image->getTextureHandle(false);
431         REPORTER_ASSERT(reporter, 0 != textureHandle);
432         surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
433         REPORTER_ASSERT(reporter, as_IB(image)->isTextureBacked());
434         REPORTER_ASSERT(reporter, textureHandle == image->getTextureHandle(false));
435     }
436 }
437 #endif
438 
439 #if SK_SUPPORT_GPU
440 #include "GrGpuResourcePriv.h"
441 #include "SkGpuDevice.h"
442 #include "SkImage_Gpu.h"
443 #include "SkSurface_Gpu.h"
444 
is_budgeted(const sk_sp<SkSurface> & surf)445 static SkBudgeted is_budgeted(const sk_sp<SkSurface>& surf) {
446     SkSurface_Gpu* gsurf = (SkSurface_Gpu*)surf.get();
447 
448     GrRenderTargetProxy* proxy = gsurf->getDevice()->accessRenderTargetContext()
449                                                                         ->asRenderTargetProxy();
450     return proxy->isBudgeted();
451 }
452 
is_budgeted(SkImage * image)453 static SkBudgeted is_budgeted(SkImage* image) {
454     return ((SkImage_Gpu*)image)->peekProxy()->isBudgeted();
455 }
456 
is_budgeted(const sk_sp<SkImage> image)457 static SkBudgeted is_budgeted(const sk_sp<SkImage> image) {
458     return is_budgeted(image.get());
459 }
460 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBudget,reporter,ctxInfo)461 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBudget, reporter, ctxInfo) {
462     SkImageInfo info = SkImageInfo::MakeN32Premul(8,8);
463     for (auto budgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {
464         auto surface(SkSurface::MakeRenderTarget(ctxInfo.grContext(), budgeted, info));
465         SkASSERT(surface);
466         REPORTER_ASSERT(reporter, budgeted == is_budgeted(surface));
467 
468         sk_sp<SkImage> image(surface->makeImageSnapshot());
469 
470         // Initially the image shares a texture with the surface, and the
471         // the budgets should always match.
472         REPORTER_ASSERT(reporter, budgeted == is_budgeted(surface));
473         REPORTER_ASSERT(reporter, budgeted == is_budgeted(image));
474 
475         // Now trigger copy-on-write
476         surface->getCanvas()->clear(SK_ColorBLUE);
477 
478         // They don't share a texture anymore but the budgets should still match.
479         REPORTER_ASSERT(reporter, budgeted == is_budgeted(surface));
480         REPORTER_ASSERT(reporter, budgeted == is_budgeted(image));
481     }
482 }
483 #endif
484 
test_no_canvas1(skiatest::Reporter * reporter,SkSurface * surface,SkSurface::ContentChangeMode mode)485 static void test_no_canvas1(skiatest::Reporter* reporter,
486                             SkSurface* surface,
487                             SkSurface::ContentChangeMode mode) {
488     // Test passes by not asserting
489     surface->notifyContentWillChange(mode);
490     SkDEBUGCODE(surface->validate();)
491 }
test_no_canvas2(skiatest::Reporter * reporter,SkSurface * surface,SkSurface::ContentChangeMode mode)492 static void test_no_canvas2(skiatest::Reporter* reporter,
493                             SkSurface* surface,
494                             SkSurface::ContentChangeMode mode) {
495     // Verifies the robustness of SkSurface for handling use cases where calls
496     // are made before a canvas is created.
497     sk_sp<SkImage> image1 = surface->makeImageSnapshot();
498     sk_sp<SkImage> aur_image1(image1);
499     SkDEBUGCODE(image1->validate();)
500     SkDEBUGCODE(surface->validate();)
501     surface->notifyContentWillChange(mode);
502     SkDEBUGCODE(image1->validate();)
503     SkDEBUGCODE(surface->validate();)
504     sk_sp<SkImage> image2 = surface->makeImageSnapshot();
505     sk_sp<SkImage> aur_image2(image2);
506     SkDEBUGCODE(image2->validate();)
507     SkDEBUGCODE(surface->validate();)
508     REPORTER_ASSERT(reporter, image1 != image2);
509 }
DEF_TEST(SurfaceNoCanvas,reporter)510 DEF_TEST(SurfaceNoCanvas, reporter) {
511     SkSurface::ContentChangeMode modes[] =
512             { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode};
513     for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) {
514         for (auto& mode : modes) {
515             test_func(reporter, create_surface().get(), mode);
516         }
517     }
518 }
519 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceNoCanvas_Gpu,reporter,ctxInfo)520 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceNoCanvas_Gpu, reporter, ctxInfo) {
521     SkSurface::ContentChangeMode modes[] =
522             { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode};
523     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
524         for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) {
525             for (auto& mode : modes) {
526                 auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
527                 test_func(reporter, surface.get(), mode);
528             }
529         }
530     }
531 }
532 #endif
533 
check_rowbytes_remain_consistent(SkSurface * surface,skiatest::Reporter * reporter)534 static void check_rowbytes_remain_consistent(SkSurface* surface, skiatest::Reporter* reporter) {
535     SkPixmap surfacePM;
536     REPORTER_ASSERT(reporter, surface->peekPixels(&surfacePM));
537 
538     sk_sp<SkImage> image(surface->makeImageSnapshot());
539     SkPixmap pm;
540     REPORTER_ASSERT(reporter, image->peekPixels(&pm));
541 
542     REPORTER_ASSERT(reporter, surfacePM.rowBytes() == pm.rowBytes());
543 
544     // trigger a copy-on-write
545     surface->getCanvas()->drawPaint(SkPaint());
546     sk_sp<SkImage> image2(surface->makeImageSnapshot());
547     REPORTER_ASSERT(reporter, image->uniqueID() != image2->uniqueID());
548 
549     SkPixmap pm2;
550     REPORTER_ASSERT(reporter, image2->peekPixels(&pm2));
551     REPORTER_ASSERT(reporter, pm2.rowBytes() == pm.rowBytes());
552 }
553 
DEF_TEST(surface_rowbytes,reporter)554 DEF_TEST(surface_rowbytes, reporter) {
555     const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
556 
557     auto surf0(SkSurface::MakeRaster(info));
558     check_rowbytes_remain_consistent(surf0.get(), reporter);
559 
560     // specify a larger rowbytes
561     auto surf1(SkSurface::MakeRaster(info, 500, nullptr));
562     check_rowbytes_remain_consistent(surf1.get(), reporter);
563 
564     // Try some illegal rowByte values
565     auto s = SkSurface::MakeRaster(info, 396, nullptr);    // needs to be at least 400
566     REPORTER_ASSERT(reporter, nullptr == s);
567     s = SkSurface::MakeRaster(info, 1 << 30, nullptr); // allocation to large
568     REPORTER_ASSERT(reporter, nullptr == s);
569 }
570 
DEF_TEST(surface_raster_zeroinitialized,reporter)571 DEF_TEST(surface_raster_zeroinitialized, reporter) {
572     sk_sp<SkSurface> s(SkSurface::MakeRasterN32Premul(100, 100));
573     SkPixmap pixmap;
574     REPORTER_ASSERT(reporter, s->peekPixels(&pixmap));
575 
576     for (int i = 0; i < pixmap.info().width(); ++i) {
577         for (int j = 0; j < pixmap.info().height(); ++j) {
578             REPORTER_ASSERT(reporter, *pixmap.addr32(i, j) == 0);
579         }
580     }
581 }
582 
583 #if SK_SUPPORT_GPU
create_gpu_surface_backend_texture(GrContext * context,int sampleCnt,uint32_t color,GrBackendObject * outTexture)584 static sk_sp<SkSurface> create_gpu_surface_backend_texture(
585     GrContext* context, int sampleCnt, uint32_t color, GrBackendObject* outTexture) {
586     const int kWidth = 10;
587     const int kHeight = 10;
588     std::unique_ptr<uint32_t[]> pixels(new uint32_t[kWidth * kHeight]);
589     sk_memset32(pixels.get(), color, kWidth * kHeight);
590     GrBackendTextureDesc desc;
591     desc.fConfig = kRGBA_8888_GrPixelConfig;
592     desc.fWidth = kWidth;
593     desc.fHeight = kHeight;
594     desc.fFlags = kRenderTarget_GrBackendTextureFlag;
595     desc.fTextureHandle = context->getGpu()->createTestingOnlyBackendTexture(
596         pixels.get(), kWidth, kHeight, kRGBA_8888_GrPixelConfig, true);
597     desc.fSampleCnt = sampleCnt;
598     sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(context, desc, nullptr);
599     if (!surface) {
600         context->getGpu()->deleteTestingOnlyBackendTexture(desc.fTextureHandle);
601         return nullptr;
602     }
603     *outTexture = desc.fTextureHandle;
604     return surface;
605 }
606 
create_gpu_surface_backend_texture_as_render_target(GrContext * context,int sampleCnt,uint32_t color,GrBackendObject * outTexture)607 static sk_sp<SkSurface> create_gpu_surface_backend_texture_as_render_target(
608     GrContext* context, int sampleCnt, uint32_t color, GrBackendObject* outTexture) {
609     const int kWidth = 10;
610     const int kHeight = 10;
611     std::unique_ptr<uint32_t[]> pixels(new uint32_t[kWidth * kHeight]);
612     sk_memset32(pixels.get(), color, kWidth * kHeight);
613     GrBackendTextureDesc desc;
614     desc.fConfig = kRGBA_8888_GrPixelConfig;
615     desc.fWidth = kWidth;
616     desc.fHeight = kHeight;
617     desc.fFlags = kRenderTarget_GrBackendTextureFlag;
618     desc.fTextureHandle = context->getGpu()->createTestingOnlyBackendTexture(
619         pixels.get(), kWidth, kHeight, kRGBA_8888_GrPixelConfig, true);
620     desc.fSampleCnt = sampleCnt;
621     sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTextureAsRenderTarget(context, desc,
622                                                                                nullptr);
623     if (!surface) {
624         context->getGpu()->deleteTestingOnlyBackendTexture(desc.fTextureHandle);
625         return nullptr;
626     }
627     *outTexture = desc.fTextureHandle;
628     return surface;
629 }
630 
test_surface_clear(skiatest::Reporter * reporter,sk_sp<SkSurface> surface,std::function<sk_sp<GrSurfaceContext> (SkSurface *)> grSurfaceGetter,uint32_t expectedValue)631 static void test_surface_clear(skiatest::Reporter* reporter, sk_sp<SkSurface> surface,
632                                std::function<sk_sp<GrSurfaceContext>(SkSurface*)> grSurfaceGetter,
633                                uint32_t expectedValue) {
634     if (!surface) {
635         ERRORF(reporter, "Could not create GPU SkSurface.");
636         return;
637     }
638     int w = surface->width();
639     int h = surface->height();
640     std::unique_ptr<uint32_t[]> pixels(new uint32_t[w * h]);
641     sk_memset32(pixels.get(), ~expectedValue, w * h);
642 
643     sk_sp<GrSurfaceContext> grSurfaceContext(grSurfaceGetter(surface.get()));
644     if (!grSurfaceContext) {
645         ERRORF(reporter, "Could access render target of GPU SkSurface.");
646         return;
647     }
648     surface.reset();
649 
650     SkImageInfo ii = SkImageInfo::Make(w, h, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
651     grSurfaceContext->readPixels(ii, pixels.get(), 0, 0, 0);
652     for (int y = 0; y < h; ++y) {
653         for (int x = 0; x < w; ++x) {
654             uint32_t pixel = pixels.get()[y * w + x];
655             if (pixel != expectedValue) {
656                 SkString msg;
657                 if (expectedValue) {
658                     msg = "SkSurface should have left render target unmodified";
659                 } else {
660                     msg = "SkSurface should have cleared the render target";
661                 }
662                 ERRORF(reporter,
663                        "%s but read 0x%08x (instead of 0x%08x) at %x,%d", msg.c_str(), pixel,
664                        expectedValue, x, y);
665                 return;
666             }
667         }
668     }
669 }
670 
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceClear_Gpu,reporter,ctxInfo)671 DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceClear_Gpu, reporter, ctxInfo) {
672     GrContext* context = ctxInfo.grContext();
673 
674     std::function<sk_sp<GrSurfaceContext>(SkSurface*)> grSurfaceContextGetters[] = {
675         [] (SkSurface* s){
676             return sk_ref_sp(s->getCanvas()->internal_private_accessTopLayerRenderTargetContext());
677         },
678         [] (SkSurface* s){
679             sk_sp<SkImage> i(s->makeImageSnapshot());
680             SkImage_Gpu* gpuImage = (SkImage_Gpu *) as_IB(i);
681             sk_sp<GrTextureProxy> proxy = gpuImage->asTextureProxyRef();
682             GrContext* context = gpuImage->context();
683             return context->contextPriv().makeWrappedSurfaceContext(std::move(proxy),
684                                                                     gpuImage->refColorSpace());
685         }
686     };
687 
688     for (auto grSurfaceGetter : grSurfaceContextGetters) {
689         // Test that non-wrapped RTs are created clear.
690         for (auto& surface_func : {&create_gpu_surface, &create_gpu_scratch_surface}) {
691             auto surface = surface_func(context, kPremul_SkAlphaType, nullptr);
692             test_surface_clear(reporter, surface, grSurfaceGetter, 0x0);
693         }
694         // Wrapped RTs are *not* supposed to clear (to allow client to partially update a surface).
695         const uint32_t kOrigColor = 0xABABABAB;
696         for (auto& surfaceFunc : {&create_gpu_surface_backend_texture,
697                                   &create_gpu_surface_backend_texture_as_render_target}) {
698             GrBackendObject textureObject;
699             auto surface = surfaceFunc(context, 0, kOrigColor, &textureObject);
700             test_surface_clear(reporter, surface, grSurfaceGetter, kOrigColor);
701             surface.reset();
702             context->getGpu()->deleteTestingOnlyBackendTexture(textureObject);
703         }
704     }
705 }
706 
test_surface_draw_partially(skiatest::Reporter * reporter,sk_sp<SkSurface> surface,uint32_t origColor)707 static void test_surface_draw_partially(
708     skiatest::Reporter* reporter, sk_sp<SkSurface> surface, uint32_t origColor) {
709     const int kW = surface->width();
710     const int kH = surface->height();
711     SkPaint paint;
712     const SkColor kRectColor = ~origColor | 0xFF000000;
713     paint.setColor(kRectColor);
714     surface->getCanvas()->drawRect(SkRect::MakeWH(SkIntToScalar(kW), SkIntToScalar(kH)/2),
715                                    paint);
716     std::unique_ptr<uint32_t[]> pixels(new uint32_t[kW * kH]);
717     sk_memset32(pixels.get(), ~origColor, kW * kH);
718     // Read back RGBA to avoid format conversions that may not be supported on all platforms.
719     SkImageInfo readInfo = SkImageInfo::Make(kW, kH, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
720     SkAssertResult(surface->readPixels(readInfo, pixels.get(), kW * sizeof(uint32_t), 0, 0));
721     bool stop = false;
722     SkPMColor origColorPM = SkPackARGB_as_RGBA((origColor >> 24 & 0xFF),
723                                                (origColor >>  0 & 0xFF),
724                                                (origColor >>  8 & 0xFF),
725                                                (origColor >> 16 & 0xFF));
726     SkPMColor rectColorPM = SkPackARGB_as_RGBA((kRectColor >> 24 & 0xFF),
727                                                (kRectColor >> 16 & 0xFF),
728                                                (kRectColor >>  8 & 0xFF),
729                                                (kRectColor >>  0 & 0xFF));
730     for (int y = 0; y < kH/2 && !stop; ++y) {
731        for (int x = 0; x < kW && !stop; ++x) {
732             REPORTER_ASSERT(reporter, rectColorPM == pixels[x + y * kW]);
733             if (rectColorPM != pixels[x + y * kW]) {
734                 stop = true;
735             }
736         }
737     }
738     stop = false;
739     for (int y = kH/2; y < kH && !stop; ++y) {
740         for (int x = 0; x < kW && !stop; ++x) {
741             REPORTER_ASSERT(reporter, origColorPM == pixels[x + y * kW]);
742             if (origColorPM != pixels[x + y * kW]) {
743                 stop = true;
744             }
745         }
746     }
747 }
748 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfacePartialDraw_Gpu,reporter,ctxInfo)749 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfacePartialDraw_Gpu, reporter, ctxInfo) {
750     GrGpu* gpu = ctxInfo.grContext()->getGpu();
751     if (!gpu) {
752         return;
753     }
754     static const uint32_t kOrigColor = 0xFFAABBCC;
755 
756     for (auto& surfaceFunc : {&create_gpu_surface_backend_texture,
757                               &create_gpu_surface_backend_texture_as_render_target}) {
758         // Validate that we can draw to the canvas and that the original texture color is
759         // preserved in pixels that aren't rendered to via the surface.
760         // This works only for non-multisampled case.
761         GrBackendObject textureObject;
762         auto surface = surfaceFunc(ctxInfo.grContext(), 0, kOrigColor, &textureObject);
763         if (surface) {
764             test_surface_draw_partially(reporter, surface, kOrigColor);
765             surface.reset();
766             gpu->deleteTestingOnlyBackendTexture(textureObject);
767         }
768     }
769 }
770 
771 
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceAttachStencil_Gpu,reporter,ctxInfo)772 DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceAttachStencil_Gpu, reporter, ctxInfo) {
773     GrGpu* gpu = ctxInfo.grContext()->getGpu();
774     if (!gpu) {
775         return;
776     }
777     static const uint32_t kOrigColor = 0xFFAABBCC;
778 
779     for (auto& surfaceFunc : {&create_gpu_surface_backend_texture,
780                               &create_gpu_surface_backend_texture_as_render_target}) {
781         for (int sampleCnt : {0, 4, 8}) {
782             GrBackendObject textureObject;
783             auto surface = surfaceFunc(ctxInfo.grContext(), sampleCnt, kOrigColor, &textureObject);
784 
785             if (!surface && sampleCnt > 0) {
786               // Certain platforms don't support MSAA, skip these.
787               continue;
788             }
789 
790             // Validate that we can attach a stencil buffer to an SkSurface created by either of
791             // our surface functions.
792             GrRenderTarget* rt = surface->getCanvas()
793                 ->internal_private_accessTopLayerRenderTargetContext()->accessRenderTarget();
794             REPORTER_ASSERT(reporter,
795                             ctxInfo.grContext()->resourceProvider()->attachStencilAttachment(rt));
796             gpu->deleteTestingOnlyBackendTexture(textureObject);
797         }
798     }
799 }
800 #endif
801 
test_surface_creation_and_snapshot_with_color_space(skiatest::Reporter * reporter,const char * prefix,bool f16Support,std::function<sk_sp<SkSurface> (const SkImageInfo &)> surfaceMaker)802 static void test_surface_creation_and_snapshot_with_color_space(
803     skiatest::Reporter* reporter,
804     const char* prefix,
805     bool f16Support,
806     std::function<sk_sp<SkSurface>(const SkImageInfo&)> surfaceMaker) {
807 
808     auto srgbColorSpace = SkColorSpace::MakeSRGB();
809     auto adobeColorSpace = SkColorSpace_Base::MakeNamed(SkColorSpace_Base::kAdobeRGB_Named);
810     const SkMatrix44* srgbMatrix = as_CSB(srgbColorSpace)->toXYZD50();
811     SkASSERT(srgbMatrix);
812     SkColorSpaceTransferFn oddGamma;
813     oddGamma.fA = 1.0f;
814     oddGamma.fB = oddGamma.fC = oddGamma.fD = oddGamma.fE = oddGamma.fF = 0.0f;
815     oddGamma.fG = 4.0f;
816     auto oddColorSpace = SkColorSpace::MakeRGB(oddGamma, *srgbMatrix);
817     auto linearColorSpace = SkColorSpace::MakeSRGBLinear();
818 
819     const struct {
820         SkColorType         fColorType;
821         sk_sp<SkColorSpace> fColorSpace;
822         bool                fShouldWork;
823         const char*         fDescription;
824     } testConfigs[] = {
825         { kN32_SkColorType,       nullptr,          true,  "N32-nullptr" },
826         { kN32_SkColorType,       linearColorSpace, false, "N32-linear"  },
827         { kN32_SkColorType,       srgbColorSpace,   true,  "N32-srgb"    },
828         { kN32_SkColorType,       adobeColorSpace,  true,  "N32-adobe"   },
829         { kN32_SkColorType,       oddColorSpace,    false, "N32-odd"     },
830         { kRGBA_F16_SkColorType,  nullptr,          true,  "F16-nullptr" },
831         { kRGBA_F16_SkColorType,  linearColorSpace, true,  "F16-linear"  },
832         { kRGBA_F16_SkColorType,  srgbColorSpace,   false, "F16-srgb"    },
833         { kRGBA_F16_SkColorType,  adobeColorSpace,  false, "F16-adobe"   },
834         { kRGBA_F16_SkColorType,  oddColorSpace,    false, "F16-odd"     },
835         { kRGB_565_SkColorType,   srgbColorSpace,   false, "565-srgb"    },
836         { kAlpha_8_SkColorType,   srgbColorSpace,   false, "A8-srgb"     },
837     };
838 
839     for (auto& testConfig : testConfigs) {
840         SkString fullTestName = SkStringPrintf("%s-%s", prefix, testConfig.fDescription);
841         SkImageInfo info = SkImageInfo::Make(10, 10, testConfig.fColorType, kPremul_SkAlphaType,
842                                              testConfig.fColorSpace);
843 
844         // For some GPU contexts (eg ANGLE), we don't have f16 support, so we should fail to create
845         // any surface of that type:
846         bool shouldWork = testConfig.fShouldWork &&
847                           (f16Support || kRGBA_F16_SkColorType != testConfig.fColorType);
848 
849         auto surface(surfaceMaker(info));
850         REPORTER_ASSERT_MESSAGE(reporter, SkToBool(surface) == shouldWork, fullTestName.c_str());
851 
852         if (shouldWork && surface) {
853             sk_sp<SkImage> image(surface->makeImageSnapshot());
854             REPORTER_ASSERT_MESSAGE(reporter, image, testConfig.fDescription);
855             SkColorSpace* imageColorSpace = as_IB(image)->onImageInfo().colorSpace();
856             REPORTER_ASSERT_MESSAGE(reporter, imageColorSpace == testConfig.fColorSpace.get(),
857                                     fullTestName.c_str());
858         }
859     }
860 }
861 
DEF_TEST(SurfaceCreationWithColorSpace,reporter)862 DEF_TEST(SurfaceCreationWithColorSpace, reporter) {
863     auto surfaceMaker = [](const SkImageInfo& info) {
864         return SkSurface::MakeRaster(info);
865     };
866 
867     test_surface_creation_and_snapshot_with_color_space(reporter, "raster", true, surfaceMaker);
868 }
869 
870 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCreationWithColorSpace_Gpu,reporter,ctxInfo)871 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCreationWithColorSpace_Gpu, reporter, ctxInfo) {
872     GrContext* context = ctxInfo.grContext();
873     bool f16Support = context->caps()->isConfigRenderable(kRGBA_half_GrPixelConfig, false);
874     auto surfaceMaker = [context](const SkImageInfo& info) {
875         return SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
876     };
877 
878     test_surface_creation_and_snapshot_with_color_space(reporter, "gpu", f16Support, surfaceMaker);
879 
880     std::vector<GrBackendObject> textureHandles;
881     auto wrappedSurfaceMaker = [context,&textureHandles](const SkImageInfo& info) {
882         GrBackendTextureDesc desc;
883         desc.fConfig = SkImageInfo2GrPixelConfig(info, *context->caps());
884         desc.fWidth = 10;
885         desc.fHeight = 10;
886         desc.fFlags = kRenderTarget_GrBackendTextureFlag;
887         desc.fTextureHandle = context->getGpu()->createTestingOnlyBackendTexture(
888             nullptr, desc.fWidth, desc.fHeight, desc.fConfig, true);
889 
890         if (!desc.fTextureHandle) {
891             return sk_sp<SkSurface>(nullptr);
892         }
893         textureHandles.push_back(desc.fTextureHandle);
894 
895         return SkSurface::MakeFromBackendTexture(context, desc, sk_ref_sp(info.colorSpace()),
896                                                  nullptr);
897     };
898 
899     test_surface_creation_and_snapshot_with_color_space(reporter, "wrapped", f16Support,
900                                                         wrappedSurfaceMaker);
901 
902     for (auto textureHandle : textureHandles) {
903         context->getGpu()->deleteTestingOnlyBackendTexture(textureHandle);
904     }
905 }
906 #endif
907 
test_overdraw_surface(skiatest::Reporter * r,SkSurface * surface)908 static void test_overdraw_surface(skiatest::Reporter* r, SkSurface* surface) {
909     SkOverdrawCanvas canvas(surface->getCanvas());
910     canvas.drawPaint(SkPaint());
911     sk_sp<SkImage> image = surface->makeImageSnapshot();
912 
913     SkBitmap bitmap;
914     image->asLegacyBitmap(&bitmap, SkImage::kRO_LegacyBitmapMode);
915     bitmap.lockPixels();
916     for (int y = 0; y < 10; y++) {
917         for (int x = 0; x < 10; x++) {
918             REPORTER_ASSERT(r, 1 == SkGetPackedA32(*bitmap.getAddr32(x, y)));
919         }
920     }
921 }
922 
DEF_TEST(OverdrawSurface_Raster,r)923 DEF_TEST(OverdrawSurface_Raster, r) {
924     sk_sp<SkSurface> surface = create_surface();
925     test_overdraw_surface(r, surface.get());
926 }
927 
928 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(OverdrawSurface_Gpu,r,ctxInfo)929 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(OverdrawSurface_Gpu, r, ctxInfo) {
930     GrContext* context = ctxInfo.grContext();
931     sk_sp<SkSurface> surface = create_gpu_surface(context);
932     test_overdraw_surface(r, surface.get());
933 }
934 #endif
935