1/*
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 "GrShadowGeoProc.h"
9
10#include "glsl/GrGLSLFragmentShaderBuilder.h"
11#include "glsl/GrGLSLGeometryProcessor.h"
12#include "glsl/GrGLSLUniformHandler.h"
13#include "glsl/GrGLSLVarying.h"
14#include "glsl/GrGLSLVertexGeoBuilder.h"
15
16class GrGLSLRRectShadowGeoProc : public GrGLSLGeometryProcessor {
17public:
18    GrGLSLRRectShadowGeoProc() {}
19
20    void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
21        const GrRRectShadowGeoProc& rsgp = args.fGP.cast<GrRRectShadowGeoProc>();
22        GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
23        GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
24        GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
25        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
26
27        // emit attributes
28        varyingHandler->emitAttributes(rsgp);
29        fragBuilder->codeAppend("half4 shadowParams;");
30        varyingHandler->addPassThroughAttribute(rsgp.inShadowParams(), "shadowParams");
31
32        // setup pass through color
33        varyingHandler->addPassThroughAttribute(rsgp.inColor(), args.fOutputColor);
34
35        // Setup position
36        this->writeOutputPosition(vertBuilder, gpArgs, rsgp.inPosition()->fName);
37
38        // emit transforms
39        this->emitTransforms(vertBuilder,
40                             varyingHandler,
41                             uniformHandler,
42                             rsgp.inPosition()->asShaderVar(),
43                             args.fFPCoordTransformHandler);
44
45        fragBuilder->codeAppend("half d = length(shadowParams.xy);");
46        fragBuilder->codeAppend("half distance = shadowParams.z * (1.0 - d);");
47
48        fragBuilder->codeAppend("half factor = 1.0 - clamp(distance, 0.0, shadowParams.w);");
49        fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.018;");
50        fragBuilder->codeAppendf("%s = half4(factor);",
51                                 args.fOutputCoverage);
52    }
53
54    void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
55                 FPCoordTransformIter&& transformIter) override {
56        this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
57    }
58
59private:
60    typedef GrGLSLGeometryProcessor INHERITED;
61};
62
63///////////////////////////////////////////////////////////////////////////////
64
65GrRRectShadowGeoProc::GrRRectShadowGeoProc()
66: INHERITED(kGrRRectShadowGeoProc_ClassID) {
67    fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
68    fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
69    fInShadowParams = &this->addVertexAttrib("inShadowParams", kHalf4_GrVertexAttribType);
70}
71
72GrGLSLPrimitiveProcessor* GrRRectShadowGeoProc::createGLSLInstance(const GrShaderCaps&) const {
73    return new GrGLSLRRectShadowGeoProc();
74}
75
76///////////////////////////////////////////////////////////////////////////////
77
78GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrRRectShadowGeoProc);
79
80#if GR_TEST_UTILS
81sk_sp<GrGeometryProcessor> GrRRectShadowGeoProc::TestCreate(GrProcessorTestData* d) {
82    return GrRRectShadowGeoProc::Make();
83}
84#endif
85