1 /*
2 * Copyright 2013 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 "GrBitmapTextGeoProc.h"
9
10 #include "GrTexture.h"
11 #include "glsl/GrGLSLFragmentShaderBuilder.h"
12 #include "glsl/GrGLSLGeometryProcessor.h"
13 #include "glsl/GrGLSLProgramDataManager.h"
14 #include "glsl/GrGLSLUniformHandler.h"
15 #include "glsl/GrGLSLVarying.h"
16 #include "glsl/GrGLSLVertexShaderBuilder.h"
17
18 class GrGLBitmapTextGeoProc : public GrGLSLGeometryProcessor {
19 public:
GrGLBitmapTextGeoProc()20 GrGLBitmapTextGeoProc() : fColor(GrColor_ILLEGAL) {}
21
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)22 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
23 const GrBitmapTextGeoProc& cte = args.fGP.cast<GrBitmapTextGeoProc>();
24
25 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
26 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
27 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
28
29 // emit attributes
30 varyingHandler->emitAttributes(cte);
31
32 // compute numbers to be hardcoded to convert texture coordinates from int to float
33 SkASSERT(cte.numTextureSamplers() == 1);
34 SkDEBUGCODE(GrTexture* atlas = cte.textureSampler(0).texture());
35 SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
36
37 GrGLSLVertToFrag v(kVec2f_GrSLType);
38 varyingHandler->addVarying("TextureCoords", &v, kHigh_GrSLPrecision);
39 vertBuilder->codeAppendf("%s = %s;", v.vsOut(),
40 cte.inTextureCoords()->fName);
41
42 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
43 // Setup pass through color
44 if (cte.hasVertexColor()) {
45 varyingHandler->addPassThroughAttribute(cte.inColor(), args.fOutputColor);
46 } else {
47 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
48 &fColorUniform);
49 }
50
51 // Setup position
52 this->setupPosition(vertBuilder, gpArgs, cte.inPosition()->fName);
53
54 // emit transforms
55 this->emitTransforms(vertBuilder,
56 varyingHandler,
57 uniformHandler,
58 gpArgs->fPositionVar,
59 cte.inPosition()->fName,
60 cte.localMatrix(),
61 args.fFPCoordTransformHandler);
62
63 if (cte.maskFormat() == kARGB_GrMaskFormat) {
64 fragBuilder->codeAppendf("%s = ", args.fOutputColor);
65 fragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
66 args.fTexSamplers[0],
67 v.fsIn(),
68 kVec2f_GrSLType);
69 fragBuilder->codeAppend(";");
70 fragBuilder->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
71 } else {
72 fragBuilder->codeAppendf("%s = ", args.fOutputCoverage);
73 fragBuilder->appendTextureLookup(args.fTexSamplers[0], v.fsIn(), kVec2f_GrSLType);
74 fragBuilder->codeAppend(";");
75 if (cte.maskFormat() == kA565_GrMaskFormat) {
76 // set alpha to be max of rgb coverage
77 fragBuilder->codeAppendf("%s.a = max(max(%s.r, %s.g), %s.b);",
78 args.fOutputCoverage, args.fOutputCoverage,
79 args.fOutputCoverage, args.fOutputCoverage);
80 }
81 }
82 }
83
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor & gp,FPCoordTransformIter && transformIter)84 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
85 FPCoordTransformIter&& transformIter) override {
86 const GrBitmapTextGeoProc& btgp = gp.cast<GrBitmapTextGeoProc>();
87 if (btgp.color() != fColor && !btgp.hasVertexColor()) {
88 float c[4];
89 GrColorToRGBAFloat(btgp.color(), c);
90 pdman.set4fv(fColorUniform, 1, c);
91 fColor = btgp.color();
92 }
93 this->setTransformDataHelper(btgp.localMatrix(), pdman, &transformIter);
94 }
95
GenKey(const GrGeometryProcessor & proc,const GrShaderCaps &,GrProcessorKeyBuilder * b)96 static inline void GenKey(const GrGeometryProcessor& proc,
97 const GrShaderCaps&,
98 GrProcessorKeyBuilder* b) {
99 const GrBitmapTextGeoProc& gp = proc.cast<GrBitmapTextGeoProc>();
100 uint32_t key = 0;
101 key |= (gp.usesLocalCoords() && gp.localMatrix().hasPerspective()) ? 0x1 : 0x0;
102 key |= gp.maskFormat() << 1;
103 b->add32(key);
104
105 // Currently we hardcode numbers to convert atlas coordinates to normalized floating point
106 SkASSERT(gp.numTextureSamplers() == 1);
107 GrTexture* atlas = gp.textureSampler(0).texture();
108 SkASSERT(atlas);
109 b->add32(atlas->width());
110 b->add32(atlas->height());
111 }
112
113 private:
114 GrColor fColor;
115 UniformHandle fColorUniform;
116
117 typedef GrGLSLGeometryProcessor INHERITED;
118 };
119
120 ///////////////////////////////////////////////////////////////////////////////
121
GrBitmapTextGeoProc(GrResourceProvider * resourceProvider,GrColor color,sk_sp<GrTextureProxy> proxy,const GrSamplerParams & params,GrMaskFormat format,const SkMatrix & localMatrix,bool usesLocalCoords)122 GrBitmapTextGeoProc::GrBitmapTextGeoProc(GrResourceProvider* resourceProvider, GrColor color,
123 sk_sp<GrTextureProxy> proxy,
124 const GrSamplerParams& params, GrMaskFormat format,
125 const SkMatrix& localMatrix, bool usesLocalCoords)
126 : fColor(color)
127 , fLocalMatrix(localMatrix)
128 , fUsesLocalCoords(usesLocalCoords)
129 , fTextureSampler(resourceProvider, std::move(proxy), params)
130 , fInColor(nullptr)
131 , fMaskFormat(format) {
132 this->initClassID<GrBitmapTextGeoProc>();
133 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType);
134
135 bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat ||
136 kA565_GrMaskFormat == fMaskFormat;
137 if (hasVertexColor) {
138 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
139 }
140 fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_GrVertexAttribType,
141 kHigh_GrSLPrecision);
142 this->addTextureSampler(&fTextureSampler);
143 }
144
getGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const145 void GrBitmapTextGeoProc::getGLSLProcessorKey(const GrShaderCaps& caps,
146 GrProcessorKeyBuilder* b) const {
147 GrGLBitmapTextGeoProc::GenKey(*this, caps, b);
148 }
149
createGLSLInstance(const GrShaderCaps & caps) const150 GrGLSLPrimitiveProcessor* GrBitmapTextGeoProc::createGLSLInstance(const GrShaderCaps& caps) const {
151 return new GrGLBitmapTextGeoProc();
152 }
153
154 ///////////////////////////////////////////////////////////////////////////////
155
156 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrBitmapTextGeoProc);
157
158 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)159 sk_sp<GrGeometryProcessor> GrBitmapTextGeoProc::TestCreate(GrProcessorTestData* d) {
160 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
161 : GrProcessorUnitTest::kAlphaTextureIdx;
162 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
163
164 static const SkShader::TileMode kTileModes[] = {
165 SkShader::kClamp_TileMode,
166 SkShader::kRepeat_TileMode,
167 SkShader::kMirror_TileMode,
168 };
169 SkShader::TileMode tileModes[] = {
170 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
171 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
172 };
173 GrSamplerParams params(tileModes, d->fRandom->nextBool() ? GrSamplerParams::kBilerp_FilterMode
174 : GrSamplerParams::kNone_FilterMode);
175
176 GrMaskFormat format = kARGB_GrMaskFormat; // init to avoid warning
177 switch (d->fRandom->nextULessThan(3)) {
178 case 0:
179 format = kA8_GrMaskFormat;
180 break;
181 case 1:
182 format = kA565_GrMaskFormat;
183 break;
184 case 2:
185 format = kARGB_GrMaskFormat;
186 break;
187 }
188
189 return GrBitmapTextGeoProc::Make(d->resourceProvider(), GrRandomColor(d->fRandom),
190 std::move(proxy),
191 params, format, GrTest::TestMatrix(d->fRandom),
192 d->fRandom->nextBool());
193 }
194 #endif
195