1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2016 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "gm.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Resources.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCodec.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorSpace.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorSpaceXform.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorSpaceXformPriv.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkHalf.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkImage.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPictureRecorder.h"
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void clamp_if_necessary(const SkImageInfo& info, void* pixels) {
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (kRGBA_F16_SkColorType != info.colorType()) {
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int y = 0; y < info.height(); y++) {
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int x = 0; x < info.width(); x++) {
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            uint64_t pixel = ((uint64_t*) pixels)[y * info.width() + x];
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            Sk4f rgba = SkHalfToFloat_finite_ftz(pixel);
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (kUnpremul_SkAlphaType == info.alphaType()) {
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                rgba = Sk4f::Max(0.0f, Sk4f::Min(rgba, 1.0f));
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } else {
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkASSERT(kPremul_SkAlphaType == info.alphaType());
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                rgba = Sk4f::Max(0.0f, Sk4f::Min(rgba, rgba[3]));
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkFloatToHalf_finite_ftz(rgba).store(&pixel);
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ((uint64_t*) pixels)[y * info.width() + x] = pixel;
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkColorSpace> fix_for_colortype(SkColorSpace* colorSpace, SkColorType colorType) {
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (kRGBA_F16_SkColorType == colorType) {
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return colorSpace->makeLinearGamma();
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return sk_ref_sp(colorSpace);
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const int kWidth = 64;
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const int kHeight = 64;
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic sk_sp<SkImage> make_raster_image(SkColorType colorType) {
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    std::unique_ptr<SkStream> stream(GetResourceAsStream("images/google_chrome.ico"));
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkBitmap bitmap;
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkImageInfo info = codec->getInfo().makeWH(kWidth, kHeight)
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                       .makeColorType(colorType)
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                       .makeAlphaType(kPremul_SkAlphaType)
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            .makeColorSpace(fix_for_colortype(codec->getInfo().colorSpace(), colorType));
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bitmap.allocPixels(info);
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    codec->getPixels(info, bitmap.getPixels(), bitmap.rowBytes());
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bitmap.setImmutable();
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkImage::MakeFromBitmap(bitmap);
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic sk_sp<SkImage> make_codec_image() {
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkData> encoded = GetResourceAsData("images/randPixels.png");
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkImage::MakeFromEncoded(encoded);
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void draw_contents(SkCanvas* canvas) {
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint paint;
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setStyle(SkPaint::kStroke_Style);
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setStrokeWidth(20);
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setColor(0xFF800000);
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas->drawCircle(40, 40, 35, paint);
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setColor(0xFF008000);
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas->drawCircle(50, 50, 35, paint);
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setColor(0xFF000080);
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas->drawCircle(60, 60, 35, paint);
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic sk_sp<SkImage> make_picture_image() {
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPictureRecorder recorder;
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    draw_contents(recorder.beginRecording(SkRect::MakeIWH(kWidth, kHeight)));
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    SkISize::Make(kWidth, kHeight), nullptr, nullptr,
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    SkImage::BitDepth::kU8,
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    SkColorSpace::MakeSRGB());
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic sk_sp<SkColorSpace> make_parametric_transfer_fn(const SkColorSpacePrimaries& primaries) {
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAssertResult(primaries.toXYZD50(&toXYZD50));
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkColorSpaceTransferFn fn;
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    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;
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkColorSpace::MakeRGB(fn, toXYZD50);
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic sk_sp<SkColorSpace> make_wide_gamut() {
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // ProPhoto
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkColorSpacePrimaries primaries;
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fRX = 0.7347f;
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fRY = 0.2653f;
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fGX = 0.1596f;
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fGY = 0.8404f;
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fBX = 0.0366f;
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fBY = 0.0001f;
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fWX = 0.34567f;
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fWY = 0.35850f;
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return make_parametric_transfer_fn(primaries);
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic sk_sp<SkColorSpace> make_small_gamut() {
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkColorSpacePrimaries primaries;
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fRX = 0.50f;
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fRY = 0.33f;
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fGX = 0.30f;
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fGY = 0.50f;
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fBX = 0.25f;
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fBY = 0.16f;
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fWX = 0.3127f;
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    primaries.fWY = 0.3290f;
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return make_parametric_transfer_fn(primaries);
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void draw_image(SkCanvas* canvas, SkImage* image, SkColorType dstColorType,
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       SkAlphaType dstAlphaType, sk_sp<SkColorSpace> dstColorSpace,
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       SkImage::CachingHint hint) {
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t rowBytes = image->width() * SkColorTypeBytesPerPixel(dstColorType);
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkData> data = SkData::MakeUninitialized(rowBytes * image->height());
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    dstColorSpace = fix_for_colortype(dstColorSpace.get(), dstColorType);
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkImageInfo dstInfo = SkImageInfo::Make(image->width(), image->height(), dstColorType,
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                            dstAlphaType, dstColorSpace);
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!image->readPixels(dstInfo, data->writable_data(), rowBytes, 0, 0, hint)) {
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        memset(data->writable_data(), 0, rowBytes * image->height());
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // SkImage must be premul, so manually premul the data if we unpremul'd during readPixels
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (kUnpremul_SkAlphaType == dstAlphaType) {
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto xform = SkColorSpaceXform::New(dstColorSpace.get(), dstColorSpace.get());
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!xform->apply(select_xform_format(dstColorType), data->writable_data(),
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                          select_xform_format(dstColorType), data->data(),
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                          image->width() * image->height(), kPremul_SkAlphaType)) {
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            memset(data->writable_data(), 0, rowBytes * image->height());
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        dstInfo = dstInfo.makeAlphaType(kPremul_SkAlphaType);
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // readPixels() does not always clamp F16.  The drawing code expects pixels in the 0-1 range.
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    clamp_if_necessary(dstInfo, data->writable_data());
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Now that we have called readPixels(), dump the raw pixels into an srgb image.
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkColorSpace> srgb = fix_for_colortype(
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkColorSpace::MakeSRGB().get(), dstColorType);
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes);
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas->drawImage(raw.get(), 0.0f, 0.0f, nullptr);
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass ReadPixelsGM : public skiagm::GM {
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ReadPixelsGM() {}
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString onShortName() override {
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkString("readpixels");
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkISize onISize() override {
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkISize::Make(6 * kWidth, 9 * kHeight);
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onDraw(SkCanvas* canvas) override {
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!canvas->imageInfo().colorSpace()) {
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // This gm is only interesting in color correct modes.
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkAlphaType alphaTypes[] = {
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kUnpremul_SkAlphaType,
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kPremul_SkAlphaType,
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkColorType colorTypes[] = {
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kRGBA_8888_SkColorType,
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kBGRA_8888_SkColorType,
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kRGBA_F16_SkColorType,
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const sk_sp<SkColorSpace> colorSpaces[] = {
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                make_wide_gamut(),
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkColorSpace::MakeSRGB(),
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                make_small_gamut(),
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (SkColorType srcColorType : colorTypes) {
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->save();
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                sk_sp<SkImage> image = make_raster_image(srcColorType);
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (GrContext* context = canvas->getGrContext()) {
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    image = image->makeTextureImage(context, canvas->imageInfo().colorSpace());
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (image) {
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    for (SkColorType dstColorType : colorTypes) {
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        for (SkAlphaType dstAlphaType : alphaTypes) {
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            draw_image(canvas, image.get(), dstColorType, dstAlphaType,
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                       dstColorSpace, SkImage::kAllow_CachingHint);
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            canvas->translate((float)kWidth, 0.0f);
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->restore();
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->translate(0.0f, (float) kHeight);
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef skiagm::GM INHERITED;
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_GM( return new ReadPixelsGM; )
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass ReadPixelsCodecGM : public skiagm::GM {
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ReadPixelsCodecGM() {}
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString onShortName() override {
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkString("readpixelscodec");
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkISize onISize() override {
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkISize::Make(3 * (kEncodedWidth + 1), 12 * (kEncodedHeight + 1));
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onDraw(SkCanvas* canvas) override {
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!canvas->imageInfo().colorSpace()) {
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // This gm is only interesting in color correct modes.
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkAlphaType alphaTypes[] = {
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kUnpremul_SkAlphaType,
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kPremul_SkAlphaType,
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkColorType colorTypes[] = {
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kRGBA_8888_SkColorType,
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kBGRA_8888_SkColorType,
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kRGBA_F16_SkColorType,
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const sk_sp<SkColorSpace> colorSpaces[] = {
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                make_wide_gamut(),
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkColorSpace::MakeSRGB(),
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                make_small_gamut(),
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkImage::CachingHint hints[] = {
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkImage::kAllow_CachingHint,
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkImage::kDisallow_CachingHint,
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<SkImage> image = make_codec_image();
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->save();
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (SkColorType dstColorType : colorTypes) {
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                for (SkAlphaType dstAlphaType : alphaTypes) {
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    for (SkImage::CachingHint hint : hints) {
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        draw_image(canvas, image.get(), dstColorType, dstAlphaType, dstColorSpace,
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                   hint);
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        canvas->translate(0.0f, (float) kEncodedHeight + 1);
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->restore();
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->translate((float) kEncodedWidth + 1, 0.0f);
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const int kEncodedWidth = 8;
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const int kEncodedHeight = 8;
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef skiagm::GM INHERITED;
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_GM( return new ReadPixelsCodecGM; )
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass ReadPixelsPictureGM : public skiagm::GM {
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ReadPixelsPictureGM() {}
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString onShortName() override {
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkString("readpixelspicture");
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkISize onISize() override {
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkISize::Make(3 * kWidth, 12 * kHeight);
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onDraw(SkCanvas* canvas) override {
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!canvas->imageInfo().colorSpace()) {
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // This gm is only interesting in color correct modes.
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const sk_sp<SkImage> images[] = {
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                make_picture_image(),
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkAlphaType alphaTypes[] = {
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kUnpremul_SkAlphaType,
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kPremul_SkAlphaType,
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkColorType colorTypes[] = {
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kRGBA_8888_SkColorType,
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kBGRA_8888_SkColorType,
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kRGBA_F16_SkColorType,
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const sk_sp<SkColorSpace> colorSpaces[] = {
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                make_wide_gamut(),
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkColorSpace::MakeSRGB(),
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                make_small_gamut(),
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkImage::CachingHint hints[] = {
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkImage::kAllow_CachingHint,
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkImage::kDisallow_CachingHint,
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (sk_sp<SkImage> image : images) {
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->save();
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                for (SkColorType dstColorType : colorTypes) {
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    for (SkAlphaType dstAlphaType : alphaTypes) {
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        for (SkImage::CachingHint hint : hints) {
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            draw_image(canvas, image.get(), dstColorType, dstAlphaType,
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                       dstColorSpace, hint);
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            canvas->translate(0.0f, (float) kHeight);
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->restore();
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->translate((float) kWidth, 0.0f);
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef skiagm::GM INHERITED;
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_GM( return new ReadPixelsPictureGM; )
349