blob: 7d06f13dd37f320b36f6cdebcf0016df1b839e37 [file] [log] [blame]
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +00001/*
2 * Copyright 2014 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "gm/gm.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040011#include "include/core/SkBlendMode.h"
12#include "include/core/SkCanvas.h"
13#include "include/core/SkMatrix.h"
14#include "include/core/SkPaint.h"
15#include "include/core/SkPath.h"
16#include "include/core/SkPoint.h"
17#include "include/core/SkRect.h"
18#include "include/core/SkRefCnt.h"
19#include "include/core/SkScalar.h"
20#include "include/core/SkSize.h"
21#include "include/core/SkString.h"
22#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "include/gpu/GrContext.h"
24#include "include/private/GrRecordingContext.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040025#include "include/private/GrSharedEnums.h"
26#include "include/private/GrTypesPriv.h"
27#include "include/private/SkColorData.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#include "src/core/SkPointPriv.h"
29#include "src/core/SkTLList.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040030#include "src/gpu/GrCaps.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050031#include "src/gpu/GrDefaultGeoProcFactory.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040032#include "src/gpu/GrFragmentProcessor.h"
33#include "src/gpu/GrGeometryProcessor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050034#include "src/gpu/GrMemoryPool.h"
35#include "src/gpu/GrOpFlushState.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040036#include "src/gpu/GrPaint.h"
37#include "src/gpu/GrProcessorAnalysis.h"
38#include "src/gpu/GrProcessorSet.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050039#include "src/gpu/GrRecordingContextPriv.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040040#include "src/gpu/GrRenderTargetContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050041#include "src/gpu/GrRenderTargetContextPriv.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040042#include "src/gpu/GrUserStencilSettings.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050043#include "src/gpu/effects/GrConvexPolyEffect.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040044#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
45#include "src/gpu/ops/GrDrawOp.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050046#include "src/gpu/ops/GrMeshDrawOp.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040047#include "src/gpu/ops/GrOp.h"
48
49#include <memory>
50#include <utility>
51
52class GrAppliedClip;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000053
bsalomon342bfc22016-04-01 06:06:20 -070054/** outset rendered rect to visualize anti-aliased poly edges */
55static SkRect outset(const SkRect& unsorted) {
56 SkRect r = unsorted;
57 r.outset(5.f, 5.f);
58 return r;
59}
joshualitt95964c62015-02-11 13:45:50 -080060
bsalomon342bfc22016-04-01 06:06:20 -070061/** sorts a rect */
62static SkRect sorted_rect(const SkRect& unsorted) {
63 SkRect r = unsorted;
64 r.sort();
65 return r;
66}
67
68namespace skiagm {
Brian Salomon576eda12017-07-14 11:30:17 -040069class PolyBoundsOp : public GrMeshDrawOp {
joshualitt95964c62015-02-11 13:45:50 -080070public:
Brian Salomon25a88092016-12-01 09:36:50 -050071 DEFINE_OP_CLASS_ID
joshualitt95964c62015-02-11 13:45:50 -080072
Robert Phillipsbe9aff22019-02-15 11:33:22 -050073 static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
Robert Phillips7c525e62018-06-12 10:11:12 -040074 GrPaint&& paint,
75 const SkRect& rect) {
Robert Phillips9da87e02019-02-04 13:26:26 -050076 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -040077
78 return pool->allocate<PolyBoundsOp>(std::move(paint), rect);
Brian Salomon576eda12017-07-14 11:30:17 -040079 }
80
Robert Phillipsb493eeb2017-09-13 13:10:52 -040081 const char* name() const override { return "PolyBoundsOp"; }
82
Brian Salomon7d94bb52018-10-12 14:37:19 -040083 void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -040084 fProcessors.visitProxies(func);
85 }
86
Brian Salomon576eda12017-07-14 11:30:17 -040087 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
88
Brian Osman5ced0bf2019-03-15 10:15:29 -040089 GrProcessorSet::Analysis finalize(const GrCaps& caps, const GrAppliedClip* clip,
90 GrFSAAType fsaaType, GrClampType clampType) override {
Chris Daltonb8fff0d2019-03-05 10:11:58 -070091 return fProcessors.finalize(
92 fColor, GrProcessorAnalysisCoverage::kNone, clip, &GrUserStencilSettings::kUnused,
Brian Osman5ced0bf2019-03-15 10:15:29 -040093 fsaaType, caps, clampType, &fColor);
joshualitt95964c62015-02-11 13:45:50 -080094 }
95
96private:
Robert Phillips7c525e62018-06-12 10:11:12 -040097 friend class ::GrOpMemoryPool; // for ctor
98
Brian Salomon576eda12017-07-14 11:30:17 -040099 PolyBoundsOp(GrPaint&& paint, const SkRect& rect)
100 : INHERITED(ClassID())
Brian Osmancf860852018-10-31 14:04:39 -0400101 , fColor(paint.getColor4f())
Brian Salomon576eda12017-07-14 11:30:17 -0400102 , fProcessors(std::move(paint))
103 , fRect(outset(rect)) {
104 this->setBounds(sorted_rect(fRect), HasAABloat::kNo, IsZeroArea::kNo);
105 }
Brian Salomon6b316e92016-12-16 09:35:49 -0500106
Brian Salomon91326c32017-08-09 16:02:19 -0400107 void onPrepareDraws(Target* target) override {
bsalomon342bfc22016-04-01 06:06:20 -0700108 using namespace GrDefaultGeoProcFactory;
joshualitt95964c62015-02-11 13:45:50 -0800109
Brian Salomon576eda12017-07-14 11:30:17 -0400110 Color color(fColor);
Brian Salomon8c852be2017-01-04 10:44:42 -0500111 sk_sp<GrGeometryProcessor> gp(GrDefaultGeoProcFactory::Make(
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400112 target->caps().shaderCaps(),
113 color,
114 Coverage::kSolid_Type,
115 LocalCoords::kUnused_Type,
116 SkMatrix::I()));
joshualitt95964c62015-02-11 13:45:50 -0800117
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500118 SkASSERT(gp->vertexStride() == sizeof(SkPoint));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000119 QuadHelper helper(target, sizeof(SkPoint), 1);
120 SkPoint* verts = reinterpret_cast<SkPoint*>(helper.vertices());
bsalomonb5238a72015-05-05 07:49:49 -0700121 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800122 return;
123 }
124
Brian Salomonec42e152018-05-18 12:52:22 -0400125 SkPointPriv::SetRectTriStrip(verts, fRect, sizeof(SkPoint));
Chris Dalton07cdcfc92019-02-26 11:13:22 -0700126 helper.recordDraw(target, std::move(gp));
127 }
joshualitt95964c62015-02-11 13:45:50 -0800128
Chris Dalton07cdcfc92019-02-26 11:13:22 -0700129 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
130 flushState->executeDrawsAndUploadsForMeshDrawOp(this, chainBounds, std::move(fProcessors));
joshualitt95964c62015-02-11 13:45:50 -0800131 }
132
Brian Osmancf860852018-10-31 14:04:39 -0400133 SkPMColor4f fColor;
Brian Salomon576eda12017-07-14 11:30:17 -0400134 GrProcessorSet fProcessors;
bsalomon342bfc22016-04-01 06:06:20 -0700135 SkRect fRect;
joshualitt95964c62015-02-11 13:45:50 -0800136
Brian Salomon576eda12017-07-14 11:30:17 -0400137 typedef GrMeshDrawOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -0800138};
139
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000140/**
joshualittb0a8a372014-09-23 09:50:21 -0700141 * This GM directly exercises a GrProcessor that draws convex polygons.
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000142 */
Chris Dalton3a778372019-02-07 15:23:36 -0700143class ConvexPolyEffect : public GpuGM {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000144public:
145 ConvexPolyEffect() {
146 this->setBGColor(0xFFFFFFFF);
147 }
148
149protected:
mtklein36352bf2015-03-25 18:17:31 -0700150 SkString onShortName() override {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000151 return SkString("convex_poly_effect");
152 }
153
mtklein36352bf2015-03-25 18:17:31 -0700154 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700155 return SkISize::Make(720, 800);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000156 }
157
mtklein36352bf2015-03-25 18:17:31 -0700158 void onOnceBeforeDraw() override {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000159 SkPath tri;
160 tri.moveTo(5.f, 5.f);
161 tri.lineTo(100.f, 20.f);
162 tri.lineTo(15.f, 100.f);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000163
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000164 fPaths.addToTail(tri);
165 fPaths.addToTail(SkPath())->reverseAddPath(tri);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000166
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000167 tri.close();
168 fPaths.addToTail(tri);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000169
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000170 SkPath ngon;
mtkleindbfd7ab2016-09-01 11:24:54 -0700171 constexpr SkScalar kRadius = 50.f;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000172 const SkPoint center = { kRadius, kRadius };
173 for (int i = 0; i < GrConvexPolyEffect::kMaxEdges; ++i) {
174 SkScalar angle = 2 * SK_ScalarPI * i / GrConvexPolyEffect::kMaxEdges;
Brian Osman4428f2c2019-04-02 10:59:28 -0400175 SkPoint point = { SkScalarCos(angle), SkScalarSin(angle) };
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000176 point.scale(kRadius);
177 point = center + point;
178 if (0 == i) {
179 ngon.moveTo(point);
180 } else {
181 ngon.lineTo(point);
182 }
183 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000184
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000185 fPaths.addToTail(ngon);
186 SkMatrix scaleM;
187 scaleM.setScale(1.1f, 0.4f);
188 ngon.transform(scaleM);
189 fPaths.addToTail(ngon);
skia.committer@gmail.comf0b0cda2014-02-09 03:02:01 +0000190
bsalomon7888de02016-03-28 15:04:45 -0700191 SkPath linePath;
192 linePath.moveTo(5.f, 5.f);
193 linePath.lineTo(6.f, 6.f);
194 fPaths.addToTail(linePath);
195
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000196 // integer edges
197 fRects.addToTail(SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f));
198 // half-integer edges
199 fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f));
200 // vertically/horizontally thin rects that cover pixel centers
201 fRects.addToTail(SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f));
202 fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 0.75f));
203 // vertically/horizontally thin rects that don't cover pixel centers
204 fRects.addToTail(SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f));
205 fRects.addToTail(SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f));
206 // small in x and y
207 fRects.addToTail(SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f));
208 // inverted in x and y
209 fRects.addToTail(SkRect::MakeLTRB(100.f, 50.5f, 5.f, 0.5f));
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000210 }
211
Chris Dalton3a778372019-02-07 15:23:36 -0700212 void onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
213 SkCanvas* canvas) override {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000214 SkScalar y = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700215 constexpr SkScalar kDX = 12.f;
bsalomonf045d602015-11-18 19:01:12 -0800216 for (PathList::Iter iter(fPaths, PathList::Iter::kHead_IterStart);
bsalomon49f085d2014-09-05 13:34:00 -0700217 iter.get();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000218 iter.next()) {
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000219 const SkPath* path = iter.get();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000220 SkScalar x = 0;
221
Ethan Nicholas1706f842017-11-10 11:58:19 -0500222 for (int et = 0; et < kGrClipEdgeTypeCnt; ++et) {
robertphillips1d24b8d2015-03-26 19:57:08 -0700223 const SkMatrix m = SkMatrix::MakeTrans(x, y);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000224 SkPath p;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000225 path->transform(m, &p);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000226
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500227 GrClipEdgeType edgeType = (GrClipEdgeType) et;
Ethan Nicholaseace9352018-10-15 20:09:54 +0000228 std::unique_ptr<GrFragmentProcessor> fp(GrConvexPolyEffect::Make(edgeType, p));
joshualittb0a8a372014-09-23 09:50:21 -0700229 if (!fp) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000230 continue;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000231 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000232
robertphillips28a838e2016-06-23 14:07:00 -0700233 GrPaint grPaint;
Brian Osmancb3d0872018-10-16 15:19:28 -0400234 grPaint.setColor4f({ 0, 0, 0, 1.f });
Brian Salomona1633922017-01-09 11:46:10 -0500235 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
robertphillips28a838e2016-06-23 14:07:00 -0700236 grPaint.addCoverageFragmentProcessor(std::move(fp));
joshualitt9853cce2014-11-17 14:22:48 -0800237
Brian Salomon576eda12017-07-14 11:30:17 -0400238 std::unique_ptr<GrDrawOp> op =
Robert Phillips7c525e62018-06-12 10:11:12 -0400239 PolyBoundsOp::Make(context, std::move(grPaint), p.getBounds());
Brian Salomon576eda12017-07-14 11:30:17 -0400240 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000241
bsalomon7888de02016-03-28 15:04:45 -0700242 x += SkScalarCeilToScalar(path->getBounds().width() + kDX);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000243 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000244
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000245 // Draw AA and non AA paths using normal API for reference.
246 canvas->save();
247 canvas->translate(x, y);
248 SkPaint paint;
249 canvas->drawPath(*path, paint);
250 canvas->translate(path->getBounds().width() + 10.f, 0);
251 paint.setAntiAlias(true);
252 canvas->drawPath(*path, paint);
253 canvas->restore();
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000254
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000255 y += SkScalarCeilToScalar(path->getBounds().height() + 20.f);
256 }
257
bsalomonf045d602015-11-18 19:01:12 -0800258 for (RectList::Iter iter(fRects, RectList::Iter::kHead_IterStart);
bsalomon49f085d2014-09-05 13:34:00 -0700259 iter.get();
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000260 iter.next()) {
261
262 SkScalar x = 0;
263
Ethan Nicholas1706f842017-11-10 11:58:19 -0500264 for (int et = 0; et < kGrClipEdgeTypeCnt; ++et) {
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000265 SkRect rect = *iter.get();
266 rect.offset(x, y);
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500267 GrClipEdgeType edgeType = (GrClipEdgeType) et;
Ethan Nicholaseace9352018-10-15 20:09:54 +0000268 std::unique_ptr<GrFragmentProcessor> fp(GrConvexPolyEffect::Make(edgeType, rect));
joshualittb0a8a372014-09-23 09:50:21 -0700269 if (!fp) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000270 continue;
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000271 }
272
robertphillips28a838e2016-06-23 14:07:00 -0700273 GrPaint grPaint;
Brian Osmancb3d0872018-10-16 15:19:28 -0400274 grPaint.setColor4f({ 0, 0, 0, 1.f });
Brian Salomona1633922017-01-09 11:46:10 -0500275 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
robertphillips28a838e2016-06-23 14:07:00 -0700276 grPaint.addCoverageFragmentProcessor(std::move(fp));
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000277
Robert Phillips7c525e62018-06-12 10:11:12 -0400278 std::unique_ptr<GrDrawOp> op = PolyBoundsOp::Make(context, std::move(grPaint),
279 rect);
Brian Salomon576eda12017-07-14 11:30:17 -0400280 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000281
bsalomon7888de02016-03-28 15:04:45 -0700282 x += SkScalarCeilToScalar(rect.width() + kDX);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000283 }
284
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000285 // Draw rect without and with AA using normal API for reference
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000286 canvas->save();
287 canvas->translate(x, y);
288 SkPaint paint;
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000289 canvas->drawRect(*iter.get(), paint);
bsalomon7888de02016-03-28 15:04:45 -0700290 x += SkScalarCeilToScalar(iter.get()->width() + kDX);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000291 paint.setAntiAlias(true);
292 canvas->drawRect(*iter.get(), paint);
293 canvas->restore();
294
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000295 y += SkScalarCeilToScalar(iter.get()->height() + 20.f);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000296 }
297 }
298
299private:
bsalomonf045d602015-11-18 19:01:12 -0800300 typedef SkTLList<SkPath, 1> PathList;
301 typedef SkTLList<SkRect, 1> RectList;
302 PathList fPaths;
303 RectList fRects;
skia.committer@gmail.comf0b0cda2014-02-09 03:02:01 +0000304
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000305 typedef GM INHERITED;
306};
307
halcanary385fe4d2015-08-26 13:07:48 -0700308DEF_GM(return new ConvexPolyEffect;)
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000309}