blob: 3240fbd3a72fee36054f4f43a7358738e0133c51 [file] [log] [blame]
robertphillipsb6c65e92016-02-04 10:52:42 -08001/*
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
robertphillipsc5035e72016-03-17 06:58:39 -07008#include "SkAutoPixmapStorage.h"
robertphillipsb6c65e92016-02-04 10:52:42 -08009#include "SkBitmap.h"
10#include "SkCanvas.h"
11#include "SkImage.h"
robertphillipsc5035e72016-03-17 06:58:39 -070012#include "SkPixmap.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080013#include "SkSpecialImage.h"
14#include "SkSpecialSurface.h"
15#include "Test.h"
robertphillips4418dba2016-03-07 12:45:14 -080016#include "TestingSpecialImageAccess.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080017
18#if SK_SUPPORT_GPU
19#include "GrContext.h"
20#endif
21
robertphillipsb6c65e92016-02-04 10:52:42 -080022
23// This test creates backing resources exactly sized to [kFullSize x kFullSize].
24// It then wraps them in an SkSpecialImage with only the center (red) region being active.
25// It then draws the SkSpecialImage to a full sized (all blue) canvas and checks that none
26// of the inactive (green) region leaked out.
27
28static const int kSmallerSize = 10;
29static const int kPad = 3;
30static const int kFullSize = kSmallerSize + 2 * kPad;
31
32// Create a bitmap with red in the center and green around it
33static SkBitmap create_bm() {
34 SkBitmap bm;
35 bm.allocN32Pixels(kFullSize, kFullSize, true);
36
37 SkCanvas temp(bm);
38
39 temp.clear(SK_ColorGREEN);
40 SkPaint p;
41 p.setColor(SK_ColorRED);
42 p.setAntiAlias(false);
43
44 temp.drawRect(SkRect::MakeXYWH(SkIntToScalar(kPad), SkIntToScalar(kPad),
45 SkIntToScalar(kSmallerSize), SkIntToScalar(kSmallerSize)),
46 p);
47
48 return bm;
49}
50
51// Basic test of the SkSpecialImage public API (e.g., peekTexture, peekPixels & draw)
robertphillips37bd7c32016-03-17 14:31:39 -070052static void test_image(const sk_sp<SkSpecialImage>& img, skiatest::Reporter* reporter,
robertphillipsc5035e72016-03-17 06:58:39 -070053 bool peekPixelsSucceeds, bool peekTextureSucceeds,
54 int offset, int size) {
robertphillips37bd7c32016-03-17 14:31:39 -070055 const SkIRect subset = TestingSpecialImageAccess::Subset(img.get());
robertphillipsc5035e72016-03-17 06:58:39 -070056 REPORTER_ASSERT(reporter, offset == subset.left());
57 REPORTER_ASSERT(reporter, offset == subset.top());
robertphillipsb6c65e92016-02-04 10:52:42 -080058 REPORTER_ASSERT(reporter, kSmallerSize == subset.width());
59 REPORTER_ASSERT(reporter, kSmallerSize == subset.height());
60
61 //--------------
robertphillips37bd7c32016-03-17 14:31:39 -070062 REPORTER_ASSERT(reporter, peekTextureSucceeds ==
63 !!TestingSpecialImageAccess::PeekTexture(img.get()));
robertphillipsb6c65e92016-02-04 10:52:42 -080064
65 //--------------
66 SkPixmap pixmap;
67 REPORTER_ASSERT(reporter, peekPixelsSucceeds ==
robertphillips37bd7c32016-03-17 14:31:39 -070068 !!TestingSpecialImageAccess::PeekPixels(img.get(), &pixmap));
robertphillipsb6c65e92016-02-04 10:52:42 -080069 if (peekPixelsSucceeds) {
robertphillipsc5035e72016-03-17 06:58:39 -070070 REPORTER_ASSERT(reporter, size == pixmap.width());
71 REPORTER_ASSERT(reporter, size == pixmap.height());
robertphillipsb6c65e92016-02-04 10:52:42 -080072 }
73
74 //--------------
75 SkImageInfo info = SkImageInfo::MakeN32(kFullSize, kFullSize, kOpaque_SkAlphaType);
76
robertphillips37bd7c32016-03-17 14:31:39 -070077 sk_sp<SkSpecialSurface> surf(img->makeSurface(info));
robertphillipsb6c65e92016-02-04 10:52:42 -080078
79 SkCanvas* canvas = surf->getCanvas();
80
81 canvas->clear(SK_ColorBLUE);
robertphillipse8c34972016-02-16 12:09:36 -080082 img->draw(canvas, SkIntToScalar(kPad), SkIntToScalar(kPad), nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -080083
84 SkBitmap bm;
85 bm.allocN32Pixels(kFullSize, kFullSize, true);
86
87 bool result = canvas->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), 0, 0);
88 SkASSERT_RELEASE(result);
89
90 // Only the center (red) portion should've been drawn into the canvas
91 REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kPad-1, kPad-1));
92 REPORTER_ASSERT(reporter, SK_ColorRED == bm.getColor(kPad, kPad));
93 REPORTER_ASSERT(reporter, SK_ColorRED == bm.getColor(kSmallerSize+kPad-1,
94 kSmallerSize+kPad-1));
95 REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kSmallerSize+kPad,
96 kSmallerSize+kPad));
97}
98
99DEF_TEST(SpecialImage_Raster, reporter) {
100 SkBitmap bm = create_bm();
101
robertphillips37bd7c32016-03-17 14:31:39 -0700102 sk_sp<SkSpecialImage> fullSImage(SkSpecialImage::MakeFromRaster(
robertphillipsc5035e72016-03-17 06:58:39 -0700103 nullptr,
104 SkIRect::MakeWH(kFullSize, kFullSize),
105 bm));
106
robertphillipsb6c65e92016-02-04 10:52:42 -0800107 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
108
robertphillipsc5035e72016-03-17 06:58:39 -0700109 {
robertphillips37bd7c32016-03-17 14:31:39 -0700110 sk_sp<SkSpecialImage> subSImg1(SkSpecialImage::MakeFromRaster(nullptr, subset, bm));
robertphillipsc5035e72016-03-17 06:58:39 -0700111 test_image(subSImg1, reporter, true, false, kPad, kFullSize);
112 }
113
114 {
robertphillips37bd7c32016-03-17 14:31:39 -0700115 sk_sp<SkSpecialImage> subSImg2(fullSImage->makeSubset(subset));
robertphillipsc5035e72016-03-17 06:58:39 -0700116 test_image(subSImg2, reporter, true, false, 0, kSmallerSize);
117 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800118}
119
120DEF_TEST(SpecialImage_Image, reporter) {
121 SkBitmap bm = create_bm();
122
reed9ce9d672016-03-17 10:51:11 -0700123 sk_sp<SkImage> fullImage(SkImage::MakeFromBitmap(bm));
robertphillipsb6c65e92016-02-04 10:52:42 -0800124
robertphillips37bd7c32016-03-17 14:31:39 -0700125 sk_sp<SkSpecialImage> fullSImage(SkSpecialImage::MakeFromImage(
robertphillipsc5035e72016-03-17 06:58:39 -0700126 nullptr,
127 SkIRect::MakeWH(kFullSize, kFullSize),
robertphillips37bd7c32016-03-17 14:31:39 -0700128 fullImage));
robertphillipsc5035e72016-03-17 06:58:39 -0700129
robertphillipsb6c65e92016-02-04 10:52:42 -0800130 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
131
robertphillipsc5035e72016-03-17 06:58:39 -0700132 {
robertphillips37bd7c32016-03-17 14:31:39 -0700133 sk_sp<SkSpecialImage> subSImg1(SkSpecialImage::MakeFromImage(nullptr, subset,
134 fullImage));
robertphillipsc5035e72016-03-17 06:58:39 -0700135 test_image(subSImg1, reporter, true, false, kPad, kFullSize);
136 }
137
138 {
robertphillips37bd7c32016-03-17 14:31:39 -0700139 sk_sp<SkSpecialImage> subSImg2(fullSImage->makeSubset(subset));
robertphillipsc5035e72016-03-17 06:58:39 -0700140 test_image(subSImg2, reporter, true, false, 0, kSmallerSize);
141 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800142}
143
robertphillipsc5035e72016-03-17 06:58:39 -0700144DEF_TEST(SpecialImage_Pixmap, reporter) {
145 SkAutoPixmapStorage pixmap;
146
147 const SkImageInfo info = SkImageInfo::MakeN32(kFullSize, kFullSize, kOpaque_SkAlphaType);
148 pixmap.alloc(info);
149 pixmap.erase(SK_ColorGREEN);
150
151 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
152
153 pixmap.erase(SK_ColorRED, subset);
154
155 {
156 // The SkAutoPixmapStorage keeps hold of the memory
robertphillips37bd7c32016-03-17 14:31:39 -0700157 sk_sp<SkSpecialImage> img(SkSpecialImage::MakeFromPixmap(nullptr, subset, pixmap,
158 nullptr, nullptr));
robertphillipsc5035e72016-03-17 06:58:39 -0700159 test_image(img, reporter, true, false, kPad, kFullSize);
160 }
161
162 {
163 // The image takes ownership of the memory
robertphillips37bd7c32016-03-17 14:31:39 -0700164 sk_sp<SkSpecialImage> img(SkSpecialImage::MakeFromPixmap(
robertphillipsc5035e72016-03-17 06:58:39 -0700165 nullptr, subset, pixmap,
robertphillips37bd7c32016-03-17 14:31:39 -0700166 [] (void* addr, void*) -> void {
167 sk_free(addr);
168 },
robertphillipsc5035e72016-03-17 06:58:39 -0700169 nullptr));
170 pixmap.release();
171 test_image(img, reporter, true, false, kPad, kFullSize);
172 }
173}
174
175
robertphillipsb6c65e92016-02-04 10:52:42 -0800176#if SK_SUPPORT_GPU
robertphillips83c17fa2016-03-18 08:14:27 -0700177
178static void test_texture_backed(skiatest::Reporter* reporter,
179 const sk_sp<SkSpecialImage>& orig,
180 const sk_sp<SkSpecialImage>& gpuBacked) {
181 REPORTER_ASSERT(reporter, gpuBacked);
182 REPORTER_ASSERT(reporter, gpuBacked->peekTexture());
183 REPORTER_ASSERT(reporter, gpuBacked->uniqueID() == orig->uniqueID());
184 REPORTER_ASSERT(reporter, gpuBacked->subset().width() == orig->subset().width() &&
185 gpuBacked->subset().height() == orig->subset().height());
186}
187
188// Test out the SkSpecialImage::makeTextureImage entry point
189DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_MakeTexture, reporter, context) {
190 SkBitmap bm = create_bm();
191
192 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
193
194 {
195 // raster
196 sk_sp<SkSpecialImage> rasterImage(SkSpecialImage::MakeFromRaster(
197 nullptr,
198 SkIRect::MakeWH(kFullSize,
199 kFullSize),
200 bm));
201
202 {
203 sk_sp<SkSpecialImage> fromRaster(rasterImage->makeTextureImage(nullptr, context));
204 test_texture_backed(reporter, rasterImage, fromRaster);
205 }
206
207 {
208 sk_sp<SkSpecialImage> subRasterImage(rasterImage->makeSubset(subset));
209
210 sk_sp<SkSpecialImage> fromSubRaster(subRasterImage->makeTextureImage(nullptr, context));
211 test_texture_backed(reporter, subRasterImage, fromSubRaster);
212 }
213 }
214
215 {
216 // gpu
217 GrSurfaceDesc desc;
218 desc.fConfig = kSkia8888_GrPixelConfig;
219 desc.fFlags = kNone_GrSurfaceFlags;
220 desc.fWidth = kFullSize;
221 desc.fHeight = kFullSize;
222
223 SkAutoTUnref<GrTexture> texture(context->textureProvider()->createTexture(desc,
224 SkBudgeted::kNo,
225 bm.getPixels(),
226 0));
227 if (!texture) {
228 return;
229 }
230
231 sk_sp<SkSpecialImage> gpuImage(SkSpecialImage::MakeFromGpu(
232 nullptr,
233 SkIRect::MakeWH(kFullSize,
234 kFullSize),
235 kNeedNewImageUniqueID_SpecialImage,
236 texture));
237
238 {
239 sk_sp<SkSpecialImage> fromGPU(gpuImage->makeTextureImage(nullptr, context));
240 test_texture_backed(reporter, gpuImage, fromGPU);
241 }
242
243 {
244 sk_sp<SkSpecialImage> subGPUImage(gpuImage->makeSubset(subset));
245
246 sk_sp<SkSpecialImage> fromSubGPU(subGPUImage->makeTextureImage(nullptr, context));
247 test_texture_backed(reporter, subGPUImage, fromSubGPU);
248 }
249 }
250}
251
robertphillipsb6c65e92016-02-04 10:52:42 -0800252DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_Gpu, reporter, context) {
253 SkBitmap bm = create_bm();
254
255 GrSurfaceDesc desc;
256 desc.fConfig = kSkia8888_GrPixelConfig;
257 desc.fFlags = kNone_GrSurfaceFlags;
258 desc.fWidth = kFullSize;
259 desc.fHeight = kFullSize;
260
robertphillips83c17fa2016-03-18 08:14:27 -0700261 SkAutoTUnref<GrTexture> texture(context->textureProvider()->createTexture(desc,
262 SkBudgeted::kNo,
robertphillipsb6c65e92016-02-04 10:52:42 -0800263 bm.getPixels(), 0));
264 if (!texture) {
265 return;
266 }
267
robertphillips37bd7c32016-03-17 14:31:39 -0700268 sk_sp<SkSpecialImage> fullSImg(SkSpecialImage::MakeFromGpu(
robertphillipsc5035e72016-03-17 06:58:39 -0700269 nullptr,
270 SkIRect::MakeWH(kFullSize, kFullSize),
271 kNeedNewImageUniqueID_SpecialImage,
272 texture));
273
robertphillipsb6c65e92016-02-04 10:52:42 -0800274 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
275
robertphillipsc5035e72016-03-17 06:58:39 -0700276 {
robertphillips37bd7c32016-03-17 14:31:39 -0700277 sk_sp<SkSpecialImage> subSImg1(SkSpecialImage::MakeFromGpu(
robertphillipsc5035e72016-03-17 06:58:39 -0700278 nullptr, subset,
279 kNeedNewImageUniqueID_SpecialImage,
280 texture));
281 test_image(subSImg1, reporter, false, true, kPad, kFullSize);
282 }
283
284 {
robertphillips37bd7c32016-03-17 14:31:39 -0700285 sk_sp<SkSpecialImage> subSImg2(fullSImg->makeSubset(subset));
robertphillipsc5035e72016-03-17 06:58:39 -0700286 test_image(subSImg2, reporter, false, true, kPad, kFullSize);
287 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800288}
289
290#endif