GrBitmapTextGeoProc.cpp revision e7492fe49c61915b70bde648b75f9b6fc60b4bef
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
18class GrGLBitmapTextGeoProc : public GrGLSLGeometryProcessor {
19public:
20    GrGLBitmapTextGeoProc() : fColor(GrColor_ILLEGAL), fAtlasSize({0,0}) {}
21
22    void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
23        const GrBitmapTextGeoProc& btgp = 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(btgp);
31
32        const char* atlasSizeInvName;
33        fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
34                                                          kVec2f_GrSLType,
35                                                          kHigh_GrSLPrecision,
36                                                          "AtlasSizeInv",
37                                                          &atlasSizeInvName);
38
39        GrGLSLVertToFrag v(kVec2f_GrSLType);
40        varyingHandler->addVarying("TextureCoords", &v, kHigh_GrSLPrecision);
41        vertBuilder->codeAppendf("%s = float2(%s.x, %s.y) * %s;", v.vsOut(),
42                                 btgp.inTextureCoords()->fName,
43                                 btgp.inTextureCoords()->fName,
44                                 atlasSizeInvName);
45
46        GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
47        // Setup pass through color
48        if (btgp.hasVertexColor()) {
49            varyingHandler->addPassThroughAttribute(btgp.inColor(), args.fOutputColor);
50        } else {
51            this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
52                                    &fColorUniform);
53        }
54
55        // Setup position
56        this->writeOutputPosition(vertBuilder, gpArgs, btgp.inPosition()->fName);
57
58        // emit transforms
59        this->emitTransforms(vertBuilder,
60                             varyingHandler,
61                             uniformHandler,
62                             gpArgs->fPositionVar,
63                             btgp.inPosition()->fName,
64                             btgp.localMatrix(),
65                             args.fFPCoordTransformHandler);
66
67        if (btgp.maskFormat() == kARGB_GrMaskFormat) {
68            fragBuilder->codeAppendf("%s = ", args.fOutputColor);
69            fragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
70                                                        args.fTexSamplers[0],
71                                                        v.fsIn(),
72                                                        kVec2f_GrSLType);
73            fragBuilder->codeAppend(";");
74            fragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
75        } else {
76            fragBuilder->codeAppendf("%s = ", args.fOutputCoverage);
77            fragBuilder->appendTextureLookup(args.fTexSamplers[0], v.fsIn(), kVec2f_GrSLType);
78            fragBuilder->codeAppend(";");
79        }
80    }
81
82    void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
83                 FPCoordTransformIter&& transformIter) override {
84        const GrBitmapTextGeoProc& btgp = gp.cast<GrBitmapTextGeoProc>();
85        if (btgp.color() != fColor && !btgp.hasVertexColor()) {
86            float c[4];
87            GrColorToRGBAFloat(btgp.color(), c);
88            pdman.set4fv(fColorUniform, 1, c);
89            fColor = btgp.color();
90        }
91
92        SkASSERT(btgp.numTextureSamplers() == 1);
93        GrTexture* atlas = btgp.textureSampler(0).peekTexture();
94        SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
95
96        if (fAtlasSize.fWidth != atlas->width() || fAtlasSize.fHeight != atlas->height()) {
97            pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlas->width(), 1.0f / atlas->height());
98            fAtlasSize.set(atlas->width(), atlas->height());
99        }
100        this->setTransformDataHelper(btgp.localMatrix(), pdman, &transformIter);
101    }
102
103    static inline void GenKey(const GrGeometryProcessor& proc,
104                              const GrShaderCaps&,
105                              GrProcessorKeyBuilder* b) {
106        const GrBitmapTextGeoProc& btgp = proc.cast<GrBitmapTextGeoProc>();
107        uint32_t key = 0;
108        key |= (btgp.usesLocalCoords() && btgp.localMatrix().hasPerspective()) ? 0x1 : 0x0;
109        key |= btgp.maskFormat() << 1;
110        b->add32(key);
111    }
112
113private:
114    GrColor       fColor;
115    UniformHandle fColorUniform;
116
117    SkISize       fAtlasSize;
118    UniformHandle fAtlasSizeInvUniform;
119
120    typedef GrGLSLGeometryProcessor INHERITED;
121};
122
123///////////////////////////////////////////////////////////////////////////////
124
125GrBitmapTextGeoProc::GrBitmapTextGeoProc(GrColor color, sk_sp<GrTextureProxy> proxy,
126                                         const GrSamplerState& params, GrMaskFormat format,
127                                         const SkMatrix& localMatrix, bool usesLocalCoords)
128        : fColor(color)
129        , fLocalMatrix(localMatrix)
130        , fUsesLocalCoords(usesLocalCoords)
131        , fTextureSampler(std::move(proxy), params)
132        , fInColor(nullptr)
133        , fMaskFormat(format) {
134    this->initClassID<GrBitmapTextGeoProc>();
135    fInPosition =
136            &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType, kHigh_GrSLPrecision);
137
138    bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat ||
139                          kA565_GrMaskFormat == fMaskFormat;
140    if (hasVertexColor) {
141        fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
142    }
143
144    fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_uint_GrVertexAttribType,
145                                              kHigh_GrSLPrecision);
146    this->addTextureSampler(&fTextureSampler);
147}
148
149void GrBitmapTextGeoProc::getGLSLProcessorKey(const GrShaderCaps& caps,
150                                              GrProcessorKeyBuilder* b) const {
151    GrGLBitmapTextGeoProc::GenKey(*this, caps, b);
152}
153
154GrGLSLPrimitiveProcessor* GrBitmapTextGeoProc::createGLSLInstance(const GrShaderCaps& caps) const {
155    return new GrGLBitmapTextGeoProc();
156}
157
158///////////////////////////////////////////////////////////////////////////////
159
160GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrBitmapTextGeoProc);
161
162#if GR_TEST_UTILS
163
164sk_sp<GrGeometryProcessor> GrBitmapTextGeoProc::TestCreate(GrProcessorTestData* d) {
165    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
166                                        : GrProcessorUnitTest::kAlphaTextureIdx;
167    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
168
169    GrSamplerState::WrapMode wrapModes[2];
170    GrTest::TestWrapModes(d->fRandom, wrapModes);
171    GrSamplerState samplerState(wrapModes, d->fRandom->nextBool()
172                                                   ? GrSamplerState::Filter::kBilerp
173                                                   : GrSamplerState::Filter::kNearest);
174
175    GrMaskFormat format = kARGB_GrMaskFormat; // init to avoid warning
176    switch (d->fRandom->nextULessThan(3)) {
177        case 0:
178            format = kA8_GrMaskFormat;
179            break;
180        case 1:
181            format = kA565_GrMaskFormat;
182            break;
183        case 2:
184            format = kARGB_GrMaskFormat;
185            break;
186    }
187
188    return GrBitmapTextGeoProc::Make(GrRandomColor(d->fRandom), std::move(proxy), samplerState,
189                                     format, GrTest::TestMatrix(d->fRandom),
190                                     d->fRandom->nextBool());
191}
192#endif
193