• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "gm/gm.h"
9 #include "include/codec/SkCodec.h"
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkColorSpace.h"
13 #include "include/core/SkData.h"
14 #include "include/core/SkImage.h"
15 #include "include/core/SkImageInfo.h"
16 #include "include/core/SkPaint.h"
17 #include "include/core/SkPicture.h"
18 #include "include/core/SkPictureRecorder.h"
19 #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"
25 #include "include/gpu/GrDirectContext.h"
26 #include "include/third_party/skcms/skcms.h"
27 #include "tools/Resources.h"
28 
29 #include <string.h>
30 #include <memory>
31 #include <utility>
32 
33 static const int kWidth = 64;
34 static const int kHeight = 64;
35 
make_raster_image(SkColorType colorType)36 static sk_sp<SkImage> make_raster_image(SkColorType colorType) {
37     std::unique_ptr<SkStream> stream(GetResourceAsStream("images/google_chrome.ico"));
38     std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
39     if (!codec) {
40         return nullptr;
41     }
42 
43     SkImageInfo info = codec->getInfo().makeWH(kWidth, kHeight)
44                                        .makeColorType(colorType)
45                                        .makeAlphaType(kPremul_SkAlphaType);
46     return std::get<0>(codec->getImage(info));
47 }
48 
make_codec_image()49 static sk_sp<SkImage> make_codec_image() {
50     sk_sp<SkData> encoded = GetResourceAsData("images/randPixels.png");
51     return SkImage::MakeFromEncoded(encoded);
52 }
53 
draw_contents(SkCanvas * canvas)54 static 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 
make_picture_image()66 static sk_sp<SkImage> make_picture_image() {
67     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,
72                                     SkColorSpace::MakeSRGB());
73 }
74 
make_parametric_transfer_fn(const SkColorSpacePrimaries & primaries)75 static sk_sp<SkColorSpace> make_parametric_transfer_fn(const SkColorSpacePrimaries& primaries) {
76     skcms_Matrix3x3 toXYZD50;
77     SkAssertResult(primaries.toXYZD50(&toXYZD50));
78     skcms_TransferFunction fn = { 1.8f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f };
79     return SkColorSpace::MakeRGB(fn, toXYZD50);
80 }
81 
make_wide_gamut()82 static 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;
93     return make_parametric_transfer_fn(primaries);
94 }
95 
make_small_gamut()96 static 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;
106     return make_parametric_transfer_fn(primaries);
107 }
108 
draw_image(GrDirectContext * dContext,SkCanvas * canvas,SkImage * image,SkColorType dstColorType,SkAlphaType dstAlphaType,sk_sp<SkColorSpace> dstColorSpace,SkImage::CachingHint hint)109 static void draw_image(GrDirectContext* dContext, SkCanvas* canvas, SkImage* image,
110                        SkColorType dstColorType, SkAlphaType dstAlphaType,
111                        sk_sp<SkColorSpace> dstColorSpace, SkImage::CachingHint hint) {
112     size_t rowBytes = image->width() * SkColorTypeBytesPerPixel(dstColorType);
113     sk_sp<SkData> data = SkData::MakeUninitialized(rowBytes * image->height());
114     SkImageInfo dstInfo = SkImageInfo::Make(image->width(), image->height(), dstColorType,
115                                             dstAlphaType, dstColorSpace);
116     if (!image->readPixels(dContext, dstInfo, data->writable_data(), rowBytes, 0, 0, hint)) {
117         memset(data->writable_data(), 0, rowBytes * image->height());
118     }
119 
120     // Now that we have called readPixels(), dump the raw pixels into an srgb image.
121     sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
122     sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes);
123     canvas->drawImage(raw.get(), 0.0f, 0.0f);
124 }
125 
126 class ReadPixelsGM : public skiagm::GM {
127 public:
ReadPixelsGM()128     ReadPixelsGM() {}
129 
130 protected:
onShortName()131     SkString onShortName() override {
132         return SkString("readpixels");
133     }
134 
onISize()135     SkISize onISize() override {
136         return SkISize::Make(6 * kWidth, 9 * kHeight);
137     }
138 
onDraw(SkCanvas * canvas)139     void onDraw(SkCanvas* canvas) override {
140         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(),
151                 SkColorSpace::MakeSRGB(),
152                 make_small_gamut(),
153         };
154 
155         for (const sk_sp<SkColorSpace>& dstColorSpace : colorSpaces) {
156             for (SkColorType srcColorType : colorTypes) {
157                 canvas->save();
158                 sk_sp<SkImage> image = make_raster_image(srcColorType);
159                 if (!image) {
160                     continue;
161                 }
162                 auto dContext = GrAsDirectContext(canvas->recordingContext());
163                 if (dContext) {
164                     image = image->makeTextureImage(dContext);
165                 }
166                 if (image) {
167                     for (SkColorType dstColorType : colorTypes) {
168                         for (SkAlphaType dstAlphaType : alphaTypes) {
169                             draw_image(dContext, canvas, image.get(), dstColorType, dstAlphaType,
170                                        dstColorSpace, SkImage::kAllow_CachingHint);
171                             canvas->translate((float)kWidth, 0.0f);
172                         }
173                     }
174                 }
175                 canvas->restore();
176                 canvas->translate(0.0f, (float) kHeight);
177             }
178         }
179     }
180 
181 private:
182     using INHERITED = skiagm::GM;
183 };
184 DEF_GM( return new ReadPixelsGM; )
185 
186 class ReadPixelsCodecGM : public skiagm::GM {
187 public:
ReadPixelsCodecGM()188     ReadPixelsCodecGM() {}
189 
190 protected:
onShortName()191     SkString onShortName() override {
192         return SkString("readpixelscodec");
193     }
194 
onISize()195     SkISize onISize() override {
196         return SkISize::Make(3 * (kEncodedWidth + 1), 12 * (kEncodedHeight + 1));
197     }
198 
onDraw(SkCanvas * canvas,SkString * errorMsg)199     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
200         if (!canvas->imageInfo().colorSpace()) {
201             *errorMsg = "This gm is only interesting in color correct modes.";
202             return DrawResult::kSkip;
203         }
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(),
216                 SkColorSpace::MakeSRGB(),
217                 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();
225         for (const sk_sp<SkColorSpace>& dstColorSpace : colorSpaces) {
226             canvas->save();
227             for (SkColorType dstColorType : colorTypes) {
228                 for (SkAlphaType dstAlphaType : alphaTypes) {
229                     for (SkImage::CachingHint hint : hints) {
230                         draw_image(nullptr, canvas, image.get(), dstColorType, dstAlphaType,
231                                    dstColorSpace, hint);
232                         canvas->translate(0.0f, (float) kEncodedHeight + 1);
233                     }
234                 }
235             }
236             canvas->restore();
237             canvas->translate((float) kEncodedWidth + 1, 0.0f);
238         }
239         return DrawResult::kOk;
240     }
241 
242 private:
243     static const int kEncodedWidth = 8;
244     static const int kEncodedHeight = 8;
245 
246     using INHERITED = skiagm::GM;
247 };
248 DEF_GM( return new ReadPixelsCodecGM; )
249 
250 class ReadPixelsPictureGM : public skiagm::GM {
251 public:
ReadPixelsPictureGM()252     ReadPixelsPictureGM() {}
253 
254 protected:
onShortName()255     SkString onShortName() override {
256         return SkString("readpixelspicture");
257     }
258 
onISize()259     SkISize onISize() override {
260         return SkISize::Make(3 * kWidth, 12 * kHeight);
261     }
262 
onDraw(SkCanvas * canvas,SkString * errorMsg)263     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
264         if (!canvas->imageInfo().colorSpace()) {
265             *errorMsg = "This gm is only interesting in color correct modes.";
266             return DrawResult::kSkip;
267         }
268 
269         const sk_sp<SkImage> images[] = {
270                 make_picture_image(),
271         };
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(),
283                 SkColorSpace::MakeSRGB(),
284                 make_small_gamut(),
285         };
286         const SkImage::CachingHint hints[] = {
287                 SkImage::kAllow_CachingHint,
288                 SkImage::kDisallow_CachingHint,
289         };
290 
291         for (const sk_sp<SkImage>& image : images) {
292             for (const sk_sp<SkColorSpace>& dstColorSpace : colorSpaces) {
293                 canvas->save();
294                 for (SkColorType dstColorType : colorTypes) {
295                     for (SkAlphaType dstAlphaType : alphaTypes) {
296                         for (SkImage::CachingHint hint : hints) {
297                             draw_image(nullptr, canvas, image.get(), dstColorType, dstAlphaType,
298                                        dstColorSpace, hint);
299                             canvas->translate(0.0f, (float) kHeight);
300                         }
301                     }
302                 }
303                 canvas->restore();
304                 canvas->translate((float) kWidth, 0.0f);
305             }
306         }
307         return DrawResult::kOk;
308     }
309 
310 private:
311 
312     using INHERITED = skiagm::GM;
313 };
314 DEF_GM( return new ReadPixelsPictureGM; )
315