aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/ccpr/GrCCPRCubicProcessor.h
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2017-07-14 15:17:41 -0600
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-07-14 21:45:35 +0000
commit1a325d25b941ef801b3e9b2c0342da43cf35cdba (patch)
tree3f65d36541399e1ae6a529a534119815a2c5ba36 /src/gpu/ccpr/GrCCPRCubicProcessor.h
parent588fb040b3ad410cdb10c87f9a7884b6eb825e90 (diff)
Coverage counting path renderer
Initial implementation of a GPU path renderer that draws antialiased paths by counting coverage in an offscreen buffer. Initially disabled until it has had time to soak. Bug: skia: Change-Id: I003d8cfdf8dc62641581b5ea2dc4f0aa00108df6 Reviewed-on: https://skia-review.googlesource.com/21541 Commit-Queue: Chris Dalton <csmartdalton@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'src/gpu/ccpr/GrCCPRCubicProcessor.h')
-rw-r--r--src/gpu/ccpr/GrCCPRCubicProcessor.h147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/gpu/ccpr/GrCCPRCubicProcessor.h b/src/gpu/ccpr/GrCCPRCubicProcessor.h
new file mode 100644
index 0000000000..f31dad793e
--- /dev/null
+++ b/src/gpu/ccpr/GrCCPRCubicProcessor.h
@@ -0,0 +1,147 @@
+/*
+ * 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 caller is expected to chop cubics at the KLM roots (a.k.a. inflection points and loop
+ * intersection points, resulting in necessarily convex segments) before feeding them into this
+ * processor.
+ *
+ * The curves are rendered in two passes:
+ *
+ * Pass 1: Draw the (convex) bezier quadrilateral, inset by 1/2 pixel all around, and use the
+ * gradient-based AA technique outlined in the Loop/Blinn paper to compute coverage.
+ *
+ * Pass 2: Draw a border around the previous inset, up to the bezier quadrilatral's conservative
+ * raster hull, and compute coverage using pseudo MSAA. This pass is necessary because the
+ * gradient approach does not work near the L and M lines.
+ *
+ * FIXME: The pseudo MSAA border is slow and ugly. We should investigate an alternate solution of
+ * just approximating the curve with straight lines for short distances across the problem points
+ * instead.
+ */
+class GrCCPRCubicProcessor : public GrCCPRCoverageProcessor::PrimitiveProcessor {
+public:
+ enum class Type {
+ kSerpentine,
+ kLoop
+ };
+
+ GrCCPRCubicProcessor(Type type)
+ : INHERITED(CoverageType::kShader)
+ , fType(type)
+ , fInset(kVec3f_GrSLType)
+ , fTS(kFloat_GrSLType)
+ , fKLMMatrix("klm_matrix", kMat33f_GrSLType, GrShaderVar::kNonArray,
+ kHigh_GrSLPrecision)
+ , fKLMDerivatives("klm_derivatives", kVec2f_GrSLType, 3, kHigh_GrSLPrecision) {}
+
+ void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
+ varyingHandler->addVarying("insets", &fInset, kHigh_GrSLPrecision);
+ varyingHandler->addVarying("ts", &fTS, 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;
+
+protected:
+ virtual void emitCubicGeometry(GrGLSLGeometryBuilder*, const char* emitVertexFn,
+ const char* wind, const char* rtAdjust) const = 0;
+
+ const Type fType;
+ GrGLSLVertToGeo fInset;
+ GrGLSLVertToGeo fTS;
+ GrShaderVar fKLMMatrix;
+ GrShaderVar fKLMDerivatives;
+
+ typedef GrCCPRCoverageProcessor::PrimitiveProcessor INHERITED;
+};
+
+class GrCCPRCubicInsetProcessor : public GrCCPRCubicProcessor {
+public:
+ GrCCPRCubicInsetProcessor(Type type)
+ : INHERITED(type)
+ , fKLM(kVec3f_GrSLType)
+ , fGradMatrix(kMat22f_GrSLType) {}
+
+ void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
+ this->INHERITED::resetVaryings(varyingHandler);
+ varyingHandler->addVarying("klm", &fKLM, kHigh_GrSLPrecision);
+ varyingHandler->addVarying("grad_matrix", &fGradMatrix, kHigh_GrSLPrecision);
+ }
+
+ void emitCubicGeometry(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;
+
+protected:
+ GrGLSLGeoToFrag fKLM;
+ GrGLSLGeoToFrag fGradMatrix;
+
+ typedef GrCCPRCubicProcessor INHERITED;
+};
+
+class GrCCPRCubicBorderProcessor : public GrCCPRCubicProcessor {
+public:
+ GrCCPRCubicBorderProcessor(Type type)
+ : INHERITED(type)
+ , fEdgeDistanceEquation("edge_distance_equation", kVec3f_GrSLType,
+ GrShaderVar::kNonArray, kHigh_GrSLPrecision)
+ , fEdgeDistanceDerivatives("edge_distance_derivatives", kVec2f_GrSLType,
+ GrShaderVar::kNonArray, kHigh_GrSLPrecision)
+ , fEdgeSpaceTransform("edge_space_transform", kVec4f_GrSLType, GrShaderVar::kNonArray,
+ kHigh_GrSLPrecision)
+ , fKLMD(kVec4f_GrSLType)
+ , fdKLMDdx(kVec4f_GrSLType)
+ , fdKLMDdy(kVec4f_GrSLType)
+ , fEdgeSpaceCoord(kVec2f_GrSLType) {}
+
+ void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
+ this->INHERITED::resetVaryings(varyingHandler);
+ varyingHandler->addVarying("klmd", &fKLMD, kHigh_GrSLPrecision);
+ varyingHandler->addFlatVarying("dklmddx", &fdKLMDdx, kHigh_GrSLPrecision);
+ varyingHandler->addFlatVarying("dklmddy", &fdKLMDdy, kHigh_GrSLPrecision);
+ varyingHandler->addVarying("edge_space_coord", &fEdgeSpaceCoord, kHigh_GrSLPrecision);
+ }
+
+ void emitCubicGeometry(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;
+
+protected:
+ GrShaderVar fEdgeDistanceEquation;
+ GrShaderVar fEdgeDistanceDerivatives;
+ GrShaderVar fEdgeSpaceTransform;
+ GrGLSLGeoToFrag fKLMD;
+ GrGLSLGeoToFrag fdKLMDdx;
+ GrGLSLGeoToFrag fdKLMDdy;
+ GrGLSLGeoToFrag fEdgeSpaceCoord;
+
+ typedef GrCCPRCubicProcessor INHERITED;
+};
+
+#endif