1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2017 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef GrCCCoverageProcessor_DEFINED
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define GrCCCoverageProcessor_DEFINED
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrCaps.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrGeometryProcessor.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrShaderCaps.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkNx.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLGeometryProcessor.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLVarying.h"
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrGLSLPPFragmentBuilder;
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrGLSLVertexGeoBuilder;
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrMesh;
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/**
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * This is the geometry processor for the simple convex primitive shapes (triangles and closed,
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * convex bezier curves) from which ccpr paths are composed. The output is a single-channel alpha
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * value, positive for clockwise shapes and negative for counter-clockwise, that indicates coverage.
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * The caller is responsible to execute all render passes for all applicable primitives into a
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * cleared, floating point, alpha-only render target using SkBlendMode::kPlus (see RenderPass
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * below). Once all of a path's primitives have been drawn, the render target contains a composite
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * coverage count that can then be used to draw the path (see GrCCPathProcessor).
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * To draw a renderer pass, see appendMesh below.
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrCCCoverageProcessor : public GrGeometryProcessor {
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Defines a single triangle or closed quadratic bezier, with transposed x,y point values.
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    struct TriangleInstance {
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float fX[3];
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float fY[3];
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void set(const SkPoint[3], const Sk2f& trans);
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void set(const SkPoint&, const SkPoint&, const SkPoint&, const Sk2f& trans);
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Defines a single closed cubic bezier, with transposed x,y point values.
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    struct CubicInstance {
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float fX[4];
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float fY[4];
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void set(const SkPoint[4], float dx, float dy);
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // All primitive shapes (triangles and closed, convex bezier curves) require more than one
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // render pass. Here we enumerate every render pass needed in order to produce a complete
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // coverage count mask. This is an exhaustive list of all ccpr coverage shaders.
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    //
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // During a render pass, the "Impl" (GSImpl or VSimpl) generates conservative geometry for
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // rasterization, and the Shader decides the coverage value at each pixel.
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum class RenderPass {
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // For a Hull, the Impl generates a "conservative raster hull" around the input points. This
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // is the geometry that causes a pixel to be rasterized if it is touched anywhere by the
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // input polygon. The input coverage values sent to the Shader at each vertex are either
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // null, or +1 all around if the Impl combines this pass with kTriangleEdges. Logically,
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // the conservative raster hull is equivalent to the convex hull of pixel size boxes
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // centered on each input point.
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kTriangleHulls,
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kQuadraticHulls,
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kCubicHulls,
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // For Edges, the Impl generates conservative rasters around every input edge (i.e. convex
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // hulls of two pixel-size boxes centered on both of the edge's endpoints). The input
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // coverage values sent to the Shader at each vertex are -1 on the outside border of the
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // edge geometry and 0 on the inside. This is the only geometry type that associates
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // coverage values with the output vertices. Interpolated, these coverage values convert
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // jagged conservative raster edges into a smooth antialiased edge.
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        //
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // NOTE: The Impl may combine this pass with kTriangleHulls, in which case DoesRenderPass()
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // will be false for kTriangleEdges and it must not be used.
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kTriangleEdges,
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // For Corners, the Impl Generates the conservative rasters of corner points (i.e.
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // pixel-size boxes). It generates 3 corner boxes for triangles and 2 for curves. The Shader
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // specifies which corners. Input coverage values sent to the Shader will be null.
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kTriangleCorners,
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kQuadraticCorners,
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kCubicCorners
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static bool RenderPassIsCubic(RenderPass);
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const char* RenderPassName(RenderPass);
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    constexpr static bool DoesRenderPass(RenderPass renderPass, const GrCaps& caps) {
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return RenderPass::kTriangleEdges != renderPass ||
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot               caps.shaderCaps()->geometryShaderSupport();
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrCCCoverageProcessor(GrResourceProvider* rp, RenderPass pass, const GrCaps& caps)
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            : INHERITED(kGrCCCoverageProcessor_ClassID)
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fRenderPass(pass)
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fImpl(caps.shaderCaps()->geometryShaderSupport() ? Impl::kGeometryShader
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                               : Impl::kVertexShader) {
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(DoesRenderPass(pass, caps));
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (Impl::kGeometryShader == fImpl) {
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->initGS();
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->initVS(rp, caps);
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Appends a GrMesh that will draw the provided instances. The instanceBuffer must be an array
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // of either TriangleInstance or CubicInstance, depending on this processor's RendererPass, with
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // coordinates in the desired shape's final atlas-space position.
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    //
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // NOTE: Quadratics use TriangleInstance since both have 3 points.
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void appendMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkTArray<GrMesh>* out) {
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (Impl::kGeometryShader == fImpl) {
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->appendGSMesh(instanceBuffer, instanceCount, baseInstance, out);
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->appendVSMesh(instanceBuffer, instanceCount, baseInstance, out);
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // GrPrimitiveProcessor overrides.
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* name() const override { return RenderPassName(fRenderPass); }
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString dumpInfo() const override {
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkStringPrintf("%s\n%s", this->name(), this->INHERITED::dumpInfo().c_str());
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Increases the 1/2 pixel AA bloat by a factor of debugBloat and outputs color instead of
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // coverage (coverage=+1 -> green, coverage=0 -> black, coverage=-1 -> red).
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void enableDebugVisualizations(float debugBloat) { fDebugBloat = debugBloat; }
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool debugVisualizationsEnabled() const { return fDebugBloat > 0; }
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    float debugBloat() const { SkASSERT(this->debugVisualizationsEnabled()); return fDebugBloat; }
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // The Shader provides code to calculate each pixel's coverage in a RenderPass. It also
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // provides details about shape-specific geometry.
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    class Shader {
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    public:
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        union GeometryVars {
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            struct {
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const char* fAlternatePoints; // floatNx2 (if left null, will use input points).
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } fHullVars;
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            struct {
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const char* fPoint; // float2
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } fCornerVars;
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GeometryVars() { memset(this, 0, sizeof(*this)); }
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Called before generating geometry. Subclasses must fill out the applicable fields in
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // GeometryVars (if any), and may also use this opportunity to setup internal member
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // variables that will be needed during onEmitVaryings (e.g. transformation matrices).
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        //
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // repetitionID is a 0-based index and indicates which edge or corner is being generated.
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // It will be null when generating a hull.
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts,
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                   const char* repetitionID, const char* wind,
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                   GeometryVars*) const {}
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void emitVaryings(GrGLSLVaryingHandler* varyingHandler, GrGLSLVarying::Scope scope,
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                          SkString* code, const char* position, const char* inputCoverage,
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                          const char* wind) {
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT(GrGLSLVarying::Scope::kVertToGeo != scope);
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->onEmitVaryings(varyingHandler, scope, code, position, inputCoverage, wind);
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void emitFragmentCode(const GrCCCoverageProcessor& proc, GrGLSLPPFragmentBuilder*,
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                              const char* skOutputColor, const char* skOutputCoverage) const;
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Defines an equation ("dot(float3(pt, 1), distance_equation)") that is -1 on the outside
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // border of a conservative raster edge and 0 on the inside. 'leftPt' and 'rightPt' must be
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // ordered clockwise.
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        static void EmitEdgeDistanceEquation(GrGLSLVertexGeoBuilder*, const char* leftPt,
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                             const char* rightPt,
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                             const char* outputDistanceEquation);
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual ~Shader() {}
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    protected:
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Here the subclass adds its internal varyings to the handler and produces code to
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // initialize those varyings from a given position, input coverage value, and wind.
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        //
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // NOTE: the coverage input is only relevant for edges (see comments in RenderPass).
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Otherwise it is +1 all around.
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    const char* position, const char* inputCoverage,
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    const char* wind) = 0;
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Emits the fragment code that calculates a pixel's signed coverage value.
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual void onEmitFragmentCode(GrGLSLPPFragmentBuilder*,
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                        const char* outputCoverage) const = 0;
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Returns the name of a Shader's internal varying at the point where where its value is
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // assigned. This is intended to work whether called for a vertex or a geometry shader.
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* OutName(const GrGLSLVarying& varying) const {
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            using Scope = GrGLSLVarying::Scope;
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT(Scope::kVertToGeo != varying.scope());
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return Scope::kGeoToFrag == varying.scope() ? varying.gsOut() : varying.vsOut();
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Defines a global float2 array that contains MSAA sample locations as offsets from pixel
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // center. Subclasses can use this for software multisampling.
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        //
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Returns the number of samples.
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        static int DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, const char* samplesName);
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    class GSImpl;
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    class VSImpl;
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Slightly undershoot a bloat radius of 0.5 so vertices that fall on integer boundaries don't
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // accidentally bleed into neighbor pixels.
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr float kAABloatRadius = 0.491111f;
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Number of bezier points for curves, or 3 for triangles.
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int numInputPoints() const { return RenderPassIsCubic(fRenderPass) ? 4 : 3; }
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum class Impl : bool {
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kGeometryShader,
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kVertexShader
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void initGS();
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void initVS(GrResourceProvider*, const GrCaps&);
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void appendGSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                      SkTArray<GrMesh>* out) const;
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void appendVSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                      SkTArray<GrMesh>* out) const;
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrGLSLPrimitiveProcessor* createGSImpl(std::unique_ptr<Shader>) const;
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrGLSLPrimitiveProcessor* createVSImpl(std::unique_ptr<Shader>) const;
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const RenderPass fRenderPass;
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const Impl fImpl;
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDEBUGCODE(float fDebugBloat = 0);
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Used by VSImpl.
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<const GrBuffer> fVertexBuffer;
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<const GrBuffer> fIndexBuffer;
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int fNumIndicesPerInstance;
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrPrimitiveType fPrimitiveType;
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef GrGeometryProcessor INHERITED;
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline void GrCCCoverageProcessor::TriangleInstance::set(const SkPoint p[3], const Sk2f& trans) {
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->set(p[0], p[1], p[2], trans);
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline void GrCCCoverageProcessor::TriangleInstance::set(const SkPoint& p0, const SkPoint& p1,
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                         const SkPoint& p2, const Sk2f& trans) {
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Sk2f P0 = Sk2f::Load(&p0) + trans;
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Sk2f P1 = Sk2f::Load(&p1) + trans;
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Sk2f P2 = Sk2f::Load(&p2) + trans;
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Sk2f::Store3(this, P0, P1, P2);
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline void GrCCCoverageProcessor::CubicInstance::set(const SkPoint p[4], float dx, float dy) {
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Sk4f X,Y;
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Sk4f::Load2(p, &X, &Y);
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    (X + dx).store(&fX);
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    (Y + dy).store(&fY);
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline bool GrCCCoverageProcessor::RenderPassIsCubic(RenderPass pass) {
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    switch (pass) {
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kTriangleHulls:
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kTriangleEdges:
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kTriangleCorners:
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kQuadraticHulls:
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kQuadraticCorners:
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kCubicHulls:
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kCubicCorners:
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return true;
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ABORT("Invalid RenderPass");
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return false;
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline const char* GrCCCoverageProcessor::RenderPassName(RenderPass pass) {
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    switch (pass) {
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kTriangleHulls: return "kTriangleHulls";
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kTriangleEdges: return "kTriangleEdges";
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kTriangleCorners: return "kTriangleCorners";
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kQuadraticHulls: return "kQuadraticHulls";
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kQuadraticCorners: return "kQuadraticCorners";
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kCubicHulls: return "kCubicHulls";
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case RenderPass::kCubicCorners: return "kCubicCorners";
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ABORT("Invalid RenderPass");
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return "";
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
303