Add fixes & test for isConfigTexturable and isConfigRenderable
[platform/upstream/libSkiaSharp.git] / gm / convexpolyeffect.cpp
1 /*
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"
15 #include "GrDefaultGeoProcFactory.h"
16 #include "GrRenderTargetContextPriv.h"
17 #include "GrPathUtils.h"
18 #include "GrTest.h"
19 #include "SkColorPriv.h"
20 #include "SkGeometry.h"
21 #include "SkTLList.h"
22
23 #include "ops/GrMeshDrawOp.h"
24 #include "ops/GrTestMeshDrawOp.h"
25
26 #include "effects/GrConvexPolyEffect.h"
27
28 /** outset rendered rect to visualize anti-aliased poly edges */
29 static SkRect outset(const SkRect& unsorted) {
30     SkRect r = unsorted;
31     r.outset(5.f, 5.f);
32     return r;
33 }
34
35 /** sorts a rect */
36 static SkRect sorted_rect(const SkRect& unsorted) {
37     SkRect r = unsorted;
38     r.sort();
39     return r;
40 }
41
42 namespace skiagm {
43 class PolyBoundsOp : public GrTestMeshDrawOp {
44 public:
45     DEFINE_OP_CLASS_ID
46
47     const char* name() const override { return "PolyBoundsOp"; }
48
49     static std::unique_ptr<GrLegacyMeshDrawOp> Make(const SkRect& rect, GrColor color) {
50         return std::unique_ptr<GrLegacyMeshDrawOp>(new PolyBoundsOp(rect, color));
51     }
52
53 private:
54     PolyBoundsOp(const SkRect& rect, GrColor color)
55             : INHERITED(ClassID(), outset(sorted_rect(rect)), color), fRect(outset(rect)) {}
56
57     void onPrepareDraws(Target* target) const override {
58         using namespace GrDefaultGeoProcFactory;
59
60         Color color(this->color());
61         sk_sp<GrGeometryProcessor> gp(GrDefaultGeoProcFactory::Make(
62                 color, Coverage::kSolid_Type, LocalCoords::kUnused_Type, SkMatrix::I()));
63
64         size_t vertexStride = gp->getVertexStride();
65         SkASSERT(vertexStride == sizeof(SkPoint));
66         QuadHelper helper;
67         SkPoint* verts = reinterpret_cast<SkPoint*>(helper.init(target, vertexStride, 1));
68         if (!verts) {
69             return;
70         }
71
72         fRect.toQuad(verts);
73
74         helper.recordDraw(target, gp.get(), this->pipeline());
75     }
76
77     SkRect fRect;
78
79     typedef GrTestMeshDrawOp INHERITED;
80 };
81
82 /**
83  * This GM directly exercises a GrProcessor that draws convex polygons.
84  */
85 class ConvexPolyEffect : public GM {
86 public:
87     ConvexPolyEffect() {
88         this->setBGColor(0xFFFFFFFF);
89     }
90
91 protected:
92     SkString onShortName() override {
93         return SkString("convex_poly_effect");
94     }
95
96     SkISize onISize() override {
97         return SkISize::Make(720, 800);
98     }
99
100     void onOnceBeforeDraw() override {
101         SkPath tri;
102         tri.moveTo(5.f, 5.f);
103         tri.lineTo(100.f, 20.f);
104         tri.lineTo(15.f, 100.f);
105
106         fPaths.addToTail(tri);
107         fPaths.addToTail(SkPath())->reverseAddPath(tri);
108
109         tri.close();
110         fPaths.addToTail(tri);
111
112         SkPath ngon;
113         constexpr SkScalar kRadius = 50.f;
114         const SkPoint center = { kRadius, kRadius };
115         for (int i = 0; i < GrConvexPolyEffect::kMaxEdges; ++i) {
116             SkScalar angle = 2 * SK_ScalarPI * i / GrConvexPolyEffect::kMaxEdges;
117             SkPoint point;
118             point.fY = SkScalarSinCos(angle, &point.fX);
119             point.scale(kRadius);
120             point = center + point;
121             if (0 == i) {
122                 ngon.moveTo(point);
123             } else {
124                 ngon.lineTo(point);
125             }
126         }
127
128         fPaths.addToTail(ngon);
129         SkMatrix scaleM;
130         scaleM.setScale(1.1f, 0.4f);
131         ngon.transform(scaleM);
132         fPaths.addToTail(ngon);
133
134         SkPath linePath;
135         linePath.moveTo(5.f, 5.f);
136         linePath.lineTo(6.f, 6.f);
137         fPaths.addToTail(linePath);
138
139         // integer edges
140         fRects.addToTail(SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f));
141         // half-integer edges
142         fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f));
143         // vertically/horizontally thin rects that cover pixel centers
144         fRects.addToTail(SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f));
145         fRects.addToTail(SkRect::MakeLTRB(5.5f,  0.5f, 29.5f, 0.75f));
146         // vertically/horizontally thin rects that don't cover pixel centers
147         fRects.addToTail(SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f));
148         fRects.addToTail(SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f));
149         // small in x and y
150         fRects.addToTail(SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f));
151         // inverted in x and y
152         fRects.addToTail(SkRect::MakeLTRB(100.f, 50.5f, 5.f, 0.5f));
153     }
154
155     void onDraw(SkCanvas* canvas) override {
156         GrRenderTargetContext* renderTargetContext =
157             canvas->internal_private_accessTopLayerRenderTargetContext();
158         if (!renderTargetContext) {
159             skiagm::GM::DrawGpuOnlyMessage(canvas);
160             return;
161         }
162
163         SkScalar y = 0;
164         constexpr SkScalar kDX = 12.f;
165         for (PathList::Iter iter(fPaths, PathList::Iter::kHead_IterStart);
166              iter.get();
167              iter.next()) {
168             const SkPath* path = iter.get();
169             SkScalar x = 0;
170
171             for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
172                 const SkMatrix m = SkMatrix::MakeTrans(x, y);
173                 SkPath p;
174                 path->transform(m, &p);
175
176                 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
177                 sk_sp<GrFragmentProcessor> fp(GrConvexPolyEffect::Make(edgeType, p));
178                 if (!fp) {
179                     continue;
180                 }
181
182                 GrPaint grPaint;
183                 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
184                 grPaint.addCoverageFragmentProcessor(std::move(fp));
185
186                 std::unique_ptr<GrLegacyMeshDrawOp> op =
187                         PolyBoundsOp::Make(p.getBounds(), 0xff000000);
188
189                 renderTargetContext->priv().testingOnly_addLegacyMeshDrawOp(
190                         std::move(grPaint), GrAAType::kNone, std::move(op));
191
192                 x += SkScalarCeilToScalar(path->getBounds().width() + kDX);
193             }
194
195             // Draw AA and non AA paths using normal API for reference.
196             canvas->save();
197             canvas->translate(x, y);
198             SkPaint paint;
199             canvas->drawPath(*path, paint);
200             canvas->translate(path->getBounds().width() + 10.f, 0);
201             paint.setAntiAlias(true);
202             canvas->drawPath(*path, paint);
203             canvas->restore();
204
205             y += SkScalarCeilToScalar(path->getBounds().height() + 20.f);
206         }
207
208         for (RectList::Iter iter(fRects, RectList::Iter::kHead_IterStart);
209              iter.get();
210              iter.next()) {
211
212             SkScalar x = 0;
213
214             for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
215                 SkRect rect = *iter.get();
216                 rect.offset(x, y);
217                 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
218                 sk_sp<GrFragmentProcessor> fp(GrConvexPolyEffect::Make(edgeType, rect));
219                 if (!fp) {
220                     continue;
221                 }
222
223                 GrPaint grPaint;
224                 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
225                 grPaint.addCoverageFragmentProcessor(std::move(fp));
226
227                 std::unique_ptr<GrLegacyMeshDrawOp> op = PolyBoundsOp::Make(rect, 0xff000000);
228
229                 renderTargetContext->priv().testingOnly_addLegacyMeshDrawOp(
230                         std::move(grPaint), GrAAType::kNone, std::move(op));
231
232                 x += SkScalarCeilToScalar(rect.width() + kDX);
233             }
234
235             // Draw rect without and with AA using normal API for reference
236             canvas->save();
237             canvas->translate(x, y);
238             SkPaint paint;
239             canvas->drawRect(*iter.get(), paint);
240             x += SkScalarCeilToScalar(iter.get()->width() + kDX);
241             paint.setAntiAlias(true);
242             canvas->drawRect(*iter.get(), paint);
243             canvas->restore();
244
245             y += SkScalarCeilToScalar(iter.get()->height() + 20.f);
246         }
247     }
248
249 private:
250     typedef SkTLList<SkPath, 1> PathList;
251     typedef SkTLList<SkRect, 1> RectList;
252     PathList fPaths;
253     RectList fRects;
254
255     typedef GM INHERITED;
256 };
257
258 DEF_GM(return new ConvexPolyEffect;)
259 }
260
261 #endif