blob: 9857ff9c6b13e6bdc746caa46c9e7941b55838d2 [file] [log] [blame]
commit-bot@chromium.org78a10782013-08-21 19:27:48 +00001/*
2 * Copyright 2013 Google Inc.
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// This test only works with the GPU backend.
9
10#include "gm.h"
Chris Dalton1d4af542018-04-16 14:23:00 -060011#include "sk_tool_utils.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000012
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000013#include "GrContext.h"
Robert Phillips7c525e62018-06-12 10:11:12 -040014#include "GrMemoryPool.h"
Brian Salomon477d0ef2017-07-14 10:12:26 -040015#include "GrOpFlushState.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000016#include "GrPathUtils.h"
Brian Salomon477d0ef2017-07-14 10:12:26 -040017#include "GrRenderTargetContextPriv.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000018#include "SkColorPriv.h"
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000019#include "SkGeometry.h"
Cary Clarke4442cb2017-10-18 11:46:18 -040020#include "SkPoint3.h"
Cary Clark74f623d2017-11-06 20:02:02 -050021#include "SkPointPriv.h"
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000022#include "effects/GrBezierEffect.h"
Brian Salomon477d0ef2017-07-14 10:12:26 -040023#include "ops/GrMeshDrawOp.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000024
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000025namespace skiagm {
joshualitt95964c62015-02-11 13:45:50 -080026
Brian Salomon477d0ef2017-07-14 10:12:26 -040027class BezierTestOp : public GrMeshDrawOp {
28public:
29 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
30
Brian Osman532b3f92018-07-11 10:02:07 -040031 RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override {
Brian Salomon477d0ef2017-07-14 10:12:26 -040032 auto analysis = fProcessorSet.finalize(fColor, GrProcessorAnalysisCoverage::kSingleChannel,
Brian Osman532b3f92018-07-11 10:02:07 -040033 clip, false, caps, &fColor);
Brian Salomon477d0ef2017-07-14 10:12:26 -040034 return analysis.requiresDstTexture() ? RequiresDstTexture::kYes : RequiresDstTexture::kNo;
35 }
36
Robert Phillipsf1748f52017-09-14 14:11:24 -040037 void visitProxies(const VisitProxyFunc& func) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -040038 fProcessorSet.visitProxies(func);
39 }
40
Brian Salomon477d0ef2017-07-14 10:12:26 -040041protected:
Brian Salomon7eae3e02018-08-07 14:02:38 +000042 BezierTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
43 int32_t classID)
Brian Salomon477d0ef2017-07-14 10:12:26 -040044 : INHERITED(classID)
45 , fRect(rect)
46 , fColor(color)
47 , fGeometryProcessor(std::move(gp))
48 , fProcessorSet(SkBlendMode::kSrc) {
49 this->setBounds(rect, HasAABloat::kYes, IsZeroArea::kNo);
50 }
51
Brian Salomon49348902018-06-26 09:12:38 -040052 Target::PipelineAndFixedDynamicState makePipeline(Target* target) {
Brian Salomonbfd18cd2017-08-09 16:27:09 -040053 return target->makePipeline(0, std::move(fProcessorSet), target->detachAppliedClip());
Brian Salomon477d0ef2017-07-14 10:12:26 -040054 }
55
Brian Salomon7eae3e02018-08-07 14:02:38 +000056 sk_sp<const GrGeometryProcessor> gp() const { return fGeometryProcessor; }
Brian Salomon477d0ef2017-07-14 10:12:26 -040057
58 const SkRect& rect() const { return fRect; }
59 GrColor color() const { return fColor; }
60
61private:
Brian Salomon477d0ef2017-07-14 10:12:26 -040062 SkRect fRect;
63 GrColor fColor;
Brian Salomon7eae3e02018-08-07 14:02:38 +000064 sk_sp<const GrGeometryProcessor> fGeometryProcessor;
Brian Salomon477d0ef2017-07-14 10:12:26 -040065 GrProcessorSet fProcessorSet;
66
67 typedef GrMeshDrawOp INHERITED;
68};
69
70class BezierCubicTestOp : public BezierTestOp {
joshualitt95964c62015-02-11 13:45:50 -080071public:
Brian Salomon25a88092016-12-01 09:36:50 -050072 DEFINE_OP_CLASS_ID
joshualitt95964c62015-02-11 13:45:50 -080073
Chris Daltonfebbffa2017-06-08 13:12:02 -060074 const char* name() const override { return "BezierCubicTestOp"; }
joshualitt95964c62015-02-11 13:45:50 -080075
Robert Phillips7c525e62018-06-12 10:11:12 -040076 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
Brian Salomon7eae3e02018-08-07 14:02:38 +000077 sk_sp<const GrGeometryProcessor> gp,
Robert Phillips7c525e62018-06-12 10:11:12 -040078 const SkRect& rect,
Brian Salomon477d0ef2017-07-14 10:12:26 -040079 GrColor color) {
Robert Phillipsc994a932018-06-19 13:09:54 -040080 GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
81
82 return pool->allocate<BezierCubicTestOp>(std::move(gp), rect, color);
Brian Salomon6b316e92016-12-16 09:35:49 -050083 }
84
85private:
Robert Phillips7c525e62018-06-12 10:11:12 -040086 friend class ::GrOpMemoryPool; // for ctor
87
Brian Salomon7eae3e02018-08-07 14:02:38 +000088 BezierCubicTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, GrColor color)
Brian Salomon477d0ef2017-07-14 10:12:26 -040089 : INHERITED(std::move(gp), rect, color, ClassID()) {}
joshualitt95964c62015-02-11 13:45:50 -080090
Brian Salomon91326c32017-08-09 16:02:19 -040091 void onPrepareDraws(Target* target) override {
Brian Salomon92be2f72018-06-19 14:33:47 -040092 SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(SkPoint));
Brian Salomon7eae3e02018-08-07 14:02:38 +000093 QuadHelper helper(target, sizeof(SkPoint), 1);
94 SkPoint* pts = reinterpret_cast<SkPoint*>(helper.vertices());
Chris Daltonfebbffa2017-06-08 13:12:02 -060095 if (!pts) {
joshualitt4b31de82015-03-05 14:33:41 -080096 return;
97 }
Brian Salomon477d0ef2017-07-14 10:12:26 -040098 SkRect rect = this->rect();
Brian Salomon92be2f72018-06-19 14:33:47 -040099 SkPointPriv::SetRectTriStrip(pts, rect, sizeof(SkPoint));
Brian Salomon49348902018-06-26 09:12:38 -0400100 auto pipe = this->makePipeline(target);
101 helper.recordDraw(target, this->gp(), pipe.fPipeline, pipe.fFixedDynamicState);
joshualitt95964c62015-02-11 13:45:50 -0800102 }
103
mtkleindbfd7ab2016-09-01 11:24:54 -0700104 static constexpr int kVertsPerCubic = 4;
105 static constexpr int kIndicesPerCubic = 6;
joshualitt95964c62015-02-11 13:45:50 -0800106
Brian Salomon477d0ef2017-07-14 10:12:26 -0400107 typedef BezierTestOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -0800108};
109
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000110/**
111 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
112 */
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000113class BezierCubicEffects : public GM {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000114public:
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000115 BezierCubicEffects() {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000116 this->setBGColor(0xFFFFFFFF);
117 }
118
119protected:
mtklein36352bf2015-03-25 18:17:31 -0700120 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000121 return SkString("bezier_cubic_effects");
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000122 }
123
mtklein36352bf2015-03-25 18:17:31 -0700124 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700125 return SkISize::Make(800, 800);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000126 }
127
mtklein36352bf2015-03-25 18:17:31 -0700128 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -0400129 GrRenderTargetContext* renderTargetContext =
130 canvas->internal_private_accessTopLayerRenderTargetContext();
131 if (!renderTargetContext) {
halcanary2a243382015-09-09 08:16:41 -0700132 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000133 return;
134 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000135
robertphillips175dd9b2016-04-28 14:32:04 -0700136 GrContext* context = canvas->getGrContext();
137 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800138 return;
139 }
140
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400141 if (!context->contextPriv().caps()->shaderCaps()->floatIs32Bits()) {
Chris Dalton1d4af542018-04-16 14:23:00 -0600142 SkPaint paint;
143 sk_tool_utils::set_portable_typeface(&paint);
144 paint.setAntiAlias(true);
145 paint.setTextSize(20);
146
147 canvas->clear(SK_ColorWHITE);
148 canvas->drawString("float != fp32", 20, 40, paint);
149 return;
150 }
151
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000152 struct Vertex {
153 SkPoint fPosition;
154 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
155 };
156
mtkleindbfd7ab2016-09-01 11:24:54 -0700157 constexpr int kNumCubics = 15;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000158 SkRandom rand;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000159
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000160 // Mult by 3 for each edge effect type
161 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumCubics*3)));
162 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumCubics*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400163 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
164 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000165 int row = 0;
166 int col = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700167 constexpr GrColor color = 0xff000000;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000168
169 for (int i = 0; i < kNumCubics; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000170 SkPoint baseControlPts[] = {
171 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
172 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
173 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
174 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000175 };
Ethan Nicholas1706f842017-11-10 11:58:19 -0500176 for(GrClipEdgeType edgeType : {GrClipEdgeType::kFillBW,
177 GrClipEdgeType::kFillAA,
178 GrClipEdgeType::kHairlineAA}) {
Mike Reeddf85c382017-02-14 10:59:19 -0500179 SkScalar x = col * w;
180 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000181 SkPoint controlPts[] = {
182 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
183 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
184 {x + baseControlPts[2].fX, y + baseControlPts[2].fY},
185 {x + baseControlPts[3].fX, y + baseControlPts[3].fY}
186 };
187 SkPoint chopped[10];
csmartdaltoncc261272017-03-23 13:38:45 -0600188 SkMatrix klm;
Greg Daniel8199d942017-03-14 10:20:24 -0400189 int loopIndex;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000190 int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts,
191 chopped,
csmartdaltoncc261272017-03-23 13:38:45 -0600192 &klm,
Greg Daniel8199d942017-03-14 10:20:24 -0400193 &loopIndex);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000194
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000195 SkPaint ctrlPtPaint;
196 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
Hal Canary23e474c2017-05-15 13:35:35 -0400197 canvas->drawCircle(controlPts[0], 8.f, ctrlPtPaint);
Greg Daniel8199d942017-03-14 10:20:24 -0400198 for (int i = 1; i < 4; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400199 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000200 }
201
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000202 SkPaint polyPaint;
203 polyPaint.setColor(0xffA0A0A0);
204 polyPaint.setStrokeWidth(0);
205 polyPaint.setStyle(SkPaint::kStroke_Style);
206 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, controlPts, polyPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000207
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000208 SkPaint choppedPtPaint;
209 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000210
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000211 for (int c = 0; c < cnt; ++c) {
212 SkPoint* pts = chopped + 3 * c;
213
214 for (int i = 0; i < 4; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400215 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000216 }
217
218 SkRect bounds;
219 bounds.set(pts, 4);
220
221 SkPaint boundsPaint;
222 boundsPaint.setColor(0xff808080);
223 boundsPaint.setStrokeWidth(0);
224 boundsPaint.setStyle(SkPaint::kStroke_Style);
225 canvas->drawRect(bounds, boundsPaint);
226
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000227
Chris Daltonfebbffa2017-06-08 13:12:02 -0600228 bool flipKL = (c == loopIndex && cnt != 3);
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400229 sk_sp<GrGeometryProcessor> gp =
230 GrCubicEffect::Make(color, SkMatrix::I(), klm, flipKL, edgeType,
231 *context->contextPriv().caps());
Chris Daltonfebbffa2017-06-08 13:12:02 -0600232 if (!gp) {
233 break;
Greg Daniel8199d942017-03-14 10:20:24 -0400234 }
235
Brian Salomon477d0ef2017-07-14 10:12:26 -0400236 std::unique_ptr<GrDrawOp> op =
Robert Phillips7c525e62018-06-12 10:11:12 -0400237 BezierCubicTestOp::Make(context, std::move(gp), bounds, color);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400238 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000239 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000240 ++col;
241 if (numCols == col) {
242 col = 0;
243 ++row;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000244 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000245 }
246 }
247 }
248
249private:
250 typedef GM INHERITED;
251};
252
253//////////////////////////////////////////////////////////////////////////////
254
Brian Salomon477d0ef2017-07-14 10:12:26 -0400255class BezierConicTestOp : public BezierTestOp {
Chris Daltonfebbffa2017-06-08 13:12:02 -0600256public:
257 DEFINE_OP_CLASS_ID
258
259 const char* name() const override { return "BezierConicTestOp"; }
260
Robert Phillips7c525e62018-06-12 10:11:12 -0400261 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
Brian Salomon7eae3e02018-08-07 14:02:38 +0000262 sk_sp<const GrGeometryProcessor> gp,
Robert Phillips7c525e62018-06-12 10:11:12 -0400263 const SkRect& rect,
264 GrColor color,
265 const SkMatrix& klm) {
Robert Phillipsc994a932018-06-19 13:09:54 -0400266 GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
267
268 return pool->allocate<BezierConicTestOp>(std::move(gp), rect, color, klm);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600269 }
270
271private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400272 friend class ::GrOpMemoryPool; // for ctor
273
Brian Salomon7eae3e02018-08-07 14:02:38 +0000274 BezierConicTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
Chris Daltonfebbffa2017-06-08 13:12:02 -0600275 const SkMatrix& klm)
Brian Salomon477d0ef2017-07-14 10:12:26 -0400276 : INHERITED(std::move(gp), rect, color, ClassID()), fKLM(klm) {}
277
Chris Daltonfebbffa2017-06-08 13:12:02 -0600278 struct Vertex {
279 SkPoint fPosition;
280 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
281 };
282
Brian Salomon91326c32017-08-09 16:02:19 -0400283 void onPrepareDraws(Target* target) override {
Brian Salomon92be2f72018-06-19 14:33:47 -0400284 SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(Vertex));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000285 QuadHelper helper(target, sizeof(Vertex), 1);
286 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
Chris Daltonfebbffa2017-06-08 13:12:02 -0600287 if (!verts) {
288 return;
289 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400290 SkRect rect = this->rect();
Cary Clark74f623d2017-11-06 20:02:02 -0500291 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect.fLeft, rect.fTop, rect.fRight,
292 rect.fBottom, sizeof(Vertex));
Chris Daltonfebbffa2017-06-08 13:12:02 -0600293 for (int v = 0; v < 4; ++v) {
Cary Clarke4442cb2017-10-18 11:46:18 -0400294 SkPoint3 pt3 = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f};
295 fKLM.mapHomogeneousPoints((SkPoint3* ) verts[v].fKLM, &pt3, 1);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600296 }
Brian Salomon49348902018-06-26 09:12:38 -0400297 auto pipe = this->makePipeline(target);
298 helper.recordDraw(target, this->gp(), pipe.fPipeline, pipe.fFixedDynamicState);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600299 }
300
301 SkMatrix fKLM;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600302
303 static constexpr int kVertsPerCubic = 4;
304 static constexpr int kIndicesPerCubic = 6;
305
Brian Salomon477d0ef2017-07-14 10:12:26 -0400306 typedef BezierTestOp INHERITED;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600307};
308
309
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000310/**
311 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
312 */
313class BezierConicEffects : public GM {
314public:
315 BezierConicEffects() {
316 this->setBGColor(0xFFFFFFFF);
317 }
318
319protected:
mtklein36352bf2015-03-25 18:17:31 -0700320 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000321 return SkString("bezier_conic_effects");
322 }
323
mtklein36352bf2015-03-25 18:17:31 -0700324 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700325 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000326 }
327
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000328
mtklein36352bf2015-03-25 18:17:31 -0700329 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -0400330 GrRenderTargetContext* renderTargetContext =
331 canvas->internal_private_accessTopLayerRenderTargetContext();
332 if (!renderTargetContext) {
halcanary2a243382015-09-09 08:16:41 -0700333 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000334 return;
335 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000336
robertphillips175dd9b2016-04-28 14:32:04 -0700337 GrContext* context = canvas->getGrContext();
338 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800339 return;
340 }
341
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000342 struct Vertex {
343 SkPoint fPosition;
344 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
345 };
346
mtkleindbfd7ab2016-09-01 11:24:54 -0700347 constexpr int kNumConics = 10;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000348 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000349
350 // Mult by 3 for each edge effect type
351 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3)));
352 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400353 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
354 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000355 int row = 0;
356 int col = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700357 constexpr GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000358
359 for (int i = 0; i < kNumConics; ++i) {
360 SkPoint baseControlPts[] = {
361 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
362 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
363 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
364 };
365 SkScalar weight = rand.nextRangeF(0.f, 2.f);
Ethan Nicholas1706f842017-11-10 11:58:19 -0500366 for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700367 sk_sp<GrGeometryProcessor> gp;
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500368 GrClipEdgeType et = (GrClipEdgeType)edgeType;
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400369 gp = GrConicEffect::Make(color, SkMatrix::I(), et, *context->contextPriv().caps(),
370 SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800371 if (!gp) {
372 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000373 }
374
Mike Reeddf85c382017-02-14 10:59:19 -0500375 SkScalar x = col * w;
376 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000377 SkPoint controlPts[] = {
378 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
379 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
380 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
381 };
382 SkConic dst[4];
csmartdaltoncc261272017-03-23 13:38:45 -0600383 SkMatrix klm;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000384 int cnt = chop_conic(controlPts, dst, weight);
csmartdaltoncc261272017-03-23 13:38:45 -0600385 GrPathUtils::getConicKLM(controlPts, weight, &klm);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000386
387 SkPaint ctrlPtPaint;
388 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
389 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400390 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000391 }
392
393 SkPaint polyPaint;
394 polyPaint.setColor(0xffA0A0A0);
395 polyPaint.setStrokeWidth(0);
396 polyPaint.setStyle(SkPaint::kStroke_Style);
397 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
398
399 SkPaint choppedPtPaint;
400 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
401
402 for (int c = 0; c < cnt; ++c) {
403 SkPoint* pts = dst[c].fPts;
404 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400405 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000406 }
407
408 SkRect bounds;
409 //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}};
410 //bounds.set(bPts, 2);
411 bounds.set(pts, 3);
412
413 SkPaint boundsPaint;
414 boundsPaint.setColor(0xff808080);
415 boundsPaint.setStrokeWidth(0);
416 boundsPaint.setStyle(SkPaint::kStroke_Style);
417 canvas->drawRect(bounds, boundsPaint);
418
Robert Phillips7c525e62018-06-12 10:11:12 -0400419 std::unique_ptr<GrDrawOp> op = BezierConicTestOp::Make(context, gp, bounds,
420 color, klm);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400421 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000422 }
423 ++col;
424 if (numCols == col) {
425 col = 0;
426 ++row;
427 }
428 }
429 }
430 }
431
432private:
433 // Uses the max curvature function for quads to estimate
434 // where to chop the conic. If the max curvature is not
435 // found along the curve segment it will return 1 and
436 // dst[0] is the original conic. If it returns 2 the dst[0]
437 // and dst[1] are the two new conics.
438 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
439 SkScalar t = SkFindQuadMaxCurvature(src);
Chris Dalton1d474dd2018-07-24 01:08:31 -0600440 if (t == 0 || t == 1) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000441 if (dst) {
442 dst[0].set(src, weight);
443 }
444 return 1;
445 } else {
446 if (dst) {
447 SkConic conic;
448 conic.set(src, weight);
caryclark414c4292016-09-26 11:03:54 -0700449 if (!conic.chopAt(t, dst)) {
450 dst[0].set(src, weight);
451 return 1;
452 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000453 }
454 return 2;
455 }
456 }
457
458 // Calls split_conic on the entire conic and then once more on each subsection.
459 // Most cases will result in either 1 conic (chop point is not within t range)
460 // or 3 points (split once and then one subsection is split again).
461 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
462 SkConic dstTemp[2];
463 int conicCnt = split_conic(src, dstTemp, weight);
464 if (2 == conicCnt) {
465 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
466 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
467 } else {
468 dst[0] = dstTemp[0];
469 }
470 return conicCnt;
471 }
472
473 typedef GM INHERITED;
474};
475
476//////////////////////////////////////////////////////////////////////////////
joshualitt95964c62015-02-11 13:45:50 -0800477
Brian Salomon477d0ef2017-07-14 10:12:26 -0400478class BezierQuadTestOp : public BezierTestOp {
joshualitt95964c62015-02-11 13:45:50 -0800479public:
Brian Salomon25a88092016-12-01 09:36:50 -0500480 DEFINE_OP_CLASS_ID
Brian Salomon6b316e92016-12-16 09:35:49 -0500481 const char* name() const override { return "BezierQuadTestOp"; }
joshualitt95964c62015-02-11 13:45:50 -0800482
Robert Phillips7c525e62018-06-12 10:11:12 -0400483 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
Brian Salomon7eae3e02018-08-07 14:02:38 +0000484 sk_sp<const GrGeometryProcessor> gp,
Robert Phillips7c525e62018-06-12 10:11:12 -0400485 const SkRect& rect,
486 GrColor color,
487 const GrPathUtils::QuadUVMatrix& devToUV) {
Robert Phillipsc994a932018-06-19 13:09:54 -0400488 GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
489
490 return pool->allocate<BezierQuadTestOp>(std::move(gp), rect, color, devToUV);
joshualitt95964c62015-02-11 13:45:50 -0800491 }
492
493private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400494 friend class ::GrOpMemoryPool; // for ctor
495
Brian Salomon7eae3e02018-08-07 14:02:38 +0000496 BezierQuadTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
Brian Salomon6b316e92016-12-16 09:35:49 -0500497 const GrPathUtils::QuadUVMatrix& devToUV)
Brian Salomon477d0ef2017-07-14 10:12:26 -0400498 : INHERITED(std::move(gp), rect, color, ClassID()), fDevToUV(devToUV) {}
joshualitt95964c62015-02-11 13:45:50 -0800499
500 struct Vertex {
501 SkPoint fPosition;
502 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
503 };
504
Brian Salomon91326c32017-08-09 16:02:19 -0400505 void onPrepareDraws(Target* target) override {
Brian Salomon92be2f72018-06-19 14:33:47 -0400506 SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(Vertex));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000507 QuadHelper helper(target, sizeof(Vertex), 1);
508 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
bsalomonb5238a72015-05-05 07:49:49 -0700509 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800510 return;
511 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400512 SkRect rect = this->rect();
Brian Salomonec42e152018-05-18 12:52:22 -0400513 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex));
joshualitt95964c62015-02-11 13:45:50 -0800514 fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts);
Brian Salomon49348902018-06-26 09:12:38 -0400515 auto pipe = this->makePipeline(target);
516 helper.recordDraw(target, this->gp(), pipe.fPipeline, pipe.fFixedDynamicState);
joshualitt95964c62015-02-11 13:45:50 -0800517 }
518
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500519 GrPathUtils::QuadUVMatrix fDevToUV;
joshualitt95964c62015-02-11 13:45:50 -0800520
mtkleindbfd7ab2016-09-01 11:24:54 -0700521 static constexpr int kVertsPerCubic = 4;
522 static constexpr int kIndicesPerCubic = 6;
joshualitt95964c62015-02-11 13:45:50 -0800523
Brian Salomon477d0ef2017-07-14 10:12:26 -0400524 typedef BezierTestOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -0800525};
526
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000527/**
528 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
529 */
530class BezierQuadEffects : public GM {
531public:
532 BezierQuadEffects() {
533 this->setBGColor(0xFFFFFFFF);
534 }
535
536protected:
mtklein36352bf2015-03-25 18:17:31 -0700537 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000538 return SkString("bezier_quad_effects");
539 }
540
mtklein36352bf2015-03-25 18:17:31 -0700541 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700542 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000543 }
544
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000545
mtklein36352bf2015-03-25 18:17:31 -0700546 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -0400547 GrRenderTargetContext* renderTargetContext =
548 canvas->internal_private_accessTopLayerRenderTargetContext();
549 if (!renderTargetContext) {
halcanary2a243382015-09-09 08:16:41 -0700550 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000551 return;
552 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000553
robertphillips175dd9b2016-04-28 14:32:04 -0700554 GrContext* context = canvas->getGrContext();
555 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800556 return;
557 }
558
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000559 struct Vertex {
560 SkPoint fPosition;
561 float fUV[4]; // The last two values are ignored. The effect expects a vec4f.
562 };
563
mtkleindbfd7ab2016-09-01 11:24:54 -0700564 constexpr int kNumQuads = 5;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000565 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000566
567 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3)));
568 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400569 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
570 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000571 int row = 0;
572 int col = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700573 constexpr GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000574
575 for (int i = 0; i < kNumQuads; ++i) {
576 SkPoint baseControlPts[] = {
577 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
578 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
579 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
580 };
Ethan Nicholas1706f842017-11-10 11:58:19 -0500581 for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700582 sk_sp<GrGeometryProcessor> gp;
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500583 GrClipEdgeType et = (GrClipEdgeType)edgeType;
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400584 gp = GrQuadEffect::Make(color, SkMatrix::I(), et, *context->contextPriv().caps(),
585 SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800586 if (!gp) {
587 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000588 }
589
Mike Reeddf85c382017-02-14 10:59:19 -0500590 SkScalar x = col * w;
591 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000592 SkPoint controlPts[] = {
593 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
594 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
595 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
596 };
597 SkPoint chopped[5];
598 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
599
600 SkPaint ctrlPtPaint;
601 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
602 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400603 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000604 }
605
606 SkPaint polyPaint;
607 polyPaint.setColor(0xffA0A0A0);
608 polyPaint.setStrokeWidth(0);
609 polyPaint.setStyle(SkPaint::kStroke_Style);
610 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
611
612 SkPaint choppedPtPaint;
613 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
614
615 for (int c = 0; c < cnt; ++c) {
616 SkPoint* pts = chopped + 2 * c;
617
618 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400619 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000620 }
621
622 SkRect bounds;
623 bounds.set(pts, 3);
624
625 SkPaint boundsPaint;
626 boundsPaint.setColor(0xff808080);
627 boundsPaint.setStrokeWidth(0);
628 boundsPaint.setStyle(SkPaint::kStroke_Style);
629 canvas->drawRect(bounds, boundsPaint);
630
robertphillips28a838e2016-06-23 14:07:00 -0700631 GrPaint grPaint;
Brian Salomona1633922017-01-09 11:46:10 -0500632 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
joshualitt3f284d72015-02-11 11:34:58 -0800633
joshualitt95964c62015-02-11 13:45:50 -0800634 GrPathUtils::QuadUVMatrix DevToUV(pts);
635
Robert Phillips7c525e62018-06-12 10:11:12 -0400636 std::unique_ptr<GrDrawOp> op = BezierQuadTestOp::Make(context, gp,
637 bounds, color, DevToUV);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400638 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000639 }
640 ++col;
641 if (numCols == col) {
642 col = 0;
643 ++row;
644 }
645 }
646 }
647 }
648
649private:
650 typedef GM INHERITED;
651};
652
halcanary385fe4d2015-08-26 13:07:48 -0700653DEF_GM(return new BezierCubicEffects;)
654DEF_GM(return new BezierConicEffects;)
655DEF_GM(return new BezierQuadEffects;)
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000656}