blob: 929489c2433300b2ee8edabe5ea76d7b1b965a88 [file] [log] [blame]
Chris Daltonb832ce62020-01-06 19:49:37 -07001/*
2 * Copyright 2019 Google LLC.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "include/core/SkCanvas.h"
9#include "samplecode/Sample.h"
10#include "src/core/SkPathPriv.h"
11#include "tools/ToolUtils.h"
12
13#if SK_SUPPORT_GPU
14
Robert Phillips30ebcf72020-07-09 13:25:17 -040015#include "include/gpu/GrRecordingContext.h"
Chris Daltonb832ce62020-01-06 19:49:37 -070016#include "src/gpu/GrClip.h"
Chris Daltonb832ce62020-01-06 19:49:37 -070017#include "src/gpu/GrMemoryPool.h"
Robert Phillips30ebcf72020-07-09 13:25:17 -040018#include "src/gpu/GrRecordingContextPriv.h"
Chris Daltonb832ce62020-01-06 19:49:37 -070019#include "src/gpu/GrRenderTargetContext.h"
20#include "src/gpu/GrRenderTargetContextPriv.h"
Chris Dalton078f8752020-07-30 19:50:46 -060021#include "src/gpu/tessellate/GrPathTessellateOp.h"
Chris Daltonb832ce62020-01-06 19:49:37 -070022
23// This sample enables wireframe and visualizes the triangulation generated by
24// GrTessellateWedgeShader.
Chris Dalton0d0758e2020-05-29 10:51:08 -060025class TessellatedWedge : public Sample {
Chris Daltonb832ce62020-01-06 19:49:37 -070026public:
Chris Dalton0d0758e2020-05-29 10:51:08 -060027 TessellatedWedge() {
Chris Daltonf9aea7f2020-01-21 11:19:26 -070028#if 0
29 fPath.moveTo(1, 0);
30 int numSides = 32 * 3;
31 for (int i = 1; i < numSides; ++i) {
32 float theta = 2*3.1415926535897932384626433832785 * i / numSides;
33 fPath.lineTo(std::cos(theta), std::sin(theta));
34 }
Mike Reed1f607332020-05-21 12:11:27 -040035 fPath.transform(SkMatrix::Scale(200, 200));
36 fPath.transform(SkMatrix::Translate(300, 300));
Chris Daltonf9aea7f2020-01-21 11:19:26 -070037#else
Chris Daltonb832ce62020-01-06 19:49:37 -070038 fPath.moveTo(100, 200);
39 fPath.cubicTo(100, 100, 400, 100, 400, 200);
40 fPath.lineTo(250, 500);
Chris Daltonf9aea7f2020-01-21 11:19:26 -070041#endif
Chris Daltonb832ce62020-01-06 19:49:37 -070042 }
43
44private:
45 void onDrawContent(SkCanvas*) override;
46 Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override;
47 bool onClick(Sample::Click*) override;
48 bool onChar(SkUnichar) override;
49
50 SkString name() override { return SkString("TessellatedWedge"); }
51
52 SkMatrix fLastViewMatrix = SkMatrix::I();
53 SkPath fPath;
Chris Daltonb96995d2020-06-04 16:44:29 -060054 GrTessellationPathRenderer::OpFlags fOpFlags = GrTessellationPathRenderer::OpFlags::kWireframe;
Chris Daltonb832ce62020-01-06 19:49:37 -070055
56 class Click;
57};
58
Chris Dalton0d0758e2020-05-29 10:51:08 -060059void TessellatedWedge::onDrawContent(SkCanvas* canvas) {
Chris Daltonb832ce62020-01-06 19:49:37 -070060 canvas->clear(SK_ColorBLACK);
61
Robert Phillips30ebcf72020-07-09 13:25:17 -040062 auto ctx = canvas->recordingContext();
Chris Daltonb832ce62020-01-06 19:49:37 -070063 GrRenderTargetContext* rtc = canvas->internal_private_accessTopLayerRenderTargetContext();
64
65 SkString error;
66 if (!rtc || !ctx) {
67 error = "GPU Only.";
Chris Dalton0d0758e2020-05-29 10:51:08 -060068 } else if (!ctx->priv().caps()->drawInstancedSupport()) {
69 error = "Instanced rendering not supported.";
Chris Daltonb832ce62020-01-06 19:49:37 -070070 } else if (1 == rtc->numSamples() && !ctx->priv().caps()->mixedSamplesSupport()) {
71 error = "MSAA/mixed samples only.";
72 }
73 if (!error.isEmpty()) {
74 SkFont font(nullptr, 20);
75 SkPaint captionPaint;
76 captionPaint.setColor(SK_ColorWHITE);
77 canvas->drawString(error.c_str(), 10, 30, font, captionPaint);
78 return;
79 }
80
81 GrPaint paint;
82 paint.setColor4f({1,0,1,1});
83
84 GrAAType aa;
85 if (rtc->numSamples() > 1) {
86 aa = GrAAType::kMSAA;
87 } else if (rtc->asRenderTargetProxy()->canUseMixedSamples(*ctx->priv().caps())) {
88 aa = GrAAType::kCoverage;
89 } else {
90 aa = GrAAType::kNone;
91 }
92
Herb Derbyc76d4092020-10-07 16:46:15 -040093 rtc->priv().testingOnly_addDrawOp(GrOp::Make<GrPathTessellateOp>(
94 ctx, canvas->getTotalMatrix(), fPath, std::move(paint), aa, fOpFlags));
Chris Daltonb832ce62020-01-06 19:49:37 -070095
96 // Draw the path points.
97 SkPaint pointsPaint;
98 pointsPaint.setColor(SK_ColorBLUE);
99 pointsPaint.setStrokeWidth(8);
Chris Daltonf9aea7f2020-01-21 11:19:26 -0700100 SkPath devPath = fPath;
101 devPath.transform(canvas->getTotalMatrix());
102 {
103 SkAutoCanvasRestore acr(canvas, true);
104 canvas->setMatrix(SkMatrix::I());
105 canvas->drawPoints(SkCanvas::kPoints_PointMode, devPath.countPoints(),
106 SkPathPriv::PointData(devPath), pointsPaint);
107 }
Chris Daltonb832ce62020-01-06 19:49:37 -0700108
109 fLastViewMatrix = canvas->getTotalMatrix();
110}
111
Chris Dalton0d0758e2020-05-29 10:51:08 -0600112class TessellatedWedge::Click : public Sample::Click {
Chris Daltonb832ce62020-01-06 19:49:37 -0700113public:
114 Click(int ptIdx) : fPtIdx(ptIdx) {}
115
116 void doClick(SkPath* path) {
117 if (fPtIdx >= 0) {
118 SkPoint pt = path->getPoint(fPtIdx);
Chris Dalton8d3eb242020-05-04 10:43:33 -0600119 SkPathPriv::UpdatePathPoint(path, fPtIdx, pt + fCurr - fPrev);
Chris Daltonb832ce62020-01-06 19:49:37 -0700120 } else {
121 path->transform(
Mike Reed1f607332020-05-21 12:11:27 -0400122 SkMatrix::Translate(fCurr.x() - fPrev.x(), fCurr.y() - fPrev.y()), path);
Chris Daltonb832ce62020-01-06 19:49:37 -0700123 }
124 }
125
126private:
127 int fPtIdx;
128};
129
Chris Dalton0d0758e2020-05-29 10:51:08 -0600130Sample::Click* TessellatedWedge::onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) {
Chris Daltonb832ce62020-01-06 19:49:37 -0700131 const SkPoint* pts = SkPathPriv::PointData(fPath);
132 float fuzz = 20 / fLastViewMatrix.getMaxScale();
133 for (int i = 0; i < fPath.countPoints(); ++i) {
134 SkPoint screenPoint = pts[i];
135 if (fabs(x - screenPoint.x()) < fuzz && fabsf(y - screenPoint.y()) < fuzz) {
136 return new Click(i);
137 }
138 }
139 return new Click(-1);
140}
141
Chris Dalton0d0758e2020-05-29 10:51:08 -0600142bool TessellatedWedge::onClick(Sample::Click* click) {
Chris Daltonb832ce62020-01-06 19:49:37 -0700143 Click* myClick = (Click*)click;
144 myClick->doClick(&fPath);
145 return true;
146}
147
Chris Dalton0d0758e2020-05-29 10:51:08 -0600148bool TessellatedWedge::onChar(SkUnichar unichar) {
Chris Daltonb832ce62020-01-06 19:49:37 -0700149 switch (unichar) {
150 case 'w':
Chris Daltonb96995d2020-06-04 16:44:29 -0600151 fOpFlags = (GrTessellationPathRenderer::OpFlags)(
152 (int)fOpFlags ^ (int)GrTessellationPathRenderer::OpFlags::kWireframe);
Chris Daltonb832ce62020-01-06 19:49:37 -0700153 return true;
154 case 'D': {
155 fPath.dump();
156 return true;
157 }
158 }
159 return false;
160}
161
Chris Dalton0d0758e2020-05-29 10:51:08 -0600162Sample* MakeTessellatedWedgeSample() { return new TessellatedWedge; }
163static SampleRegistry gTessellatedWedgeSample(MakeTessellatedWedgeSample);
Chris Daltonb832ce62020-01-06 19:49:37 -0700164
165#endif // SK_SUPPORT_GPU