diff options
Diffstat (limited to 'src/gpu/effects')
-rw-r--r-- | src/gpu/effects/GrDitherEffect.cpp | 75 | ||||
-rw-r--r-- | src/gpu/effects/GrDitherEffect.fp | 85 | ||||
-rw-r--r-- | src/gpu/effects/GrDitherEffect.h | 67 | ||||
-rw-r--r-- | src/gpu/effects/GrRectBlurEffect.cpp | 34 | ||||
-rw-r--r-- | src/gpu/effects/GrSkSLFP.cpp | 268 | ||||
-rw-r--r-- | src/gpu/effects/GrSkSLFP.h | 147 |
6 files changed, 244 insertions, 432 deletions
diff --git a/src/gpu/effects/GrDitherEffect.cpp b/src/gpu/effects/GrDitherEffect.cpp new file mode 100644 index 0000000000..17c8776524 --- /dev/null +++ b/src/gpu/effects/GrDitherEffect.cpp @@ -0,0 +1,75 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/************************************************************************************************** + *** This file was autogenerated from GrDitherEffect.fp; do not modify. + **************************************************************************************************/ +#include "GrDitherEffect.h" +#include "glsl/GrGLSLFragmentProcessor.h" +#include "glsl/GrGLSLFragmentShaderBuilder.h" +#include "glsl/GrGLSLProgramBuilder.h" +#include "GrTexture.h" +#include "SkSLCPP.h" +#include "SkSLUtil.h" +class GrGLSLDitherEffect : public GrGLSLFragmentProcessor { +public: + GrGLSLDitherEffect() {} + void emitCode(EmitArgs& args) override { + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; + const GrDitherEffect& _outer = args.fFp.cast<GrDitherEffect>(); + (void)_outer; + auto rangeType = _outer.rangeType(); + (void)rangeType; + fragBuilder->codeAppendf( + "half value;\nhalf range;\n@switch (%d) {\n case 0:\n range = " + "0.0039215686274509803;\n break;\n case 1:\n range = " + "0.015873015873015872;\n break;\n default:\n range = " + "0.066666666666666666;\n break;\n}\n@if (sk_Caps.integerSupport) {\n " + "uint x = uint(sk_FragCoord.x);\n uint y = uint(sk_FragCoord.y);\n uint m = " + "(((((y & 1) << 5 | (x & 1) << 4) | (y & 2) << 2) | (x & 2) << 1) | (y & 4) >> 1) " + "| (x & 4) >> 2;\n value = float(float(half(m)) / 64.0) - 0.4", + _outer.rangeType()); + fragBuilder->codeAppendf( + "921875;\n} else {\n half4 modValues = half4(mod(sk_FragCoord.xyxy, " + "float4(half4(2.0, 2.0, 4.0, 4.0))));\n half4 stepValues = " + "half4(step(float4(modValues), float4(half4(1.0, 1.0, 2.0, 2.0))));\n value = " + "float(dot(stepValues, half4(0.5, 0.25, 0.125, 0.0625))) - 0.46875;\n}\n%s = " + "half4(clamp(float3(%s.xyz + value * range), 0.0, float(%s.w)), %s.w);\n", + args.fOutputColor, args.fInputColor ? args.fInputColor : "half4(1)", + args.fInputColor ? args.fInputColor : "half4(1)", + args.fInputColor ? args.fInputColor : "half4(1)"); + } + +private: + void onSetData(const GrGLSLProgramDataManager& pdman, + const GrFragmentProcessor& _proc) override {} +}; +GrGLSLFragmentProcessor* GrDitherEffect::onCreateGLSLInstance() const { + return new GrGLSLDitherEffect(); +} +void GrDitherEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, + GrProcessorKeyBuilder* b) const { + b->add32((int32_t)fRangeType); +} +bool GrDitherEffect::onIsEqual(const GrFragmentProcessor& other) const { + const GrDitherEffect& that = other.cast<GrDitherEffect>(); + (void)that; + if (fRangeType != that.fRangeType) return false; + return true; +} +GrDitherEffect::GrDitherEffect(const GrDitherEffect& src) + : INHERITED(kGrDitherEffect_ClassID, src.optimizationFlags()), fRangeType(src.fRangeType) {} +std::unique_ptr<GrFragmentProcessor> GrDitherEffect::clone() const { + return std::unique_ptr<GrFragmentProcessor>(new GrDitherEffect(*this)); +} +GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDitherEffect); +#if GR_TEST_UTILS +std::unique_ptr<GrFragmentProcessor> GrDitherEffect::TestCreate(GrProcessorTestData* testData) { + float range = testData->fRandom->nextRangeF(0.001f, 0.05f); + return std::unique_ptr<GrFragmentProcessor>(new GrDitherEffect(range)); +} +#endif diff --git a/src/gpu/effects/GrDitherEffect.fp b/src/gpu/effects/GrDitherEffect.fp new file mode 100644 index 0000000000..ed6c0e6b70 --- /dev/null +++ b/src/gpu/effects/GrDitherEffect.fp @@ -0,0 +1,85 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +// This controls the range of values added to color channels +layout(key) in int rangeType; + +@make { + static std::unique_ptr<GrFragmentProcessor> Make(GrPixelConfig dstConfig) { + int rangeType; + switch (dstConfig) { + case kGray_8_GrPixelConfig: + case kGray_8_as_Lum_GrPixelConfig: + case kGray_8_as_Red_GrPixelConfig: + case kRGBA_8888_GrPixelConfig: + case kRGB_888_GrPixelConfig: + case kBGRA_8888_GrPixelConfig: + rangeType = 0; + break; + case kRGB_565_GrPixelConfig: + rangeType = 1; + break; + case kRGBA_4444_GrPixelConfig: + rangeType = 2; + break; + case kUnknown_GrPixelConfig: + case kSRGBA_8888_GrPixelConfig: + case kSBGRA_8888_GrPixelConfig: + case kRGBA_1010102_GrPixelConfig: + case kAlpha_half_GrPixelConfig: + case kAlpha_half_as_Red_GrPixelConfig: + case kRGBA_float_GrPixelConfig: + case kRG_float_GrPixelConfig: + case kRGBA_half_GrPixelConfig: + case kAlpha_8_GrPixelConfig: + case kAlpha_8_as_Alpha_GrPixelConfig: + case kAlpha_8_as_Red_GrPixelConfig: + return nullptr; + } + return std::unique_ptr<GrFragmentProcessor>(new GrDitherEffect(rangeType)); + } +} + +void main() { + half value; + half range; + @switch (rangeType) { + case 0: + range = 1.0 / 255.0; + break; + case 1: + range = 1.0 / 63.0; + break; + default: + // Experimentally this looks better than the expected value of 1/15. + range = 1.0 / 15.0; + break; + } + @if (sk_Caps.integerSupport) { + // This ordered-dither code is lifted from the cpu backend. + uint x = uint(sk_FragCoord.x); + uint y = uint(sk_FragCoord.y); + uint m = (y & 1) << 5 | (x & 1) << 4 | + (y & 2) << 2 | (x & 2) << 1 | + (y & 4) >> 1 | (x & 4) >> 2; + value = half(m) * 1.0 / 64.0 - 63.0 / 128.0; + } else { + // Simulate the integer effect used above using step/mod. For speed, simulates a 4x4 + // dither pattern rather than an 8x8 one. + half4 modValues = mod(sk_FragCoord.xyxy, half4(2.0, 2.0, 4.0, 4.0)); + half4 stepValues = step(modValues, half4(1.0, 1.0, 2.0, 2.0)); + value = dot(stepValues, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0; + } + // For each color channel, add the random offset to the channel value and then clamp + // between 0 and alpha to keep the color premultiplied. + sk_OutColor = half4(clamp(sk_InColor.rgb + value * range, 0, sk_InColor.a), sk_InColor.a); +} + +@test(testData) { + float range = testData->fRandom->nextRangeF(0.001f, 0.05f); + return std::unique_ptr<GrFragmentProcessor>(new GrDitherEffect(range)); +} diff --git a/src/gpu/effects/GrDitherEffect.h b/src/gpu/effects/GrDitherEffect.h new file mode 100644 index 0000000000..70adc45e6a --- /dev/null +++ b/src/gpu/effects/GrDitherEffect.h @@ -0,0 +1,67 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/************************************************************************************************** + *** This file was autogenerated from GrDitherEffect.fp; do not modify. + **************************************************************************************************/ +#ifndef GrDitherEffect_DEFINED +#define GrDitherEffect_DEFINED +#include "SkTypes.h" +#include "GrFragmentProcessor.h" +#include "GrCoordTransform.h" +class GrDitherEffect : public GrFragmentProcessor { +public: + int rangeType() const { return fRangeType; } + + static std::unique_ptr<GrFragmentProcessor> Make(GrPixelConfig dstConfig) { + int rangeType; + switch (dstConfig) { + case kGray_8_GrPixelConfig: + case kGray_8_as_Lum_GrPixelConfig: + case kGray_8_as_Red_GrPixelConfig: + case kRGBA_8888_GrPixelConfig: + case kRGB_888_GrPixelConfig: + case kBGRA_8888_GrPixelConfig: + rangeType = 0; + break; + case kRGB_565_GrPixelConfig: + rangeType = 1; + break; + case kRGBA_4444_GrPixelConfig: + rangeType = 2; + break; + case kUnknown_GrPixelConfig: + case kSRGBA_8888_GrPixelConfig: + case kSBGRA_8888_GrPixelConfig: + case kRGBA_1010102_GrPixelConfig: + case kAlpha_half_GrPixelConfig: + case kAlpha_half_as_Red_GrPixelConfig: + case kRGBA_float_GrPixelConfig: + case kRG_float_GrPixelConfig: + case kRGBA_half_GrPixelConfig: + case kAlpha_8_GrPixelConfig: + case kAlpha_8_as_Alpha_GrPixelConfig: + case kAlpha_8_as_Red_GrPixelConfig: + return nullptr; + } + return std::unique_ptr<GrFragmentProcessor>(new GrDitherEffect(rangeType)); + } + GrDitherEffect(const GrDitherEffect& src); + std::unique_ptr<GrFragmentProcessor> clone() const override; + const char* name() const override { return "DitherEffect"; } + +private: + GrDitherEffect(int rangeType) + : INHERITED(kGrDitherEffect_ClassID, kNone_OptimizationFlags), fRangeType(rangeType) {} + GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; + void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; + bool onIsEqual(const GrFragmentProcessor&) const override; + GR_DECLARE_FRAGMENT_PROCESSOR_TEST + int fRangeType; + typedef GrFragmentProcessor INHERITED; +}; +#endif diff --git a/src/gpu/effects/GrRectBlurEffect.cpp b/src/gpu/effects/GrRectBlurEffect.cpp index d423b786ce..219fefa713 100644 --- a/src/gpu/effects/GrRectBlurEffect.cpp +++ b/src/gpu/effects/GrRectBlurEffect.cpp @@ -46,13 +46,13 @@ public: fProfileSizeVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, kDefault_GrSLPrecision, "profileSize"); fragBuilder->codeAppendf( - "/* key */ bool highPrecision = %s;\n@if (highPrecision) {\n float2 " - "translatedPos = sk_FragCoord.xy - %s.xy;\n float width = %s.z - %s.x;\n " - "float height = %s.w - %s.y;\n float2 smallDims = float2(width - float(%s), " - "height - float(%s));\n float center = 2.0 * floor(float(float(%s / 2.0) + " - "0.25)) - 1.0;\n float2 wh = smallDims - float2(center, center);\n half " - "hcoord = half((abs(translatedPos.x - 0.5 * width) - 0.5 * wh.x) / float(%s));\n " - " half hlookup = texture(%s, float2(float(hcoord), ", + "bool highPrecision = %s;\n@if (highPrecision) {\n float2 translatedPos = " + "sk_FragCoord.xy - %s.xy;\n float width = %s.z - %s.x;\n float height = %s.w " + "- %s.y;\n float2 smallDims = float2(width - float(%s), height - float(%s));\n " + " float center = 2.0 * floor(float(float(%s / 2.0) + 0.25)) - 1.0;\n float2 wh " + "= smallDims - float2(center, center);\n half hcoord = " + "half((abs(translatedPos.x - 0.5 * width) - 0.5 * wh.x) / float(%s));\n half " + "hlookup = texture(%s, float2(float(hcoord), 0.5)).%s.w", (highPrecision ? "true" : "false"), args.fUniformHandler->getUniformCStr(fRectVar), args.fUniformHandler->getUniformCStr(fRectVar), args.fUniformHandler->getUniformCStr(fRectVar), @@ -62,16 +62,16 @@ public: args.fUniformHandler->getUniformCStr(fProfileSizeVar), args.fUniformHandler->getUniformCStr(fProfileSizeVar), args.fUniformHandler->getUniformCStr(fProfileSizeVar), - fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str()); + fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(), + fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str()); fragBuilder->codeAppendf( - "0.5)).%s.w;\n half vcoord = half((abs(translatedPos.y - 0.5 * height) - 0.5 * " - "wh.y) / float(%s));\n half vlookup = texture(%s, float2(float(vcoord), " - "0.5)).%s.w;\n %s = (%s * hlookup) * vlookup;\n} else {\n half2 " - "translatedPos = half2(sk_FragCoord.xy - %s.xy);\n half width = half(%s.z - " - "%s.x);\n half height = half(%s.w - %s.y);\n half2 smallDims = half2(width - " - "%s, height - %s);\n half center = half(2.0 * floor(float(float(%s / 2.0) + " - "0.25)) - 1.0);\n half2 wh = smallDims - half2(f", - fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(), + ";\n half vcoord = half((abs(translatedPos.y - 0.5 * height) - 0.5 * wh.y) / " + "float(%s));\n half vlookup = texture(%s, float2(float(vcoord), 0.5)).%s.w;\n " + " %s = (%s * hlookup) * vlookup;\n} else {\n half2 translatedPos = " + "half2(sk_FragCoord.xy - %s.xy);\n half width = half(%s.z - %s.x);\n half " + "height = half(%s.w - %s.y);\n half2 smallDims = half2(width - %s, height - " + "%s);\n half center = half(2.0 * floor(float(float(%s / 2.0) + 0.25)) - 1.0);\n " + " half2 wh = smallDims - half2(float2(floa", args.fUniformHandler->getUniformCStr(fProfileSizeVar), fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(), fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(), @@ -85,7 +85,7 @@ public: args.fUniformHandler->getUniformCStr(fProfileSizeVar), args.fUniformHandler->getUniformCStr(fProfileSizeVar)); fragBuilder->codeAppendf( - "loat2(float(center), float(center)));\n half hcoord = " + "t(center), float(center)));\n half hcoord = " "half((abs(float(float(translatedPos.x) - 0.5 * float(width))) - 0.5 * " "float(wh.x)) / float(%s));\n half hlookup = texture(%s, float2(float(hcoord), " "0.5)).%s.w;\n half vcoord = half((abs(float(float(translatedPos.y) - 0.5 * " diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp deleted file mode 100644 index bc84c833d7..0000000000 --- a/src/gpu/effects/GrSkSLFP.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "GrSkSLFP.h" -#include "glsl/GrGLSLFragmentProcessor.h" -#include "glsl/GrGLSLFragmentShaderBuilder.h" -#include "glsl/GrGLSLProgramBuilder.h" -#include "GrContext.h" -#include "GrContextPriv.h" -#include "GrTexture.h" -#include "SkSLUtil.h" - -GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl) - : fName(name) { - SkSL::Program::Settings settings; - settings.fCaps = shaderCaps; - fBaseProgram = fCompiler.convertProgram(SkSL::Program::kPipelineStage_Kind, - SkSL::String(sksl), - settings); - if (fCompiler.errorCount()) { - SkDebugf("%s\n", fCompiler.errorText().c_str()); - } - SkASSERT(fBaseProgram); - SkASSERT(!fCompiler.errorCount()); - for (const auto& e : *fBaseProgram) { - if (e.fKind == SkSL::ProgramElement::kVar_Kind) { - SkSL::VarDeclarations& v = (SkSL::VarDeclarations&) e; - for (const auto& varStatement : v.fVars) { - const SkSL::Variable& var = *((SkSL::VarDeclaration&) *varStatement).fVar; - if (var.fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { - fInputVars.push_back(&var); - } - if (var.fModifiers.fLayout.fKey) { - fKeyVars.push_back(&var); - } - } - } - } -} - -const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key, const void* inputs, - size_t inputSize) { - const auto& found = fSpecializations.find(key); - if (found != fSpecializations.end()) { - return found->second.get(); - } - - std::unordered_map<SkSL::String, SkSL::Program::Settings::Value> inputMap; - size_t offset = 0; - for (const auto& v : fInputVars) { - SkSL::String name(v->fName); - if (&v->fType == fCompiler.context().fInt_Type.get()) { - offset = SkAlign4(offset); - int32_t v = *(int32_t*) (((uint8_t*) inputs) + offset); - inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v))); - offset += sizeof(int32_t); - } - } - SkASSERT(offset == inputSize); - - std::unique_ptr<SkSL::Program> specialized = fCompiler.specialize(*fBaseProgram, inputMap); - SkAssertResult(fCompiler.optimize(*specialized)); - const SkSL::Program* result = specialized.get(); - fSpecializations.insert(std::make_pair(key, std::move(specialized))); - return result; -} - -class GrGLSLSkSLFP : public GrGLSLFragmentProcessor { -public: - GrGLSLSkSLFP(SkSL::String glsl, std::vector<SkSL::Compiler::FormatArg> formatArgs) - : fGLSL(glsl) - , fFormatArgs(formatArgs) {} - - void emitCode(EmitArgs& args) override { - GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - int substringStartIndex = 0; - int formatArgIndex = 0; - for (size_t i = 0; i < fGLSL.length(); ++i) { - char c = fGLSL[i]; - if (c == '%') { - fragBuilder->codeAppend(fGLSL.c_str() + substringStartIndex, - i - substringStartIndex); - ++i; - c = fGLSL[i]; - switch (c) { - case 's': - switch (fFormatArgs[formatArgIndex++]) { - case SkSL::Compiler::FormatArg::kInput: - fragBuilder->codeAppend(args.fInputColor ? args.fInputColor - : "half4(1)"); - break; - case SkSL::Compiler::FormatArg::kOutput: - fragBuilder->codeAppend(args.fOutputColor); - break; - } - break; - default: - fragBuilder->codeAppendf("%c", c); - } - substringStartIndex = i + 1; - } - } - fragBuilder->codeAppend(fGLSL.c_str() + substringStartIndex, - fGLSL.length() - substringStartIndex); - } - - // nearly-finished GLSL; still contains printf-style "%s" format tokens - const SkSL::String fGLSL; - std::vector<SkSL::Compiler::FormatArg> fFormatArgs; -}; - -std::unique_ptr<GrFragmentProcessor> GrSkSLFP::Make(GrContext* context, int index, const char* name, - const char* sksl, const void* inputs, - size_t inputSize) { - return std::unique_ptr<GrFragmentProcessor>(new GrSkSLFP( - context->contextPriv().getFPFactoryCache(), - context->contextPriv().caps()->shaderCaps(), - index, name, sksl, inputs, inputSize)); -} - - -GrSkSLFP::GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps, - int index, const char* name, const char* sksl, const void* inputs, - size_t inputSize) - : INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags) - , fFactoryCache(factoryCache) - , fShaderCaps(sk_ref_sp(shaderCaps)) - , fIndex(index) - , fName(name) - , fSkSL(sksl) - , fInputs(new int8_t[inputSize]) - , fInputSize(inputSize) { - memcpy(fInputs.get(), inputs, inputSize); -} - -GrSkSLFP::GrSkSLFP(const GrSkSLFP& other) - : INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags) - , fFactoryCache(other.fFactoryCache) - , fShaderCaps(other.fShaderCaps) - , fFactory(other.fFactory) - , fIndex(other.fIndex) - , fName(other.fName) - , fSkSL(other.fSkSL) - , fInputs(new int8_t[other.fInputSize]) - , fInputSize(other.fInputSize) { - memcpy(fInputs.get(), other.fInputs.get(), fInputSize); -} - -const char* GrSkSLFP::name() const { - return fName; -} - -void GrSkSLFP::createFactory() const { - if (!fFactory) { - fFactory = fFactoryCache->get(fIndex); - if (!fFactory) { - fFactory = sk_sp<GrSkSLFPFactory>(new GrSkSLFPFactory(fName, fShaderCaps.get(), fSkSL)); - fFactoryCache->set(fIndex, fFactory); - } - } -} - -GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const { - this->createFactory(); - const SkSL::Program* specialized = fFactory->getSpecialization(fKey, fInputs.get(), fInputSize); - SkSL::String glsl; - std::vector<SkSL::Compiler::FormatArg> formatArgs; - if (!fFactory->fCompiler.toPipelineStage(*specialized, &glsl, &formatArgs)) { - printf("%s\n", fFactory->fCompiler.errorText().c_str()); - abort(); - } - return new GrGLSLSkSLFP(glsl, formatArgs); -} - -void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps, - GrProcessorKeyBuilder* b) const { - this->createFactory(); - size_t offset = 0; - char* inputs = (char*) fInputs.get(); - for (const auto& v : fFactory->fInputVars) { - if (&v->fType == fFactory->fCompiler.context().fInt_Type.get()) { - offset = SkAlign4(offset); - if (v->fModifiers.fLayout.fKey) { - fKey += inputs[offset + 0]; - fKey += inputs[offset + 1]; - fKey += inputs[offset + 2]; - fKey += inputs[offset + 3]; - b->add32(*(int32_t*) (inputs + offset)); - } - offset += sizeof(int32_t); - } - else { - // unsupported input var type - SkASSERT(false); - } - } - SkASSERT(offset == fInputSize); -} - -bool GrSkSLFP::onIsEqual(const GrFragmentProcessor& other) const { - const GrSkSLFP& sk = other.cast<GrSkSLFP>(); - SkASSERT(fIndex != sk.fIndex || fInputSize == sk.fInputSize); - return fIndex == sk.fIndex && - !memcmp(fInputs.get(), sk.fInputs.get(), fInputSize); -} - -std::unique_ptr<GrFragmentProcessor> GrSkSLFP::clone() const { - return std::unique_ptr<GrFragmentProcessor>(new GrSkSLFP(*this)); -} - -// We have to do a bit of manual refcounting in the cache methods below. Ideally, we could just -// define fFactories to contain sk_sp<GrSkSLFPFactory> rather than GrSkSLFPFactory*, but that would -// require GrContext to include GrSkSLFP, which creates much bigger headaches than a few manual -// refcounts. - -sk_sp<GrSkSLFPFactory> GrSkSLFPFactoryCache::get(int index) { - if (index >= (int) fFactories.size()) { - return nullptr; - } - GrSkSLFPFactory* result = fFactories[index]; - result->ref(); - return sk_sp<GrSkSLFPFactory>(result); -} - -void GrSkSLFPFactoryCache::set(int index, sk_sp<GrSkSLFPFactory> factory) { - while (index >= (int) fFactories.size()) { - fFactories.emplace_back(); - } - factory->ref(); - SkASSERT(!fFactories[index]); - fFactories[index] = factory.get(); -} - -GrSkSLFPFactoryCache::~GrSkSLFPFactoryCache() { - for (GrSkSLFPFactory* factory : fFactories) { - if (factory) { - factory->unref(); - } - } -} - -GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSkSLFP); - -#if GR_TEST_UTILS - -#include "SkGr.h" - -using Value = SkSL::Program::Settings::Value; - -std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d) { - int type = d->fRandom->nextULessThan(1); - switch (type) { - case 0: { - static int ditherIndex = NewIndex(); - int rangeType = d->fRandom->nextULessThan(3); - return GrSkSLFP::Make(d->context(), ditherIndex, "Dither", SKSL_DITHER_SRC, &rangeType, - sizeof(rangeType)); - } - } - SK_ABORT("unreachable"); - return nullptr; -} - -#endif diff --git a/src/gpu/effects/GrSkSLFP.h b/src/gpu/effects/GrSkSLFP.h deleted file mode 100644 index 428e0892e0..0000000000 --- a/src/gpu/effects/GrSkSLFP.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrSkSLFP_DEFINED -#define GrSkSLFP_DEFINED - -#include "GrCaps.h" -#include "GrFragmentProcessor.h" -#include "GrCoordTransform.h" -#include "GrShaderCaps.h" -#include "SkSLCompiler.h" -#include "SkSLPipelineStageCodeGenerator.h" -#include "SkRefCnt.h" -#include "../private/GrSkSLFPFactoryCache.h" - -class GrContext; -class GrSkSLFPFactory; - -class GrSkSLFP : public GrFragmentProcessor { -public: - /** - * Returns a new unique identifier. Each different SkSL fragment processor should call - * NewIndex once, statically, and use this index for all calls to Make. - */ - static int NewIndex() { - static int index = 0; - return sk_atomic_inc(&index); - } - - /** - * Creates a new fragment processor from an SkSL source string and a struct of inputs to the - * program. The input struct's type is derived from the 'in' variables in the SkSL source, so - * e.g. the shader: - * - * in bool dither; - * in float x; - * in float y; - * .... - * - * would expect a pointer to a struct set up like: - * - * struct { - * bool dither; - * float x; - * float y; - * }; - * - * As turning SkSL into GLSL / SPIR-V / etc. is fairly expensive, and the output may differ - * based on the inputs, internally the process is divided into two steps: we first parse and - * semantically analyze the SkSL into an internal representation, and then "specialize" this - * internal representation based on the inputs. The unspecialized internal representation of - * the program is cached, so further specializations of the same code are much faster than the - * first call. - * - * This caching is based on the 'index' parameter, which should be derived by statically calling - * 'NewIndex()'. Each given SkSL string should have a single, statically defined index - * associated with it. - */ - static std::unique_ptr<GrFragmentProcessor> Make( - GrContext* context, - int index, - const char* name, - const char* sksl, - const void* inputs, - size_t inputSize); - - const char* name() const override; - - std::unique_ptr<GrFragmentProcessor> clone() const override; - -private: - GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps, int fIndex, - const char* name, const char* sksl, const void* inputs, size_t inputSize); - - GrSkSLFP(const GrSkSLFP& other); - - GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; - - void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; - - bool onIsEqual(const GrFragmentProcessor&) const override; - - void createFactory() const; - - sk_sp<GrSkSLFPFactoryCache> fFactoryCache; - - const sk_sp<GrShaderCaps> fShaderCaps; - - mutable sk_sp<GrSkSLFPFactory> fFactory; - - int fIndex; - - const char* fName; - - const char* fSkSL; - - const std::unique_ptr<int8_t[]> fInputs; - - size_t fInputSize; - - mutable SkSL::String fKey; - - GR_DECLARE_FRAGMENT_PROCESSOR_TEST - - typedef GrFragmentProcessor INHERITED; - - friend class GrSkSLFPFactory; -}; - -/** - * Produces GrFragmentProcessors from SkSL code. As the shader code produced from the SkSL depends - * upon the inputs to the SkSL (static if's, etc.) we first create a factory for a given SkSL - * string, then use that to create the actual GrFragmentProcessor. - */ -class GrSkSLFPFactory : public SkNVRefCnt<GrSkSLFPFactory> { -public: - /** - * Constructs a GrSkSLFPFactory for a given SkSL source string. Creating a factory will - * preprocess the SkSL and determine which of its inputs are declared "key" (meaning they cause - * the produced shaders to differ), so it is important to reuse the same factory instance for - * the same shader in order to avoid repeatedly re-parsing the SkSL. - */ - GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl); - - const SkSL::Program* getSpecialization(const SkSL::String& key, const void* inputs, - size_t inputSize); - - const char* fName; - - SkSL::Compiler fCompiler; - - std::shared_ptr<SkSL::Program> fBaseProgram; - - std::vector<const SkSL::Variable*> fInputVars; - - std::vector<const SkSL::Variable*> fKeyVars; - - std::unordered_map<SkSL::String, std::unique_ptr<const SkSL::Program>> fSpecializations; - - friend class GrSkSLFP; -}; - -#endif |