aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/ccpr/GrCCPRCubicProcessor.h
blob: 20ca3f25477b86adede414ab186eca90c292c0b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrCCPRCubicProcessor_DEFINED
#define GrCCPRCubicProcessor_DEFINED

#include "ccpr/GrCCPRCoverageProcessor.h"

class GrGLSLGeometryBuilder;

/**
 * This class renders the coverage of convex closed cubic segments using the techniques outlined in
 * "Resolution Independent Curve Rendering using Programmable Graphics Hardware" by Charles Loop and
 * Jim Blinn:
 *
 * https://www.microsoft.com/en-us/research/wp-content/uploads/2005/01/p1000-loop.pdf
 *
 * The provided curves must be convex, monotonic with respect to the vector of their closing edge
 * [P3 - P0], and must not contain or be near any inflection points or loop intersections.
 * (Use GrCCPRGeometry.)
 */
class GrCCPRCubicProcessor : public GrCCPRCoverageProcessor::PrimitiveProcessor {
public:
    enum class CubicType {
        kSerpentine,
        kLoop
    };

    GrCCPRCubicProcessor(CubicType cubicType)
            : INHERITED(CoverageType::kShader)
            , fCubicType(cubicType)
            , fKLMMatrix("klm_matrix", kHighFloat3x3_GrSLType, GrShaderVar::kNonArray,
                         kHigh_GrSLPrecision)
            , fKLMDerivatives("klm_derivatives", kHighFloat2_GrSLType, 3, kHigh_GrSLPrecision)
            , fEdgeDistanceEquation("edge_distance_equation", kHighFloat3_GrSLType,
                                    GrShaderVar::kNonArray, kHigh_GrSLPrecision)
            , fKLMD(kHighFloat4_GrSLType) {}

    void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
        varyingHandler->addVarying("klmd", &fKLMD, kHigh_GrSLPrecision);
    }

    void onEmitVertexShader(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder*,
                            const TexelBufferHandle& pointsBuffer, const char* atlasOffset,
                            const char* rtAdjust, GrGPArgs*) const override;
    void emitWind(GrGLSLGeometryBuilder*, const char* rtAdjust, const char* outputWind) const final;
    void onEmitGeometryShader(GrGLSLGeometryBuilder*, const char* emitVertexFn, const char* wind,
                              const char* rtAdjust) const final;
    void emitPerVertexGeometryCode(SkString* fnBody, const char* position, const char* coverage,
                                   const char* wind) const final;

protected:
    virtual void emitCubicGeometry(GrGLSLGeometryBuilder*, const char* emitVertexFn,
                                   const char* wind, const char* rtAdjust) const = 0;
    virtual void onEmitPerVertexGeometryCode(SkString* fnBody) const = 0;

    const CubicType   fCubicType;
    GrShaderVar       fKLMMatrix;
    GrShaderVar       fKLMDerivatives;
    GrShaderVar       fEdgeDistanceEquation;
    GrGLSLGeoToFrag   fKLMD;

    typedef GrCCPRCoverageProcessor::PrimitiveProcessor INHERITED;
};

class GrCCPRCubicHullProcessor : public GrCCPRCubicProcessor {
public:
    GrCCPRCubicHullProcessor(CubicType cubicType)
            : INHERITED(cubicType)
            , fGradMatrix(kHighFloat2x2_GrSLType) {}

    void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
        this->INHERITED::resetVaryings(varyingHandler);
        varyingHandler->addVarying("grad_matrix", &fGradMatrix, kHigh_GrSLPrecision);
    }

    void emitCubicGeometry(GrGLSLGeometryBuilder*, const char* emitVertexFn,
                           const char* wind, const char* rtAdjust) const override;
    void onEmitPerVertexGeometryCode(SkString* fnBody) const override;
    void emitShaderCoverage(GrGLSLFragmentBuilder*, const char* outputCoverage) const override;

protected:
    GrGLSLGeoToFrag   fGradMatrix;

    typedef GrCCPRCubicProcessor INHERITED;
};

class GrCCPRCubicCornerProcessor : public GrCCPRCubicProcessor {
public:
    GrCCPRCubicCornerProcessor(CubicType cubicType)
            : INHERITED(cubicType)
            , fEdgeDistanceDerivatives("edge_distance_derivatives", kHighFloat2_GrSLType,
                                        GrShaderVar::kNonArray, kHigh_GrSLPrecision)
            , fdKLMDdx(kHighFloat4_GrSLType)
            , fdKLMDdy(kHighFloat4_GrSLType) {}

    void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
        this->INHERITED::resetVaryings(varyingHandler);
        varyingHandler->addFlatVarying("dklmddx", &fdKLMDdx, kHigh_GrSLPrecision);
        varyingHandler->addFlatVarying("dklmddy", &fdKLMDdy, kHigh_GrSLPrecision);
    }

    void emitCubicGeometry(GrGLSLGeometryBuilder*, const char* emitVertexFn,
                           const char* wind, const char* rtAdjust) const override;
    void onEmitPerVertexGeometryCode(SkString* fnBody) const override;
    void emitShaderCoverage(GrGLSLFragmentBuilder*, const char* outputCoverage) const override;

protected:
    GrShaderVar        fEdgeDistanceDerivatives;
    GrGLSLGeoToFrag    fdKLMDdx;
    GrGLSLGeoToFrag    fdKLMDdy;

    typedef GrCCPRCubicProcessor INHERITED;
};

#endif