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 |