blob: 897d44768fbb0ab614415be74ba099e67204a4e5 [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
Robert Phillips8e1c4e62017-02-19 12:27:01 -050012#include "GrContext.h"
bungeman06ca8ec2016-06-09 08:01:03 -070013#include "SkRefCnt.h"
Brian Osman6fb592e2016-10-03 13:15:12 -040014#include "glsl/GrGLSLColorSpaceXformHelper.h"
robertphillipsf7142e72016-04-18 07:20:05 -070015#include "glsl/GrGLSLFragmentProcessor.h"
16#include "glsl/GrGLSLFragmentShaderBuilder.h"
17#include "glsl/GrGLSLUniformHandler.h"
Brian Salomon94efbf52016-11-29 13:43:05 -050018#include "../private/GrGLSL.h"
robertphillipsf7142e72016-04-18 07:20:05 -070019
Brian Salomon587e08f2017-01-27 10:59:27 -050020inline GrFragmentProcessor::OptimizationFlags GrAlphaThresholdFragmentProcessor::OptFlags(float outerThreshold) {
21 if (outerThreshold >= 1.f) {
Brian Salomonf3b995b2017-02-15 10:22:23 -050022 return kPreservesOpaqueInput_OptimizationFlag |
23 kCompatibleWithCoverageAsAlpha_OptimizationFlag;
Brian Salomon587e08f2017-01-27 10:59:27 -050024 } else {
Brian Salomonf3b995b2017-02-15 10:22:23 -050025 return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
Brian Salomon587e08f2017-01-27 10:59:27 -050026 }
27}
28
Brian Osman6fb592e2016-10-03 13:15:12 -040029GrAlphaThresholdFragmentProcessor::GrAlphaThresholdFragmentProcessor(
Robert Phillips8e1c4e62017-02-19 12:27:01 -050030 GrContext* context,
31 sk_sp<GrTextureProxy> proxy,
32 sk_sp<GrColorSpaceXform> colorSpaceXform,
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -050033 sk_sp<GrTextureProxy> maskProxy,
Robert Phillips8e1c4e62017-02-19 12:27:01 -050034 float innerThreshold,
35 float outerThreshold,
36 const SkIRect& bounds)
37 : INHERITED(OptFlags(outerThreshold))
38 , fInnerThreshold(innerThreshold)
39 , fOuterThreshold(outerThreshold)
40 , fImageCoordTransform(context, SkMatrix::I(), proxy.get(),
41 GrSamplerParams::kNone_FilterMode)
Brian Osman32342f02017-03-04 08:12:46 -050042 , fImageTextureSampler(context->resourceProvider(), std::move(proxy))
Robert Phillips8e1c4e62017-02-19 12:27:01 -050043 , fColorSpaceXform(std::move(colorSpaceXform))
44 , fMaskCoordTransform(
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -050045 context,
Robert Phillips8e1c4e62017-02-19 12:27:01 -050046 SkMatrix::MakeTrans(SkIntToScalar(-bounds.x()), SkIntToScalar(-bounds.y())),
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -050047 maskProxy.get(),
Robert Phillips8e1c4e62017-02-19 12:27:01 -050048 GrSamplerParams::kNone_FilterMode)
Brian Osman32342f02017-03-04 08:12:46 -050049 , fMaskTextureSampler(context->resourceProvider(), maskProxy) {
Robert Phillips8e1c4e62017-02-19 12:27:01 -050050 this->initClassID<GrAlphaThresholdFragmentProcessor>();
51 this->addCoordTransform(&fImageCoordTransform);
52 this->addTextureSampler(&fImageTextureSampler);
53 this->addCoordTransform(&fMaskCoordTransform);
54 this->addTextureSampler(&fMaskTextureSampler);
55}
56
robertphillipsf7142e72016-04-18 07:20:05 -070057bool GrAlphaThresholdFragmentProcessor::onIsEqual(const GrFragmentProcessor& sBase) const {
58 const GrAlphaThresholdFragmentProcessor& s = sBase.cast<GrAlphaThresholdFragmentProcessor>();
59 return (this->fInnerThreshold == s.fInnerThreshold &&
60 this->fOuterThreshold == s.fOuterThreshold);
61}
62
robertphillipsf7142e72016-04-18 07:20:05 -070063///////////////////////////////////////////////////////////////////////////////
64
65class GrGLAlphaThresholdFragmentProcessor : public GrGLSLFragmentProcessor {
66public:
67 void emitCode(EmitArgs&) override;
68
Brian Salomon94efbf52016-11-29 13:43:05 -050069 static inline void GenKey(const GrProcessor& effect, const GrShaderCaps&,
Brian Osman6fb592e2016-10-03 13:15:12 -040070 GrProcessorKeyBuilder* b) {
71 const GrAlphaThresholdFragmentProcessor& atfp =
72 effect.cast<GrAlphaThresholdFragmentProcessor>();
73 b->add32(GrColorSpaceXform::XformKey(atfp.colorSpaceXform()));
74 }
75
robertphillipsf7142e72016-04-18 07:20:05 -070076protected:
77 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
78
79private:
80 GrGLSLProgramDataManager::UniformHandle fInnerThresholdVar;
81 GrGLSLProgramDataManager::UniformHandle fOuterThresholdVar;
Brian Osman6fb592e2016-10-03 13:15:12 -040082 GrGLSLProgramDataManager::UniformHandle fColorSpaceXformVar;
robertphillipsf7142e72016-04-18 07:20:05 -070083 typedef GrGLSLFragmentProcessor INHERITED;
84};
85
86void GrGLAlphaThresholdFragmentProcessor::emitCode(EmitArgs& args) {
87 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
88 fInnerThresholdVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
89 kFloat_GrSLType, kDefault_GrSLPrecision,
90 "inner_threshold");
91 fOuterThresholdVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
92 kFloat_GrSLType, kDefault_GrSLPrecision,
93 "outer_threshold");
94
Brian Osman6fb592e2016-10-03 13:15:12 -040095 const GrAlphaThresholdFragmentProcessor& atfp =
96 args.fFp.cast<GrAlphaThresholdFragmentProcessor>();
97 GrGLSLColorSpaceXformHelper colorSpaceHelper(uniformHandler, atfp.colorSpaceXform(),
98 &fColorSpaceXformVar);
99
robertphillipsf7142e72016-04-18 07:20:05 -0700100 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700101 SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
102 SkString maskCoords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[1]);
robertphillipsf7142e72016-04-18 07:20:05 -0700103
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 = ");
Brian Osman6fb592e2016-10-03 13:15:12 -0400107 fragBuilder->appendTextureLookup(args.fTexSamplers[0], "coord", kVec2f_GrSLType,
108 &colorSpaceHelper);
robertphillipsf7142e72016-04-18 07:20:05 -0700109 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());
Brian Osman6fb592e2016-10-03 13:15:12 -0400142 if (SkToBool(atfp.colorSpaceXform())) {
143 pdman.setSkMatrix44(fColorSpaceXformVar, atfp.colorSpaceXform()->srcToDst());
144 }
robertphillipsf7142e72016-04-18 07:20:05 -0700145}
146
147/////////////////////////////////////////////////////////////////////
148
149GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrAlphaThresholdFragmentProcessor);
150
Hal Canary6f6961e2017-01-31 13:50:44 -0500151#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700152sk_sp<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::TestCreate(GrProcessorTestData* d) {
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500153 sk_sp<GrTextureProxy> bmpProxy = d->textureProxy(GrProcessorUnitTest::kSkiaPMTextureIdx);
154 sk_sp<GrTextureProxy> maskProxy = d->textureProxy(GrProcessorUnitTest::kAlphaTextureIdx);
Brian Salomon5d4cd9e2017-02-09 11:16:46 -0500155 // Make the inner and outer thresholds be in (0, 1) exclusive and be sorted correctly.
156 float innerThresh = d->fRandom->nextUScalar1() * .99f + 0.005f;
157 float outerThresh = d->fRandom->nextUScalar1() * .99f + 0.005f;
robertphillipsf7142e72016-04-18 07:20:05 -0700158 const int kMaxWidth = 1000;
159 const int kMaxHeight = 1000;
160 uint32_t width = d->fRandom->nextULessThan(kMaxWidth);
161 uint32_t height = d->fRandom->nextULessThan(kMaxHeight);
162 uint32_t x = d->fRandom->nextULessThan(kMaxWidth - width);
163 uint32_t y = d->fRandom->nextULessThan(kMaxHeight - height);
164 SkIRect bounds = SkIRect::MakeXYWH(x, y, width, height);
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500165 sk_sp<GrColorSpaceXform> colorSpaceXform = GrTest::TestColorXform(d->fRandom);
166 return GrAlphaThresholdFragmentProcessor::Make(d->context(),
167 std::move(bmpProxy),
168 std::move(colorSpaceXform),
169 std::move(maskProxy),
robertphillipsf7142e72016-04-18 07:20:05 -0700170 innerThresh, outerThresh,
bungeman06ca8ec2016-06-09 08:01:03 -0700171 bounds);
robertphillipsf7142e72016-04-18 07:20:05 -0700172}
Hal Canary6f6961e2017-01-31 13:50:44 -0500173#endif
robertphillipsf7142e72016-04-18 07:20:05 -0700174
175///////////////////////////////////////////////////////////////////////////////
176
Brian Salomon94efbf52016-11-29 13:43:05 -0500177void GrAlphaThresholdFragmentProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
robertphillipsf7142e72016-04-18 07:20:05 -0700178 GrProcessorKeyBuilder* b) const {
179 GrGLAlphaThresholdFragmentProcessor::GenKey(*this, caps, b);
180}
181
182GrGLSLFragmentProcessor* GrAlphaThresholdFragmentProcessor::onCreateGLSLInstance() const {
183 return new GrGLAlphaThresholdFragmentProcessor;
184}
185
186#endif