aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar brianosman <brianosman@google.com>2016-05-11 06:49:32 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-05-11 06:49:32 -0700
commitfe4d5d3af53e2c6903abf9bdac2503e3e69ceffe (patch)
tree34f2235a835354437d3ea650d159c7dc5b1158c1 /src
parentfbb3102d0e5f4c7d4b89d710f806b163ae27c3c8 (diff)
Make GrGammaEffect have explicit sRGB modes, plus exponential mode.
Convert it to a "standard" FP that just transforms the input color. For now, we still infer the sRGB transfer curves from the exponent, but I'm hoping that eventually SkGammas will provide us with the exact curve we're supposed to be applying. In any case, this adds support for doing the inverse transformation, as well, which will be needed in an upcoming Vulkan YUV change, among other things. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1954863002 Committed: https://skia.googlesource.com/skia/+/2139303e4c0a9cbcfac695977a80eb026a9296ab Review-Url: https://codereview.chromium.org/1954863002
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrContext.cpp9
-rw-r--r--src/gpu/effects/GrGammaEffect.cpp106
-rw-r--r--src/gpu/effects/GrGammaEffect.h25
3 files changed, 77 insertions, 63 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 443494073a..4235ae8552 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -550,12 +550,9 @@ bool GrContext::applyGamma(GrRenderTarget* dst, GrTexture* src, SkScalar gamma){
}
GrPaint paint;
- if (SkScalarNearlyEqual(gamma, 1.0f)) {
- paint.addColorTextureProcessor(src, GrCoordTransform::MakeDivByTextureWHMatrix(src));
- } else {
- SkAutoTUnref<const GrFragmentProcessor> fp;
- fp.reset(GrGammaEffect::Create(src, gamma));
- paint.addColorFragmentProcessor(fp);
+ paint.addColorTextureProcessor(src, GrCoordTransform::MakeDivByTextureWHMatrix(src));
+ if (!SkScalarNearlyEqual(gamma, 1.0f)) {
+ paint.addColorFragmentProcessor(GrGammaEffect::Create(gamma))->unref();
}
paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
paint.setGammaCorrect(true);
diff --git a/src/gpu/effects/GrGammaEffect.cpp b/src/gpu/effects/GrGammaEffect.cpp
index b2aa48aad2..71d8c91423 100644
--- a/src/gpu/effects/GrGammaEffect.cpp
+++ b/src/gpu/effects/GrGammaEffect.cpp
@@ -23,54 +23,59 @@ public:
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
const char* gammaUniName = nullptr;
- if (!ge.gammaIsSRGB()) {
+ if (GrGammaEffect::Mode::kExponential == ge.mode()) {
fGammaUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType,
kDefault_GrSLPrecision, "Gamma", &gammaUniName);
}
- GrGLSLShaderVar tmpVar("tmpColor", kVec4f_GrSLType, 0, kHigh_GrSLPrecision);
- SkString tmpDecl;
- tmpVar.appendDecl(args.fGLSLCaps, &tmpDecl);
-
SkString srgbFuncName;
- if (ge.gammaIsSRGB()) {
- static const GrGLSLShaderVar gSrgbArgs[] = {
- GrGLSLShaderVar("x", kFloat_GrSLType),
- };
-
- fragBuilder->emitFunction(kFloat_GrSLType,
- "linear_to_srgb",
- SK_ARRAY_COUNT(gSrgbArgs),
- gSrgbArgs,
- "return (x <= 0.0031308) ? (x * 12.92) "
- ": (1.055 * pow(x, 0.416666667) - 0.055);",
- &srgbFuncName);
+ static const GrGLSLShaderVar gSrgbArgs[] = {
+ GrGLSLShaderVar("x", kFloat_GrSLType),
+ };
+ switch (ge.mode()) {
+ case GrGammaEffect::Mode::kLinearToSRGB:
+ fragBuilder->emitFunction(kFloat_GrSLType,
+ "linear_to_srgb",
+ SK_ARRAY_COUNT(gSrgbArgs),
+ gSrgbArgs,
+ "return (x <= 0.0031308) ? (x * 12.92) "
+ ": (1.055 * pow(x, 0.416666667) - 0.055);",
+ &srgbFuncName);
+ break;
+ case GrGammaEffect::Mode::kSRGBToLinear:
+ fragBuilder->emitFunction(kFloat_GrSLType,
+ "srgb_to_linear",
+ SK_ARRAY_COUNT(gSrgbArgs),
+ gSrgbArgs,
+ "return (x <= 0.04045) ? (x / 12.92) "
+ ": pow((x + 0.055) / 1.055, 2.4);",
+ &srgbFuncName);
+ default:
+ // No helper function needed
+ break;
}
- fragBuilder->codeAppendf("%s;", tmpDecl.c_str());
-
- fragBuilder->codeAppendf("%s = ", tmpVar.c_str());
- fragBuilder->appendTextureLookup(args.fTexSamplers[0], args.fCoords[0].c_str(),
- args.fCoords[0].getType());
- fragBuilder->codeAppend(";");
+ if (nullptr == args.fInputColor) {
+ args.fInputColor = "vec4(1)";
+ }
- if (ge.gammaIsSRGB()) {
- fragBuilder->codeAppendf("%s = vec4(%s(%s.r), %s(%s.g), %s(%s.b), %s.a);",
- args.fOutputColor,
- srgbFuncName.c_str(), tmpVar.c_str(),
- srgbFuncName.c_str(), tmpVar.c_str(),
- srgbFuncName.c_str(), tmpVar.c_str(),
- tmpVar.c_str());
- } else {
+ if (GrGammaEffect::Mode::kExponential == ge.mode()) {
fragBuilder->codeAppendf("%s = vec4(pow(%s.rgb, vec3(%s)), %s.a);",
- args.fOutputColor, tmpVar.c_str(), gammaUniName,
- tmpVar.c_str());
+ args.fOutputColor, args.fInputColor, gammaUniName,
+ args.fInputColor);
+ } else {
+ fragBuilder->codeAppendf("%s = vec4(%s(%s.r), %s(%s.g), %s(%s.b), %s.a);",
+ args.fOutputColor,
+ srgbFuncName.c_str(), args.fInputColor,
+ srgbFuncName.c_str(), args.fInputColor,
+ srgbFuncName.c_str(), args.fInputColor,
+ args.fInputColor);
}
}
void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {
const GrGammaEffect& ge = proc.cast<GrGammaEffect>();
- if (!ge.gammaIsSRGB()) {
+ if (GrGammaEffect::Mode::kExponential == ge.mode()) {
pdman.set1f(fGammaUni, ge.gamma());
}
}
@@ -78,7 +83,7 @@ public:
static inline void GenKey(const GrProcessor& processor, const GrGLSLCaps&,
GrProcessorKeyBuilder* b) {
const GrGammaEffect& ge = processor.cast<GrGammaEffect>();
- uint32_t key = ge.gammaIsSRGB() ? 0x1 : 0x0;
+ uint32_t key = static_cast<uint32_t>(ge.mode());
b->add32(key);
}
@@ -90,19 +95,17 @@ private:
///////////////////////////////////////////////////////////////////////////////
-GrGammaEffect::GrGammaEffect(GrTexture* texture, SkScalar gamma)
- : INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture)) {
+GrGammaEffect::GrGammaEffect(Mode mode, SkScalar gamma)
+ : fMode(mode)
+ , fGamma(gamma) {
this->initClassID<GrGammaEffect>();
-
- fGamma = gamma;
- fGammaIsSRGB = SkScalarNearlyEqual(gamma, 1.0f / 2.2f);
}
bool GrGammaEffect::onIsEqual(const GrFragmentProcessor& s) const {
const GrGammaEffect& other = s.cast<GrGammaEffect>();
return
- other.fGammaIsSRGB == fGammaIsSRGB &&
- other.fGamma == fGamma;
+ other.fMode == fMode &&
+ (fMode != Mode::kExponential || other.fGamma == fGamma);
}
void GrGammaEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
@@ -115,9 +118,9 @@ GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrGammaEffect);
const GrFragmentProcessor* GrGammaEffect::TestCreate(GrProcessorTestData* d) {
// We want to be sure and test sRGB sometimes
- bool srgb = d->fRandom->nextBool();
- return new GrGammaEffect(d->fTextures[GrProcessorUnitTest::kSkiaPMTextureIdx],
- srgb ? 1.0f / 2.2f : d->fRandom->nextRangeScalar(0.5f, 2.0f));
+ Mode testMode = static_cast<Mode>(d->fRandom->nextRangeU(0, 2));
+ SkScalar gamma = d->fRandom->nextRangeScalar(0.5f, 2.0f);
+ return new GrGammaEffect(testMode, gamma);
}
///////////////////////////////////////////////////////////////////////////////
@@ -131,6 +134,15 @@ GrGLSLFragmentProcessor* GrGammaEffect::onCreateGLSLInstance() const {
return new GrGLGammaEffect();
}
-const GrFragmentProcessor* GrGammaEffect::Create(GrTexture* texture, SkScalar gamma) {
- return new GrGammaEffect(texture, gamma);
+const GrFragmentProcessor* GrGammaEffect::Create(SkScalar gamma) {
+ // TODO: Once our public-facing API for specifying gamma curves settles down, expose this,
+ // and allow clients to explicitly request sRGB, rather than inferring from the exponent.
+ // Note that AdobeRGB (for example) is speficied as x^2.2, not the Rec.709 curves.
+ if (SkScalarNearlyEqual(gamma, 2.2f)) {
+ return new GrGammaEffect(Mode::kSRGBToLinear, 2.2f);
+ } else if (SkScalarNearlyEqual(gamma, 1.0f / 2.2f)) {
+ return new GrGammaEffect(Mode::kLinearToSRGB, 1.0f / 2.2f);
+ } else {
+ return new GrGammaEffect(Mode::kExponential, gamma);
+ }
}
diff --git a/src/gpu/effects/GrGammaEffect.h b/src/gpu/effects/GrGammaEffect.h
index 44d6d6707c..2e53b09278 100644
--- a/src/gpu/effects/GrGammaEffect.h
+++ b/src/gpu/effects/GrGammaEffect.h
@@ -8,35 +8,40 @@
#ifndef GrGammaEffect_DEFINED
#define GrGammaEffect_DEFINED
-#include "GrSingleTextureEffect.h"
+#include "GrFragmentProcessor.h"
-class GrGammaEffect : public GrSingleTextureEffect {
+class GrGammaEffect : public GrFragmentProcessor {
public:
+ enum class Mode {
+ kLinearToSRGB,
+ kSRGBToLinear,
+ kExponential,
+ };
+
/**
- * Creates an effect that applies a gamma curve. The source texture is always
- * sampled unfiltered and with clamping.
- */
- static const GrFragmentProcessor* Create(GrTexture*, SkScalar gamma);
+ * Creates an effect that applies a gamma curve.
+ */
+ static const GrFragmentProcessor* Create(SkScalar gamma);
const char* name() const override { return "Gamma"; }
- bool gammaIsSRGB() const { return fGammaIsSRGB; }
+ Mode mode() const { return fMode; }
SkScalar gamma() const { return fGamma; }
private:
- GrGammaEffect(GrTexture*, SkScalar gamma);
+ GrGammaEffect(Mode mode, SkScalar gamma);
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
- bool fGammaIsSRGB;
+ Mode fMode;
SkScalar fGamma;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
- typedef GrSingleTextureEffect INHERITED;
+ typedef GrFragmentProcessor INHERITED;
};
#endif