Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: src/gpu/effects/GrGammaEffect.cpp

Issue 1954863002: Make GrGammaEffect have explicit sRGB modes, plus exponential mode. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: powf -> pow in shader code Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/effects/GrGammaEffect.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrGammaEffect.h" 8 #include "GrGammaEffect.h"
9 9
10 #include "GrContext.h" 10 #include "GrContext.h"
11 #include "GrCoordTransform.h" 11 #include "GrCoordTransform.h"
12 #include "GrFragmentProcessor.h" 12 #include "GrFragmentProcessor.h"
13 #include "GrInvariantOutput.h" 13 #include "GrInvariantOutput.h"
14 #include "GrProcessor.h" 14 #include "GrProcessor.h"
15 #include "glsl/GrGLSLFragmentProcessor.h" 15 #include "glsl/GrGLSLFragmentProcessor.h"
16 #include "glsl/GrGLSLFragmentShaderBuilder.h" 16 #include "glsl/GrGLSLFragmentShaderBuilder.h"
17 17
18 class GrGLGammaEffect : public GrGLSLFragmentProcessor { 18 class GrGLGammaEffect : public GrGLSLFragmentProcessor {
19 public: 19 public:
20 void emitCode(EmitArgs& args) override { 20 void emitCode(EmitArgs& args) override {
21 const GrGammaEffect& ge = args.fFp.cast<GrGammaEffect>(); 21 const GrGammaEffect& ge = args.fFp.cast<GrGammaEffect>();
22 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 22 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
23 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 23 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
24 24
25 const char* gammaUniName = nullptr; 25 const char* gammaUniName = nullptr;
26 if (!ge.gammaIsSRGB()) { 26 if (GrGammaEffect::Mode::kExponential == ge.mode()) {
27 fGammaUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloa t_GrSLType, 27 fGammaUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloa t_GrSLType,
28 kDefault_GrSLPrecision, "Gamm a", &gammaUniName); 28 kDefault_GrSLPrecision, "Gamm a", &gammaUniName);
29 } 29 }
30 30
31 GrGLSLShaderVar tmpVar("tmpColor", kVec4f_GrSLType, 0, kHigh_GrSLPrecisi on);
32 SkString tmpDecl;
33 tmpVar.appendDecl(args.fGLSLCaps, &tmpDecl);
34
35 SkString srgbFuncName; 31 SkString srgbFuncName;
36 if (ge.gammaIsSRGB()) { 32 static const GrGLSLShaderVar gSrgbArgs[] = {
37 static const GrGLSLShaderVar gSrgbArgs[] = { 33 GrGLSLShaderVar("x", kFloat_GrSLType),
38 GrGLSLShaderVar("x", kFloat_GrSLType), 34 };
39 }; 35 switch (ge.mode()) {
40 36 case GrGammaEffect::Mode::kLinearToSRGB:
41 fragBuilder->emitFunction(kFloat_GrSLType, 37 fragBuilder->emitFunction(kFloat_GrSLType,
42 "linear_to_srgb", 38 "linear_to_srgb",
43 SK_ARRAY_COUNT(gSrgbArgs), 39 SK_ARRAY_COUNT(gSrgbArgs),
44 gSrgbArgs, 40 gSrgbArgs,
45 "return (x <= 0.0031308) ? (x * 12.92) " 41 "return (x <= 0.0031308) ? (x * 12.92) "
46 ": (1.055 * pow(x, 0.416666667) - 0.055) ;", 42 ": (1.055 * pow(x, 0.416666667) - 0.05 5);",
47 &srgbFuncName); 43 &srgbFuncName);
44 break;
45 case GrGammaEffect::Mode::kSRGBToLinear:
46 fragBuilder->emitFunction(kFloat_GrSLType,
47 "srgb_to_linear",
48 SK_ARRAY_COUNT(gSrgbArgs),
49 gSrgbArgs,
50 "return (x <= 0.04045) ? (x / 12.92) "
51 ": pow((x + 0.055) / 1.055, 2.4);",
52 &srgbFuncName);
53 default:
54 // No helper function needed
55 break;
48 } 56 }
49 57
50 fragBuilder->codeAppendf("%s;", tmpDecl.c_str()); 58 if (nullptr == args.fInputColor) {
59 args.fInputColor = "vec4(1)";
60 }
51 61
52 fragBuilder->codeAppendf("%s = ", tmpVar.c_str()); 62 if (GrGammaEffect::Mode::kExponential == ge.mode()) {
53 fragBuilder->appendTextureLookup(args.fTexSamplers[0], args.fCoords[0].c _str(), 63 fragBuilder->codeAppendf("%s = vec4(pow(%s.rgb, vec3(%s)), %s.a);",
54 args.fCoords[0].getType()); 64 args.fOutputColor, args.fInputColor, gammaU niName,
55 fragBuilder->codeAppend(";"); 65 args.fInputColor);
56 66 } else {
57 if (ge.gammaIsSRGB()) {
58 fragBuilder->codeAppendf("%s = vec4(%s(%s.r), %s(%s.g), %s(%s.b), %s .a);", 67 fragBuilder->codeAppendf("%s = vec4(%s(%s.r), %s(%s.g), %s(%s.b), %s .a);",
59 args.fOutputColor, 68 args.fOutputColor,
60 srgbFuncName.c_str(), tmpVar.c_str(), 69 srgbFuncName.c_str(), args.fInputColor,
61 srgbFuncName.c_str(), tmpVar.c_str(), 70 srgbFuncName.c_str(), args.fInputColor,
62 srgbFuncName.c_str(), tmpVar.c_str(), 71 srgbFuncName.c_str(), args.fInputColor,
63 tmpVar.c_str()); 72 args.fInputColor);
64 } else {
65 fragBuilder->codeAppendf("%s = vec4(pow(%s.rgb, vec3(%s)), %s.a);",
66 args.fOutputColor, tmpVar.c_str(), gamma UniName,
67 tmpVar.c_str());
68 } 73 }
69 } 74 }
70 75
71 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& pro c) override { 76 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& pro c) override {
72 const GrGammaEffect& ge = proc.cast<GrGammaEffect>(); 77 const GrGammaEffect& ge = proc.cast<GrGammaEffect>();
73 if (!ge.gammaIsSRGB()) { 78 if (GrGammaEffect::Mode::kExponential == ge.mode()) {
74 pdman.set1f(fGammaUni, ge.gamma()); 79 pdman.set1f(fGammaUni, ge.gamma());
75 } 80 }
76 } 81 }
77 82
78 static inline void GenKey(const GrProcessor& processor, const GrGLSLCaps&, 83 static inline void GenKey(const GrProcessor& processor, const GrGLSLCaps&,
79 GrProcessorKeyBuilder* b) { 84 GrProcessorKeyBuilder* b) {
80 const GrGammaEffect& ge = processor.cast<GrGammaEffect>(); 85 const GrGammaEffect& ge = processor.cast<GrGammaEffect>();
81 uint32_t key = ge.gammaIsSRGB() ? 0x1 : 0x0; 86 uint32_t key = static_cast<uint32_t>(ge.mode());
82 b->add32(key); 87 b->add32(key);
83 } 88 }
84 89
85 private: 90 private:
86 GrGLSLProgramDataManager::UniformHandle fGammaUni; 91 GrGLSLProgramDataManager::UniformHandle fGammaUni;
87 92
88 typedef GrGLSLFragmentProcessor INHERITED; 93 typedef GrGLSLFragmentProcessor INHERITED;
89 }; 94 };
90 95
91 /////////////////////////////////////////////////////////////////////////////// 96 ///////////////////////////////////////////////////////////////////////////////
92 97
93 GrGammaEffect::GrGammaEffect(GrTexture* texture, SkScalar gamma) 98 GrGammaEffect::GrGammaEffect(Mode mode, SkScalar gamma)
94 : INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture)) { 99 : fMode(mode)
100 , fGamma(gamma) {
95 this->initClassID<GrGammaEffect>(); 101 this->initClassID<GrGammaEffect>();
96
97 fGamma = gamma;
98 fGammaIsSRGB = SkScalarNearlyEqual(gamma, 1.0f / 2.2f);
99 } 102 }
100 103
101 bool GrGammaEffect::onIsEqual(const GrFragmentProcessor& s) const { 104 bool GrGammaEffect::onIsEqual(const GrFragmentProcessor& s) const {
102 const GrGammaEffect& other = s.cast<GrGammaEffect>(); 105 const GrGammaEffect& other = s.cast<GrGammaEffect>();
103 return 106 return
104 other.fGammaIsSRGB == fGammaIsSRGB && 107 other.fMode == fMode &&
105 other.fGamma == fGamma; 108 (fMode != Mode::kExponential || other.fGamma == fGamma);
106 } 109 }
107 110
108 void GrGammaEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { 111 void GrGammaEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
109 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); 112 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
110 } 113 }
111 114
112 /////////////////////////////////////////////////////////////////////////////// 115 ///////////////////////////////////////////////////////////////////////////////
113 116
114 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrGammaEffect); 117 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrGammaEffect);
115 118
116 const GrFragmentProcessor* GrGammaEffect::TestCreate(GrProcessorTestData* d) { 119 const GrFragmentProcessor* GrGammaEffect::TestCreate(GrProcessorTestData* d) {
117 // We want to be sure and test sRGB sometimes 120 // We want to be sure and test sRGB sometimes
118 bool srgb = d->fRandom->nextBool(); 121 Mode testMode = static_cast<Mode>(d->fRandom->nextRangeU(0, 2));
119 return new GrGammaEffect(d->fTextures[GrProcessorUnitTest::kSkiaPMTextureIdx ], 122 SkScalar gamma = d->fRandom->nextRangeScalar(0.5f, 2.0f);
120 srgb ? 1.0f / 2.2f : d->fRandom->nextRangeScalar(0. 5f, 2.0f)); 123 return new GrGammaEffect(testMode, gamma);
121 } 124 }
122 125
123 /////////////////////////////////////////////////////////////////////////////// 126 ///////////////////////////////////////////////////////////////////////////////
124 127
125 void GrGammaEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, 128 void GrGammaEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
126 GrProcessorKeyBuilder* b) const { 129 GrProcessorKeyBuilder* b) const {
127 GrGLGammaEffect::GenKey(*this, caps, b); 130 GrGLGammaEffect::GenKey(*this, caps, b);
128 } 131 }
129 132
130 GrGLSLFragmentProcessor* GrGammaEffect::onCreateGLSLInstance() const { 133 GrGLSLFragmentProcessor* GrGammaEffect::onCreateGLSLInstance() const {
131 return new GrGLGammaEffect(); 134 return new GrGLGammaEffect();
132 } 135 }
133 136
134 const GrFragmentProcessor* GrGammaEffect::Create(GrTexture* texture, SkScalar ga mma) { 137 const GrFragmentProcessor* GrGammaEffect::Create(SkScalar gamma) {
135 return new GrGammaEffect(texture, gamma); 138 // TODO: Once our public-facing API for specifying gamma curves settles down , expose this,
139 // and allow clients to explicitly request sRGB, rather than inferring from the exponent.
140 // Note that AdobeRGB (for example) is speficied as x^2.2, not the Rec.709 c urves.
141 if (SkScalarNearlyEqual(gamma, 2.2f)) {
142 return new GrGammaEffect(Mode::kSRGBToLinear, 2.2f);
143 } else if (SkScalarNearlyEqual(gamma, 1.0f / 2.2f)) {
144 return new GrGammaEffect(Mode::kLinearToSRGB, 1.0f / 2.2f);
145 } else {
146 return new GrGammaEffect(Mode::kExponential, gamma);
147 }
136 } 148 }
OLDNEW
« no previous file with comments | « src/gpu/effects/GrGammaEffect.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698