aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/ccpr/GrCCPRTriangleProcessor.h
blob: 1e52d51a45e6b87ed7c695093e9453ec311e41d7 (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
/*
 * 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 GrCCPRTriangleProcessor_DEFINED
#define GrCCPRTriangleProcessor_DEFINED

#include "ccpr/GrCCPRCoverageProcessor.h"

/**
 * This class renders the coverage of triangles.
 *
 * Triangles are rendered in three passes:
 *
 * Pass 1: Draw the triangle's conservative raster hull with a coverage of 1. (Conservative raster
 *         is drawn by considering 3 pixel size boxes, one centered at each vertex, and drawing the
 *         convex hull of those boxes.)
 *
 * Pass 2: Smooth the edges that were over-rendered during Pass 1. Draw the conservative raster of
 *         each edge (i.e. convex hull of two pixel-size boxes at the endpoints), interpolating from
 *         coverage=-1 on the outside edge to coverage=0 on the inside edge.
 *
 * Pass 3: Touch up the corner pixels to have the correct coverage.
 */
class GrCCPRTriangleProcessor : public GrCCPRCoverageProcessor::PrimitiveProcessor {
public:
    GrCCPRTriangleProcessor(CoverageType initialCoverage) : INHERITED(initialCoverage) {}

    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;

protected:
    void defineInputVertices(GrGLSLGeometryBuilder*) const;

private:
    typedef GrCCPRCoverageProcessor::PrimitiveProcessor INHERITED;
};

class GrCCPRTriangleHullAndEdgeProcessor : public GrCCPRTriangleProcessor {
public:
    enum class GeometryType {
        kHulls,
        kEdges,
        kHullsAndEdges
    };

    GrCCPRTriangleHullAndEdgeProcessor(GeometryType geometryType)
            : INHERITED(GeometryType::kHulls == geometryType ?
                        CoverageType::kOne : CoverageType::kInterpolated)
            , fGeometryType(geometryType) {}

    void onEmitGeometryShader(GrGLSLGeometryBuilder*, const char* emitVertexFn, const char* wind,
                              const char* rtAdjust) const override;

private:
    const GeometryType fGeometryType;

    typedef GrCCPRTriangleProcessor INHERITED;
};

/**
 * This pass fixes the corner pixels of a triangle. It erases the (incorrect) coverage that was
 * written at the corners during the previous hull and edge passes, and then approximates the true
 * coverage by sampling the triangle with horizontal lines.
 */
class GrCCPRTriangleCornerProcessor : public GrCCPRTriangleProcessor {
public:
    GrCCPRTriangleCornerProcessor()
            : INHERITED(CoverageType::kShader)
            , fEdgeDistance(kVec3f_GrSLType)
            , fDevCoord(kVec2f_GrSLType)
            , fNeighbors(kVec4f_GrSLType)
            , fEdgeDistances(kMat33f_GrSLType)
            , fCornerIdx(kInt_GrSLType) {}

    void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
        this->INHERITED::resetVaryings(varyingHandler);
        varyingHandler->addFlatVarying("edge_distance", &fEdgeDistance, kHigh_GrSLPrecision);
        varyingHandler->addFlatVarying("devcoord", &fDevCoord, kHigh_GrSLPrecision);
        varyingHandler->addFlatVarying("neighbors", &fNeighbors, kHigh_GrSLPrecision);
        varyingHandler->addFlatVarying("edge_distances", &fEdgeDistances, kHigh_GrSLPrecision);
        varyingHandler->addFlatVarying("corner_idx", &fCornerIdx, kLow_GrSLPrecision);
    }

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

private:
    GrGLSLVertToGeo fEdgeDistance;
    GrGLSLVertToGeo fDevCoord;
    GrGLSLGeoToFrag fNeighbors;
    GrGLSLGeoToFrag fEdgeDistances;
    GrGLSLGeoToFrag fCornerIdx;

    typedef GrCCPRTriangleProcessor INHERITED;
};

#endif