OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2016 Google Inc. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. |
| 6 */ |
| 7 |
| 8 #include "GrAlphaThresholdFragmentProcessor.h" |
| 9 |
| 10 #if SK_SUPPORT_GPU |
| 11 |
| 12 #include "GrInvariantOutput.h" |
| 13 #include "GrTextureAccess.h" |
| 14 |
| 15 #include "glsl/GrGLSLFragmentProcessor.h" |
| 16 #include "glsl/GrGLSLFragmentShaderBuilder.h" |
| 17 #include "glsl/GrGLSLUniformHandler.h" |
| 18 |
| 19 sk_sp<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::Make(GrTexture* te
xture, |
| 20 GrTexture* ma
skTexture, |
| 21 float innerTh
reshold, |
| 22 float outerTh
reshold, |
| 23 const SkIRect
& bounds) { |
| 24 return sk_sp<GrFragmentProcessor>(new GrAlphaThresholdFragmentProcessor( |
| 25 texture, maskTexture, |
| 26 innerThreshold, outerThresho
ld, |
| 27 bounds)); |
| 28 } |
| 29 |
| 30 static SkMatrix make_div_and_translate_matrix(GrTexture* texture, int x, int y)
{ |
| 31 SkMatrix matrix = GrCoordTransform::MakeDivByTextureWHMatrix(texture); |
| 32 matrix.preTranslate(SkIntToScalar(x), SkIntToScalar(y)); |
| 33 return matrix; |
| 34 } |
| 35 |
| 36 GrAlphaThresholdFragmentProcessor::GrAlphaThresholdFragmentProcessor(GrTexture*
texture, |
| 37 GrTexture*
maskTexture, |
| 38 float inner
Threshold, |
| 39 float outer
Threshold, |
| 40 const SkIRe
ct& bounds) |
| 41 : fInnerThreshold(innerThreshold) |
| 42 , fOuterThreshold(outerThreshold) |
| 43 , fImageCoordTransform(kLocal_GrCoordSet, |
| 44 GrCoordTransform::MakeDivByTextureWHMatrix(texture),
texture, |
| 45 GrTextureParams::kNone_FilterMode) |
| 46 , fImageTextureAccess(texture) |
| 47 , fMaskCoordTransform(kLocal_GrCoordSet, |
| 48 make_div_and_translate_matrix(maskTexture, -bounds.x()
, -bounds.y()), |
| 49 maskTexture, |
| 50 GrTextureParams::kNone_FilterMode) |
| 51 , fMaskTextureAccess(maskTexture) { |
| 52 this->initClassID<GrAlphaThresholdFragmentProcessor>(); |
| 53 this->addCoordTransform(&fImageCoordTransform); |
| 54 this->addTextureAccess(&fImageTextureAccess); |
| 55 this->addCoordTransform(&fMaskCoordTransform); |
| 56 this->addTextureAccess(&fMaskTextureAccess); |
| 57 } |
| 58 |
| 59 bool GrAlphaThresholdFragmentProcessor::onIsEqual(const GrFragmentProcessor& sBa
se) const { |
| 60 const GrAlphaThresholdFragmentProcessor& s = sBase.cast<GrAlphaThresholdFrag
mentProcessor>(); |
| 61 return (this->fInnerThreshold == s.fInnerThreshold && |
| 62 this->fOuterThreshold == s.fOuterThreshold); |
| 63 } |
| 64 |
| 65 void GrAlphaThresholdFragmentProcessor::onComputeInvariantOutput(GrInvariantOutp
ut* inout) const { |
| 66 if (GrPixelConfigIsAlphaOnly(this->texture(0)->config())) { |
| 67 inout->mulByUnknownSingleComponent(); |
| 68 } else if (GrPixelConfigIsOpaque(this->texture(0)->config()) && fOuterThresh
old >= 1.f) { |
| 69 inout->mulByUnknownOpaqueFourComponents(); |
| 70 } else { |
| 71 inout->mulByUnknownFourComponents(); |
| 72 } |
| 73 } |
| 74 |
| 75 /////////////////////////////////////////////////////////////////////////////// |
| 76 |
| 77 class GrGLAlphaThresholdFragmentProcessor : public GrGLSLFragmentProcessor { |
| 78 public: |
| 79 void emitCode(EmitArgs&) override; |
| 80 |
| 81 protected: |
| 82 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override
; |
| 83 |
| 84 private: |
| 85 GrGLSLProgramDataManager::UniformHandle fInnerThresholdVar; |
| 86 GrGLSLProgramDataManager::UniformHandle fOuterThresholdVar; |
| 87 |
| 88 typedef GrGLSLFragmentProcessor INHERITED; |
| 89 }; |
| 90 |
| 91 void GrGLAlphaThresholdFragmentProcessor::emitCode(EmitArgs& args) { |
| 92 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
| 93 fInnerThresholdVar = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| 94 kFloat_GrSLType, kDefault_Gr
SLPrecision, |
| 95 "inner_threshold"); |
| 96 fOuterThresholdVar = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| 97 kFloat_GrSLType, kDefault_Gr
SLPrecision, |
| 98 "outer_threshold"); |
| 99 |
| 100 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; |
| 101 SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0); |
| 102 SkString maskCoords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 1); |
| 103 |
| 104 fragBuilder->codeAppendf("vec2 coord = %s;", coords2D.c_str()); |
| 105 fragBuilder->codeAppendf("vec2 mask_coord = %s;", maskCoords2D.c_str()); |
| 106 fragBuilder->codeAppend("vec4 input_color = "); |
| 107 fragBuilder->appendTextureLookup(args.fTexSamplers[0], "coord"); |
| 108 fragBuilder->codeAppend(";"); |
| 109 fragBuilder->codeAppend("vec4 mask_color = "); |
| 110 fragBuilder->appendTextureLookup(args.fTexSamplers[1], "mask_coord"); |
| 111 fragBuilder->codeAppend(";"); |
| 112 |
| 113 fragBuilder->codeAppendf("float inner_thresh = %s;", |
| 114 uniformHandler->getUniformCStr(fInnerThresholdVar))
; |
| 115 fragBuilder->codeAppendf("float outer_thresh = %s;", |
| 116 uniformHandler->getUniformCStr(fOuterThresholdVar))
; |
| 117 fragBuilder->codeAppend("float mask = mask_color.a;"); |
| 118 |
| 119 fragBuilder->codeAppend("vec4 color = input_color;"); |
| 120 fragBuilder->codeAppend("if (mask < 0.5) {" |
| 121 "if (color.a > outer_thresh) {" |
| 122 "float scale = outer_thresh / color.a;" |
| 123 "color.rgb *= scale;" |
| 124 "color.a = outer_thresh;" |
| 125 "}" |
| 126 "} else if (color.a < inner_thresh) {" |
| 127 "float scale = inner_thresh / max(0.001, color.a);" |
| 128 "color.rgb *= scale;" |
| 129 "color.a = inner_thresh;" |
| 130 "}"); |
| 131 |
| 132 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, |
| 133 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr4("color
")).c_str()); |
| 134 } |
| 135 |
| 136 void GrGLAlphaThresholdFragmentProcessor::onSetData(const GrGLSLProgramDataManag
er& pdman, |
| 137 const GrProcessor& proc) { |
| 138 const GrAlphaThresholdFragmentProcessor& atfp = proc.cast<GrAlphaThresholdFr
agmentProcessor>(); |
| 139 pdman.set1f(fInnerThresholdVar, atfp.innerThreshold()); |
| 140 pdman.set1f(fOuterThresholdVar, atfp.outerThreshold()); |
| 141 } |
| 142 |
| 143 ///////////////////////////////////////////////////////////////////// |
| 144 |
| 145 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrAlphaThresholdFragmentProcessor); |
| 146 |
| 147 const GrFragmentProcessor* GrAlphaThresholdFragmentProcessor::TestCreate(GrProce
ssorTestData* d) { |
| 148 GrTexture* bmpTex = d->fTextures[GrProcessorUnitTest::kSkiaPMTextureIdx]; |
| 149 GrTexture* maskTex = d->fTextures[GrProcessorUnitTest::kAlphaTextureIdx]; |
| 150 float innerThresh = d->fRandom->nextUScalar1(); |
| 151 float outerThresh = d->fRandom->nextUScalar1(); |
| 152 const int kMaxWidth = 1000; |
| 153 const int kMaxHeight = 1000; |
| 154 uint32_t width = d->fRandom->nextULessThan(kMaxWidth); |
| 155 uint32_t height = d->fRandom->nextULessThan(kMaxHeight); |
| 156 uint32_t x = d->fRandom->nextULessThan(kMaxWidth - width); |
| 157 uint32_t y = d->fRandom->nextULessThan(kMaxHeight - height); |
| 158 SkIRect bounds = SkIRect::MakeXYWH(x, y, width, height); |
| 159 return GrAlphaThresholdFragmentProcessor::Make(bmpTex, maskTex, |
| 160 innerThresh, outerThresh, |
| 161 bounds).release(); |
| 162 } |
| 163 |
| 164 /////////////////////////////////////////////////////////////////////////////// |
| 165 |
| 166 void GrAlphaThresholdFragmentProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&
caps, |
| 167 GrProcessorKeyBuil
der* b) const { |
| 168 GrGLAlphaThresholdFragmentProcessor::GenKey(*this, caps, b); |
| 169 } |
| 170 |
| 171 GrGLSLFragmentProcessor* GrAlphaThresholdFragmentProcessor::onCreateGLSLInstance
() const { |
| 172 return new GrGLAlphaThresholdFragmentProcessor; |
| 173 } |
| 174 |
| 175 #endif |
OLD | NEW |