diff options
author | brianosman <brianosman@google.com> | 2016-05-05 12:24:31 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-05-05 12:24:31 -0700 |
commit | 2d1ee7936e3536e45c963db004e3b512bb415fd8 (patch) | |
tree | edefade2fbe8c19d10abae08f3a658f202bbb5c1 /src/gpu | |
parent | d215a95882485026d176a81bf58871276b21c89c (diff) |
Added --deepColor option to SampleApp, triggers creation of a ten-bit/channel
buffer. (Only on Windows at the moment). Uses new effect to do the final
gamma adjustment
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1919993002
Review-Url: https://codereview.chromium.org/1919993002
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrContext.cpp | 39 | ||||
-rw-r--r-- | src/gpu/GrProcessor.cpp | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrGammaEffect.cpp | 136 | ||||
-rw-r--r-- | src/gpu/effects/GrGammaEffect.h | 42 |
4 files changed, 218 insertions, 1 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 31845f9d6d..3ea67c9f01 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -20,6 +20,7 @@ #include "batches/GrCopySurfaceBatch.h" #include "effects/GrConfigConversionEffect.h" +#include "effects/GrGammaEffect.h" #include "text/GrTextBlobCache.h" #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this) @@ -529,6 +530,44 @@ bool GrContext::readSurfacePixels(GrSurface* src, return true; } +bool GrContext::applyGamma(GrRenderTarget* dst, GrTexture* src, SkScalar gamma){ + ASSERT_SINGLE_OWNER + RETURN_FALSE_IF_ABANDONED + ASSERT_OWNED_RESOURCE(dst); + ASSERT_OWNED_RESOURCE(src); + GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::applyGamma"); + + // Dimensions must match exactly. + if (dst->width() != src->width() || dst->height() != src->height()) { + return false; + } + + SkSurfaceProps props(SkSurfaceProps::kGammaCorrect_Flag, + SkSurfaceProps::kLegacyFontHost_InitType); + sk_sp<GrDrawContext> drawContext(this->drawContext(sk_ref_sp(dst), &props)); + if (!drawContext) { + return false; + } + + 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.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); + paint.setGammaCorrect(true); + + SkRect rect; + src->getBoundsRect(&rect); + drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), rect); + + this->flushSurfaceWrites(dst); + return true; +} + void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) { ASSERT_SINGLE_OWNER RETURN_IF_ABANDONED diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp index 0d3f8d9166..29482ccc63 100644 --- a/src/gpu/GrProcessor.cpp +++ b/src/gpu/GrProcessor.cpp @@ -48,7 +48,7 @@ GrProcessorTestFactory<GrGeometryProcessor>::GetFactories() { * we verify the count is as expected. If a new factory is added, then these numbers must be * manually adjusted. */ -static const int kFPFactoryCount = 39; +static const int kFPFactoryCount = 40; static const int kGPFactoryCount = 14; static const int kXPFactoryCount = 6; diff --git a/src/gpu/effects/GrGammaEffect.cpp b/src/gpu/effects/GrGammaEffect.cpp new file mode 100644 index 0000000000..b2aa48aad2 --- /dev/null +++ b/src/gpu/effects/GrGammaEffect.cpp @@ -0,0 +1,136 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGammaEffect.h" + +#include "GrContext.h" +#include "GrCoordTransform.h" +#include "GrFragmentProcessor.h" +#include "GrInvariantOutput.h" +#include "GrProcessor.h" +#include "glsl/GrGLSLFragmentProcessor.h" +#include "glsl/GrGLSLFragmentShaderBuilder.h" + +class GrGLGammaEffect : public GrGLSLFragmentProcessor { +public: + void emitCode(EmitArgs& args) override { + const GrGammaEffect& ge = args.fFp.cast<GrGammaEffect>(); + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; + GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; + + const char* gammaUniName = nullptr; + if (!ge.gammaIsSRGB()) { + 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); + } + + 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 (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 { + fragBuilder->codeAppendf("%s = vec4(pow(%s.rgb, vec3(%s)), %s.a);", + args.fOutputColor, tmpVar.c_str(), gammaUniName, + tmpVar.c_str()); + } + } + + void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override { + const GrGammaEffect& ge = proc.cast<GrGammaEffect>(); + if (!ge.gammaIsSRGB()) { + pdman.set1f(fGammaUni, ge.gamma()); + } + } + + static inline void GenKey(const GrProcessor& processor, const GrGLSLCaps&, + GrProcessorKeyBuilder* b) { + const GrGammaEffect& ge = processor.cast<GrGammaEffect>(); + uint32_t key = ge.gammaIsSRGB() ? 0x1 : 0x0; + b->add32(key); + } + +private: + GrGLSLProgramDataManager::UniformHandle fGammaUni; + + typedef GrGLSLFragmentProcessor INHERITED; +}; + +/////////////////////////////////////////////////////////////////////////////// + +GrGammaEffect::GrGammaEffect(GrTexture* texture, SkScalar gamma) + : INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture)) { + 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; +} + +void GrGammaEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { + inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); +} + +/////////////////////////////////////////////////////////////////////////////// + +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)); +} + +/////////////////////////////////////////////////////////////////////////////// + +void GrGammaEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, + GrProcessorKeyBuilder* b) const { + GrGLGammaEffect::GenKey(*this, caps, b); +} + +GrGLSLFragmentProcessor* GrGammaEffect::onCreateGLSLInstance() const { + return new GrGLGammaEffect(); +} + +const GrFragmentProcessor* GrGammaEffect::Create(GrTexture* texture, SkScalar gamma) { + return new GrGammaEffect(texture, gamma); +} diff --git a/src/gpu/effects/GrGammaEffect.h b/src/gpu/effects/GrGammaEffect.h new file mode 100644 index 0000000000..44d6d6707c --- /dev/null +++ b/src/gpu/effects/GrGammaEffect.h @@ -0,0 +1,42 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGammaEffect_DEFINED +#define GrGammaEffect_DEFINED + +#include "GrSingleTextureEffect.h" + +class GrGammaEffect : public GrSingleTextureEffect { +public: + /** + * 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); + + const char* name() const override { return "Gamma"; } + + bool gammaIsSRGB() const { return fGammaIsSRGB; } + SkScalar gamma() const { return fGamma; } + +private: + GrGammaEffect(GrTexture*, 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; + SkScalar fGamma; + + GR_DECLARE_FRAGMENT_PROCESSOR_TEST; + + typedef GrSingleTextureEffect INHERITED; +}; + +#endif |