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