blob: a922545235afa72edeaea3e59584d9e4488b1441 [file] [log] [blame]
Dominic Mazzoni394d4142017-02-14 11:15:31 -08001/*
2* Copyright 2017 Google Inc.
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
7
8#include "SkHighContrastFilter.h"
Dominic Mazzoni394d4142017-02-14 11:15:31 -08009#include "SkArenaAlloc.h"
Brian Osman81cbd032018-09-21 11:09:15 -040010#include "SkColorData.h"
Dominic Mazzoni394d4142017-02-14 11:15:31 -080011#include "SkRasterPipeline.h"
12#include "SkReadBuffer.h"
13#include "SkString.h"
14#include "SkWriteBuffer.h"
15
16#if SK_SUPPORT_GPU
Brian Osman8c68c652017-11-06 15:25:10 -050017#include "GrColorSpaceInfo.h"
Dominic Mazzoni394d4142017-02-14 11:15:31 -080018#include "GrContext.h"
19#include "glsl/GrGLSLFragmentProcessor.h"
20#include "glsl/GrGLSLFragmentShaderBuilder.h"
21#endif
22
23using InvertStyle = SkHighContrastConfig::InvertStyle;
24
Dominic Mazzoni394d4142017-02-14 11:15:31 -080025class SkHighContrast_Filter : public SkColorFilter {
26public:
27 SkHighContrast_Filter(const SkHighContrastConfig& config) {
28 fConfig = config;
29 // Clamp contrast to just inside -1 to 1 to avoid division by zero.
30 fConfig.fContrast = SkScalarPin(fConfig.fContrast,
31 -1.0f + FLT_EPSILON,
32 1.0f - FLT_EPSILON);
33 }
34
Brian Salomond3b65972017-03-22 12:05:03 -040035 ~SkHighContrast_Filter() override {}
Dominic Mazzoni394d4142017-02-14 11:15:31 -080036
37#if SK_SUPPORT_GPU
Brian Salomon4cbb6e62017-10-25 15:12:19 -040038 std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
39 GrContext*, const GrColorSpaceInfo&) const override;
Dominic Mazzoni394d4142017-02-14 11:15:31 -080040 #endif
41
Mike Kleinfdf31032017-05-09 14:57:58 -040042 void onAppendStages(SkRasterPipeline* p,
Dominic Mazzoni394d4142017-02-14 11:15:31 -080043 SkColorSpace* dst,
44 SkArenaAlloc* scratch,
45 bool shaderIsOpaque) const override;
46
Dominic Mazzoni394d4142017-02-14 11:15:31 -080047protected:
48 void flatten(SkWriteBuffer&) const override;
49
50private:
Mike Klein4fee3232018-10-18 17:27:16 -040051 SK_FLATTENABLE_HOOKS(SkHighContrast_Filter)
52
Dominic Mazzoni394d4142017-02-14 11:15:31 -080053 SkHighContrastConfig fConfig;
54
55 friend class SkHighContrastFilter;
56
57 typedef SkColorFilter INHERITED;
58};
59
Mike Kleinfdf31032017-05-09 14:57:58 -040060void SkHighContrast_Filter::onAppendStages(SkRasterPipeline* p,
Mike Klein8b96b372017-05-12 12:24:04 -040061 SkColorSpace* dstCS,
62 SkArenaAlloc* alloc,
Dominic Mazzoni394d4142017-02-14 11:15:31 -080063 bool shaderIsOpaque) const {
64 if (!shaderIsOpaque) {
65 p->append(SkRasterPipeline::unpremul);
66 }
67
Mike Klein8b96b372017-05-12 12:24:04 -040068 if (!dstCS) {
69 // In legacy draws this effect approximately linearizes by squaring.
70 // When non-legacy, we're already (better) linearized.
Brian Osman5deadca2019-01-24 12:18:17 -050071 auto square = alloc->make<skcms_TransferFunction>();
72 square->g = 2.0f; square->a = 1.0f;
73 square->b = square->c = square->d = square->e = square->f = 0;
Mike Klein8b96b372017-05-12 12:24:04 -040074
Mike Klein4eebd9e2018-07-11 14:49:51 -040075 p->append(SkRasterPipeline::parametric, square);
Mike Klein8b96b372017-05-12 12:24:04 -040076 }
77
Dominic Mazzoni394d4142017-02-14 11:15:31 -080078 if (fConfig.fGrayscale) {
79 float r = SK_LUM_COEFF_R;
80 float g = SK_LUM_COEFF_G;
81 float b = SK_LUM_COEFF_B;
Mike Klein8b96b372017-05-12 12:24:04 -040082 float* matrix = alloc->makeArray<float>(12);
Dominic Mazzoni394d4142017-02-14 11:15:31 -080083 matrix[0] = matrix[1] = matrix[2] = r;
84 matrix[3] = matrix[4] = matrix[5] = g;
85 matrix[6] = matrix[7] = matrix[8] = b;
86 p->append(SkRasterPipeline::matrix_3x4, matrix);
87 }
88
89 if (fConfig.fInvertStyle == InvertStyle::kInvertBrightness) {
Mike Klein8b96b372017-05-12 12:24:04 -040090 float* matrix = alloc->makeArray<float>(12);
Dominic Mazzoni394d4142017-02-14 11:15:31 -080091 matrix[0] = matrix[4] = matrix[8] = -1;
92 matrix[9] = matrix[10] = matrix[11] = 1;
93 p->append(SkRasterPipeline::matrix_3x4, matrix);
94 } else if (fConfig.fInvertStyle == InvertStyle::kInvertLightness) {
95 p->append(SkRasterPipeline::rgb_to_hsl);
Mike Klein8b96b372017-05-12 12:24:04 -040096 float* matrix = alloc->makeArray<float>(12);
Dominic Mazzoni394d4142017-02-14 11:15:31 -080097 matrix[0] = matrix[4] = matrix[11] = 1;
98 matrix[8] = -1;
99 p->append(SkRasterPipeline::matrix_3x4, matrix);
100 p->append(SkRasterPipeline::hsl_to_rgb);
101 }
102
103 if (fConfig.fContrast != 0.0) {
Mike Klein8b96b372017-05-12 12:24:04 -0400104 float* matrix = alloc->makeArray<float>(12);
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800105 float c = fConfig.fContrast;
106 float m = (1 + c) / (1 - c);
107 float b = (-0.5f * m + 0.5f);
108 matrix[0] = matrix[4] = matrix[8] = m;
109 matrix[9] = matrix[10] = matrix[11] = b;
110 p->append(SkRasterPipeline::matrix_3x4, matrix);
111 }
112
113 p->append(SkRasterPipeline::clamp_0);
114 p->append(SkRasterPipeline::clamp_1);
115
Mike Klein8b96b372017-05-12 12:24:04 -0400116 if (!dstCS) {
117 // See the previous if(!dstCS) { ... }
Brian Osman5deadca2019-01-24 12:18:17 -0500118 auto sqrt = alloc->make<skcms_TransferFunction>();
119 sqrt->g = 0.5f; sqrt->a = 1.0f;
120 sqrt->b = sqrt->c = sqrt->d = sqrt->e = sqrt->f = 0;
Mike Klein8b96b372017-05-12 12:24:04 -0400121
Mike Klein4eebd9e2018-07-11 14:49:51 -0400122 p->append(SkRasterPipeline::parametric, sqrt);
Mike Klein8b96b372017-05-12 12:24:04 -0400123 }
124
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800125 if (!shaderIsOpaque) {
126 p->append(SkRasterPipeline::premul);
127 }
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800128}
129
130void SkHighContrast_Filter::flatten(SkWriteBuffer& buffer) const {
131 buffer.writeBool(fConfig.fGrayscale);
132 buffer.writeInt(static_cast<int>(fConfig.fInvertStyle));
133 buffer.writeScalar(fConfig.fContrast);
134}
135
136sk_sp<SkFlattenable> SkHighContrast_Filter::CreateProc(SkReadBuffer& buffer) {
137 SkHighContrastConfig config;
138 config.fGrayscale = buffer.readBool();
Mike Reedde5c5022018-01-26 14:59:12 -0500139 config.fInvertStyle = buffer.read32LE(InvertStyle::kLast);
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800140 config.fContrast = buffer.readScalar();
Robert Phillipsa83d0132018-01-24 14:46:38 -0500141
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800142 return SkHighContrastFilter::Make(config);
143}
144
145sk_sp<SkColorFilter> SkHighContrastFilter::Make(
146 const SkHighContrastConfig& config) {
Mike Reedde5c5022018-01-26 14:59:12 -0500147 if (!config.isValid()) {
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800148 return nullptr;
Mike Reedde5c5022018-01-26 14:59:12 -0500149 }
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800150 return sk_make_sp<SkHighContrast_Filter>(config);
151}
152
Mike Kleinfa5f6ce2018-10-20 08:21:31 -0400153void SkHighContrastFilter::RegisterFlattenables() {
Brian Salomon23356442018-11-30 15:33:19 -0500154 SK_REGISTER_FLATTENABLE(SkHighContrast_Filter);
Mike Klein12956722018-10-19 10:00:21 -0400155}
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800156
157#if SK_SUPPORT_GPU
158class HighContrastFilterEffect : public GrFragmentProcessor {
159public:
Brian Osman8c68c652017-11-06 15:25:10 -0500160 static std::unique_ptr<GrFragmentProcessor> Make(const SkHighContrastConfig& config,
161 bool linearize) {
162 return std::unique_ptr<GrFragmentProcessor>(new HighContrastFilterEffect(config,
163 linearize));
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800164 }
165
166 const char* name() const override { return "HighContrastFilter"; }
167
168 const SkHighContrastConfig& config() const { return fConfig; }
Brian Osman8c68c652017-11-06 15:25:10 -0500169 bool linearize() const { return fLinearize; }
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800170
Brian Osman8c68c652017-11-06 15:25:10 -0500171 std::unique_ptr<GrFragmentProcessor> clone() const override {
172 return Make(fConfig, fLinearize);
173 }
Brian Salomon164f6ec2017-07-25 15:32:17 -0400174
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800175private:
Brian Osman8c68c652017-11-06 15:25:10 -0500176 HighContrastFilterEffect(const SkHighContrastConfig& config, bool linearize)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400177 : INHERITED(kHighContrastFilterEffect_ClassID, kNone_OptimizationFlags)
Brian Osman8c68c652017-11-06 15:25:10 -0500178 , fConfig(config)
Brian Salomonf7dcd762018-07-30 14:48:15 -0400179 , fLinearize(linearize) {}
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800180
181 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
182
183 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
184 GrProcessorKeyBuilder* b) const override;
185
186 bool onIsEqual(const GrFragmentProcessor& other) const override {
187 const HighContrastFilterEffect& that = other.cast<HighContrastFilterEffect>();
188 return fConfig.fGrayscale == that.fConfig.fGrayscale &&
189 fConfig.fInvertStyle == that.fConfig.fInvertStyle &&
Brian Osman8c68c652017-11-06 15:25:10 -0500190 fConfig.fContrast == that.fConfig.fContrast &&
191 fLinearize == that.fLinearize;
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800192 }
193
194 SkHighContrastConfig fConfig;
Brian Osman8c68c652017-11-06 15:25:10 -0500195 bool fLinearize;
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800196
197 typedef GrFragmentProcessor INHERITED;
198};
199
200class GLHighContrastFilterEffect : public GrGLSLFragmentProcessor {
201public:
202 static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
203
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800204protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400205 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800206 void emitCode(EmitArgs& args) override;
207
208private:
209 UniformHandle fContrastUni;
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800210
211 typedef GrGLSLFragmentProcessor INHERITED;
212};
213
214GrGLSLFragmentProcessor* HighContrastFilterEffect::onCreateGLSLInstance() const {
Brian Osman8c68c652017-11-06 15:25:10 -0500215 return new GLHighContrastFilterEffect();
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800216}
217
218void HighContrastFilterEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
219 GrProcessorKeyBuilder* b) const {
220 GLHighContrastFilterEffect::GenKey(*this, caps, b);
221}
222
Brian Salomonab015ef2017-04-04 10:15:51 -0400223void GLHighContrastFilterEffect::onSetData(const GrGLSLProgramDataManager& pdm,
224 const GrFragmentProcessor& proc) {
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800225 const HighContrastFilterEffect& hcfe = proc.cast<HighContrastFilterEffect>();
226 pdm.set1f(fContrastUni, hcfe.config().fContrast);
227}
228
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800229void GLHighContrastFilterEffect::GenKey(
230 const GrProcessor& proc, const GrShaderCaps&, GrProcessorKeyBuilder* b) {
231 const HighContrastFilterEffect& hcfe = proc.cast<HighContrastFilterEffect>();
232 b->add32(static_cast<uint32_t>(hcfe.config().fGrayscale));
233 b->add32(static_cast<uint32_t>(hcfe.config().fInvertStyle));
Brian Osman8c68c652017-11-06 15:25:10 -0500234 b->add32(hcfe.linearize() ? 1 : 0);
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800235}
236
237void GLHighContrastFilterEffect::emitCode(EmitArgs& args) {
Brian Osman8c68c652017-11-06 15:25:10 -0500238 const HighContrastFilterEffect& hcfe = args.fFp.cast<HighContrastFilterEffect>();
239 const SkHighContrastConfig& config = hcfe.config();
240
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800241 const char* contrast;
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400242 fContrastUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800243 "contrast", &contrast);
244
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800245 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
246
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400247 fragBuilder->codeAppendf("half4 color = %s;", args.fInputColor);
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800248
249 // Unpremultiply. The max() is to guard against 0 / 0.
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400250 fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.00001);");
251 fragBuilder->codeAppendf("color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800252
Brian Osman8c68c652017-11-06 15:25:10 -0500253 if (hcfe.linearize()) {
254 fragBuilder->codeAppend("color.rgb = color.rgb * color.rgb;");
255 }
256
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800257 // Grayscale.
Brian Osman8c68c652017-11-06 15:25:10 -0500258 if (config.fGrayscale) {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400259 fragBuilder->codeAppendf("half luma = dot(color, half4(%f, %f, %f, 0));",
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800260 SK_LUM_COEFF_R, SK_LUM_COEFF_G, SK_LUM_COEFF_B);
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400261 fragBuilder->codeAppendf("color = half4(luma, luma, luma, 0);");
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800262 }
263
Brian Osman8c68c652017-11-06 15:25:10 -0500264 if (config.fInvertStyle == InvertStyle::kInvertBrightness) {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400265 fragBuilder->codeAppendf("color = half4(1, 1, 1, 1) - color;");
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800266 }
267
Brian Osman8c68c652017-11-06 15:25:10 -0500268 if (config.fInvertStyle == InvertStyle::kInvertLightness) {
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800269 // Convert from RGB to HSL.
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400270 fragBuilder->codeAppendf("half fmax = max(color.r, max(color.g, color.b));");
271 fragBuilder->codeAppendf("half fmin = min(color.r, min(color.g, color.b));");
272 fragBuilder->codeAppendf("half l = (fmax + fmin) / 2;");
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800273
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400274 fragBuilder->codeAppendf("half h;");
275 fragBuilder->codeAppendf("half s;");
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800276
277 fragBuilder->codeAppendf("if (fmax == fmin) {");
278 fragBuilder->codeAppendf(" h = 0;");
279 fragBuilder->codeAppendf(" s = 0;");
280 fragBuilder->codeAppendf("} else {");
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400281 fragBuilder->codeAppendf(" half d = fmax - fmin;");
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800282 fragBuilder->codeAppendf(" s = l > 0.5 ?");
283 fragBuilder->codeAppendf(" d / (2 - fmax - fmin) :");
284 fragBuilder->codeAppendf(" d / (fmax + fmin);");
Brian Osman43a0aa52017-11-07 15:39:55 -0500285 // We'd like to just write "if (color.r == fmax) { ... }". On many GPUs, running the
286 // angle_d3d9_es2 config, that failed. It seems that max(x, y) is not necessarily equal
287 // to either x or y. Tried several ways to fix it, but this was the only reasonable fix.
288 fragBuilder->codeAppendf(" if (color.r >= color.g && color.r >= color.b) {");
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800289 fragBuilder->codeAppendf(" h = (color.g - color.b) / d + ");
290 fragBuilder->codeAppendf(" (color.g < color.b ? 6 : 0);");
Brian Osman43a0aa52017-11-07 15:39:55 -0500291 fragBuilder->codeAppendf(" } else if (color.g >= color.b) {");
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800292 fragBuilder->codeAppendf(" h = (color.b - color.r) / d + 2;");
293 fragBuilder->codeAppendf(" } else {");
294 fragBuilder->codeAppendf(" h = (color.r - color.g) / d + 4;");
295 fragBuilder->codeAppendf(" }");
296 fragBuilder->codeAppendf("}");
297 fragBuilder->codeAppendf("h /= 6;");
298 fragBuilder->codeAppendf("l = 1.0 - l;");
299 // Convert back from HSL to RGB.
300 SkString hue2rgbFuncName;
Nico Webere50efdf2018-10-01 14:40:44 -0400301 const GrShaderVar gHue2rgbArgs[] = {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400302 GrShaderVar("p", kHalf_GrSLType),
303 GrShaderVar("q", kHalf_GrSLType),
304 GrShaderVar("t", kHalf_GrSLType),
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800305 };
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400306 fragBuilder->emitFunction(kHalf_GrSLType,
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800307 "hue2rgb",
308 SK_ARRAY_COUNT(gHue2rgbArgs),
309 gHue2rgbArgs,
310 "if (t < 0)"
311 " t += 1;"
312 "if (t > 1)"
313 " t -= 1;"
314 "if (t < 1/6.)"
315 " return p + (q - p) * 6 * t;"
316 "if (t < 1/2.)"
317 " return q;"
318 "if (t < 2/3.)"
319 " return p + (q - p) * (2/3. - t) * 6;"
320 "return p;",
321 &hue2rgbFuncName);
322 fragBuilder->codeAppendf("if (s == 0) {");
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400323 fragBuilder->codeAppendf(" color = half4(l, l, l, 0);");
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800324 fragBuilder->codeAppendf("} else {");
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400325 fragBuilder->codeAppendf(" half q = l < 0.5 ? l * (1 + s) : l + s - l * s;");
326 fragBuilder->codeAppendf(" half p = 2 * l - q;");
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800327 fragBuilder->codeAppendf(" color.r = %s(p, q, h + 1/3.);", hue2rgbFuncName.c_str());
328 fragBuilder->codeAppendf(" color.g = %s(p, q, h);", hue2rgbFuncName.c_str());
329 fragBuilder->codeAppendf(" color.b = %s(p, q, h - 1/3.);", hue2rgbFuncName.c_str());
330 fragBuilder->codeAppendf("}");
331 }
332
333 // Contrast.
334 fragBuilder->codeAppendf("if (%s != 0) {", contrast);
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400335 fragBuilder->codeAppendf(" half m = (1 + %s) / (1 - %s);", contrast, contrast);
336 fragBuilder->codeAppendf(" half off = (-0.5 * m + 0.5);");
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800337 fragBuilder->codeAppendf(" color = m * color + off;");
338 fragBuilder->codeAppendf("}");
339
340 // Clamp.
Ethan Nicholas12fb9cf2018-08-03 16:16:57 -0400341 fragBuilder->codeAppendf("color = saturate(color);");
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800342
Brian Osman8c68c652017-11-06 15:25:10 -0500343 if (hcfe.linearize()) {
344 fragBuilder->codeAppend("color.rgb = sqrt(color.rgb);");
345 }
346
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800347 // Restore the original alpha and premultiply.
348 fragBuilder->codeAppendf("color.a = %s.a;", args.fInputColor);
349 fragBuilder->codeAppendf("color.rgb *= color.a;");
350
351 // Copy to the output color.
352 fragBuilder->codeAppendf("%s = color;", args.fOutputColor);
353}
354
Brian Salomonaff329b2017-08-11 09:40:37 -0400355std::unique_ptr<GrFragmentProcessor> SkHighContrast_Filter::asFragmentProcessor(
Brian Osman8c68c652017-11-06 15:25:10 -0500356 GrContext*, const GrColorSpaceInfo& csi) const {
Brian Osman34ec3742018-07-03 10:40:57 -0400357 bool linearize = !csi.isLinearlyBlended();
Brian Osman8c68c652017-11-06 15:25:10 -0500358 return HighContrastFilterEffect::Make(fConfig, linearize);
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800359}
360#endif