blob: 5da83429952294acaad611da34b45f1b918609d3 [file] [log] [blame]
reed871872f2015-06-22 12:48:26 -07001/*
2 * Copyright 2015 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 "SkDevice.h"
11#include "SkImageEncoder.h"
12#include "SkImage_Base.h"
13#include "SkRRect.h"
14#include "SkSurface.h"
15#include "SkUtils.h"
16#include "Test.h"
17
18#if SK_SUPPORT_GPU
19#include "GrContextFactory.h"
20#include "GrTest.h"
21#include "gl/GrGLInterface.h"
22#include "gl/GrGLUtil.h"
23#else
24class GrContextFactory;
25class GrContext;
26#endif
27
28static void assert_equal(skiatest::Reporter* reporter, SkImage* a, const SkIRect* subsetA,
29 SkImage* b) {
30 const int widthA = subsetA ? subsetA->width() : a->width();
31 const int heightA = subsetA ? subsetA->height() : a->height();
32
33 REPORTER_ASSERT(reporter, widthA == b->width());
34 REPORTER_ASSERT(reporter, heightA == b->height());
35#if 0
36 // see skbug.com/3965
37 bool AO = a->isOpaque();
38 bool BO = b->isOpaque();
39 REPORTER_ASSERT(reporter, AO == BO);
40#endif
41
42 SkImageInfo info = SkImageInfo::MakeN32(widthA, heightA,
43 a->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
44 SkAutoPixmapStorage pmapA, pmapB;
45 pmapA.alloc(info);
46 pmapB.alloc(info);
47
48 const int srcX = subsetA ? subsetA->x() : 0;
49 const int srcY = subsetA ? subsetA->y() : 0;
50
51 REPORTER_ASSERT(reporter, a->readPixels(pmapA, srcX, srcY));
52 REPORTER_ASSERT(reporter, b->readPixels(pmapB, 0, 0));
53
54 const size_t widthBytes = widthA * info.bytesPerPixel();
55 for (int y = 0; y < heightA; ++y) {
56 REPORTER_ASSERT(reporter, !memcmp(pmapA.addr32(0, y), pmapB.addr32(0, y), widthBytes));
57 }
58}
59
60static SkImage* make_image(GrContext* ctx, int w, int h, const SkIRect& ir) {
61 const SkImageInfo info = SkImageInfo::MakeN32(w, h, kOpaque_SkAlphaType);
62 SkAutoTUnref<SkSurface> surface(ctx ?
63 SkSurface::NewRenderTarget(ctx, SkSurface::kNo_Budgeted, info) :
64 SkSurface::NewRaster(info));
65 SkCanvas* canvas = surface->getCanvas();
66 canvas->clear(SK_ColorWHITE);
67
68 SkPaint paint;
69 paint.setColor(SK_ColorBLACK);
70 canvas->drawRect(SkRect::Make(ir), paint);
71 return surface->newImageSnapshot();
72}
73
74static void test_encode(skiatest::Reporter* reporter, GrContext* ctx) {
75 const SkIRect ir = SkIRect::MakeXYWH(5, 5, 10, 10);
76 SkAutoTUnref<SkImage> orig(make_image(ctx, 20, 20, ir));
77 SkAutoTUnref<SkData> origEncoded(orig->encode());
78 REPORTER_ASSERT(reporter, origEncoded);
79 REPORTER_ASSERT(reporter, origEncoded->size() > 0);
80
81 SkAutoTUnref<SkImage> decoded(SkImage::NewFromEncoded(origEncoded));
82 REPORTER_ASSERT(reporter, decoded);
83 assert_equal(reporter, orig, NULL, decoded);
84
85 // Now see if we can instantiate an image from a subset of the surface/origEncoded
86
87 decoded.reset(SkImage::NewFromEncoded(origEncoded, &ir));
88 REPORTER_ASSERT(reporter, decoded);
89 assert_equal(reporter, orig, &ir, decoded);
90}
91
92DEF_TEST(Image_Encode_Cpu, reporter) {
93 test_encode(reporter, NULL);
94}
95
96#if SK_SUPPORT_GPU
97DEF_GPUTEST(Image_Encode_Gpu, reporter, factory) {
98 GrContext* ctx = factory->get(GrContextFactory::kNative_GLContextType);
99 if (!ctx) {
100 REPORTER_ASSERT(reporter, false);
101 return;
102 }
103 test_encode(reporter, ctx);
104}
105#endif
reed759373a2015-07-03 21:01:10 -0700106
107DEF_TEST(Image_NewRasterCopy, reporter) {
108 const SkPMColor red = SkPackARGB32(0xFF, 0xFF, 0, 0);
109 const SkPMColor green = SkPackARGB32(0xFF, 0, 0xFF, 0);
110 const SkPMColor blue = SkPackARGB32(0xFF, 0, 0, 0xFF);
111 SkPMColor colors[] = { red, green, blue, 0 };
112 SkAutoTUnref<SkColorTable> ctable(SkNEW_ARGS(SkColorTable, (colors, SK_ARRAY_COUNT(colors))));
113 // The colortable made a copy, so we can trash the original colors
114 memset(colors, 0xFF, sizeof(colors));
115
116 const SkImageInfo srcInfo = SkImageInfo::Make(2, 2, kIndex_8_SkColorType, kPremul_SkAlphaType);
117 const size_t srcRowBytes = 2 * sizeof(uint8_t);
118 uint8_t indices[] = { 0, 1, 2, 3 };
119 SkAutoTUnref<SkImage> image(SkImage::NewRasterCopy(srcInfo, indices, srcRowBytes, ctable));
120 // The image made a copy, so we can trash the original indices
121 memset(indices, 0xFF, sizeof(indices));
122
123 const SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(2, 2);
124 const size_t dstRowBytes = 2 * sizeof(SkPMColor);
125 SkPMColor pixels[4];
126 memset(pixels, 0xFF, sizeof(pixels)); // init with values we don't expect
127 image->readPixels(dstInfo, pixels, dstRowBytes, 0, 0);
128 REPORTER_ASSERT(reporter, red == pixels[0]);
129 REPORTER_ASSERT(reporter, green == pixels[1]);
130 REPORTER_ASSERT(reporter, blue == pixels[2]);
131 REPORTER_ASSERT(reporter, 0 == pixels[3]);
132}
fmalita8c0144c2015-07-22 05:56:16 -0700133
134// Test that a draw that only partially covers the drawing surface isn't
135// interpreted as covering the entire drawing surface (i.e., exercise one of the
136// conditions of SkCanvas::wouldOverwriteEntireSurface()).
137DEF_TEST(Image_RetainSnapshot, reporter) {
138 const SkPMColor red = SkPackARGB32(0xFF, 0xFF, 0, 0);
139 const SkPMColor green = SkPackARGB32(0xFF, 0, 0xFF, 0);
140 SkImageInfo info = SkImageInfo::MakeN32Premul(2, 2);
141 SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
142 surface->getCanvas()->clear(0xFF00FF00);
143
144 SkPMColor pixels[4];
145 memset(pixels, 0xFF, sizeof(pixels)); // init with values we don't expect
146 const SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(2, 2);
147 const size_t dstRowBytes = 2 * sizeof(SkPMColor);
148
149 SkAutoTUnref<SkImage> image1(surface->newImageSnapshot());
150 REPORTER_ASSERT(reporter, image1->readPixels(dstInfo, pixels, dstRowBytes, 0, 0));
151 for (size_t i = 0; i < SK_ARRAY_COUNT(pixels); ++i) {
152 REPORTER_ASSERT(reporter, pixels[i] == green);
153 }
154
155 SkPaint paint;
156 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
157 paint.setColor(SK_ColorRED);
158
159 surface->getCanvas()->drawRect(SkRect::MakeXYWH(1, 1, 1, 1), paint);
160
161 SkAutoTUnref<SkImage> image2(surface->newImageSnapshot());
162 REPORTER_ASSERT(reporter, image2->readPixels(dstInfo, pixels, dstRowBytes, 0, 0));
163 REPORTER_ASSERT(reporter, pixels[0] == green);
164 REPORTER_ASSERT(reporter, pixels[1] == green);
165 REPORTER_ASSERT(reporter, pixels[2] == green);
166 REPORTER_ASSERT(reporter, pixels[3] == red);
167}
reed80c772b2015-07-30 18:58:23 -0700168
169/////////////////////////////////////////////////////////////////////////////////////////////////
170#include "SkImageGenerator.h"
171#include "SkData.h"
172
173const uint8_t tiny_png[] = {
174 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
175 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x64,
176 0x08, 0x06, 0x00, 0x00, 0x00, 0x70, 0xe2, 0x95, 0x54, 0x00, 0x00, 0x00,
177 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
178 0x01, 0x6b, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, 0xd3, 0x41, 0x11,
179 0x00, 0x20, 0x0c, 0xc4, 0x40, 0xc0, 0xbf, 0xe7, 0xc2, 0xa0, 0x22, 0x8f,
180 0xad, 0x82, 0x4c, 0xd2, 0xdb, 0xf3, 0x6e, 0xb9, 0x8c, 0x81, 0x93, 0x21,
181 0x01, 0xf2, 0x0d, 0x08, 0x12, 0x7b, 0x04, 0x41, 0x04, 0x89, 0x19, 0x88,
182 0xe1, 0x58, 0x88, 0x20, 0x31, 0x03, 0x31, 0x1c, 0x0b, 0x11, 0x24, 0x66,
183 0x20, 0x86, 0x63, 0x21, 0x82, 0xc4, 0x0c, 0xc4, 0x70, 0x2c, 0x44, 0x90,
184 0x98, 0x81, 0x18, 0x8e, 0x85, 0x08, 0x12, 0x33, 0x10, 0xc3, 0xb1, 0x10,
185 0x41, 0x62, 0x06, 0x62, 0x38, 0x16, 0x22, 0x48, 0xcc, 0x40, 0x0c, 0xc7,
186 0x42, 0x04, 0x89, 0x19, 0x88, 0xe1, 0x58, 0x88, 0x20, 0x31, 0x03, 0x31,
187 0x1c, 0x0b, 0x11, 0x24, 0x66, 0x20, 0x86, 0x63, 0x21, 0x82, 0xc4, 0x0c,
188 0xc4, 0x70, 0x2c, 0x44, 0x90, 0x98, 0x81, 0x18, 0x8e, 0x85, 0x08, 0x12,
189 0x33, 0x10, 0xc3, 0xb1, 0x10, 0x41, 0x62, 0x06, 0x62, 0x38, 0x16, 0x22,
190 0x48, 0xcc, 0x40, 0x0c, 0xc7, 0x42, 0x04, 0x89, 0x19, 0x88, 0xe1, 0x58,
191 0x88, 0x20, 0x31, 0x03, 0x31, 0x1c, 0x0b, 0x11, 0x24, 0x66, 0x20, 0x86,
192 0x63, 0x21, 0x82, 0xc4, 0x0c, 0xc4, 0x70, 0x2c, 0x44, 0x90, 0x98, 0x81,
193 0x18, 0x8e, 0x85, 0x08, 0x12, 0x33, 0x10, 0xc3, 0xb1, 0x10, 0x41, 0x62,
194 0x06, 0x62, 0x38, 0x16, 0x22, 0x48, 0xcc, 0x40, 0x0c, 0xc7, 0x42, 0x04,
195 0x89, 0x19, 0x88, 0xe1, 0x58, 0x88, 0x20, 0x31, 0x03, 0x31, 0x1c, 0x0b,
196 0x11, 0x24, 0x66, 0x20, 0x86, 0x63, 0x21, 0x82, 0xc4, 0x0c, 0xc4, 0x70,
197 0x2c, 0x44, 0x90, 0x98, 0x81, 0x18, 0x8e, 0x85, 0x08, 0x12, 0x33, 0x10,
198 0xc3, 0xb1, 0x10, 0x41, 0x62, 0x06, 0x62, 0x38, 0x16, 0x22, 0x48, 0xcc,
199 0x40, 0x0c, 0xc7, 0x42, 0x04, 0x89, 0x19, 0x88, 0xe1, 0x58, 0x88, 0x20,
200 0x31, 0x03, 0x31, 0x1c, 0x0b, 0x11, 0x24, 0x66, 0x20, 0x86, 0x63, 0x21,
201 0x82, 0xc4, 0x0c, 0xc4, 0x70, 0x2c, 0x44, 0x90, 0x98, 0x81, 0x18, 0x8e,
202 0x85, 0x08, 0x12, 0x33, 0x10, 0xc3, 0xb1, 0x10, 0x41, 0x62, 0x06, 0x62,
203 0x38, 0x16, 0x22, 0x48, 0xcc, 0x40, 0x0c, 0xc7, 0x42, 0x04, 0x89, 0x19,
204 0x88, 0xe1, 0x58, 0x88, 0x20, 0x31, 0x03, 0x31, 0x1c, 0x0b, 0x11, 0x24,
205 0x66, 0x20, 0x86, 0x63, 0x21, 0x82, 0xc4, 0x0c, 0xc4, 0x70, 0x2c, 0x44,
206 0x90, 0x98, 0x81, 0x18, 0x8e, 0x85, 0x08, 0x12, 0x33, 0x10, 0xc3, 0xb1,
207 0x10, 0x41, 0x62, 0x06, 0x62, 0x38, 0x16, 0x22, 0x48, 0xcc, 0x40, 0x0c,
208 0xc7, 0x42, 0x62, 0x41, 0x2e, 0x08, 0x60, 0x04, 0xc4, 0x4c, 0x5d, 0x6e,
209 0xf2, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60,
210 0x82
211};
212
213static void make_bitmap_lazy(SkBitmap* bm) {
214 SkAutoTUnref<SkData> data(SkData::NewWithoutCopy(tiny_png, sizeof(tiny_png)));
215 SkInstallDiscardablePixelRef(data, bm);
216}
217
218static void make_bitmap_mutable(SkBitmap* bm) {
219 bm->allocN32Pixels(10, 10);
220}
221
222static void make_bitmap_immutable(SkBitmap* bm) {
223 bm->allocN32Pixels(10, 10);
224 bm->setImmutable();
225}
226
227DEF_TEST(image_newfrombitmap, reporter) {
228 const struct {
229 void (*fMakeProc)(SkBitmap*);
230 bool fExpectPeekSuccess;
231 bool fExpectSharedID;
232 } rec[] = {
233 { make_bitmap_lazy, false, true },
234 { make_bitmap_mutable, true, false },
235 { make_bitmap_immutable, true, true },
236 };
237
238 for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
239 SkBitmap bm;
240 rec[i].fMakeProc(&bm);
241
242 SkAutoTUnref<SkImage> image(SkImage::NewFromBitmap(bm));
243 SkPixmap pmap;
244
245 const bool sharedID = (image->uniqueID() == bm.getGenerationID());
246 REPORTER_ASSERT(reporter, sharedID == rec[i].fExpectSharedID);
247
248#if 0 // TODO: fix so that peek will succeed in the immutable case
249 const bool peekSuccess = image->peekPixels(&pmap);
250 REPORTER_ASSERT(reporter, peekSuccess == rec[i].fExpectPeekSuccess);
251#endif
252 }
253}