| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkAlphaThresholdFilter.h" | 8 #include "SkAlphaThresholdFilter.h" |
| 9 | 9 |
| 10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
| 11 #include "SkReadBuffer.h" | 11 #include "SkReadBuffer.h" |
| 12 #include "SkSpecialImage.h" | 12 #include "SkSpecialImage.h" |
| 13 #include "SkWriteBuffer.h" | 13 #include "SkWriteBuffer.h" |
| 14 #include "SkRegion.h" | 14 #include "SkRegion.h" |
| 15 |
| 15 #if SK_SUPPORT_GPU | 16 #if SK_SUPPORT_GPU |
| 17 #include "GrAlphaThresholdFragmentProcessor.h" |
| 18 #include "GrContext.h" |
| 16 #include "GrDrawContext.h" | 19 #include "GrDrawContext.h" |
| 17 #endif | 20 #endif |
| 18 | 21 |
| 19 class SK_API SkAlphaThresholdFilterImpl : public SkImageFilter { | 22 class SK_API SkAlphaThresholdFilterImpl : public SkImageFilter { |
| 20 public: | 23 public: |
| 21 SkAlphaThresholdFilterImpl(const SkRegion& region, SkScalar innerThreshold, | 24 SkAlphaThresholdFilterImpl(const SkRegion& region, SkScalar innerThreshold, |
| 22 SkScalar outerThreshold, sk_sp<SkImageFilter> inp
ut, | 25 SkScalar outerThreshold, sk_sp<SkImageFilter> inp
ut, |
| 23 const CropRect* cropRect = nullptr); | 26 const CropRect* cropRect = nullptr); |
| 24 | 27 |
| 25 SK_TO_STRING_OVERRIDE() | 28 SK_TO_STRING_OVERRIDE() |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 outerThreshold = pin_0_1(outerThreshold); | 63 outerThreshold = pin_0_1(outerThreshold); |
| 61 if (!SkScalarIsFinite(innerThreshold) || !SkScalarIsFinite(outerThreshold))
{ | 64 if (!SkScalarIsFinite(innerThreshold) || !SkScalarIsFinite(outerThreshold))
{ |
| 62 return nullptr; | 65 return nullptr; |
| 63 } | 66 } |
| 64 return sk_sp<SkImageFilter>(new SkAlphaThresholdFilterImpl(region, innerThre
shold, | 67 return sk_sp<SkImageFilter>(new SkAlphaThresholdFilterImpl(region, innerThre
shold, |
| 65 outerThreshold, | 68 outerThreshold, |
| 66 std::move(input), | 69 std::move(input), |
| 67 cropRect)); | 70 cropRect)); |
| 68 } | 71 } |
| 69 | 72 |
| 70 #if SK_SUPPORT_GPU | |
| 71 #include "GrContext.h" | |
| 72 #include "GrCoordTransform.h" | |
| 73 #include "GrFragmentProcessor.h" | |
| 74 #include "GrInvariantOutput.h" | |
| 75 #include "GrTextureAccess.h" | |
| 76 #include "effects/GrPorterDuffXferProcessor.h" | |
| 77 | |
| 78 #include "SkGr.h" | |
| 79 | |
| 80 #include "glsl/GrGLSLFragmentProcessor.h" | |
| 81 #include "glsl/GrGLSLFragmentShaderBuilder.h" | |
| 82 #include "glsl/GrGLSLProgramDataManager.h" | |
| 83 #include "glsl/GrGLSLUniformHandler.h" | |
| 84 | |
| 85 namespace { | |
| 86 | |
| 87 SkMatrix make_div_and_translate_matrix(GrTexture* texture, int x, int y) { | |
| 88 SkMatrix matrix = GrCoordTransform::MakeDivByTextureWHMatrix(texture); | |
| 89 matrix.preTranslate(SkIntToScalar(x), SkIntToScalar(y)); | |
| 90 return matrix; | |
| 91 } | |
| 92 | |
| 93 }; | |
| 94 | |
| 95 class AlphaThresholdEffect : public GrFragmentProcessor { | |
| 96 | |
| 97 public: | |
| 98 static GrFragmentProcessor* Create(GrTexture* texture, | |
| 99 GrTexture* maskTexture, | |
| 100 float innerThreshold, | |
| 101 float outerThreshold, | |
| 102 const SkIRect& bounds) { | |
| 103 return new AlphaThresholdEffect(texture, maskTexture, innerThreshold, ou
terThreshold, | |
| 104 bounds); | |
| 105 } | |
| 106 | |
| 107 virtual ~AlphaThresholdEffect() {}; | |
| 108 | |
| 109 const char* name() const override { return "Alpha Threshold"; } | |
| 110 | |
| 111 float innerThreshold() const { return fInnerThreshold; } | |
| 112 float outerThreshold() const { return fOuterThreshold; } | |
| 113 | |
| 114 private: | |
| 115 AlphaThresholdEffect(GrTexture* texture, | |
| 116 GrTexture* maskTexture, | |
| 117 float innerThreshold, | |
| 118 float outerThreshold, | |
| 119 const SkIRect& bounds) | |
| 120 : fInnerThreshold(innerThreshold) | |
| 121 , fOuterThreshold(outerThreshold) | |
| 122 , fImageCoordTransform(kLocal_GrCoordSet, | |
| 123 GrCoordTransform::MakeDivByTextureWHMatrix(textur
e), texture, | |
| 124 GrTextureParams::kNone_FilterMode) | |
| 125 , fImageTextureAccess(texture) | |
| 126 , fMaskCoordTransform(kLocal_GrCoordSet, | |
| 127 make_div_and_translate_matrix(maskTexture, -bounds
.x(), -bounds.y()), | |
| 128 maskTexture, | |
| 129 GrTextureParams::kNone_FilterMode) | |
| 130 , fMaskTextureAccess(maskTexture) { | |
| 131 this->initClassID<AlphaThresholdEffect>(); | |
| 132 this->addCoordTransform(&fImageCoordTransform); | |
| 133 this->addTextureAccess(&fImageTextureAccess); | |
| 134 this->addCoordTransform(&fMaskCoordTransform); | |
| 135 this->addTextureAccess(&fMaskTextureAccess); | |
| 136 } | |
| 137 | |
| 138 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; | |
| 139 | |
| 140 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const
override; | |
| 141 | |
| 142 bool onIsEqual(const GrFragmentProcessor&) const override; | |
| 143 | |
| 144 void onComputeInvariantOutput(GrInvariantOutput* inout) const override; | |
| 145 | |
| 146 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; | |
| 147 | |
| 148 float fInnerThreshold; | |
| 149 float fOuterThreshold; | |
| 150 GrCoordTransform fImageCoordTransform; | |
| 151 GrTextureAccess fImageTextureAccess; | |
| 152 GrCoordTransform fMaskCoordTransform; | |
| 153 GrTextureAccess fMaskTextureAccess; | |
| 154 | |
| 155 typedef GrFragmentProcessor INHERITED; | |
| 156 }; | |
| 157 | |
| 158 class GrGLAlphaThresholdEffect : public GrGLSLFragmentProcessor { | |
| 159 public: | |
| 160 void emitCode(EmitArgs&) override; | |
| 161 | |
| 162 protected: | |
| 163 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override
; | |
| 164 | |
| 165 private: | |
| 166 GrGLSLProgramDataManager::UniformHandle fInnerThresholdVar; | |
| 167 GrGLSLProgramDataManager::UniformHandle fOuterThresholdVar; | |
| 168 | |
| 169 typedef GrGLSLFragmentProcessor INHERITED; | |
| 170 }; | |
| 171 | |
| 172 void GrGLAlphaThresholdEffect::emitCode(EmitArgs& args) { | |
| 173 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; | |
| 174 fInnerThresholdVar = uniformHandler->addUniform(kFragment_GrShaderFlag, | |
| 175 kFloat_GrSLType, kDefault_Gr
SLPrecision, | |
| 176 "inner_threshold"); | |
| 177 fOuterThresholdVar = uniformHandler->addUniform(kFragment_GrShaderFlag, | |
| 178 kFloat_GrSLType, kDefault_Gr
SLPrecision, | |
| 179 "outer_threshold"); | |
| 180 | |
| 181 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; | |
| 182 SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0); | |
| 183 SkString maskCoords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 1); | |
| 184 | |
| 185 fragBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); | |
| 186 fragBuilder->codeAppendf("\t\tvec2 mask_coord = %s;\n", maskCoords2D.c_str()
); | |
| 187 fragBuilder->codeAppend("\t\tvec4 input_color = "); | |
| 188 fragBuilder->appendTextureLookup(args.fTexSamplers[0], "coord"); | |
| 189 fragBuilder->codeAppend(";\n"); | |
| 190 fragBuilder->codeAppend("\t\tvec4 mask_color = "); | |
| 191 fragBuilder->appendTextureLookup(args.fTexSamplers[1], "mask_coord"); | |
| 192 fragBuilder->codeAppend(";\n"); | |
| 193 | |
| 194 fragBuilder->codeAppendf("\t\tfloat inner_thresh = %s;\n", | |
| 195 uniformHandler->getUniformCStr(fInnerThresholdVar))
; | |
| 196 fragBuilder->codeAppendf("\t\tfloat outer_thresh = %s;\n", | |
| 197 uniformHandler->getUniformCStr(fOuterThresholdVar))
; | |
| 198 fragBuilder->codeAppend("\t\tfloat mask = mask_color.a;\n"); | |
| 199 | |
| 200 fragBuilder->codeAppend("vec4 color = input_color;\n"); | |
| 201 fragBuilder->codeAppend("\t\tif (mask < 0.5) {\n" | |
| 202 "\t\t\tif (color.a > outer_thresh) {\n" | |
| 203 "\t\t\t\tfloat scale = outer_thresh / color.a;\n" | |
| 204 "\t\t\t\tcolor.rgb *= scale;\n" | |
| 205 "\t\t\t\tcolor.a = outer_thresh;\n" | |
| 206 "\t\t\t}\n" | |
| 207 "\t\t} else if (color.a < inner_thresh) {\n" | |
| 208 "\t\t\tfloat scale = inner_thresh / max(0.001, color
.a);\n" | |
| 209 "\t\t\tcolor.rgb *= scale;\n" | |
| 210 "\t\t\tcolor.a = inner_thresh;\n" | |
| 211 "\t\t}\n"); | |
| 212 | |
| 213 fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, | |
| 214 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr4("color
")).c_str()); | |
| 215 } | |
| 216 | |
| 217 void GrGLAlphaThresholdEffect::onSetData(const GrGLSLProgramDataManager& pdman, | |
| 218 const GrProcessor& proc) { | |
| 219 const AlphaThresholdEffect& alpha_threshold = proc.cast<AlphaThresholdEffect
>(); | |
| 220 pdman.set1f(fInnerThresholdVar, alpha_threshold.innerThreshold()); | |
| 221 pdman.set1f(fOuterThresholdVar, alpha_threshold.outerThreshold()); | |
| 222 } | |
| 223 | |
| 224 ///////////////////////////////////////////////////////////////////// | |
| 225 | |
| 226 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(AlphaThresholdEffect); | |
| 227 | |
| 228 const GrFragmentProcessor* AlphaThresholdEffect::TestCreate(GrProcessorTestData*
d) { | |
| 229 GrTexture* bmpTex = d->fTextures[GrProcessorUnitTest::kSkiaPMTextureIdx]; | |
| 230 GrTexture* maskTex = d->fTextures[GrProcessorUnitTest::kAlphaTextureIdx]; | |
| 231 float innerThresh = d->fRandom->nextUScalar1(); | |
| 232 float outerThresh = d->fRandom->nextUScalar1(); | |
| 233 const int kMaxWidth = 1000; | |
| 234 const int kMaxHeight = 1000; | |
| 235 uint32_t width = d->fRandom->nextULessThan(kMaxWidth); | |
| 236 uint32_t height = d->fRandom->nextULessThan(kMaxHeight); | |
| 237 uint32_t x = d->fRandom->nextULessThan(kMaxWidth - width); | |
| 238 uint32_t y = d->fRandom->nextULessThan(kMaxHeight - height); | |
| 239 SkIRect bounds = SkIRect::MakeXYWH(x, y, width, height); | |
| 240 return AlphaThresholdEffect::Create(bmpTex, maskTex, innerThresh, outerThres
h, bounds); | |
| 241 } | |
| 242 | |
| 243 /////////////////////////////////////////////////////////////////////////////// | |
| 244 | |
| 245 void AlphaThresholdEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, | |
| 246 GrProcessorKeyBuilder* b) const
{ | |
| 247 GrGLAlphaThresholdEffect::GenKey(*this, caps, b); | |
| 248 } | |
| 249 | |
| 250 GrGLSLFragmentProcessor* AlphaThresholdEffect::onCreateGLSLInstance() const { | |
| 251 return new GrGLAlphaThresholdEffect; | |
| 252 } | |
| 253 | |
| 254 bool AlphaThresholdEffect::onIsEqual(const GrFragmentProcessor& sBase) const { | |
| 255 const AlphaThresholdEffect& s = sBase.cast<AlphaThresholdEffect>(); | |
| 256 return (this->fInnerThreshold == s.fInnerThreshold && | |
| 257 this->fOuterThreshold == s.fOuterThreshold); | |
| 258 } | |
| 259 | |
| 260 void AlphaThresholdEffect::onComputeInvariantOutput(GrInvariantOutput* inout) co
nst { | |
| 261 if (GrPixelConfigIsAlphaOnly(this->texture(0)->config())) { | |
| 262 inout->mulByUnknownSingleComponent(); | |
| 263 } else if (GrPixelConfigIsOpaque(this->texture(0)->config()) && fOuterThresh
old >= 1.f) { | |
| 264 inout->mulByUnknownOpaqueFourComponents(); | |
| 265 } else { | |
| 266 inout->mulByUnknownFourComponents(); | |
| 267 } | |
| 268 } | |
| 269 | |
| 270 #endif | |
| 271 | |
| 272 sk_sp<SkFlattenable> SkAlphaThresholdFilterImpl::CreateProc(SkReadBuffer& buffer
) { | 73 sk_sp<SkFlattenable> SkAlphaThresholdFilterImpl::CreateProc(SkReadBuffer& buffer
) { |
| 273 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); | 74 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); |
| 274 SkScalar inner = buffer.readScalar(); | 75 SkScalar inner = buffer.readScalar(); |
| 275 SkScalar outer = buffer.readScalar(); | 76 SkScalar outer = buffer.readScalar(); |
| 276 SkRegion rgn; | 77 SkRegion rgn; |
| 277 buffer.readRegion(&rgn); | 78 buffer.readRegion(&rgn); |
| 278 return SkAlphaThresholdFilter::Make(rgn, inner, outer, common.getInput(0), | 79 return SkAlphaThresholdFilter::Make(rgn, inner, outer, common.getInput(0), |
| 279 &common.cropRect()); | 80 &common.cropRect()); |
| 280 } | 81 } |
| 281 | 82 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 | 170 |
| 370 SkMatrix matrix(ctx.ctm()); | 171 SkMatrix matrix(ctx.ctm()); |
| 371 matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bound
s.top())); | 172 matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bound
s.top())); |
| 372 | 173 |
| 373 sk_sp<GrTexture> maskTexture(this->createMaskTexture(context, matrix, bo
unds)); | 174 sk_sp<GrTexture> maskTexture(this->createMaskTexture(context, matrix, bo
unds)); |
| 374 if (!maskTexture) { | 175 if (!maskTexture) { |
| 375 return nullptr; | 176 return nullptr; |
| 376 } | 177 } |
| 377 | 178 |
| 378 // SRGBTODO: handle sRGB here | 179 // SRGBTODO: handle sRGB here |
| 379 sk_sp<GrFragmentProcessor> fp(AlphaThresholdEffect::Create(inputTexture.
get(), | 180 sk_sp<GrFragmentProcessor> fp(GrAlphaThresholdFragmentProcessor::Make( |
| 181 inputTexture.
get(), |
| 380 maskTexture.g
et(), | 182 maskTexture.g
et(), |
| 381 fInnerThresho
ld, | 183 fInnerThresho
ld, |
| 382 fOuterThresho
ld, | 184 fOuterThresho
ld, |
| 383 bounds)); | 185 bounds)); |
| 384 if (!fp) { | 186 if (!fp) { |
| 385 return nullptr; | 187 return nullptr; |
| 386 } | 188 } |
| 387 | 189 |
| 388 return DrawWithFP(context, std::move(fp), bounds, source->internal_getPr
oxy()); | 190 return DrawWithFP(context, std::move(fp), bounds, source->internal_getPr
oxy()); |
| 389 } | 191 } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 dst); | 267 dst); |
| 466 } | 268 } |
| 467 | 269 |
| 468 #ifndef SK_IGNORE_TO_STRING | 270 #ifndef SK_IGNORE_TO_STRING |
| 469 void SkAlphaThresholdFilterImpl::toString(SkString* str) const { | 271 void SkAlphaThresholdFilterImpl::toString(SkString* str) const { |
| 470 str->appendf("SkAlphaThresholdImageFilter: ("); | 272 str->appendf("SkAlphaThresholdImageFilter: ("); |
| 471 str->appendf("inner: %f outer: %f", fInnerThreshold, fOuterThreshold); | 273 str->appendf("inner: %f outer: %f", fInnerThreshold, fOuterThreshold); |
| 472 str->append(")"); | 274 str->append(")"); |
| 473 } | 275 } |
| 474 #endif | 276 #endif |
| OLD | NEW |