diff options
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrContext.cpp | 9 | ||||
-rw-r--r-- | src/gpu/effects/GrGammaEffect.cpp | 106 | ||||
-rw-r--r-- | src/gpu/effects/GrGammaEffect.h | 25 |
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..454f057de5 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) " + ": powf((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 |