blob: 3559694f0560ab597adf1fd1fe3075fbc306b5c8 [file] [log] [blame]
robertphillipsf7142e72016-04-18 07:20:05 -07001/*
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"
bungeman06ca8ec2016-06-09 08:01:03 -070014#include "SkRefCnt.h"
robertphillipsf7142e72016-04-18 07:20:05 -070015
16#include "glsl/GrGLSLFragmentProcessor.h"
17#include "glsl/GrGLSLFragmentShaderBuilder.h"
18#include "glsl/GrGLSLUniformHandler.h"
19
20sk_sp<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::Make(GrTexture* texture,
21 GrTexture* maskTexture,
22 float innerThreshold,
23 float outerThreshold,
24 const SkIRect& bounds) {
25 return sk_sp<GrFragmentProcessor>(new GrAlphaThresholdFragmentProcessor(
26 texture, maskTexture,
27 innerThreshold, outerThreshold,
28 bounds));
29}
30
31static SkMatrix make_div_and_translate_matrix(GrTexture* texture, int x, int y) {
32 SkMatrix matrix = GrCoordTransform::MakeDivByTextureWHMatrix(texture);
33 matrix.preTranslate(SkIntToScalar(x), SkIntToScalar(y));
34 return matrix;
35}
36
37GrAlphaThresholdFragmentProcessor::GrAlphaThresholdFragmentProcessor(GrTexture* texture,
38 GrTexture* maskTexture,
39 float innerThreshold,
40 float outerThreshold,
41 const SkIRect& bounds)
42 : fInnerThreshold(innerThreshold)
43 , fOuterThreshold(outerThreshold)
44 , fImageCoordTransform(kLocal_GrCoordSet,
45 GrCoordTransform::MakeDivByTextureWHMatrix(texture), texture,
46 GrTextureParams::kNone_FilterMode)
47 , fImageTextureAccess(texture)
48 , fMaskCoordTransform(kLocal_GrCoordSet,
49 make_div_and_translate_matrix(maskTexture, -bounds.x(), -bounds.y()),
50 maskTexture,
51 GrTextureParams::kNone_FilterMode)
52 , fMaskTextureAccess(maskTexture) {
53 this->initClassID<GrAlphaThresholdFragmentProcessor>();
54 this->addCoordTransform(&fImageCoordTransform);
55 this->addTextureAccess(&fImageTextureAccess);
56 this->addCoordTransform(&fMaskCoordTransform);
57 this->addTextureAccess(&fMaskTextureAccess);
58}
59
60bool GrAlphaThresholdFragmentProcessor::onIsEqual(const GrFragmentProcessor& sBase) const {
61 const GrAlphaThresholdFragmentProcessor& s = sBase.cast<GrAlphaThresholdFragmentProcessor>();
62 return (this->fInnerThreshold == s.fInnerThreshold &&
63 this->fOuterThreshold == s.fOuterThreshold);
64}
65
66void GrAlphaThresholdFragmentProcessor::onComputeInvariantOutput(GrInvariantOutput* inout) const {
67 if (GrPixelConfigIsAlphaOnly(this->texture(0)->config())) {
68 inout->mulByUnknownSingleComponent();
69 } else if (GrPixelConfigIsOpaque(this->texture(0)->config()) && fOuterThreshold >= 1.f) {
70 inout->mulByUnknownOpaqueFourComponents();
71 } else {
72 inout->mulByUnknownFourComponents();
73 }
74}
75
76///////////////////////////////////////////////////////////////////////////////
77
78class GrGLAlphaThresholdFragmentProcessor : public GrGLSLFragmentProcessor {
79public:
80 void emitCode(EmitArgs&) override;
81
82protected:
83 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
84
85private:
86 GrGLSLProgramDataManager::UniformHandle fInnerThresholdVar;
87 GrGLSLProgramDataManager::UniformHandle fOuterThresholdVar;
88
89 typedef GrGLSLFragmentProcessor INHERITED;
90};
91
92void GrGLAlphaThresholdFragmentProcessor::emitCode(EmitArgs& args) {
93 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
94 fInnerThresholdVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
95 kFloat_GrSLType, kDefault_GrSLPrecision,
96 "inner_threshold");
97 fOuterThresholdVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
98 kFloat_GrSLType, kDefault_GrSLPrecision,
99 "outer_threshold");
100
101 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700102 SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
103 SkString maskCoords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[1]);
robertphillipsf7142e72016-04-18 07:20:05 -0700104
105 fragBuilder->codeAppendf("vec2 coord = %s;", coords2D.c_str());
106 fragBuilder->codeAppendf("vec2 mask_coord = %s;", maskCoords2D.c_str());
107 fragBuilder->codeAppend("vec4 input_color = ");
108 fragBuilder->appendTextureLookup(args.fTexSamplers[0], "coord");
109 fragBuilder->codeAppend(";");
110 fragBuilder->codeAppend("vec4 mask_color = ");
111 fragBuilder->appendTextureLookup(args.fTexSamplers[1], "mask_coord");
112 fragBuilder->codeAppend(";");
113
114 fragBuilder->codeAppendf("float inner_thresh = %s;",
115 uniformHandler->getUniformCStr(fInnerThresholdVar));
116 fragBuilder->codeAppendf("float outer_thresh = %s;",
117 uniformHandler->getUniformCStr(fOuterThresholdVar));
118 fragBuilder->codeAppend("float mask = mask_color.a;");
119
120 fragBuilder->codeAppend("vec4 color = input_color;");
121 fragBuilder->codeAppend("if (mask < 0.5) {"
122 "if (color.a > outer_thresh) {"
123 "float scale = outer_thresh / color.a;"
124 "color.rgb *= scale;"
125 "color.a = outer_thresh;"
126 "}"
127 "} else if (color.a < inner_thresh) {"
128 "float scale = inner_thresh / max(0.001, color.a);"
129 "color.rgb *= scale;"
130 "color.a = inner_thresh;"
131 "}");
132
133 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor,
134 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr4("color")).c_str());
135}
136
137void GrGLAlphaThresholdFragmentProcessor::onSetData(const GrGLSLProgramDataManager& pdman,
138 const GrProcessor& proc) {
139 const GrAlphaThresholdFragmentProcessor& atfp = proc.cast<GrAlphaThresholdFragmentProcessor>();
140 pdman.set1f(fInnerThresholdVar, atfp.innerThreshold());
141 pdman.set1f(fOuterThresholdVar, atfp.outerThreshold());
142}
143
144/////////////////////////////////////////////////////////////////////
145
146GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrAlphaThresholdFragmentProcessor);
147
bungeman06ca8ec2016-06-09 08:01:03 -0700148sk_sp<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::TestCreate(GrProcessorTestData* d) {
robertphillipsf7142e72016-04-18 07:20:05 -0700149 GrTexture* bmpTex = d->fTextures[GrProcessorUnitTest::kSkiaPMTextureIdx];
150 GrTexture* maskTex = d->fTextures[GrProcessorUnitTest::kAlphaTextureIdx];
151 float innerThresh = d->fRandom->nextUScalar1();
152 float outerThresh = d->fRandom->nextUScalar1();
153 const int kMaxWidth = 1000;
154 const int kMaxHeight = 1000;
155 uint32_t width = d->fRandom->nextULessThan(kMaxWidth);
156 uint32_t height = d->fRandom->nextULessThan(kMaxHeight);
157 uint32_t x = d->fRandom->nextULessThan(kMaxWidth - width);
158 uint32_t y = d->fRandom->nextULessThan(kMaxHeight - height);
159 SkIRect bounds = SkIRect::MakeXYWH(x, y, width, height);
160 return GrAlphaThresholdFragmentProcessor::Make(bmpTex, maskTex,
161 innerThresh, outerThresh,
bungeman06ca8ec2016-06-09 08:01:03 -0700162 bounds);
robertphillipsf7142e72016-04-18 07:20:05 -0700163}
164
165///////////////////////////////////////////////////////////////////////////////
166
167void GrAlphaThresholdFragmentProcessor::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
168 GrProcessorKeyBuilder* b) const {
169 GrGLAlphaThresholdFragmentProcessor::GenKey(*this, caps, b);
170}
171
172GrGLSLFragmentProcessor* GrAlphaThresholdFragmentProcessor::onCreateGLSLInstance() const {
173 return new GrGLAlphaThresholdFragmentProcessor;
174}
175
176#endif