1909d3791f53eae590314992aad82c71fb45e9164Matt Sarett/*
2909d3791f53eae590314992aad82c71fb45e9164Matt Sarett * Copyright 2016 Google Inc.
3909d3791f53eae590314992aad82c71fb45e9164Matt Sarett *
4909d3791f53eae590314992aad82c71fb45e9164Matt Sarett * Use of this source code is governed by a BSD-style license that can be
5909d3791f53eae590314992aad82c71fb45e9164Matt Sarett * found in the LICENSE file.
6909d3791f53eae590314992aad82c71fb45e9164Matt Sarett */
7909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
8909d3791f53eae590314992aad82c71fb45e9164Matt Sarett#include "gm.h"
9909d3791f53eae590314992aad82c71fb45e9164Matt Sarett#include "Resources.h"
10909d3791f53eae590314992aad82c71fb45e9164Matt Sarett#include "SkCodec.h"
11909d3791f53eae590314992aad82c71fb45e9164Matt Sarett#include "SkColorSpace.h"
12b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman#include "SkColorSpaceXform.h"
13b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman#include "SkColorSpaceXformPriv.h"
14909d3791f53eae590314992aad82c71fb45e9164Matt Sarett#include "SkHalf.h"
15909d3791f53eae590314992aad82c71fb45e9164Matt Sarett#include "SkImage.h"
167fcfb621998648ba018e3b89e2cab3135bd46a1fMike Reed#include "SkImageInfoPriv.h"
1734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett#include "SkPictureRecorder.h"
18909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
19909d3791f53eae590314992aad82c71fb45e9164Matt Sarettstatic void clamp_if_necessary(const SkImageInfo& info, void* pixels) {
20909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    if (kRGBA_F16_SkColorType != info.colorType()) {
21909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        return;
22909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    }
23909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
24909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    for (int y = 0; y < info.height(); y++) {
25909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        for (int x = 0; x < info.width(); x++) {
26909d3791f53eae590314992aad82c71fb45e9164Matt Sarett            uint64_t pixel = ((uint64_t*) pixels)[y * info.width() + x];
27909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
28909d3791f53eae590314992aad82c71fb45e9164Matt Sarett            Sk4f rgba = SkHalfToFloat_finite_ftz(pixel);
29909d3791f53eae590314992aad82c71fb45e9164Matt Sarett            if (kUnpremul_SkAlphaType == info.alphaType()) {
30909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                rgba = Sk4f::Max(0.0f, Sk4f::Min(rgba, 1.0f));
31909d3791f53eae590314992aad82c71fb45e9164Matt Sarett            } else {
32909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                SkASSERT(kPremul_SkAlphaType == info.alphaType());
33909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                rgba = Sk4f::Max(0.0f, Sk4f::Min(rgba, rgba[3]));
34909d3791f53eae590314992aad82c71fb45e9164Matt Sarett            }
35909d3791f53eae590314992aad82c71fb45e9164Matt Sarett            SkFloatToHalf_finite_ftz(rgba).store(&pixel);
36909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
37909d3791f53eae590314992aad82c71fb45e9164Matt Sarett            ((uint64_t*) pixels)[y * info.width() + x] = pixel;
38909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        }
39909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    }
40909d3791f53eae590314992aad82c71fb45e9164Matt Sarett}
41909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
42909d3791f53eae590314992aad82c71fb45e9164Matt Sarettsk_sp<SkColorSpace> fix_for_colortype(SkColorSpace* colorSpace, SkColorType colorType) {
43909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    if (kRGBA_F16_SkColorType == colorType) {
4436703d9d368050a20764b5336534bd718fd00a6eBrian Osman        return colorSpace->makeLinearGamma();
45909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    }
46909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
47909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    return sk_ref_sp(colorSpace);
48909d3791f53eae590314992aad82c71fb45e9164Matt Sarett}
49909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
50909d3791f53eae590314992aad82c71fb45e9164Matt Sarettstatic const int kWidth = 64;
51909d3791f53eae590314992aad82c71fb45e9164Matt Sarettstatic const int kHeight = 64;
52909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
53b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osmanstatic sk_sp<SkImage> make_raster_image(SkColorType colorType) {
54c465d13e6fca5e171bde45d35b2dd43117f4702eHal Canary    std::unique_ptr<SkStream> stream(GetResourceAsStream("images/google_chrome.ico"));
55ede7bac43fbc69b9fdf1c178890ba6353f5bb140Mike Reed    std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
56909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
57909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    SkBitmap bitmap;
58909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    SkImageInfo info = codec->getInfo().makeWH(kWidth, kHeight)
59909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                                       .makeColorType(colorType)
60b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman                                       .makeAlphaType(kPremul_SkAlphaType)
61909d3791f53eae590314992aad82c71fb45e9164Matt Sarett            .makeColorSpace(fix_for_colortype(codec->getInfo().colorSpace(), colorType));
62909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    bitmap.allocPixels(info);
63909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    codec->getPixels(info, bitmap.getPixels(), bitmap.rowBytes());
64909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    bitmap.setImmutable();
65909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    return SkImage::MakeFromBitmap(bitmap);
66909d3791f53eae590314992aad82c71fb45e9164Matt Sarett}
67909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
6834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarettstatic sk_sp<SkImage> make_codec_image() {
69c465d13e6fca5e171bde45d35b2dd43117f4702eHal Canary    sk_sp<SkData> encoded = GetResourceAsData("images/randPixels.png");
7034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    return SkImage::MakeFromEncoded(encoded);
7134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett}
7234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
7334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarettstatic void draw_contents(SkCanvas* canvas) {
7434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    SkPaint paint;
7534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    paint.setStyle(SkPaint::kStroke_Style);
7634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    paint.setStrokeWidth(20);
7734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    paint.setColor(0xFF800000);
7834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    canvas->drawCircle(40, 40, 35, paint);
7934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    paint.setColor(0xFF008000);
8034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    canvas->drawCircle(50, 50, 35, paint);
8134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    paint.setColor(0xFF000080);
8234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    canvas->drawCircle(60, 60, 35, paint);
8334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett}
8434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
859df70bb74db8294283e8d2d8e20c95d290d2a34dMatt Sarettstatic sk_sp<SkImage> make_picture_image() {
8634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    SkPictureRecorder recorder;
8734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    draw_contents(recorder.beginRecording(SkRect::MakeIWH(kWidth, kHeight)));
8834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
8934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                                    SkISize::Make(kWidth, kHeight), nullptr, nullptr,
9034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                                    SkImage::BitDepth::kU8,
9177a7a1b57c16c97f056c1e50c03bdc954947778cMatt Sarett                                    SkColorSpace::MakeSRGB());
9234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett}
9334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
94733340a6997762dc2fe5048cfe5af33bf8293d93Matt Sarettstatic sk_sp<SkColorSpace> make_parametric_transfer_fn(const SkColorSpacePrimaries& primaries) {
95578f52c6cf6372b88a88a05dee0efc5b67aa9a9cMatt Sarett    SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
96909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    SkAssertResult(primaries.toXYZD50(&toXYZD50));
97733340a6997762dc2fe5048cfe5af33bf8293d93Matt Sarett    SkColorSpaceTransferFn fn;
98733340a6997762dc2fe5048cfe5af33bf8293d93Matt Sarett    fn.fA = 1.f; fn.fB = 0.f; fn.fC = 0.f; fn.fD = 0.f; fn.fE = 0.f; fn.fF = 0.f; fn.fG = 1.8f;
99733340a6997762dc2fe5048cfe5af33bf8293d93Matt Sarett    return SkColorSpace::MakeRGB(fn, toXYZD50);
100909d3791f53eae590314992aad82c71fb45e9164Matt Sarett}
101909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
102909d3791f53eae590314992aad82c71fb45e9164Matt Sarettstatic sk_sp<SkColorSpace> make_wide_gamut() {
103909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    // ProPhoto
104909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    SkColorSpacePrimaries primaries;
105909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fRX = 0.7347f;
106909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fRY = 0.2653f;
107909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fGX = 0.1596f;
108909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fGY = 0.8404f;
109909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fBX = 0.0366f;
110909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fBY = 0.0001f;
111909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fWX = 0.34567f;
112909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fWY = 0.35850f;
113733340a6997762dc2fe5048cfe5af33bf8293d93Matt Sarett    return make_parametric_transfer_fn(primaries);
114909d3791f53eae590314992aad82c71fb45e9164Matt Sarett}
115909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
116909d3791f53eae590314992aad82c71fb45e9164Matt Sarettstatic sk_sp<SkColorSpace> make_small_gamut() {
117909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    SkColorSpacePrimaries primaries;
118909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fRX = 0.50f;
119909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fRY = 0.33f;
120909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fGX = 0.30f;
121909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fGY = 0.50f;
122909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fBX = 0.25f;
123909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fBY = 0.16f;
124909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fWX = 0.3127f;
125909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    primaries.fWY = 0.3290f;
126733340a6997762dc2fe5048cfe5af33bf8293d93Matt Sarett    return make_parametric_transfer_fn(primaries);
127909d3791f53eae590314992aad82c71fb45e9164Matt Sarett}
128909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
129909d3791f53eae590314992aad82c71fb45e9164Matt Sarettstatic void draw_image(SkCanvas* canvas, SkImage* image, SkColorType dstColorType,
13034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                       SkAlphaType dstAlphaType, sk_sp<SkColorSpace> dstColorSpace,
13134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                       SkImage::CachingHint hint) {
132909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    size_t rowBytes = image->width() * SkColorTypeBytesPerPixel(dstColorType);
133909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    sk_sp<SkData> data = SkData::MakeUninitialized(rowBytes * image->height());
134909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    dstColorSpace = fix_for_colortype(dstColorSpace.get(), dstColorType);
135909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    SkImageInfo dstInfo = SkImageInfo::Make(image->width(), image->height(), dstColorType,
136909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                                            dstAlphaType, dstColorSpace);
13789150582643f1ef4893a0cdeaadf5886e5cde76dBrian Osman    if (!image->readPixels(dstInfo, data->writable_data(), rowBytes, 0, 0, hint)) {
13889150582643f1ef4893a0cdeaadf5886e5cde76dBrian Osman        memset(data->writable_data(), 0, rowBytes * image->height());
13989150582643f1ef4893a0cdeaadf5886e5cde76dBrian Osman    }
140909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
141b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman    // SkImage must be premul, so manually premul the data if we unpremul'd during readPixels
142b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman    if (kUnpremul_SkAlphaType == dstAlphaType) {
143b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman        auto xform = SkColorSpaceXform::New(dstColorSpace.get(), dstColorSpace.get());
144b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman        if (!xform->apply(select_xform_format(dstColorType), data->writable_data(),
145b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman                          select_xform_format(dstColorType), data->data(),
146b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman                          image->width() * image->height(), kPremul_SkAlphaType)) {
147b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman            memset(data->writable_data(), 0, rowBytes * image->height());
148b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman        }
149b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman        dstInfo = dstInfo.makeAlphaType(kPremul_SkAlphaType);
150b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman    }
151b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman
152909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    // readPixels() does not always clamp F16.  The drawing code expects pixels in the 0-1 range.
153909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    clamp_if_necessary(dstInfo, data->writable_data());
154909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
155909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    // Now that we have called readPixels(), dump the raw pixels into an srgb image.
156909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    sk_sp<SkColorSpace> srgb = fix_for_colortype(
15777a7a1b57c16c97f056c1e50c03bdc954947778cMatt Sarett            SkColorSpace::MakeSRGB().get(), dstColorType);
158909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes);
159909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    canvas->drawImage(raw.get(), 0.0f, 0.0f, nullptr);
160909d3791f53eae590314992aad82c71fb45e9164Matt Sarett}
161909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
162909d3791f53eae590314992aad82c71fb45e9164Matt Sarettclass ReadPixelsGM : public skiagm::GM {
163909d3791f53eae590314992aad82c71fb45e9164Matt Sarettpublic:
164909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    ReadPixelsGM() {}
165909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
166909d3791f53eae590314992aad82c71fb45e9164Matt Sarettprotected:
167909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    SkString onShortName() override {
168909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        return SkString("readpixels");
169909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    }
170909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
171909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    SkISize onISize() override {
172b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman        return SkISize::Make(6 * kWidth, 9 * kHeight);
173909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    }
174909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
175909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    void onDraw(SkCanvas* canvas) override {
176909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        if (!canvas->imageInfo().colorSpace()) {
177909d3791f53eae590314992aad82c71fb45e9164Matt Sarett            // This gm is only interesting in color correct modes.
178909d3791f53eae590314992aad82c71fb45e9164Matt Sarett            return;
179909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        }
180909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
181909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        const SkAlphaType alphaTypes[] = {
182909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                kUnpremul_SkAlphaType,
183909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                kPremul_SkAlphaType,
184909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        };
185909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        const SkColorType colorTypes[] = {
186909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                kRGBA_8888_SkColorType,
187909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                kBGRA_8888_SkColorType,
188909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                kRGBA_F16_SkColorType,
189909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        };
190909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        const sk_sp<SkColorSpace> colorSpaces[] = {
191909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                make_wide_gamut(),
19277a7a1b57c16c97f056c1e50c03bdc954947778cMatt Sarett                SkColorSpace::MakeSRGB(),
193909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                make_small_gamut(),
194909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        };
195909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
196909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
197909d3791f53eae590314992aad82c71fb45e9164Matt Sarett            for (SkColorType srcColorType : colorTypes) {
198b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman                canvas->save();
199b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman                sk_sp<SkImage> image = make_raster_image(srcColorType);
20089150582643f1ef4893a0cdeaadf5886e5cde76dBrian Osman                if (GrContext* context = canvas->getGrContext()) {
20189150582643f1ef4893a0cdeaadf5886e5cde76dBrian Osman                    image = image->makeTextureImage(context, canvas->imageInfo().colorSpace());
20289150582643f1ef4893a0cdeaadf5886e5cde76dBrian Osman                }
20389150582643f1ef4893a0cdeaadf5886e5cde76dBrian Osman                if (image) {
20489150582643f1ef4893a0cdeaadf5886e5cde76dBrian Osman                    for (SkColorType dstColorType : colorTypes) {
20589150582643f1ef4893a0cdeaadf5886e5cde76dBrian Osman                        for (SkAlphaType dstAlphaType : alphaTypes) {
20689150582643f1ef4893a0cdeaadf5886e5cde76dBrian Osman                            draw_image(canvas, image.get(), dstColorType, dstAlphaType,
20789150582643f1ef4893a0cdeaadf5886e5cde76dBrian Osman                                       dstColorSpace, SkImage::kAllow_CachingHint);
20889150582643f1ef4893a0cdeaadf5886e5cde76dBrian Osman                            canvas->translate((float)kWidth, 0.0f);
20989150582643f1ef4893a0cdeaadf5886e5cde76dBrian Osman                        }
210909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                    }
211909d3791f53eae590314992aad82c71fb45e9164Matt Sarett                }
212b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman                canvas->restore();
213b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman                canvas->translate(0.0f, (float) kHeight);
214909d3791f53eae590314992aad82c71fb45e9164Matt Sarett            }
215909d3791f53eae590314992aad82c71fb45e9164Matt Sarett        }
216909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    }
217909d3791f53eae590314992aad82c71fb45e9164Matt Sarett
218909d3791f53eae590314992aad82c71fb45e9164Matt Sarettprivate:
219909d3791f53eae590314992aad82c71fb45e9164Matt Sarett    typedef skiagm::GM INHERITED;
220909d3791f53eae590314992aad82c71fb45e9164Matt Sarett};
221909d3791f53eae590314992aad82c71fb45e9164Matt SarettDEF_GM( return new ReadPixelsGM; )
22234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
22334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarettclass ReadPixelsCodecGM : public skiagm::GM {
22434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarettpublic:
22534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    ReadPixelsCodecGM() {}
22634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
22734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarettprotected:
22834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    SkString onShortName() override {
22934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        return SkString("readpixelscodec");
23034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    }
23134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
23234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    SkISize onISize() override {
23334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        return SkISize::Make(3 * (kEncodedWidth + 1), 12 * (kEncodedHeight + 1));
23434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    }
23534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
23634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    void onDraw(SkCanvas* canvas) override {
23734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        if (!canvas->imageInfo().colorSpace()) {
23834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett            // This gm is only interesting in color correct modes.
23934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett            return;
24034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        }
24134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
24234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        const SkAlphaType alphaTypes[] = {
24334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                kUnpremul_SkAlphaType,
24434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                kPremul_SkAlphaType,
24534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        };
24634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        const SkColorType colorTypes[] = {
24734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                kRGBA_8888_SkColorType,
24834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                kBGRA_8888_SkColorType,
24934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                kRGBA_F16_SkColorType,
25034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        };
25134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        const sk_sp<SkColorSpace> colorSpaces[] = {
25234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                make_wide_gamut(),
25377a7a1b57c16c97f056c1e50c03bdc954947778cMatt Sarett                SkColorSpace::MakeSRGB(),
25434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                make_small_gamut(),
25534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        };
25634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        const SkImage::CachingHint hints[] = {
25734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                SkImage::kAllow_CachingHint,
25834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                SkImage::kDisallow_CachingHint,
25934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        };
26034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
26134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        sk_sp<SkImage> image = make_codec_image();
26234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
26334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett            canvas->save();
26434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett            for (SkColorType dstColorType : colorTypes) {
26534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                for (SkAlphaType dstAlphaType : alphaTypes) {
26634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                    for (SkImage::CachingHint hint : hints) {
26734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                        draw_image(canvas, image.get(), dstColorType, dstAlphaType, dstColorSpace,
26834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                                   hint);
26934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                        canvas->translate(0.0f, (float) kEncodedHeight + 1);
27034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                    }
27134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                }
27234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett            }
27334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett            canvas->restore();
27434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett            canvas->translate((float) kEncodedWidth + 1, 0.0f);
27534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        }
27634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    }
27734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
27834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarettprivate:
27934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    static const int kEncodedWidth = 8;
28034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    static const int kEncodedHeight = 8;
28134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
28234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    typedef skiagm::GM INHERITED;
28334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett};
28434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt SarettDEF_GM( return new ReadPixelsCodecGM; )
28534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
28634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarettclass ReadPixelsPictureGM : public skiagm::GM {
28734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarettpublic:
28834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    ReadPixelsPictureGM() {}
28934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
29034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarettprotected:
29134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    SkString onShortName() override {
29234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        return SkString("readpixelspicture");
29334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    }
29434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
29534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    SkISize onISize() override {
29634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        return SkISize::Make(3 * kWidth, 12 * kHeight);
29734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    }
29834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
29934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    void onDraw(SkCanvas* canvas) override {
30034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        if (!canvas->imageInfo().colorSpace()) {
30134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett            // This gm is only interesting in color correct modes.
30234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett            return;
30334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        }
30434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
30534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        const sk_sp<SkImage> images[] = {
3069df70bb74db8294283e8d2d8e20c95d290d2a34dMatt Sarett                make_picture_image(),
30734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        };
30834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        const SkAlphaType alphaTypes[] = {
30934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                kUnpremul_SkAlphaType,
31034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                kPremul_SkAlphaType,
31134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        };
31234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        const SkColorType colorTypes[] = {
31334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                kRGBA_8888_SkColorType,
31434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                kBGRA_8888_SkColorType,
31534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                kRGBA_F16_SkColorType,
31634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        };
31734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        const sk_sp<SkColorSpace> colorSpaces[] = {
31834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                make_wide_gamut(),
31977a7a1b57c16c97f056c1e50c03bdc954947778cMatt Sarett                SkColorSpace::MakeSRGB(),
32034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                make_small_gamut(),
32134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        };
32234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        const SkImage::CachingHint hints[] = {
32334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                SkImage::kAllow_CachingHint,
32434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                SkImage::kDisallow_CachingHint,
32534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        };
32634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
32734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        for (sk_sp<SkImage> image : images) {
32834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett            for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
32934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                canvas->save();
33034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                for (SkColorType dstColorType : colorTypes) {
33134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                    for (SkAlphaType dstAlphaType : alphaTypes) {
33234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                        for (SkImage::CachingHint hint : hints) {
33334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                            draw_image(canvas, image.get(), dstColorType, dstAlphaType,
33434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                                       dstColorSpace, hint);
33534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                            canvas->translate(0.0f, (float) kHeight);
33634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                        }
33734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                    }
33834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                }
33934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                canvas->restore();
34034855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett                canvas->translate((float) kWidth, 0.0f);
34134855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett            }
34234855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett        }
34334855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    }
34434855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
34534855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarettprivate:
34634855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett
34734855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett    typedef skiagm::GM INHERITED;
34834855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt Sarett};
34934855f9e1c40bf91d2bdbd34b32868eb06327c9fMatt SarettDEF_GM( return new ReadPixelsPictureGM; )
350