1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot* Copyright 2017 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 "SkHighContrastFilter.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPM4f.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkArenaAlloc.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRasterPipeline.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkReadBuffer.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkString.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkWriteBuffer.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "../jumper/SkJumper.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrColorSpaceInfo.h"
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrContext.h"
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLFragmentProcessor.h"
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLFragmentShaderBuilder.h"
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotusing InvertStyle = SkHighContrastConfig::InvertStyle;
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkHighContrast_Filter : public SkColorFilter {
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkHighContrast_Filter(const SkHighContrastConfig& config) {
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fConfig = config;
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Clamp contrast to just inside -1 to 1 to avoid division by zero.
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fConfig.fContrast = SkScalarPin(fConfig.fContrast,
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                        -1.0f + FLT_EPSILON,
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                        1.0f - FLT_EPSILON);
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ~SkHighContrast_Filter() override {}
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrContext*, const GrColorSpaceInfo&) const override;
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot #endif
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onAppendStages(SkRasterPipeline* p,
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkColorSpace* dst,
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkArenaAlloc* scratch,
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        bool shaderIsOpaque) const override;
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_TO_STRING_OVERRIDE()
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkHighContrast_Filter)
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void flatten(SkWriteBuffer&) const override;
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkHighContrastConfig fConfig;
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    friend class SkHighContrastFilter;
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef SkColorFilter INHERITED;
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkHighContrast_Filter::onAppendStages(SkRasterPipeline* p,
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           SkColorSpace* dstCS,
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           SkArenaAlloc* alloc,
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           bool shaderIsOpaque) const {
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!shaderIsOpaque) {
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::unpremul);
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!dstCS) {
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // In legacy draws this effect approximately linearizes by squaring.
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // When non-legacy, we're already (better) linearized.
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto square = alloc->make<SkJumper_ParametricTransferFunction>();
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        square->G = 2.0f; square->A = 1.0f;
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        square->B = square->C = square->D = square->E = square->F = 0;
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::parametric_r, square);
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::parametric_g, square);
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::parametric_b, square);
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (fConfig.fGrayscale) {
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float r = SK_LUM_COEFF_R;
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float g = SK_LUM_COEFF_G;
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float b = SK_LUM_COEFF_B;
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float* matrix = alloc->makeArray<float>(12);
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        matrix[0] = matrix[1] = matrix[2] = r;
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        matrix[3] = matrix[4] = matrix[5] = g;
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        matrix[6] = matrix[7] = matrix[8] = b;
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::matrix_3x4, matrix);
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (fConfig.fInvertStyle == InvertStyle::kInvertBrightness) {
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float* matrix = alloc->makeArray<float>(12);
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        matrix[0] = matrix[4] = matrix[8] = -1;
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        matrix[9] = matrix[10] = matrix[11] = 1;
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::matrix_3x4, matrix);
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if (fConfig.fInvertStyle == InvertStyle::kInvertLightness) {
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::rgb_to_hsl);
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float* matrix = alloc->makeArray<float>(12);
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        matrix[0] = matrix[4] = matrix[11] = 1;
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        matrix[8] = -1;
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::matrix_3x4, matrix);
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::hsl_to_rgb);
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (fConfig.fContrast != 0.0) {
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float* matrix = alloc->makeArray<float>(12);
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float c = fConfig.fContrast;
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float m = (1 + c) / (1 - c);
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float b = (-0.5f * m + 0.5f);
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        matrix[0] = matrix[4] = matrix[8] = m;
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        matrix[9] = matrix[10] = matrix[11] = b;
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::matrix_3x4, matrix);
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    p->append(SkRasterPipeline::clamp_0);
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    p->append(SkRasterPipeline::clamp_1);
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!dstCS) {
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // See the previous if(!dstCS) { ... }
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto sqrt = alloc->make<SkJumper_ParametricTransferFunction>();
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sqrt->G = 0.5f; sqrt->A = 1.0f;
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sqrt->B = sqrt->C = sqrt->D = sqrt->E = sqrt->F = 0;
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::parametric_r, sqrt);
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::parametric_g, sqrt);
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::parametric_b, sqrt);
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!shaderIsOpaque) {
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p->append(SkRasterPipeline::premul);
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkHighContrast_Filter::flatten(SkWriteBuffer& buffer) const {
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    buffer.writeBool(fConfig.fGrayscale);
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    buffer.writeInt(static_cast<int>(fConfig.fInvertStyle));
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    buffer.writeScalar(fConfig.fContrast);
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkFlattenable> SkHighContrast_Filter::CreateProc(SkReadBuffer& buffer) {
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkHighContrastConfig config;
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    config.fGrayscale = buffer.readBool();
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    config.fInvertStyle = buffer.read32LE(InvertStyle::kLast);
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    config.fContrast = buffer.readScalar();
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkHighContrastFilter::Make(config);
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkColorFilter> SkHighContrastFilter::Make(
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkHighContrastConfig& config) {
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!config.isValid()) {
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return sk_make_sp<SkHighContrast_Filter>(config);
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_IGNORE_TO_STRING
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkHighContrast_Filter::toString(SkString* str) const {
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    str->append("SkHighContrastColorFilter ");
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkHighContrastFilter)
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkHighContrast_Filter)
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass HighContrastFilterEffect : public GrFragmentProcessor {
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static std::unique_ptr<GrFragmentProcessor> Make(const SkHighContrastConfig& config,
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                     bool linearize) {
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return std::unique_ptr<GrFragmentProcessor>(new HighContrastFilterEffect(config,
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                                 linearize));
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* name() const override { return "HighContrastFilter"; }
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkHighContrastConfig& config() const { return fConfig; }
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool linearize() const { return fLinearize; }
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    std::unique_ptr<GrFragmentProcessor> clone() const override {
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return Make(fConfig, fLinearize);
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    HighContrastFilterEffect(const SkHighContrastConfig& config, bool linearize)
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : INHERITED(kHighContrastFilterEffect_ClassID, kNone_OptimizationFlags)
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fConfig(config)
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fLinearize(linearize) {
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                       GrProcessorKeyBuilder* b) const override;
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onIsEqual(const GrFragmentProcessor& other) const override {
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const HighContrastFilterEffect& that = other.cast<HighContrastFilterEffect>();
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fConfig.fGrayscale == that.fConfig.fGrayscale &&
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fConfig.fInvertStyle == that.fConfig.fInvertStyle &&
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fConfig.fContrast == that.fConfig.fContrast &&
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fLinearize == that.fLinearize;
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkHighContrastConfig fConfig;
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fLinearize;
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef GrFragmentProcessor INHERITED;
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GLHighContrastFilterEffect : public GrGLSLFragmentProcessor {
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void emitCode(EmitArgs& args) override;
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    UniformHandle fContrastUni;
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef GrGLSLFragmentProcessor INHERITED;
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrGLSLFragmentProcessor* HighContrastFilterEffect::onCreateGLSLInstance() const {
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return new GLHighContrastFilterEffect();
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid HighContrastFilterEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                     GrProcessorKeyBuilder* b) const {
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GLHighContrastFilterEffect::GenKey(*this, caps, b);
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GLHighContrastFilterEffect::onSetData(const GrGLSLProgramDataManager& pdm,
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           const GrFragmentProcessor& proc) {
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const HighContrastFilterEffect& hcfe = proc.cast<HighContrastFilterEffect>();
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    pdm.set1f(fContrastUni, hcfe.config().fContrast);
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GLHighContrastFilterEffect::GenKey(
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const GrProcessor& proc, const GrShaderCaps&, GrProcessorKeyBuilder* b) {
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot  const HighContrastFilterEffect& hcfe = proc.cast<HighContrastFilterEffect>();
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot  b->add32(static_cast<uint32_t>(hcfe.config().fGrayscale));
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot  b->add32(static_cast<uint32_t>(hcfe.config().fInvertStyle));
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot  b->add32(hcfe.linearize() ? 1 : 0);
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GLHighContrastFilterEffect::emitCode(EmitArgs& args) {
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const HighContrastFilterEffect& hcfe = args.fFp.cast<HighContrastFilterEffect>();
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkHighContrastConfig& config = hcfe.config();
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* contrast;
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fContrastUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                    "contrast", &contrast);
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (nullptr == args.fInputColor) {
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        args.fInputColor = "half4(1)";
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("half4 color = %s;", args.fInputColor);
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Unpremultiply. The max() is to guard against 0 / 0.
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.00001);");
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (hcfe.linearize()) {
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppend("color.rgb = color.rgb * color.rgb;");
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Grayscale.
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (config.fGrayscale) {
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("half luma = dot(color, half4(%f, %f, %f, 0));",
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                 SK_LUM_COEFF_R, SK_LUM_COEFF_G, SK_LUM_COEFF_B);
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("color = half4(luma, luma, luma, 0);");
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (config.fInvertStyle == InvertStyle::kInvertBrightness) {
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("color = half4(1, 1, 1, 1) - color;");
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (config.fInvertStyle == InvertStyle::kInvertLightness) {
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Convert from RGB to HSL.
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("half fmax = max(color.r, max(color.g, color.b));");
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("half fmin = min(color.r, min(color.g, color.b));");
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("half l = (fmax + fmin) / 2;");
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("half h;");
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("half s;");
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("if (fmax == fmin) {");
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  h = 0;");
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  s = 0;");
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("} else {");
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  half d = fmax - fmin;");
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  s = l > 0.5 ?");
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("      d / (2 - fmax - fmin) :");
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("      d / (fmax + fmin);");
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // We'd like to just write "if (color.r == fmax) { ... }". On many GPUs, running the
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // angle_d3d9_es2 config, that failed. It seems that max(x, y) is not necessarily equal
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // to either x or y. Tried several ways to fix it, but this was the only reasonable fix.
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  if (color.r >= color.g && color.r >= color.b) {");
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("    h = (color.g - color.b) / d + ");
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("        (color.g < color.b ? 6 : 0);");
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  } else if (color.g >= color.b) {");
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("    h = (color.b - color.r) / d + 2;");
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  } else {");
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("    h = (color.r - color.g) / d + 4;");
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  }");
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("}");
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("h /= 6;");
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("l = 1.0 - l;");
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Convert back from HSL to RGB.
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString hue2rgbFuncName;
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        static const GrShaderVar gHue2rgbArgs[] = {
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrShaderVar("p", kHalf_GrSLType),
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrShaderVar("q", kHalf_GrSLType),
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrShaderVar("t", kHalf_GrSLType),
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->emitFunction(kHalf_GrSLType,
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  "hue2rgb",
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  SK_ARRAY_COUNT(gHue2rgbArgs),
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  gHue2rgbArgs,
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  "if (t < 0)"
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  "  t += 1;"
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  "if (t > 1)"
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  "  t -= 1;"
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  "if (t < 1/6.)"
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  "  return p + (q - p) * 6 * t;"
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  "if (t < 1/2.)"
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  "  return q;"
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  "if (t < 2/3.)"
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  "  return p + (q - p) * (2/3. - t) * 6;"
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  "return p;",
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  &hue2rgbFuncName);
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("if (s == 0) {");
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  color = half4(l, l, l, 0);");
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("} else {");
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  half q = l < 0.5 ? l * (1 + s) : l + s - l * s;");
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  half p = 2 * l - q;");
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  color.r = %s(p, q, h + 1/3.);", hue2rgbFuncName.c_str());
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  color.g = %s(p, q, h);", hue2rgbFuncName.c_str());
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("  color.b = %s(p, q, h - 1/3.);", hue2rgbFuncName.c_str());
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppendf("}");
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Contrast.
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("if (%s != 0) {", contrast);
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("  half m = (1 + %s) / (1 - %s);", contrast, contrast);
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("  half off = (-0.5 * m + 0.5);");
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("  color = m * color + off;");
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("}");
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Clamp.
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("color = clamp(color, 0, 1);");
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (hcfe.linearize()) {
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppend("color.rgb = sqrt(color.rgb);");
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Restore the original alpha and premultiply.
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("color.a = %s.a;", args.fInputColor);
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("color.rgb *= color.a;");
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Copy to the output color.
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("%s = color;", args.fOutputColor);
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstd::unique_ptr<GrFragmentProcessor> SkHighContrast_Filter::asFragmentProcessor(
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrContext*, const GrColorSpaceInfo& csi) const {
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool linearize = !csi.isGammaCorrect();
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return HighContrastFilterEffect::Make(fConfig, linearize);
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
379