blob: f12d45f2842548fa20cce610ce819b41c797203d [file] [log] [blame]
Matt Sarett909d3792016-12-22 10:52:25 -05001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
9#include "include/codec/SkCodec.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040010#include "include/core/SkBitmap.h"
11#include "include/core/SkCanvas.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkColorSpace.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040013#include "include/core/SkData.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "include/core/SkImage.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040015#include "include/core/SkImageInfo.h"
16#include "include/core/SkPaint.h"
17#include "include/core/SkPicture.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "include/core/SkPictureRecorder.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040019#include "include/core/SkRect.h"
20#include "include/core/SkRefCnt.h"
21#include "include/core/SkSize.h"
22#include "include/core/SkStream.h"
23#include "include/core/SkString.h"
24#include "include/core/SkTypes.h"
Adlai Holler4caa9352020-07-16 10:58:58 -040025#include "include/gpu/GrDirectContext.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040026#include "include/third_party/skcms/skcms.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "tools/Resources.h"
Matt Sarett909d3792016-12-22 10:52:25 -050028
Ben Wagner7fde8e12019-05-01 17:28:53 -040029#include <string.h>
30#include <memory>
31#include <utility>
32
Matt Sarett909d3792016-12-22 10:52:25 -050033static const int kWidth = 64;
34static const int kHeight = 64;
35
Brian Osmanb1168a72017-03-20 14:21:18 -040036static sk_sp<SkImage> make_raster_image(SkColorType colorType) {
Hal Canaryc465d132017-12-08 10:21:31 -050037 std::unique_ptr<SkStream> stream(GetResourceAsStream("images/google_chrome.ico"));
Mike Reedede7bac2017-07-23 15:30:02 -040038 std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
Hal Canarybaa2a282018-11-26 15:34:12 -050039 if (!codec) {
40 return nullptr;
41 }
Matt Sarett909d3792016-12-22 10:52:25 -050042
Matt Sarett909d3792016-12-22 10:52:25 -050043 SkImageInfo info = codec->getInfo().makeWH(kWidth, kHeight)
44 .makeColorType(colorType)
Brian Osman6b622962018-08-27 19:16:02 +000045 .makeAlphaType(kPremul_SkAlphaType);
Mike Reed844beb52021-01-25 15:36:09 -050046 return std::get<0>(codec->getImage(info));
Matt Sarett909d3792016-12-22 10:52:25 -050047}
48
Matt Sarett34855f92017-01-10 17:41:53 -050049static sk_sp<SkImage> make_codec_image() {
Hal Canaryc465d132017-12-08 10:21:31 -050050 sk_sp<SkData> encoded = GetResourceAsData("images/randPixels.png");
Matt Sarett34855f92017-01-10 17:41:53 -050051 return SkImage::MakeFromEncoded(encoded);
52}
53
54static void draw_contents(SkCanvas* canvas) {
55 SkPaint paint;
56 paint.setStyle(SkPaint::kStroke_Style);
57 paint.setStrokeWidth(20);
58 paint.setColor(0xFF800000);
59 canvas->drawCircle(40, 40, 35, paint);
60 paint.setColor(0xFF008000);
61 canvas->drawCircle(50, 50, 35, paint);
62 paint.setColor(0xFF000080);
63 canvas->drawCircle(60, 60, 35, paint);
64}
65
Matt Sarett9df70bb2017-02-14 13:50:43 -050066static sk_sp<SkImage> make_picture_image() {
Matt Sarett34855f92017-01-10 17:41:53 -050067 SkPictureRecorder recorder;
68 draw_contents(recorder.beginRecording(SkRect::MakeIWH(kWidth, kHeight)));
69 return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
70 SkISize::Make(kWidth, kHeight), nullptr, nullptr,
71 SkImage::BitDepth::kU8,
Matt Sarett77a7a1b2017-02-07 13:56:11 -050072 SkColorSpace::MakeSRGB());
Matt Sarett34855f92017-01-10 17:41:53 -050073}
74
Matt Sarett733340a2017-05-02 16:19:51 -040075static sk_sp<SkColorSpace> make_parametric_transfer_fn(const SkColorSpacePrimaries& primaries) {
Brian Osman82ebe042019-01-04 17:03:00 -050076 skcms_Matrix3x3 toXYZD50;
Matt Sarett909d3792016-12-22 10:52:25 -050077 SkAssertResult(primaries.toXYZD50(&toXYZD50));
Brian Osman82ebe042019-01-04 17:03:00 -050078 skcms_TransferFunction fn = { 1.8f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f };
Matt Sarett733340a2017-05-02 16:19:51 -040079 return SkColorSpace::MakeRGB(fn, toXYZD50);
Matt Sarett909d3792016-12-22 10:52:25 -050080}
81
82static sk_sp<SkColorSpace> make_wide_gamut() {
83 // ProPhoto
84 SkColorSpacePrimaries primaries;
85 primaries.fRX = 0.7347f;
86 primaries.fRY = 0.2653f;
87 primaries.fGX = 0.1596f;
88 primaries.fGY = 0.8404f;
89 primaries.fBX = 0.0366f;
90 primaries.fBY = 0.0001f;
91 primaries.fWX = 0.34567f;
92 primaries.fWY = 0.35850f;
Matt Sarett733340a2017-05-02 16:19:51 -040093 return make_parametric_transfer_fn(primaries);
Matt Sarett909d3792016-12-22 10:52:25 -050094}
95
96static sk_sp<SkColorSpace> make_small_gamut() {
97 SkColorSpacePrimaries primaries;
98 primaries.fRX = 0.50f;
99 primaries.fRY = 0.33f;
100 primaries.fGX = 0.30f;
101 primaries.fGY = 0.50f;
102 primaries.fBX = 0.25f;
103 primaries.fBY = 0.16f;
104 primaries.fWX = 0.3127f;
105 primaries.fWY = 0.3290f;
Matt Sarett733340a2017-05-02 16:19:51 -0400106 return make_parametric_transfer_fn(primaries);
Matt Sarett909d3792016-12-22 10:52:25 -0500107}
108
Adlai Hollerbcfc5542020-08-27 12:44:07 -0400109static void draw_image(GrDirectContext* dContext, SkCanvas* canvas, SkImage* image,
110 SkColorType dstColorType, SkAlphaType dstAlphaType,
111 sk_sp<SkColorSpace> dstColorSpace, SkImage::CachingHint hint) {
Matt Sarett909d3792016-12-22 10:52:25 -0500112 size_t rowBytes = image->width() * SkColorTypeBytesPerPixel(dstColorType);
113 sk_sp<SkData> data = SkData::MakeUninitialized(rowBytes * image->height());
Matt Sarett909d3792016-12-22 10:52:25 -0500114 SkImageInfo dstInfo = SkImageInfo::Make(image->width(), image->height(), dstColorType,
115 dstAlphaType, dstColorSpace);
Adlai Hollerbcfc5542020-08-27 12:44:07 -0400116 if (!image->readPixels(dContext, dstInfo, data->writable_data(), rowBytes, 0, 0, hint)) {
Brian Osman89150582017-03-20 16:54:28 -0400117 memset(data->writable_data(), 0, rowBytes * image->height());
118 }
Matt Sarett909d3792016-12-22 10:52:25 -0500119
Matt Sarett909d3792016-12-22 10:52:25 -0500120 // Now that we have called readPixels(), dump the raw pixels into an srgb image.
Brian Osman6b622962018-08-27 19:16:02 +0000121 sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
Matt Sarett909d3792016-12-22 10:52:25 -0500122 sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes);
Mike Reed8d29ab62021-01-23 18:10:39 -0500123 canvas->drawImage(raw.get(), 0.0f, 0.0f);
Matt Sarett909d3792016-12-22 10:52:25 -0500124}
125
126class ReadPixelsGM : public skiagm::GM {
127public:
128 ReadPixelsGM() {}
129
130protected:
131 SkString onShortName() override {
132 return SkString("readpixels");
133 }
134
135 SkISize onISize() override {
Brian Osmanb1168a72017-03-20 14:21:18 -0400136 return SkISize::Make(6 * kWidth, 9 * kHeight);
Matt Sarett909d3792016-12-22 10:52:25 -0500137 }
138
139 void onDraw(SkCanvas* canvas) override {
Matt Sarett909d3792016-12-22 10:52:25 -0500140 const SkAlphaType alphaTypes[] = {
141 kUnpremul_SkAlphaType,
142 kPremul_SkAlphaType,
143 };
144 const SkColorType colorTypes[] = {
145 kRGBA_8888_SkColorType,
146 kBGRA_8888_SkColorType,
147 kRGBA_F16_SkColorType,
148 };
149 const sk_sp<SkColorSpace> colorSpaces[] = {
150 make_wide_gamut(),
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500151 SkColorSpace::MakeSRGB(),
Matt Sarett909d3792016-12-22 10:52:25 -0500152 make_small_gamut(),
153 };
154
John Stilesbd3ffa42020-07-30 20:24:57 -0400155 for (const sk_sp<SkColorSpace>& dstColorSpace : colorSpaces) {
Matt Sarett909d3792016-12-22 10:52:25 -0500156 for (SkColorType srcColorType : colorTypes) {
Brian Osmanb1168a72017-03-20 14:21:18 -0400157 canvas->save();
158 sk_sp<SkImage> image = make_raster_image(srcColorType);
Hal Canarybaa2a282018-11-26 15:34:12 -0500159 if (!image) {
160 continue;
161 }
Adlai Hollerbcfc5542020-08-27 12:44:07 -0400162 auto dContext = GrAsDirectContext(canvas->recordingContext());
163 if (dContext) {
164 image = image->makeTextureImage(dContext);
Brian Osman89150582017-03-20 16:54:28 -0400165 }
166 if (image) {
167 for (SkColorType dstColorType : colorTypes) {
168 for (SkAlphaType dstAlphaType : alphaTypes) {
Adlai Hollerbcfc5542020-08-27 12:44:07 -0400169 draw_image(dContext, canvas, image.get(), dstColorType, dstAlphaType,
Brian Osman89150582017-03-20 16:54:28 -0400170 dstColorSpace, SkImage::kAllow_CachingHint);
171 canvas->translate((float)kWidth, 0.0f);
172 }
Matt Sarett909d3792016-12-22 10:52:25 -0500173 }
Matt Sarett909d3792016-12-22 10:52:25 -0500174 }
Brian Osmanb1168a72017-03-20 14:21:18 -0400175 canvas->restore();
176 canvas->translate(0.0f, (float) kHeight);
Matt Sarett909d3792016-12-22 10:52:25 -0500177 }
178 }
179 }
180
181private:
John Stiles7571f9e2020-09-02 22:42:33 -0400182 using INHERITED = skiagm::GM;
Matt Sarett909d3792016-12-22 10:52:25 -0500183};
184DEF_GM( return new ReadPixelsGM; )
Matt Sarett34855f92017-01-10 17:41:53 -0500185
186class ReadPixelsCodecGM : public skiagm::GM {
187public:
188 ReadPixelsCodecGM() {}
189
190protected:
191 SkString onShortName() override {
192 return SkString("readpixelscodec");
193 }
194
195 SkISize onISize() override {
196 return SkISize::Make(3 * (kEncodedWidth + 1), 12 * (kEncodedHeight + 1));
197 }
198
Chris Dalton50e24d72019-02-07 16:20:09 -0700199 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
Matt Sarett34855f92017-01-10 17:41:53 -0500200 if (!canvas->imageInfo().colorSpace()) {
Chris Dalton50e24d72019-02-07 16:20:09 -0700201 *errorMsg = "This gm is only interesting in color correct modes.";
202 return DrawResult::kSkip;
Matt Sarett34855f92017-01-10 17:41:53 -0500203 }
204
205 const SkAlphaType alphaTypes[] = {
206 kUnpremul_SkAlphaType,
207 kPremul_SkAlphaType,
208 };
209 const SkColorType colorTypes[] = {
210 kRGBA_8888_SkColorType,
211 kBGRA_8888_SkColorType,
212 kRGBA_F16_SkColorType,
213 };
214 const sk_sp<SkColorSpace> colorSpaces[] = {
215 make_wide_gamut(),
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500216 SkColorSpace::MakeSRGB(),
Matt Sarett34855f92017-01-10 17:41:53 -0500217 make_small_gamut(),
218 };
219 const SkImage::CachingHint hints[] = {
220 SkImage::kAllow_CachingHint,
221 SkImage::kDisallow_CachingHint,
222 };
223
224 sk_sp<SkImage> image = make_codec_image();
John Stilesbd3ffa42020-07-30 20:24:57 -0400225 for (const sk_sp<SkColorSpace>& dstColorSpace : colorSpaces) {
Matt Sarett34855f92017-01-10 17:41:53 -0500226 canvas->save();
227 for (SkColorType dstColorType : colorTypes) {
228 for (SkAlphaType dstAlphaType : alphaTypes) {
229 for (SkImage::CachingHint hint : hints) {
Adlai Hollerbcfc5542020-08-27 12:44:07 -0400230 draw_image(nullptr, canvas, image.get(), dstColorType, dstAlphaType,
231 dstColorSpace, hint);
Matt Sarett34855f92017-01-10 17:41:53 -0500232 canvas->translate(0.0f, (float) kEncodedHeight + 1);
233 }
234 }
235 }
236 canvas->restore();
237 canvas->translate((float) kEncodedWidth + 1, 0.0f);
238 }
Chris Dalton50e24d72019-02-07 16:20:09 -0700239 return DrawResult::kOk;
Matt Sarett34855f92017-01-10 17:41:53 -0500240 }
241
242private:
243 static const int kEncodedWidth = 8;
244 static const int kEncodedHeight = 8;
245
John Stiles7571f9e2020-09-02 22:42:33 -0400246 using INHERITED = skiagm::GM;
Matt Sarett34855f92017-01-10 17:41:53 -0500247};
248DEF_GM( return new ReadPixelsCodecGM; )
249
250class ReadPixelsPictureGM : public skiagm::GM {
251public:
252 ReadPixelsPictureGM() {}
253
254protected:
255 SkString onShortName() override {
256 return SkString("readpixelspicture");
257 }
258
259 SkISize onISize() override {
260 return SkISize::Make(3 * kWidth, 12 * kHeight);
261 }
262
Chris Dalton50e24d72019-02-07 16:20:09 -0700263 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
Matt Sarett34855f92017-01-10 17:41:53 -0500264 if (!canvas->imageInfo().colorSpace()) {
Chris Dalton50e24d72019-02-07 16:20:09 -0700265 *errorMsg = "This gm is only interesting in color correct modes.";
266 return DrawResult::kSkip;
Matt Sarett34855f92017-01-10 17:41:53 -0500267 }
268
269 const sk_sp<SkImage> images[] = {
Matt Sarett9df70bb2017-02-14 13:50:43 -0500270 make_picture_image(),
Matt Sarett34855f92017-01-10 17:41:53 -0500271 };
272 const SkAlphaType alphaTypes[] = {
273 kUnpremul_SkAlphaType,
274 kPremul_SkAlphaType,
275 };
276 const SkColorType colorTypes[] = {
277 kRGBA_8888_SkColorType,
278 kBGRA_8888_SkColorType,
279 kRGBA_F16_SkColorType,
280 };
281 const sk_sp<SkColorSpace> colorSpaces[] = {
282 make_wide_gamut(),
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500283 SkColorSpace::MakeSRGB(),
Matt Sarett34855f92017-01-10 17:41:53 -0500284 make_small_gamut(),
285 };
286 const SkImage::CachingHint hints[] = {
287 SkImage::kAllow_CachingHint,
288 SkImage::kDisallow_CachingHint,
289 };
290
John Stilesbd3ffa42020-07-30 20:24:57 -0400291 for (const sk_sp<SkImage>& image : images) {
292 for (const sk_sp<SkColorSpace>& dstColorSpace : colorSpaces) {
Matt Sarett34855f92017-01-10 17:41:53 -0500293 canvas->save();
294 for (SkColorType dstColorType : colorTypes) {
295 for (SkAlphaType dstAlphaType : alphaTypes) {
296 for (SkImage::CachingHint hint : hints) {
Adlai Hollerbcfc5542020-08-27 12:44:07 -0400297 draw_image(nullptr, canvas, image.get(), dstColorType, dstAlphaType,
Matt Sarett34855f92017-01-10 17:41:53 -0500298 dstColorSpace, hint);
299 canvas->translate(0.0f, (float) kHeight);
300 }
301 }
302 }
303 canvas->restore();
304 canvas->translate((float) kWidth, 0.0f);
305 }
306 }
Chris Dalton50e24d72019-02-07 16:20:09 -0700307 return DrawResult::kOk;
Matt Sarett34855f92017-01-10 17:41:53 -0500308 }
309
310private:
311
John Stiles7571f9e2020-09-02 22:42:33 -0400312 using INHERITED = skiagm::GM;
Matt Sarett34855f92017-01-10 17:41:53 -0500313};
314DEF_GM( return new ReadPixelsPictureGM; )