blob: 1e52d51a45e6b87ed7c695093e9453ec311e41d7 [file] [log] [blame]
/*
* 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