blob: ca27e285e2654973cf0f84e34662361a731e21a2 [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
10#include "gm.h"
11
12#if SK_SUPPORT_GPU
13
14#include "GrContext.h"
joshualitt5478d422014-11-14 16:00:38 -080015#include "GrDefaultGeoProcFactory.h"
Brian Salomon576eda12017-07-14 11:30:17 -040016#include "GrOpFlushState.h"
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000017#include "GrPathUtils.h"
Brian Salomon576eda12017-07-14 11:30:17 -040018#include "GrRenderTargetContextPriv.h"
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000019#include "GrTest.h"
20#include "SkColorPriv.h"
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000021#include "SkGeometry.h"
Cary Clark74f623d2017-11-06 20:02:02 -050022#include "SkPointPriv.h"
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000023#include "SkTLList.h"
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000024#include "effects/GrConvexPolyEffect.h"
Brian Salomon576eda12017-07-14 11:30:17 -040025#include "ops/GrMeshDrawOp.h"
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000026
bsalomon342bfc22016-04-01 06:06:20 -070027/** outset rendered rect to visualize anti-aliased poly edges */
28static SkRect outset(const SkRect& unsorted) {
29 SkRect r = unsorted;
30 r.outset(5.f, 5.f);
31 return r;
32}
joshualitt95964c62015-02-11 13:45:50 -080033
bsalomon342bfc22016-04-01 06:06:20 -070034/** sorts a rect */
35static SkRect sorted_rect(const SkRect& unsorted) {
36 SkRect r = unsorted;
37 r.sort();
38 return r;
39}
40
41namespace skiagm {
Brian Salomon576eda12017-07-14 11:30:17 -040042class PolyBoundsOp : public GrMeshDrawOp {
joshualitt95964c62015-02-11 13:45:50 -080043public:
Brian Salomon25a88092016-12-01 09:36:50 -050044 DEFINE_OP_CLASS_ID
joshualitt95964c62015-02-11 13:45:50 -080045
Brian Salomon576eda12017-07-14 11:30:17 -040046 static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkRect& rect) {
47 return std::unique_ptr<GrDrawOp>(new PolyBoundsOp(std::move(paint), rect));
48 }
49
Robert Phillipsb493eeb2017-09-13 13:10:52 -040050 const char* name() const override { return "PolyBoundsOp"; }
51
Robert Phillipsf1748f52017-09-14 14:11:24 -040052 void visitProxies(const VisitProxyFunc& func) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -040053 fProcessors.visitProxies(func);
54 }
55
Brian Salomon576eda12017-07-14 11:30:17 -040056 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
57
Brian Osman9a725dd2017-09-20 09:53:22 -040058 RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip,
59 GrPixelConfigIsClamped dstIsClamped) override {
60 auto analysis = fProcessors.finalize(fColor, GrProcessorAnalysisCoverage::kNone, clip,
61 false, caps, dstIsClamped, &fColor);
Brian Salomon576eda12017-07-14 11:30:17 -040062 return analysis.requiresDstTexture() ? RequiresDstTexture::kYes : RequiresDstTexture::kNo;
joshualitt95964c62015-02-11 13:45:50 -080063 }
64
65private:
Brian Salomon576eda12017-07-14 11:30:17 -040066 PolyBoundsOp(GrPaint&& paint, const SkRect& rect)
67 : INHERITED(ClassID())
68 , fColor(paint.getColor())
69 , fProcessors(std::move(paint))
70 , fRect(outset(rect)) {
71 this->setBounds(sorted_rect(fRect), HasAABloat::kNo, IsZeroArea::kNo);
72 }
Brian Salomon6b316e92016-12-16 09:35:49 -050073
Brian Salomon91326c32017-08-09 16:02:19 -040074 void onPrepareDraws(Target* target) override {
bsalomon342bfc22016-04-01 06:06:20 -070075 using namespace GrDefaultGeoProcFactory;
joshualitt95964c62015-02-11 13:45:50 -080076
Brian Salomon576eda12017-07-14 11:30:17 -040077 Color color(fColor);
Brian Salomon8c852be2017-01-04 10:44:42 -050078 sk_sp<GrGeometryProcessor> gp(GrDefaultGeoProcFactory::Make(
79 color, Coverage::kSolid_Type, LocalCoords::kUnused_Type, SkMatrix::I()));
joshualitt95964c62015-02-11 13:45:50 -080080
bsalomon342bfc22016-04-01 06:06:20 -070081 size_t vertexStride = gp->getVertexStride();
bsalomonb5238a72015-05-05 07:49:49 -070082 SkASSERT(vertexStride == sizeof(SkPoint));
83 QuadHelper helper;
bsalomon75398562015-08-17 12:55:38 -070084 SkPoint* verts = reinterpret_cast<SkPoint*>(helper.init(target, vertexStride, 1));
bsalomonb5238a72015-05-05 07:49:49 -070085 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -080086 return;
87 }
88
Cary Clark74f623d2017-11-06 20:02:02 -050089 SkPointPriv::SetRectTriStrip(verts, fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom,
Brian Salomon57caa662017-10-18 12:21:05 +000090 sizeof(SkPoint));
joshualitt95964c62015-02-11 13:45:50 -080091
Brian Salomonbfd18cd2017-08-09 16:27:09 -040092 helper.recordDraw(
93 target, gp.get(),
94 target->makePipeline(0, std::move(fProcessors), target->detachAppliedClip()));
joshualitt95964c62015-02-11 13:45:50 -080095 }
96
Brian Salomon576eda12017-07-14 11:30:17 -040097 bool onCombineIfPossible(GrOp* op, const GrCaps& caps) override { return false; }
98
99 GrColor fColor;
100 GrProcessorSet fProcessors;
bsalomon342bfc22016-04-01 06:06:20 -0700101 SkRect fRect;
joshualitt95964c62015-02-11 13:45:50 -0800102
Brian Salomon576eda12017-07-14 11:30:17 -0400103 typedef GrMeshDrawOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -0800104};
105
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000106/**
joshualittb0a8a372014-09-23 09:50:21 -0700107 * This GM directly exercises a GrProcessor that draws convex polygons.
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000108 */
109class ConvexPolyEffect : public GM {
110public:
111 ConvexPolyEffect() {
112 this->setBGColor(0xFFFFFFFF);
113 }
114
115protected:
mtklein36352bf2015-03-25 18:17:31 -0700116 SkString onShortName() override {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000117 return SkString("convex_poly_effect");
118 }
119
mtklein36352bf2015-03-25 18:17:31 -0700120 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700121 return SkISize::Make(720, 800);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000122 }
123
mtklein36352bf2015-03-25 18:17:31 -0700124 void onOnceBeforeDraw() override {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000125 SkPath tri;
126 tri.moveTo(5.f, 5.f);
127 tri.lineTo(100.f, 20.f);
128 tri.lineTo(15.f, 100.f);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000129
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000130 fPaths.addToTail(tri);
131 fPaths.addToTail(SkPath())->reverseAddPath(tri);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000132
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000133 tri.close();
134 fPaths.addToTail(tri);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000135
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000136 SkPath ngon;
mtkleindbfd7ab2016-09-01 11:24:54 -0700137 constexpr SkScalar kRadius = 50.f;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000138 const SkPoint center = { kRadius, kRadius };
139 for (int i = 0; i < GrConvexPolyEffect::kMaxEdges; ++i) {
140 SkScalar angle = 2 * SK_ScalarPI * i / GrConvexPolyEffect::kMaxEdges;
141 SkPoint point;
142 point.fY = SkScalarSinCos(angle, &point.fX);
143 point.scale(kRadius);
144 point = center + point;
145 if (0 == i) {
146 ngon.moveTo(point);
147 } else {
148 ngon.lineTo(point);
149 }
150 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000151
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000152 fPaths.addToTail(ngon);
153 SkMatrix scaleM;
154 scaleM.setScale(1.1f, 0.4f);
155 ngon.transform(scaleM);
156 fPaths.addToTail(ngon);
skia.committer@gmail.comf0b0cda2014-02-09 03:02:01 +0000157
bsalomon7888de02016-03-28 15:04:45 -0700158 SkPath linePath;
159 linePath.moveTo(5.f, 5.f);
160 linePath.lineTo(6.f, 6.f);
161 fPaths.addToTail(linePath);
162
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000163 // integer edges
164 fRects.addToTail(SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f));
165 // half-integer edges
166 fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f));
167 // vertically/horizontally thin rects that cover pixel centers
168 fRects.addToTail(SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f));
169 fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 0.75f));
170 // vertically/horizontally thin rects that don't cover pixel centers
171 fRects.addToTail(SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f));
172 fRects.addToTail(SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f));
173 // small in x and y
174 fRects.addToTail(SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f));
175 // inverted in x and y
176 fRects.addToTail(SkRect::MakeLTRB(100.f, 50.5f, 5.f, 0.5f));
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000177 }
178
mtklein36352bf2015-03-25 18:17:31 -0700179 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -0400180 GrRenderTargetContext* renderTargetContext =
181 canvas->internal_private_accessTopLayerRenderTargetContext();
182 if (!renderTargetContext) {
robertphillips175dd9b2016-04-28 14:32:04 -0700183 skiagm::GM::DrawGpuOnlyMessage(canvas);
joshualittf5883a62016-01-13 07:47:38 -0800184 return;
185 }
186
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000187 SkScalar y = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700188 constexpr SkScalar kDX = 12.f;
bsalomonf045d602015-11-18 19:01:12 -0800189 for (PathList::Iter iter(fPaths, PathList::Iter::kHead_IterStart);
bsalomon49f085d2014-09-05 13:34:00 -0700190 iter.get();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000191 iter.next()) {
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000192 const SkPath* path = iter.get();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000193 SkScalar x = 0;
194
Ethan Nicholas1706f842017-11-10 11:58:19 -0500195 for (int et = 0; et < kGrClipEdgeTypeCnt; ++et) {
robertphillips1d24b8d2015-03-26 19:57:08 -0700196 const SkMatrix m = SkMatrix::MakeTrans(x, y);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000197 SkPath p;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000198 path->transform(m, &p);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000199
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500200 GrClipEdgeType edgeType = (GrClipEdgeType) et;
Brian Salomonaff329b2017-08-11 09:40:37 -0400201 std::unique_ptr<GrFragmentProcessor> fp(GrConvexPolyEffect::Make(edgeType, p));
joshualittb0a8a372014-09-23 09:50:21 -0700202 if (!fp) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000203 continue;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000204 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000205
robertphillips28a838e2016-06-23 14:07:00 -0700206 GrPaint grPaint;
Brian Salomon576eda12017-07-14 11:30:17 -0400207 grPaint.setColor4f(GrColor4f(0, 0, 0, 1.f));
Brian Salomona1633922017-01-09 11:46:10 -0500208 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
robertphillips28a838e2016-06-23 14:07:00 -0700209 grPaint.addCoverageFragmentProcessor(std::move(fp));
joshualitt9853cce2014-11-17 14:22:48 -0800210
Brian Salomon576eda12017-07-14 11:30:17 -0400211 std::unique_ptr<GrDrawOp> op =
212 PolyBoundsOp::Make(std::move(grPaint), p.getBounds());
213 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000214
bsalomon7888de02016-03-28 15:04:45 -0700215 x += SkScalarCeilToScalar(path->getBounds().width() + kDX);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000216 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000217
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000218 // Draw AA and non AA paths using normal API for reference.
219 canvas->save();
220 canvas->translate(x, y);
221 SkPaint paint;
222 canvas->drawPath(*path, paint);
223 canvas->translate(path->getBounds().width() + 10.f, 0);
224 paint.setAntiAlias(true);
225 canvas->drawPath(*path, paint);
226 canvas->restore();
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000227
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000228 y += SkScalarCeilToScalar(path->getBounds().height() + 20.f);
229 }
230
bsalomonf045d602015-11-18 19:01:12 -0800231 for (RectList::Iter iter(fRects, RectList::Iter::kHead_IterStart);
bsalomon49f085d2014-09-05 13:34:00 -0700232 iter.get();
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000233 iter.next()) {
234
235 SkScalar x = 0;
236
Ethan Nicholas1706f842017-11-10 11:58:19 -0500237 for (int et = 0; et < kGrClipEdgeTypeCnt; ++et) {
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000238 SkRect rect = *iter.get();
239 rect.offset(x, y);
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500240 GrClipEdgeType edgeType = (GrClipEdgeType) et;
Brian Salomonaff329b2017-08-11 09:40:37 -0400241 std::unique_ptr<GrFragmentProcessor> fp(GrConvexPolyEffect::Make(edgeType, rect));
joshualittb0a8a372014-09-23 09:50:21 -0700242 if (!fp) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000243 continue;
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000244 }
245
robertphillips28a838e2016-06-23 14:07:00 -0700246 GrPaint grPaint;
Brian Salomon576eda12017-07-14 11:30:17 -0400247 grPaint.setColor4f(GrColor4f(0, 0, 0, 1.f));
Brian Salomona1633922017-01-09 11:46:10 -0500248 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
robertphillips28a838e2016-06-23 14:07:00 -0700249 grPaint.addCoverageFragmentProcessor(std::move(fp));
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000250
Brian Salomon576eda12017-07-14 11:30:17 -0400251 std::unique_ptr<GrDrawOp> op = PolyBoundsOp::Make(std::move(grPaint), rect);
252 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000253
bsalomon7888de02016-03-28 15:04:45 -0700254 x += SkScalarCeilToScalar(rect.width() + kDX);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000255 }
256
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000257 // Draw rect without and with AA using normal API for reference
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000258 canvas->save();
259 canvas->translate(x, y);
260 SkPaint paint;
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000261 canvas->drawRect(*iter.get(), paint);
bsalomon7888de02016-03-28 15:04:45 -0700262 x += SkScalarCeilToScalar(iter.get()->width() + kDX);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000263 paint.setAntiAlias(true);
264 canvas->drawRect(*iter.get(), paint);
265 canvas->restore();
266
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000267 y += SkScalarCeilToScalar(iter.get()->height() + 20.f);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000268 }
269 }
270
271private:
bsalomonf045d602015-11-18 19:01:12 -0800272 typedef SkTLList<SkPath, 1> PathList;
273 typedef SkTLList<SkRect, 1> RectList;
274 PathList fPaths;
275 RectList fRects;
skia.committer@gmail.comf0b0cda2014-02-09 03:02:01 +0000276
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000277 typedef GM INHERITED;
278};
279
halcanary385fe4d2015-08-26 13:07:48 -0700280DEF_GM(return new ConvexPolyEffect;)
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000281}
282
283#endif