• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2014 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 // This test only works with the GPU backend.
10 
11 #include "gm.h"
12 
13 #if SK_SUPPORT_GPU
14 
15 #include "GrContext.h"
16 #include "GrDefaultGeoProcFactory.h"
17 #include "GrDrawContext.h"
18 #include "GrPathUtils.h"
19 #include "GrTest.h"
20 #include "SkColorPriv.h"
21 #include "SkDevice.h"
22 #include "SkGeometry.h"
23 #include "SkTLList.h"
24 
25 #include "batches/GrTestBatch.h"
26 #include "batches/GrVertexBatch.h"
27 
28 #include "effects/GrConvexPolyEffect.h"
29 
30 namespace skiagm {
31 
32 class ConvexPolyTestBatch : public GrTestBatch {
33 public:
34     DEFINE_BATCH_CLASS_ID
35     struct Geometry : public GrTestBatch::Geometry {
36         SkRect fRect;
37         SkRect fBounds; // This will be == fRect, except fBounds must be sorted, whereas fRect can
38                         // be inverted
39     };
40 
name() const41     const char* name() const override { return "ConvexPolyTestBatch"; }
42 
Create(const GrGeometryProcessor * gp,const Geometry & geo)43     static GrDrawBatch* Create(const GrGeometryProcessor* gp, const Geometry& geo) {
44         return new ConvexPolyTestBatch(gp, geo);
45     }
46 
47 private:
ConvexPolyTestBatch(const GrGeometryProcessor * gp,const Geometry & geo)48     ConvexPolyTestBatch(const GrGeometryProcessor* gp, const Geometry& geo)
49         : INHERITED(ClassID(), gp, geo.fBounds)
50         , fGeometry(geo) {
51         // Make sure any artifacts around the exterior of path are visible by using overly
52         // conservative bounding geometry.
53         fGeometry.fBounds.outset(5.f, 5.f);
54         fGeometry.fRect.outset(5.f, 5.f);
55     }
56 
geoData(int index)57     Geometry* geoData(int index) override {
58         SkASSERT(0 == index);
59         return &fGeometry;
60     }
61 
geoData(int index) const62     const Geometry* geoData(int index) const override {
63         SkASSERT(0 == index);
64         return &fGeometry;
65     }
66 
generateGeometry(Target * target) const67     void generateGeometry(Target* target) const override {
68         size_t vertexStride = this->geometryProcessor()->getVertexStride();
69         SkASSERT(vertexStride == sizeof(SkPoint));
70         QuadHelper helper;
71         SkPoint* verts = reinterpret_cast<SkPoint*>(helper.init(target, vertexStride, 1));
72         if (!verts) {
73             return;
74         }
75 
76         fGeometry.fRect.toQuad(verts);
77 
78         helper.recordDraw(target);
79     }
80 
81     Geometry fGeometry;
82 
83     typedef GrTestBatch INHERITED;
84 };
85 
86 /**
87  * This GM directly exercises a GrProcessor that draws convex polygons.
88  */
89 class ConvexPolyEffect : public GM {
90 public:
ConvexPolyEffect()91     ConvexPolyEffect() {
92         this->setBGColor(0xFFFFFFFF);
93     }
94 
95 protected:
onShortName()96     SkString onShortName() override {
97         return SkString("convex_poly_effect");
98     }
99 
onISize()100     SkISize onISize() override {
101         return SkISize::Make(720, 800);
102     }
103 
onOnceBeforeDraw()104     void onOnceBeforeDraw() override {
105         SkPath tri;
106         tri.moveTo(5.f, 5.f);
107         tri.lineTo(100.f, 20.f);
108         tri.lineTo(15.f, 100.f);
109 
110         fPaths.addToTail(tri);
111         fPaths.addToTail(SkPath())->reverseAddPath(tri);
112 
113         tri.close();
114         fPaths.addToTail(tri);
115 
116         SkPath ngon;
117         static const SkScalar kRadius = 50.f;
118         const SkPoint center = { kRadius, kRadius };
119         for (int i = 0; i < GrConvexPolyEffect::kMaxEdges; ++i) {
120             SkScalar angle = 2 * SK_ScalarPI * i / GrConvexPolyEffect::kMaxEdges;
121             SkPoint point;
122             point.fY = SkScalarSinCos(angle, &point.fX);
123             point.scale(kRadius);
124             point = center + point;
125             if (0 == i) {
126                 ngon.moveTo(point);
127             } else {
128                 ngon.lineTo(point);
129             }
130         }
131 
132         fPaths.addToTail(ngon);
133         SkMatrix scaleM;
134         scaleM.setScale(1.1f, 0.4f);
135         ngon.transform(scaleM);
136         fPaths.addToTail(ngon);
137 
138         // integer edges
139         fRects.addToTail(SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f));
140         // half-integer edges
141         fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f));
142         // vertically/horizontally thin rects that cover pixel centers
143         fRects.addToTail(SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f));
144         fRects.addToTail(SkRect::MakeLTRB(5.5f,  0.5f, 29.5f, 0.75f));
145         // vertically/horizontally thin rects that don't cover pixel centers
146         fRects.addToTail(SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f));
147         fRects.addToTail(SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f));
148         // small in x and y
149         fRects.addToTail(SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f));
150         // inverted in x and y
151         fRects.addToTail(SkRect::MakeLTRB(100.f, 50.5f, 5.f, 0.5f));
152     }
153 
onDraw(SkCanvas * canvas)154     void onDraw(SkCanvas* canvas) override {
155         using namespace GrDefaultGeoProcFactory;
156         GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
157         if (nullptr == rt) {
158             skiagm::GM::DrawGpuOnlyMessage(canvas);
159             return;
160         }
161         GrContext* context = rt->getContext();
162         if (nullptr == context) {
163             return;
164         }
165 
166         SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt));
167         if (!drawContext) {
168             return;
169         }
170 
171         Color color(0xff000000);
172         Coverage coverage(Coverage::kSolid_Type);
173         LocalCoords localCoords(LocalCoords::kUnused_Type);
174         SkAutoTUnref<const GrGeometryProcessor> gp(
175                 GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkMatrix::I()));
176 
177         SkScalar y = 0;
178         for (PathList::Iter iter(fPaths, PathList::Iter::kHead_IterStart);
179              iter.get();
180              iter.next()) {
181             const SkPath* path = iter.get();
182             SkScalar x = 0;
183 
184             for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
185                 const SkMatrix m = SkMatrix::MakeTrans(x, y);
186                 SkPath p;
187                 path->transform(m, &p);
188 
189                 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
190                 SkAutoTUnref<GrFragmentProcessor> fp(GrConvexPolyEffect::Create(edgeType, p));
191                 if (!fp) {
192                     continue;
193                 }
194 
195                 GrPipelineBuilder pipelineBuilder;
196                 pipelineBuilder.setXPFactory(
197                     GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
198                 pipelineBuilder.addCoverageFragmentProcessor(fp);
199                 pipelineBuilder.setRenderTarget(rt);
200 
201                 ConvexPolyTestBatch::Geometry geometry;
202                 geometry.fColor = color.fColor;
203                 geometry.fRect = p.getBounds();
204                 geometry.fBounds = p.getBounds();
205 
206                 SkAutoTUnref<GrDrawBatch> batch(ConvexPolyTestBatch::Create(gp, geometry));
207 
208                 drawContext->internal_drawBatch(pipelineBuilder, batch);
209 
210                 x += SkScalarCeilToScalar(path->getBounds().width() + 10.f);
211             }
212 
213             // Draw AA and non AA paths using normal API for reference.
214             canvas->save();
215             canvas->translate(x, y);
216             SkPaint paint;
217             canvas->drawPath(*path, paint);
218             canvas->translate(path->getBounds().width() + 10.f, 0);
219             paint.setAntiAlias(true);
220             canvas->drawPath(*path, paint);
221             canvas->restore();
222 
223             y += SkScalarCeilToScalar(path->getBounds().height() + 20.f);
224         }
225 
226         for (RectList::Iter iter(fRects, RectList::Iter::kHead_IterStart);
227              iter.get();
228              iter.next()) {
229 
230             SkScalar x = 0;
231 
232             for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
233                 SkRect rect = *iter.get();
234                 rect.offset(x, y);
235                 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
236                 SkAutoTUnref<GrFragmentProcessor> fp(GrConvexPolyEffect::Create(edgeType, rect));
237                 if (!fp) {
238                     continue;
239                 }
240 
241                 GrPipelineBuilder pipelineBuilder;
242                 pipelineBuilder.setXPFactory(
243                     GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
244                 pipelineBuilder.addCoverageFragmentProcessor(fp);
245                 pipelineBuilder.setRenderTarget(rt);
246 
247                 ConvexPolyTestBatch::Geometry geometry;
248                 geometry.fColor = color.fColor;
249                 geometry.fRect = rect;
250                 geometry.fBounds = rect;
251                 geometry.fBounds.sort();
252 
253                 SkAutoTUnref<GrDrawBatch> batch(ConvexPolyTestBatch::Create(gp, geometry));
254 
255                 drawContext->internal_drawBatch(pipelineBuilder, batch);
256 
257                 x += SkScalarCeilToScalar(rect.width() + 10.f);
258             }
259 
260             // Draw rect without and with AA using normal API for reference
261             canvas->save();
262             canvas->translate(x, y);
263             SkPaint paint;
264             canvas->drawRect(*iter.get(), paint);
265             x += SkScalarCeilToScalar(iter.get()->width() + 10.f);
266             paint.setAntiAlias(true);
267             canvas->drawRect(*iter.get(), paint);
268             canvas->restore();
269 
270             y += SkScalarCeilToScalar(iter.get()->height() + 20.f);
271         }
272     }
273 
274 private:
275     typedef SkTLList<SkPath, 1> PathList;
276     typedef SkTLList<SkRect, 1> RectList;
277     PathList fPaths;
278     RectList fRects;
279 
280     typedef GM INHERITED;
281 };
282 
283 DEF_GM(return new ConvexPolyEffect;)
284 }
285 
286 #endif
287