blob: 29f624eca181a86158aa69703e97923410fbf72f [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
15#include "include/gpu/GrContext.h"
16#include "src/gpu/GrClip.h"
17#include "src/gpu/GrContextPriv.h"
18#include "src/gpu/GrMemoryPool.h"
19#include "src/gpu/GrRenderTargetContext.h"
20#include "src/gpu/GrRenderTargetContextPriv.h"
21#include "src/gpu/tessellate/GrTessellatePathOp.h"
22
23// This sample enables wireframe and visualizes the triangulation generated by
24// GrTessellateWedgeShader.
25class TessellatedWedgeView : public Sample {
26public:
27 TessellatedWedgeView() {
28 fPath.moveTo(100, 200);
29 fPath.cubicTo(100, 100, 400, 100, 400, 200);
30 fPath.lineTo(250, 500);
31 }
32
33private:
34 void onDrawContent(SkCanvas*) override;
35 Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override;
36 bool onClick(Sample::Click*) override;
37 bool onChar(SkUnichar) override;
38
39 SkString name() override { return SkString("TessellatedWedge"); }
40
41 SkMatrix fLastViewMatrix = SkMatrix::I();
42 SkPath fPath;
43 GrTessellatePathOp::Flags fFlags = GrTessellatePathOp::Flags::kWireframe;
44
45 class Click;
46};
47
48void TessellatedWedgeView::onDrawContent(SkCanvas* canvas) {
49 canvas->clear(SK_ColorBLACK);
50
51 GrContext* ctx = canvas->getGrContext();
52 GrRenderTargetContext* rtc = canvas->internal_private_accessTopLayerRenderTargetContext();
53
54 SkString error;
55 if (!rtc || !ctx) {
56 error = "GPU Only.";
57 } else if (!ctx->priv().caps()->shaderCaps()->tessellationSupport()) {
58 error = "GPU tessellation not supported.";
59 } else if (1 == rtc->numSamples() && !ctx->priv().caps()->mixedSamplesSupport()) {
60 error = "MSAA/mixed samples only.";
61 }
62 if (!error.isEmpty()) {
63 SkFont font(nullptr, 20);
64 SkPaint captionPaint;
65 captionPaint.setColor(SK_ColorWHITE);
66 canvas->drawString(error.c_str(), 10, 30, font, captionPaint);
67 return;
68 }
69
70 GrPaint paint;
71 paint.setColor4f({1,0,1,1});
72
73 GrAAType aa;
74 if (rtc->numSamples() > 1) {
75 aa = GrAAType::kMSAA;
76 } else if (rtc->asRenderTargetProxy()->canUseMixedSamples(*ctx->priv().caps())) {
77 aa = GrAAType::kCoverage;
78 } else {
79 aa = GrAAType::kNone;
80 }
81
82 GrOpMemoryPool* pool = ctx->priv().opMemoryPool();
83 rtc->priv().testingOnly_addDrawOp(pool->allocate<GrTessellatePathOp>(
84 canvas->getTotalMatrix(), fPath, std::move(paint), aa, fFlags));
85
86 // Draw the path points.
87 SkPaint pointsPaint;
88 pointsPaint.setColor(SK_ColorBLUE);
89 pointsPaint.setStrokeWidth(8);
90 canvas->drawPoints(SkCanvas::kPoints_PointMode, fPath.countPoints(),
91 SkPathPriv::PointData(fPath), pointsPaint);
92
93 fLastViewMatrix = canvas->getTotalMatrix();
94}
95
96class TessellatedWedgeView::Click : public Sample::Click {
97public:
98 Click(int ptIdx) : fPtIdx(ptIdx) {}
99
100 void doClick(SkPath* path) {
101 if (fPtIdx >= 0) {
102 SkPoint pt = path->getPoint(fPtIdx);
103 ToolUtils::set_path_pt(fPtIdx, pt + fCurr - fPrev, path);
104 } else {
105 path->transform(
106 SkMatrix::MakeTrans(fCurr.x() - fPrev.x(), fCurr.y() - fPrev.y()), path);
107 }
108 }
109
110private:
111 int fPtIdx;
112};
113
114Sample::Click* TessellatedWedgeView::onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) {
115 const SkPoint* pts = SkPathPriv::PointData(fPath);
116 float fuzz = 20 / fLastViewMatrix.getMaxScale();
117 for (int i = 0; i < fPath.countPoints(); ++i) {
118 SkPoint screenPoint = pts[i];
119 if (fabs(x - screenPoint.x()) < fuzz && fabsf(y - screenPoint.y()) < fuzz) {
120 return new Click(i);
121 }
122 }
123 return new Click(-1);
124}
125
126bool TessellatedWedgeView::onClick(Sample::Click* click) {
127 Click* myClick = (Click*)click;
128 myClick->doClick(&fPath);
129 return true;
130}
131
132bool TessellatedWedgeView::onChar(SkUnichar unichar) {
133 switch (unichar) {
134 case 'w':
135 fFlags = (GrTessellatePathOp::Flags)(
136 (int)fFlags ^ (int)GrTessellatePathOp::Flags::kWireframe);
137 return true;
138 case 'D': {
139 fPath.dump();
140 return true;
141 }
142 }
143 return false;
144}
145
146DEF_SAMPLE(return new TessellatedWedgeView;)
147
148#endif // SK_SUPPORT_GPU