aboutsummaryrefslogtreecommitdiffhomepage
path: root/samplecode/SampleCCPRGeometry.cpp
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2017-09-05 16:46:48 -0600
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-09-05 23:06:42 +0000
commit7f578bf07b016778e3105b7655a895728b12d847 (patch)
tree5bdc64da012a72147750dfe20f0887b388944d49 /samplecode/SampleCCPRGeometry.cpp
parentc1e59638b4a08f5210f72f671292b1b3759f54c6 (diff)
CCPR: Remove cubic insets and MSAA borders
Avoids the need for MSAA cubic borders by chopping up the cubic geometry and crossing the inflections points and loop intersections with lines and quadratic(s) instead. This allows us to render the remaining cubic segments with simple hulls and analytic AA, giving better image quality and performance. Bug: skia: Change-Id: If371229f575ee0286c325c230a116d602a9d38ce Reviewed-on: https://skia-review.googlesource.com/41883 Commit-Queue: Chris Dalton <csmartdalton@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'samplecode/SampleCCPRGeometry.cpp')
-rw-r--r--samplecode/SampleCCPRGeometry.cpp130
1 files changed, 91 insertions, 39 deletions
diff --git a/samplecode/SampleCCPRGeometry.cpp b/samplecode/SampleCCPRGeometry.cpp
index afbeae4839..3fb4fb6cbf 100644
--- a/samplecode/SampleCCPRGeometry.cpp
+++ b/samplecode/SampleCCPRGeometry.cpp
@@ -10,12 +10,12 @@
#if SK_SUPPORT_GPU
#include "GrContextPriv.h"
+#include "GrPathUtils.h"
#include "GrRenderTargetContext.h"
#include "GrRenderTargetContextPriv.h"
#include "GrResourceProvider.h"
#include "SampleCode.h"
#include "SkCanvas.h"
-#include "SkGeometry.h"
#include "SkMakeUnique.h"
#include "SkPaint.h"
#include "SkPath.h"
@@ -30,11 +30,11 @@ using CurveInstance = GrCCPRCoverageProcessor::CurveInstance;
using Mode = GrCCPRCoverageProcessor::Mode;
static int num_points(Mode mode) {
- return mode >= Mode::kSerpentineInsets ? 4 : 3;
+ return mode >= Mode::kSerpentineHulls ? 4 : 3;
}
static int is_quadratic(Mode mode) {
- return mode >= Mode::kQuadraticHulls && mode < Mode::kSerpentineInsets;
+ return mode >= Mode::kQuadraticHulls && mode < Mode::kSerpentineHulls;
}
/**
@@ -64,6 +64,7 @@ private:
void updateGpuData();
Mode fMode = Mode::kTriangleHulls;
+ SkMatrix fCubicKLM;
SkPoint fPoints[4] = {
{100.05f, 100.05f},
@@ -105,6 +106,27 @@ private:
typedef GrDrawOp INHERITED;
};
+static void draw_klm_line(int w, int h, SkCanvas* canvas, const SkScalar line[3], SkColor color) {
+ SkPoint p1, p2;
+ if (SkScalarAbs(line[1]) > SkScalarAbs(line[0])) {
+ // Draw from vertical edge to vertical edge.
+ p1 = {0, -line[2] / line[1]};
+ p2 = {(SkScalar) w, (-line[2] - w * line[0]) / line[1]};
+ } else {
+ // Draw from horizontal edge to horizontal edge.
+ p1 = {-line[2] / line[0], 0};
+ p2 = {(-line[2] - h * line[1]) / line[0], (SkScalar) h};
+ }
+
+ SkPaint linePaint;
+ linePaint.setColor(color);
+ linePaint.setAlpha(128);
+ linePaint.setStyle(SkPaint::kStroke_Style);
+ linePaint.setStrokeWidth(0);
+ linePaint.setAntiAlias(true);
+ canvas->drawLine(p1, p2, linePaint);
+}
+
void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
SkAutoCanvasRestore acr(canvas, true);
canvas->setMatrix(SkMatrix::I());
@@ -118,17 +140,30 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
} else {
outline.lineTo(fPoints[1]);
outline.lineTo(fPoints[3]);
+ outline.close();
}
- outline.close();
SkPaint outlinePaint;
outlinePaint.setColor(0x30000000);
outlinePaint.setStyle(SkPaint::kStroke_Style);
outlinePaint.setStrokeWidth(0);
outlinePaint.setAntiAlias(true);
-
canvas->drawPath(outline, outlinePaint);
+#if 0
+ SkPaint gridPaint;
+ gridPaint.setColor(0x10000000);
+ gridPaint.setStyle(SkPaint::kStroke_Style);
+ gridPaint.setStrokeWidth(0);
+ gridPaint.setAntiAlias(true);
+ for (int y = 0; y < this->height(); y += GrCCPRCoverageProcessor::kDebugBloat) {
+ canvas->drawLine(0, y, this->width(), y, gridPaint);
+ }
+ for (int x = 0; x < this->width(); x += GrCCPRCoverageProcessor::kDebugBloat) {
+ canvas->drawLine(x, 0, x, this->height(), outlinePaint);
+ }
+#endif
+
const char* caption = "Use GPU backend to visualize geometry.";
if (GrRenderTargetContext* rtc =
@@ -143,7 +178,11 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
pointsPaint.setAntiAlias(true);
if (4 == num_points(fMode)) {
+ int w = this->width(), h = this->height();
canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, fPoints, pointsPaint);
+ draw_klm_line(w, h, canvas, &fCubicKLM[0], SK_ColorYELLOW);
+ draw_klm_line(w, h, canvas, &fCubicKLM[3], SK_ColorBLUE);
+ draw_klm_line(w, h, canvas, &fCubicKLM[6], SK_ColorRED);
} else {
canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, fPoints, pointsPaint);
canvas->drawPoints(SkCanvas::kPoints_PointMode, 1, fPoints + 3, pointsPaint);
@@ -165,41 +204,45 @@ void CCPRGeometryView::updateGpuData() {
if (4 == vertexCount) {
double t[2], s[2];
- SkCubicType type = SkClassifyCubic(fPoints, t, s);
- SkSTArray<2, float> chops;
- for (int i = 0; i < 2; ++i) {
- float chop = t[i] / s[i];
- if (chop > 0 && chop < 1) {
- chops.push_back(chop);
- }
+ SkCubicType type = GrPathUtils::getCubicKLM(fPoints, &fCubicKLM, t, s);
+ if (Mode::kSerpentineHulls == fMode && SkCubicType::kLoop == type) {
+ fMode = Mode::kLoopHulls;
}
-
- int instanceCount = chops.count() + 1;
- SkPoint chopped[10];
- SkChopCubicAt(fPoints, chopped, chops.begin(), chops.count());
-
- fGpuPoints.push_back(chopped[0]);
- for (int i = 0; i < instanceCount; ++i) {
- fGpuPoints.push_back(chopped[3*i + 1]);
- fGpuPoints.push_back(chopped[3*i + 2]);
- if (3 == instanceCount && SkCubicType::kLoop == type) {
- fGpuPoints.push_back(chopped[3*i]); // Account for floating point error.
- } else {
- fGpuPoints.push_back(chopped[3*i + 3]);
- }
+ if (Mode::kSerpentineCorners == fMode && SkCubicType::kLoop == type) {
+ fMode = Mode::kLoopCorners;
}
-
- if (fMode < Mode::kLoopInsets && SkCubicType::kLoop == type) {
- fMode = (Mode) ((int) fMode + 2);
+ if (Mode::kLoopHulls == fMode && SkCubicType::kLoop != type) {
+ fMode = Mode::kSerpentineHulls;
}
- if (fMode >= Mode::kLoopInsets && SkCubicType::kLoop != type) {
- fMode = (Mode) ((int) fMode - 2);
+ if (Mode::kLoopCorners == fMode && SkCubicType::kLoop != type) {
+ fMode = Mode::kSerpentineCorners;
}
- for (int i = 0; i < instanceCount; ++i) {
- fInstanceData.push_back(3*i);
- fInstanceData.push_back(0); // Atlas offset.
- ++fInstanceCount;
+ GrCCPRGeometry geometry;
+ geometry.beginContour(fPoints[0]);
+ geometry.cubicTo(fPoints[1], fPoints[2], fPoints[3],
+ GrCCPRCoverageProcessor::kDebugBloat / 2,
+ GrCCPRCoverageProcessor::kDebugBloat / 2);
+ geometry.endContour();
+ fGpuPoints.push_back_n(geometry.points().count(), geometry.points().begin());
+ int ptsIdx = 0;
+ for (GrCCPRGeometry::Verb verb : geometry.verbs()) {
+ switch (verb) {
+ case GrCCPRGeometry::Verb::kLineTo:
+ ++ptsIdx;
+ continue;
+ case GrCCPRGeometry::Verb::kMonotonicQuadraticTo:
+ ptsIdx += 2;
+ continue;
+ case GrCCPRGeometry::Verb::kMonotonicSerpentineTo:
+ case GrCCPRGeometry::Verb::kMonotonicLoopTo:
+ fInstanceData.push_back(ptsIdx);
+ fInstanceData.push_back(0); // Atlas offset.
+ ptsIdx += 3;
+ ++fInstanceCount;
+ continue;
+ default: continue;
+ }
}
} else if (is_quadratic(fMode)) {
GrCCPRGeometry geometry;
@@ -230,6 +273,10 @@ void CCPRGeometryView::updateGpuData() {
}
void CCPRGeometryView::Op::onExecute(GrOpFlushState* state) {
+ if (fView->fInstanceData.empty()) {
+ return;
+ }
+
GrResourceProvider* rp = state->resourceProvider();
GrContext* context = state->gpu()->getContext();
GrGLGpu* glGpu = kOpenGL_GrBackend == context->contextPriv().getBackend() ?
@@ -330,15 +377,20 @@ bool CCPRGeometryView::onQuery(SkEvent* evt) {
if (fMode >= Mode::kCombinedTriangleHullsAndEdges) {
fMode = Mode(int(fMode) + 1);
}
+ if (fMode >= Mode::kLoopHulls) {
+ // '6' -> kSerpentineHulls, '7' -> kSerpentineCorners. updateGpuData converts to
+ // kLoop* if needed.
+ fMode = Mode(int(fMode) + 1);
+ }
this->updateAndInval();
return true;
}
if (unichar == 'D') {
SkDebugf(" SkPoint fPoints[4] = {\n");
- SkDebugf(" {%f, %f},\n", fPoints[0].x(), fPoints[0].y());
- SkDebugf(" {%f, %f},\n", fPoints[1].x(), fPoints[1].y());
- SkDebugf(" {%f, %f},\n", fPoints[2].x(), fPoints[2].y());
- SkDebugf(" {%f, %f}\n", fPoints[3].x(), fPoints[3].y());
+ SkDebugf(" {%ff, %ff},\n", fPoints[0].x(), fPoints[0].y());
+ SkDebugf(" {%ff, %ff},\n", fPoints[1].x(), fPoints[1].y());
+ SkDebugf(" {%ff, %ff},\n", fPoints[2].x(), fPoints[2].y());
+ SkDebugf(" {%ff, %ff}\n", fPoints[3].x(), fPoints[3].y());
SkDebugf(" };\n");
return true;
}