• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "GrSRGBEffect.h"
9 
10 #include "GrFragmentProcessor.h"
11 #include "GrProcessor.h"
12 #include "glsl/GrGLSLFragmentProcessor.h"
13 #include "glsl/GrGLSLFragmentShaderBuilder.h"
14 
15 class GrGLSRGBEffect : public GrGLSLFragmentProcessor {
16 public:
emitCode(EmitArgs & args)17     void emitCode(EmitArgs& args) override {
18         const GrSRGBEffect& srgbe = args.fFp.cast<GrSRGBEffect>();
19         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
20 
21         SkString srgbFuncName;
22         static const GrShaderVar gSrgbArgs[] = {
23             GrShaderVar("x", kFloat_GrSLType),
24         };
25         switch (srgbe.mode()) {
26             case GrSRGBEffect::Mode::kLinearToSRGB:
27                 fragBuilder->emitFunction(kFloat_GrSLType,
28                                           "linear_to_srgb",
29                                           SK_ARRAY_COUNT(gSrgbArgs),
30                                           gSrgbArgs,
31                                           "return (x <= 0.0031308) ? (x * 12.92) "
32                                           ": (1.055 * pow(x, 0.416666667) - 0.055);",
33                                           &srgbFuncName);
34                 break;
35             case GrSRGBEffect::Mode::kSRGBToLinear:
36                 fragBuilder->emitFunction(kFloat_GrSLType,
37                                           "srgb_to_linear",
38                                           SK_ARRAY_COUNT(gSrgbArgs),
39                                           gSrgbArgs,
40                                           "return (x <= 0.04045) ? (x / 12.92) "
41                                           ": pow((x + 0.055) / 1.055, 2.4);",
42                                           &srgbFuncName);
43                 break;
44         }
45 
46         if (nullptr == args.fInputColor) {
47             args.fInputColor = "vec4(1)";
48         }
49 
50         fragBuilder->codeAppendf("vec4 color = %s;", args.fInputColor);
51         if (srgbe.alpha() == GrSRGBEffect::Alpha::kPremul) {
52             fragBuilder->codeAppendf("float nonZeroAlpha = max(color.a, 0.00001);");
53             fragBuilder->codeAppendf("color = vec4(color.rgb / nonZeroAlpha, color.a);");
54         }
55         fragBuilder->codeAppendf("color = vec4(%s(color.r), %s(color.g), %s(color.b), color.a);",
56                                     srgbFuncName.c_str(),
57                                     srgbFuncName.c_str(),
58                                     srgbFuncName.c_str());
59         if (srgbe.alpha() == GrSRGBEffect::Alpha::kPremul) {
60             fragBuilder->codeAppendf("color = vec4(color.rgb, 1) * color.a;");
61         }
62         fragBuilder->codeAppendf("%s = color;", args.fOutputColor);
63     }
64 
GenKey(const GrProcessor & processor,const GrShaderCaps &,GrProcessorKeyBuilder * b)65     static inline void GenKey(const GrProcessor& processor, const GrShaderCaps&,
66                               GrProcessorKeyBuilder* b) {
67         const GrSRGBEffect& srgbe = processor.cast<GrSRGBEffect>();
68         uint32_t key = static_cast<uint32_t>(srgbe.mode()) |
69                       (static_cast<uint32_t>(srgbe.alpha()) << 1);
70         b->add32(key);
71     }
72 
73 private:
74     typedef GrGLSLFragmentProcessor INHERITED;
75 };
76 
77 ///////////////////////////////////////////////////////////////////////////////
78 
GrSRGBEffect(Mode mode,Alpha alpha)79 GrSRGBEffect::GrSRGBEffect(Mode mode, Alpha alpha)
80     : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
81                 kConstantOutputForConstantInput_OptimizationFlag)
82     , fMode(mode)
83     , fAlpha(alpha)
84 {
85     this->initClassID<GrSRGBEffect>();
86 }
87 
onIsEqual(const GrFragmentProcessor & s) const88 bool GrSRGBEffect::onIsEqual(const GrFragmentProcessor& s) const {
89     const GrSRGBEffect& other = s.cast<GrSRGBEffect>();
90     return other.fMode == fMode;
91 }
92 
srgb_to_linear(float srgb)93 static inline float srgb_to_linear(float srgb) {
94     return (srgb <= 0.04045f) ? srgb / 12.92f : powf((srgb + 0.055f) / 1.055f, 2.4f);
95 }
linear_to_srgb(float linear)96 static inline float linear_to_srgb(float linear) {
97     return (linear <= 0.0031308) ? linear * 12.92f : 1.055f * powf(linear, 1.f / 2.4f) - 0.055f;
98 }
99 
constantOutputForConstantInput(GrColor4f color) const100 GrColor4f GrSRGBEffect::constantOutputForConstantInput(GrColor4f color) const {
101     color = color.unpremul();
102     switch (fMode) {
103         case Mode::kLinearToSRGB:
104             color = GrColor4f(linear_to_srgb(color.fRGBA[0]), linear_to_srgb(color.fRGBA[1]),
105                               linear_to_srgb(color.fRGBA[2]), color.fRGBA[3]);
106             break;
107         case Mode::kSRGBToLinear:
108             color = GrColor4f(srgb_to_linear(color.fRGBA[0]), srgb_to_linear(color.fRGBA[1]),
109                               srgb_to_linear(color.fRGBA[2]), color.fRGBA[3]);
110             break;
111     }
112     return color.premul();
113 }
114 
115 ///////////////////////////////////////////////////////////////////////////////
116 
117 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSRGBEffect);
118 
119 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)120 sk_sp<GrFragmentProcessor> GrSRGBEffect::TestCreate(GrProcessorTestData* d) {
121     Mode testMode = static_cast<Mode>(d->fRandom->nextRangeU(0, 1));
122     return GrSRGBEffect::Make(testMode, Alpha::kPremul);
123 }
124 #endif
125 
126 ///////////////////////////////////////////////////////////////////////////////
127 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const128 void GrSRGBEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
129                                           GrProcessorKeyBuilder* b) const {
130     GrGLSRGBEffect::GenKey(*this, caps, b);
131 }
132 
onCreateGLSLInstance() const133 GrGLSLFragmentProcessor* GrSRGBEffect::onCreateGLSLInstance() const {
134     return new GrGLSRGBEffect;
135 }
136 
137