Plumb dst color space in many places, rather than "mode"
[platform/upstream/libSkiaSharp.git] / tests / SpecialImageTest.cpp
1 /*
2  * Copyright 2016 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 "SkAutoPixmapStorage.h"
9 #include "SkBitmap.h"
10 #include "SkCanvas.h"
11 #include "SkImage.h"
12 #include "SkPixmap.h"
13 #include "SkSpecialImage.h"
14 #include "SkSpecialSurface.h"
15 #include "SkSurface.h"
16 #include "Test.h"
17
18 #if SK_SUPPORT_GPU
19 #include "GrContext.h"
20 #include "GrSurfaceProxy.h"
21 #endif
22
23
24 // This test creates backing resources exactly sized to [kFullSize x kFullSize].
25 // It then wraps them in an SkSpecialImage with only the center (red) region being active.
26 // It then draws the SkSpecialImage to a full sized (all blue) canvas and checks that none
27 // of the inactive (green) region leaked out.
28
29 static const int kSmallerSize = 10;
30 static const int kPad = 3;
31 static const int kFullSize = kSmallerSize + 2 * kPad;
32
33 // Create a bitmap with red in the center and green around it
34 static SkBitmap create_bm() {
35     SkBitmap bm;
36     bm.allocN32Pixels(kFullSize, kFullSize, true);
37
38     SkCanvas temp(bm);
39
40     temp.clear(SK_ColorGREEN);
41     SkPaint p;
42     p.setColor(SK_ColorRED);
43     p.setAntiAlias(false);
44
45     temp.drawRect(SkRect::MakeXYWH(SkIntToScalar(kPad), SkIntToScalar(kPad),
46                                    SkIntToScalar(kSmallerSize), SkIntToScalar(kSmallerSize)),
47                   p);
48
49     return bm;
50 }
51
52 // Basic test of the SkSpecialImage public API (e.g., peekTexture, peekPixels & draw)
53 static void test_image(const sk_sp<SkSpecialImage>& img, skiatest::Reporter* reporter,
54                        GrContext* context, bool peekTextureSucceeds,
55                        int offset, int size) {
56     const SkIRect subset = img->subset();
57     REPORTER_ASSERT(reporter, offset == subset.left());
58     REPORTER_ASSERT(reporter, offset == subset.top());
59     REPORTER_ASSERT(reporter, kSmallerSize == subset.width());
60     REPORTER_ASSERT(reporter, kSmallerSize == subset.height());
61
62     //--------------
63     // Test that peekTexture reports the correct backing type
64     REPORTER_ASSERT(reporter, peekTextureSucceeds == img->isTextureBacked());
65
66 #if SK_SUPPORT_GPU
67     //--------------
68     // Test getTextureAsRef - as long as there is a context this should succeed
69     if (context) {
70         sk_sp<GrTexture> texture(img->asTextureRef(context));
71         REPORTER_ASSERT(reporter, texture);
72     }
73 #endif
74
75     //--------------
76     // Test getROPixels - this should always succeed regardless of backing store
77     SkBitmap bitmap;
78     REPORTER_ASSERT(reporter, img->getROPixels(&bitmap));
79     if (context) {
80         REPORTER_ASSERT(reporter, kSmallerSize == bitmap.width());
81         REPORTER_ASSERT(reporter, kSmallerSize == bitmap.height());
82     } else {
83         REPORTER_ASSERT(reporter, size == bitmap.width());
84         REPORTER_ASSERT(reporter, size == bitmap.height());
85     }
86
87     //--------------
88     // Test that draw restricts itself to the subset
89     SkImageFilter::OutputProperties outProps(img->getColorSpace());
90     sk_sp<SkSpecialSurface> surf(img->makeSurface(outProps, SkISize::Make(kFullSize, kFullSize),
91                                                   kOpaque_SkAlphaType));
92
93     SkCanvas* canvas = surf->getCanvas();
94
95     canvas->clear(SK_ColorBLUE);
96     img->draw(canvas, SkIntToScalar(kPad), SkIntToScalar(kPad), nullptr);
97
98     SkBitmap bm;
99     bm.allocN32Pixels(kFullSize, kFullSize, true);
100
101     bool result = canvas->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), 0, 0);
102     SkASSERT_RELEASE(result);
103
104     // Only the center (red) portion should've been drawn into the canvas
105     REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kPad-1, kPad-1));
106     REPORTER_ASSERT(reporter, SK_ColorRED  == bm.getColor(kPad, kPad));
107     REPORTER_ASSERT(reporter, SK_ColorRED  == bm.getColor(kSmallerSize+kPad-1,
108                                                           kSmallerSize+kPad-1));
109     REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kSmallerSize+kPad,
110                                                           kSmallerSize+kPad));
111
112     //--------------
113     // Test that makeTightSubset & makeTightSurface return appropriately sized objects
114     // of the correct backing type
115     SkIRect newSubset = SkIRect::MakeWH(subset.width(), subset.height());
116     {
117         sk_sp<SkImage> tightImg(img->makeTightSubset(newSubset));
118
119         REPORTER_ASSERT(reporter, tightImg->width() == subset.width());
120         REPORTER_ASSERT(reporter, tightImg->height() == subset.height());
121         REPORTER_ASSERT(reporter, peekTextureSucceeds == !!tightImg->getTexture());
122         SkPixmap tmpPixmap;
123         REPORTER_ASSERT(reporter, peekTextureSucceeds != !!tightImg->peekPixels(&tmpPixmap));
124     }
125     {
126         SkImageFilter::OutputProperties outProps(img->getColorSpace());
127         sk_sp<SkSurface> tightSurf(img->makeTightSurface(outProps, subset.size()));
128
129         REPORTER_ASSERT(reporter, tightSurf->width() == subset.width());
130         REPORTER_ASSERT(reporter, tightSurf->height() == subset.height());
131         REPORTER_ASSERT(reporter, peekTextureSucceeds ==
132                      !!tightSurf->getTextureHandle(SkSurface::kDiscardWrite_BackendHandleAccess));
133         SkPixmap tmpPixmap;
134         REPORTER_ASSERT(reporter, peekTextureSucceeds != !!tightSurf->peekPixels(&tmpPixmap));
135     }
136 }
137
138 DEF_TEST(SpecialImage_Raster, reporter) {
139     SkBitmap bm = create_bm();
140
141     sk_sp<SkSpecialImage> fullSImage(SkSpecialImage::MakeFromRaster(
142                                                             SkIRect::MakeWH(kFullSize, kFullSize),
143                                                             bm));
144
145     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
146
147     {
148         sk_sp<SkSpecialImage> subSImg1(SkSpecialImage::MakeFromRaster(subset, bm));
149         test_image(subSImg1, reporter, nullptr, false, kPad, kFullSize);
150     }
151
152     {
153         sk_sp<SkSpecialImage> subSImg2(fullSImage->makeSubset(subset));
154         test_image(subSImg2, reporter, nullptr, false, 0, kSmallerSize);
155     }
156 }
157
158 static void test_specialimage_image(skiatest::Reporter* reporter, SkColorSpace* dstColorSpace) {
159     SkBitmap bm = create_bm();
160
161     sk_sp<SkImage> fullImage(SkImage::MakeFromBitmap(bm));
162
163     sk_sp<SkSpecialImage> fullSImage(SkSpecialImage::MakeFromImage(
164                                                             SkIRect::MakeWH(kFullSize, kFullSize),
165                                                             fullImage, dstColorSpace));
166
167     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
168
169     {
170         sk_sp<SkSpecialImage> subSImg1(SkSpecialImage::MakeFromImage(subset, fullImage,
171                                                                      dstColorSpace));
172         test_image(subSImg1, reporter, nullptr, false, kPad, kFullSize);
173     }
174
175     {
176         sk_sp<SkSpecialImage> subSImg2(fullSImage->makeSubset(subset));
177         test_image(subSImg2, reporter, nullptr, false, 0, kSmallerSize);
178     }
179 }
180
181 DEF_TEST(SpecialImage_Image_Legacy, reporter) {
182     SkColorSpace* legacyColorSpace = nullptr;
183     test_specialimage_image(reporter, legacyColorSpace);
184 }
185
186 DEF_TEST(SpecialImage_Image_ColorSpaceAware, reporter) {
187     sk_sp<SkColorSpace> srgbColorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
188     test_specialimage_image(reporter, srgbColorSpace.get());
189 }
190
191 #if SK_SUPPORT_GPU
192
193 static void test_texture_backed(skiatest::Reporter* reporter,
194                                 const sk_sp<SkSpecialImage>& orig,
195                                 const sk_sp<SkSpecialImage>& gpuBacked) {
196     REPORTER_ASSERT(reporter, gpuBacked);
197     REPORTER_ASSERT(reporter, gpuBacked->isTextureBacked());
198     REPORTER_ASSERT(reporter, gpuBacked->uniqueID() == orig->uniqueID());
199     REPORTER_ASSERT(reporter, gpuBacked->subset().width() == orig->subset().width() &&
200                               gpuBacked->subset().height() == orig->subset().height());
201     REPORTER_ASSERT(reporter, gpuBacked->getColorSpace() == orig->getColorSpace());
202 }
203
204 // Test out the SkSpecialImage::makeTextureImage entry point
205 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_MakeTexture, reporter, ctxInfo) {
206     GrContext* context = ctxInfo.grContext();
207     SkBitmap bm = create_bm();
208
209     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
210
211     {
212         // raster
213         sk_sp<SkSpecialImage> rasterImage(SkSpecialImage::MakeFromRaster(
214                                                                         SkIRect::MakeWH(kFullSize,
215                                                                                         kFullSize),
216                                                                         bm));
217
218         {
219             sk_sp<SkSpecialImage> fromRaster(rasterImage->makeTextureImage(context));
220             test_texture_backed(reporter, rasterImage, fromRaster);
221         }
222
223         {
224             sk_sp<SkSpecialImage> subRasterImage(rasterImage->makeSubset(subset));
225
226             sk_sp<SkSpecialImage> fromSubRaster(subRasterImage->makeTextureImage(context));
227             test_texture_backed(reporter, subRasterImage, fromSubRaster);
228         }
229     }
230
231     {
232         // gpu
233         GrSurfaceDesc desc;
234         desc.fConfig = kSkia8888_GrPixelConfig;
235         desc.fFlags = kNone_GrSurfaceFlags;
236         desc.fWidth = kFullSize;
237         desc.fHeight = kFullSize;
238
239         sk_sp<GrTexture> texture(context->textureProvider()->createTexture(desc,
240                                                                            SkBudgeted::kNo,
241                                                                            bm.getPixels(),
242                                                                            0));
243         if (!texture) {
244             return;
245         }
246
247         sk_sp<SkSpecialImage> gpuImage(SkSpecialImage::MakeFromGpu(
248                                                                 SkIRect::MakeWH(kFullSize,
249                                                                                 kFullSize),
250                                                                 kNeedNewImageUniqueID_SpecialImage,
251                                                                 std::move(texture), nullptr));
252
253         {
254             sk_sp<SkSpecialImage> fromGPU(gpuImage->makeTextureImage(context));
255             test_texture_backed(reporter, gpuImage, fromGPU);
256         }
257
258         {
259             sk_sp<SkSpecialImage> subGPUImage(gpuImage->makeSubset(subset));
260
261             sk_sp<SkSpecialImage> fromSubGPU(subGPUImage->makeTextureImage(context));
262             test_texture_backed(reporter, subGPUImage, fromSubGPU);
263         }
264     }
265 }
266
267 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_Gpu, reporter, ctxInfo) {
268     GrContext* context = ctxInfo.grContext();
269     SkBitmap bm = create_bm();
270
271     GrSurfaceDesc desc;
272     desc.fConfig = kSkia8888_GrPixelConfig;
273     desc.fFlags  = kNone_GrSurfaceFlags;
274     desc.fWidth  = kFullSize;
275     desc.fHeight = kFullSize;
276
277     sk_sp<GrTexture> texture(context->textureProvider()->createTexture(desc,
278                                                                        SkBudgeted::kNo,
279                                                                        bm.getPixels(), 0));
280     if (!texture) {
281         return;
282     }
283
284     sk_sp<SkSpecialImage> fullSImg(SkSpecialImage::MakeFromGpu(
285                                                             SkIRect::MakeWH(kFullSize, kFullSize),
286                                                             kNeedNewImageUniqueID_SpecialImage,
287                                                             texture, nullptr));
288
289     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
290
291     {
292         sk_sp<SkSpecialImage> subSImg1(SkSpecialImage::MakeFromGpu(
293                                                                subset,
294                                                                kNeedNewImageUniqueID_SpecialImage,
295                                                                texture, nullptr));
296         test_image(subSImg1, reporter, context, true, kPad, kFullSize);
297     }
298
299     {
300         sk_sp<SkSpecialImage> subSImg2(fullSImg->makeSubset(subset));
301         test_image(subSImg2, reporter, context, true, kPad, kFullSize);
302     }
303 }
304
305 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_DeferredGpu, reporter, ctxInfo) {
306     GrContext* context = ctxInfo.grContext();
307     SkBitmap bm = create_bm();
308
309     GrSurfaceDesc desc;
310     desc.fConfig = kSkia8888_GrPixelConfig;
311     desc.fFlags  = kNone_GrSurfaceFlags;
312     desc.fWidth  = kFullSize;
313     desc.fHeight = kFullSize;
314
315     sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeDeferred(*context->caps(),
316                                                              context->textureProvider(),
317                                                              desc, SkBudgeted::kNo,
318                                                              bm.getPixels(), 0));
319     if (!proxy) {
320         return;
321     }
322
323     sk_sp<SkSpecialImage> fullSImg(SkSpecialImage::MakeDeferredFromGpu(
324                                                             context,
325                                                             SkIRect::MakeWH(kFullSize, kFullSize),
326                                                             kNeedNewImageUniqueID_SpecialImage,
327                                                             proxy, nullptr));
328
329     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
330
331     {
332         sk_sp<SkSpecialImage> subSImg1(SkSpecialImage::MakeDeferredFromGpu(
333                                                                context,
334                                                                subset,
335                                                                kNeedNewImageUniqueID_SpecialImage,
336                                                                proxy, nullptr));
337         test_image(subSImg1, reporter, context, true, kPad, kFullSize);
338     }
339
340     {
341         sk_sp<SkSpecialImage> subSImg2(fullSImg->makeSubset(subset));
342         test_image(subSImg2, reporter, context, true, kPad, kFullSize);
343     }
344 }
345
346 #endif