blob: 609586526304827683d32c1b7eae563a80997330 [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
33class GrContext;
34
Matt Sarett909d3792016-12-22 10:52:25 -050035static const int kWidth = 64;
36static const int kHeight = 64;
37
Brian Osmanb1168a72017-03-20 14:21:18 -040038static sk_sp<SkImage> make_raster_image(SkColorType colorType) {
Hal Canaryc465d132017-12-08 10:21:31 -050039 std::unique_ptr<SkStream> stream(GetResourceAsStream("images/google_chrome.ico"));
Mike Reedede7bac2017-07-23 15:30:02 -040040 std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
Hal Canarybaa2a282018-11-26 15:34:12 -050041 if (!codec) {
42 return nullptr;
43 }
Matt Sarett909d3792016-12-22 10:52:25 -050044
45 SkBitmap bitmap;
46 SkImageInfo info = codec->getInfo().makeWH(kWidth, kHeight)
47 .makeColorType(colorType)
Brian Osman6b622962018-08-27 19:16:02 +000048 .makeAlphaType(kPremul_SkAlphaType);
Matt Sarett909d3792016-12-22 10:52:25 -050049 bitmap.allocPixels(info);
50 codec->getPixels(info, bitmap.getPixels(), bitmap.rowBytes());
51 bitmap.setImmutable();
52 return SkImage::MakeFromBitmap(bitmap);
53}
54
Matt Sarett34855f92017-01-10 17:41:53 -050055static sk_sp<SkImage> make_codec_image() {
Hal Canaryc465d132017-12-08 10:21:31 -050056 sk_sp<SkData> encoded = GetResourceAsData("images/randPixels.png");
Matt Sarett34855f92017-01-10 17:41:53 -050057 return SkImage::MakeFromEncoded(encoded);
58}
59
60static void draw_contents(SkCanvas* canvas) {
61 SkPaint paint;
62 paint.setStyle(SkPaint::kStroke_Style);
63 paint.setStrokeWidth(20);
64 paint.setColor(0xFF800000);
65 canvas->drawCircle(40, 40, 35, paint);
66 paint.setColor(0xFF008000);
67 canvas->drawCircle(50, 50, 35, paint);
68 paint.setColor(0xFF000080);
69 canvas->drawCircle(60, 60, 35, paint);
70}
71
Matt Sarett9df70bb2017-02-14 13:50:43 -050072static sk_sp<SkImage> make_picture_image() {
Matt Sarett34855f92017-01-10 17:41:53 -050073 SkPictureRecorder recorder;
74 draw_contents(recorder.beginRecording(SkRect::MakeIWH(kWidth, kHeight)));
75 return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
76 SkISize::Make(kWidth, kHeight), nullptr, nullptr,
77 SkImage::BitDepth::kU8,
Matt Sarett77a7a1b2017-02-07 13:56:11 -050078 SkColorSpace::MakeSRGB());
Matt Sarett34855f92017-01-10 17:41:53 -050079}
80
Matt Sarett733340a2017-05-02 16:19:51 -040081static sk_sp<SkColorSpace> make_parametric_transfer_fn(const SkColorSpacePrimaries& primaries) {
Brian Osman82ebe042019-01-04 17:03:00 -050082 skcms_Matrix3x3 toXYZD50;
Matt Sarett909d3792016-12-22 10:52:25 -050083 SkAssertResult(primaries.toXYZD50(&toXYZD50));
Brian Osman82ebe042019-01-04 17:03:00 -050084 skcms_TransferFunction fn = { 1.8f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f };
Matt Sarett733340a2017-05-02 16:19:51 -040085 return SkColorSpace::MakeRGB(fn, toXYZD50);
Matt Sarett909d3792016-12-22 10:52:25 -050086}
87
88static sk_sp<SkColorSpace> make_wide_gamut() {
89 // ProPhoto
90 SkColorSpacePrimaries primaries;
91 primaries.fRX = 0.7347f;
92 primaries.fRY = 0.2653f;
93 primaries.fGX = 0.1596f;
94 primaries.fGY = 0.8404f;
95 primaries.fBX = 0.0366f;
96 primaries.fBY = 0.0001f;
97 primaries.fWX = 0.34567f;
98 primaries.fWY = 0.35850f;
Matt Sarett733340a2017-05-02 16:19:51 -040099 return make_parametric_transfer_fn(primaries);
Matt Sarett909d3792016-12-22 10:52:25 -0500100}
101
102static sk_sp<SkColorSpace> make_small_gamut() {
103 SkColorSpacePrimaries primaries;
104 primaries.fRX = 0.50f;
105 primaries.fRY = 0.33f;
106 primaries.fGX = 0.30f;
107 primaries.fGY = 0.50f;
108 primaries.fBX = 0.25f;
109 primaries.fBY = 0.16f;
110 primaries.fWX = 0.3127f;
111 primaries.fWY = 0.3290f;
Matt Sarett733340a2017-05-02 16:19:51 -0400112 return make_parametric_transfer_fn(primaries);
Matt Sarett909d3792016-12-22 10:52:25 -0500113}
114
115static void draw_image(SkCanvas* canvas, SkImage* image, SkColorType dstColorType,
Matt Sarett34855f92017-01-10 17:41:53 -0500116 SkAlphaType dstAlphaType, sk_sp<SkColorSpace> dstColorSpace,
117 SkImage::CachingHint hint) {
Matt Sarett909d3792016-12-22 10:52:25 -0500118 size_t rowBytes = image->width() * SkColorTypeBytesPerPixel(dstColorType);
119 sk_sp<SkData> data = SkData::MakeUninitialized(rowBytes * image->height());
Matt Sarett909d3792016-12-22 10:52:25 -0500120 SkImageInfo dstInfo = SkImageInfo::Make(image->width(), image->height(), dstColorType,
121 dstAlphaType, dstColorSpace);
Brian Osman89150582017-03-20 16:54:28 -0400122 if (!image->readPixels(dstInfo, data->writable_data(), rowBytes, 0, 0, hint)) {
123 memset(data->writable_data(), 0, rowBytes * image->height());
124 }
Matt Sarett909d3792016-12-22 10:52:25 -0500125
Matt Sarett909d3792016-12-22 10:52:25 -0500126 // Now that we have called readPixels(), dump the raw pixels into an srgb image.
Brian Osman6b622962018-08-27 19:16:02 +0000127 sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
Matt Sarett909d3792016-12-22 10:52:25 -0500128 sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes);
129 canvas->drawImage(raw.get(), 0.0f, 0.0f, nullptr);
130}
131
132class ReadPixelsGM : public skiagm::GM {
133public:
134 ReadPixelsGM() {}
135
136protected:
137 SkString onShortName() override {
138 return SkString("readpixels");
139 }
140
141 SkISize onISize() override {
Brian Osmanb1168a72017-03-20 14:21:18 -0400142 return SkISize::Make(6 * kWidth, 9 * kHeight);
Matt Sarett909d3792016-12-22 10:52:25 -0500143 }
144
145 void onDraw(SkCanvas* canvas) override {
Matt Sarett909d3792016-12-22 10:52:25 -0500146 const SkAlphaType alphaTypes[] = {
147 kUnpremul_SkAlphaType,
148 kPremul_SkAlphaType,
149 };
150 const SkColorType colorTypes[] = {
151 kRGBA_8888_SkColorType,
152 kBGRA_8888_SkColorType,
153 kRGBA_F16_SkColorType,
154 };
155 const sk_sp<SkColorSpace> colorSpaces[] = {
156 make_wide_gamut(),
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500157 SkColorSpace::MakeSRGB(),
Matt Sarett909d3792016-12-22 10:52:25 -0500158 make_small_gamut(),
159 };
160
John Stilesbd3ffa42020-07-30 20:24:57 -0400161 for (const sk_sp<SkColorSpace>& dstColorSpace : colorSpaces) {
Matt Sarett909d3792016-12-22 10:52:25 -0500162 for (SkColorType srcColorType : colorTypes) {
Brian Osmanb1168a72017-03-20 14:21:18 -0400163 canvas->save();
164 sk_sp<SkImage> image = make_raster_image(srcColorType);
Hal Canarybaa2a282018-11-26 15:34:12 -0500165 if (!image) {
166 continue;
167 }
Adlai Holler4caa9352020-07-16 10:58:58 -0400168 if (auto direct = GrAsDirectContext(canvas->recordingContext())) {
169 image = image->makeTextureImage(direct);
Brian Osman89150582017-03-20 16:54:28 -0400170 }
171 if (image) {
172 for (SkColorType dstColorType : colorTypes) {
173 for (SkAlphaType dstAlphaType : alphaTypes) {
174 draw_image(canvas, image.get(), dstColorType, dstAlphaType,
175 dstColorSpace, SkImage::kAllow_CachingHint);
176 canvas->translate((float)kWidth, 0.0f);
177 }
Matt Sarett909d3792016-12-22 10:52:25 -0500178 }
Matt Sarett909d3792016-12-22 10:52:25 -0500179 }
Brian Osmanb1168a72017-03-20 14:21:18 -0400180 canvas->restore();
181 canvas->translate(0.0f, (float) kHeight);
Matt Sarett909d3792016-12-22 10:52:25 -0500182 }
183 }
184 }
185
186private:
187 typedef skiagm::GM INHERITED;
188};
189DEF_GM( return new ReadPixelsGM; )
Matt Sarett34855f92017-01-10 17:41:53 -0500190
191class ReadPixelsCodecGM : public skiagm::GM {
192public:
193 ReadPixelsCodecGM() {}
194
195protected:
196 SkString onShortName() override {
197 return SkString("readpixelscodec");
198 }
199
200 SkISize onISize() override {
201 return SkISize::Make(3 * (kEncodedWidth + 1), 12 * (kEncodedHeight + 1));
202 }
203
Chris Dalton50e24d72019-02-07 16:20:09 -0700204 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
Matt Sarett34855f92017-01-10 17:41:53 -0500205 if (!canvas->imageInfo().colorSpace()) {
Chris Dalton50e24d72019-02-07 16:20:09 -0700206 *errorMsg = "This gm is only interesting in color correct modes.";
207 return DrawResult::kSkip;
Matt Sarett34855f92017-01-10 17:41:53 -0500208 }
209
210 const SkAlphaType alphaTypes[] = {
211 kUnpremul_SkAlphaType,
212 kPremul_SkAlphaType,
213 };
214 const SkColorType colorTypes[] = {
215 kRGBA_8888_SkColorType,
216 kBGRA_8888_SkColorType,
217 kRGBA_F16_SkColorType,
218 };
219 const sk_sp<SkColorSpace> colorSpaces[] = {
220 make_wide_gamut(),
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500221 SkColorSpace::MakeSRGB(),
Matt Sarett34855f92017-01-10 17:41:53 -0500222 make_small_gamut(),
223 };
224 const SkImage::CachingHint hints[] = {
225 SkImage::kAllow_CachingHint,
226 SkImage::kDisallow_CachingHint,
227 };
228
229 sk_sp<SkImage> image = make_codec_image();
John Stilesbd3ffa42020-07-30 20:24:57 -0400230 for (const sk_sp<SkColorSpace>& dstColorSpace : colorSpaces) {
Matt Sarett34855f92017-01-10 17:41:53 -0500231 canvas->save();
232 for (SkColorType dstColorType : colorTypes) {
233 for (SkAlphaType dstAlphaType : alphaTypes) {
234 for (SkImage::CachingHint hint : hints) {
235 draw_image(canvas, image.get(), dstColorType, dstAlphaType, dstColorSpace,
236 hint);
237 canvas->translate(0.0f, (float) kEncodedHeight + 1);
238 }
239 }
240 }
241 canvas->restore();
242 canvas->translate((float) kEncodedWidth + 1, 0.0f);
243 }
Chris Dalton50e24d72019-02-07 16:20:09 -0700244 return DrawResult::kOk;
Matt Sarett34855f92017-01-10 17:41:53 -0500245 }
246
247private:
248 static const int kEncodedWidth = 8;
249 static const int kEncodedHeight = 8;
250
251 typedef skiagm::GM INHERITED;
252};
253DEF_GM( return new ReadPixelsCodecGM; )
254
255class ReadPixelsPictureGM : public skiagm::GM {
256public:
257 ReadPixelsPictureGM() {}
258
259protected:
260 SkString onShortName() override {
261 return SkString("readpixelspicture");
262 }
263
264 SkISize onISize() override {
265 return SkISize::Make(3 * kWidth, 12 * kHeight);
266 }
267
Chris Dalton50e24d72019-02-07 16:20:09 -0700268 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
Matt Sarett34855f92017-01-10 17:41:53 -0500269 if (!canvas->imageInfo().colorSpace()) {
Chris Dalton50e24d72019-02-07 16:20:09 -0700270 *errorMsg = "This gm is only interesting in color correct modes.";
271 return DrawResult::kSkip;
Matt Sarett34855f92017-01-10 17:41:53 -0500272 }
273
274 const sk_sp<SkImage> images[] = {
Matt Sarett9df70bb2017-02-14 13:50:43 -0500275 make_picture_image(),
Matt Sarett34855f92017-01-10 17:41:53 -0500276 };
277 const SkAlphaType alphaTypes[] = {
278 kUnpremul_SkAlphaType,
279 kPremul_SkAlphaType,
280 };
281 const SkColorType colorTypes[] = {
282 kRGBA_8888_SkColorType,
283 kBGRA_8888_SkColorType,
284 kRGBA_F16_SkColorType,
285 };
286 const sk_sp<SkColorSpace> colorSpaces[] = {
287 make_wide_gamut(),
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500288 SkColorSpace::MakeSRGB(),
Matt Sarett34855f92017-01-10 17:41:53 -0500289 make_small_gamut(),
290 };
291 const SkImage::CachingHint hints[] = {
292 SkImage::kAllow_CachingHint,
293 SkImage::kDisallow_CachingHint,
294 };
295
John Stilesbd3ffa42020-07-30 20:24:57 -0400296 for (const sk_sp<SkImage>& image : images) {
297 for (const sk_sp<SkColorSpace>& dstColorSpace : colorSpaces) {
Matt Sarett34855f92017-01-10 17:41:53 -0500298 canvas->save();
299 for (SkColorType dstColorType : colorTypes) {
300 for (SkAlphaType dstAlphaType : alphaTypes) {
301 for (SkImage::CachingHint hint : hints) {
302 draw_image(canvas, image.get(), dstColorType, dstAlphaType,
303 dstColorSpace, hint);
304 canvas->translate(0.0f, (float) kHeight);
305 }
306 }
307 }
308 canvas->restore();
309 canvas->translate((float) kWidth, 0.0f);
310 }
311 }
Chris Dalton50e24d72019-02-07 16:20:09 -0700312 return DrawResult::kOk;
Matt Sarett34855f92017-01-10 17:41:53 -0500313 }
314
315private:
316
317 typedef skiagm::GM INHERITED;
318};
319DEF_GM( return new ReadPixelsPictureGM; )