• 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 "GrPathUtils.h"
17 #include "GrTest.h"
18 #include "SkColorPriv.h"
19 #include "SkDevice.h"
20 #include "SkGeometry.h"
21 #include "SkTLList.h"
22 
23 #include "effects/GrConvexPolyEffect.h"
24 
25 namespace skiagm {
26 /**
27  * This GM directly exercises a GrProcessor that draws convex polygons.
28  */
29 class ConvexPolyEffect : public GM {
30 public:
ConvexPolyEffect()31     ConvexPolyEffect() {
32         this->setBGColor(0xFFFFFFFF);
33     }
34 
35 protected:
onShortName()36     virtual SkString onShortName() SK_OVERRIDE {
37         return SkString("convex_poly_effect");
38     }
39 
onISize()40     virtual SkISize onISize() SK_OVERRIDE {
41         return SkISize::Make(720, 800);
42     }
43 
onGetFlags() const44     virtual uint32_t onGetFlags() const SK_OVERRIDE {
45         // This is a GPU-specific GM.
46         return kGPUOnly_Flag;
47     }
48 
onOnceBeforeDraw()49     virtual void onOnceBeforeDraw() SK_OVERRIDE {
50         SkPath tri;
51         tri.moveTo(5.f, 5.f);
52         tri.lineTo(100.f, 20.f);
53         tri.lineTo(15.f, 100.f);
54 
55         fPaths.addToTail(tri);
56         fPaths.addToTail(SkPath())->reverseAddPath(tri);
57 
58         tri.close();
59         fPaths.addToTail(tri);
60 
61         SkPath ngon;
62         static const SkScalar kRadius = 50.f;
63         const SkPoint center = { kRadius, kRadius };
64         for (int i = 0; i < GrConvexPolyEffect::kMaxEdges; ++i) {
65             SkScalar angle = 2 * SK_ScalarPI * i / GrConvexPolyEffect::kMaxEdges;
66             SkPoint point;
67             point.fY = SkScalarSinCos(angle, &point.fX);
68             point.scale(kRadius);
69             point = center + point;
70             if (0 == i) {
71                 ngon.moveTo(point);
72             } else {
73                 ngon.lineTo(point);
74             }
75         }
76 
77         fPaths.addToTail(ngon);
78         SkMatrix scaleM;
79         scaleM.setScale(1.1f, 0.4f);
80         ngon.transform(scaleM);
81         fPaths.addToTail(ngon);
82 
83         // integer edges
84         fRects.addToTail(SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f));
85         // half-integer edges
86         fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f));
87         // vertically/horizontally thin rects that cover pixel centers
88         fRects.addToTail(SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f));
89         fRects.addToTail(SkRect::MakeLTRB(5.5f,  0.5f, 29.5f, 0.75f));
90         // vertically/horizontally thin rects that don't cover pixel centers
91         fRects.addToTail(SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f));
92         fRects.addToTail(SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f));
93         // small in x and y
94         fRects.addToTail(SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f));
95         // inverted in x and y
96         fRects.addToTail(SkRect::MakeLTRB(100.f, 50.5f, 5.f, 0.5f));
97     }
98 
onDraw(SkCanvas * canvas)99     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
100         GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
101         if (NULL == rt) {
102             return;
103         }
104         GrContext* context = rt->getContext();
105         if (NULL == context) {
106             return;
107         }
108 
109         SkScalar y = 0;
110         for (SkTLList<SkPath>::Iter iter(fPaths, SkTLList<SkPath>::Iter::kHead_IterStart);
111              iter.get();
112              iter.next()) {
113             const SkPath* path = iter.get();
114             SkScalar x = 0;
115 
116             for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
117                 GrTestTarget tt;
118                 context->getTestTarget(&tt);
119                 if (NULL == tt.target()) {
120                     SkDEBUGFAIL("Couldn't get Gr test target.");
121                     return;
122                 }
123                 GrDrawState* drawState = tt.target()->drawState();
124 
125                 SkMatrix m;
126                 SkPath p;
127                 m.setTranslate(x, y);
128                 path->transform(m, &p);
129 
130                 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
131                 SkAutoTUnref<GrFragmentProcessor> fp(GrConvexPolyEffect::Create(edgeType, p));
132                 if (!fp) {
133                     continue;
134                 }
135                 drawState->addCoverageProcessor(fp);
136                 drawState->setIdentityViewMatrix();
137                 drawState->setRenderTarget(rt);
138                 drawState->setColor(0xff000000);
139 
140                 SkPoint verts[4];
141                 SkRect bounds = p.getBounds();
142                 // Make sure any artifacts around the exterior of path are visible by using overly
143                 // conservative bounding geometry.
144                 bounds.outset(5.f, 5.f);
145                 bounds.toQuad(verts);
146 
147                 tt.target()->setVertexSourceToArray(verts, 4);
148                 tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer());
149                 tt.target()->drawIndexed(kTriangleFan_GrPrimitiveType, 0, 0, 4, 6);
150 
151                 x += SkScalarCeilToScalar(path->getBounds().width() + 10.f);
152             }
153 
154             // Draw AA and non AA paths using normal API for reference.
155             canvas->save();
156             canvas->translate(x, y);
157             SkPaint paint;
158             canvas->drawPath(*path, paint);
159             canvas->translate(path->getBounds().width() + 10.f, 0);
160             paint.setAntiAlias(true);
161             canvas->drawPath(*path, paint);
162             canvas->restore();
163 
164             y += SkScalarCeilToScalar(path->getBounds().height() + 20.f);
165         }
166 
167         for (SkTLList<SkRect>::Iter iter(fRects, SkTLList<SkRect>::Iter::kHead_IterStart);
168              iter.get();
169              iter.next()) {
170 
171             SkScalar x = 0;
172 
173             for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
174                 GrTestTarget tt;
175                 context->getTestTarget(&tt);
176                 if (NULL == tt.target()) {
177                     SkDEBUGFAIL("Couldn't get Gr test target.");
178                     return;
179                 }
180                 SkRect rect = *iter.get();
181                 rect.offset(x, y);
182                 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
183                 SkAutoTUnref<GrFragmentProcessor> fp(GrConvexPolyEffect::Create(edgeType, rect));
184                 if (!fp) {
185                     continue;
186                 }
187 
188                 GrDrawState* drawState = tt.target()->drawState();
189                 drawState->addCoverageProcessor(fp);
190                 drawState->setIdentityViewMatrix();
191                 drawState->setRenderTarget(rt);
192                 drawState->setColor(0xff000000);
193 
194                 SkPoint verts[4];
195                 SkRect bounds = rect;
196                 bounds.outset(5.f, 5.f);
197                 bounds.toQuad(verts);
198 
199                 tt.target()->setVertexSourceToArray(verts, 4);
200                 tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer());
201                 tt.target()->drawIndexed(kTriangleFan_GrPrimitiveType, 0, 0, 4, 6);
202 
203                 x += SkScalarCeilToScalar(rect.width() + 10.f);
204             }
205 
206             // Draw rect without and with AA using normal API for reference
207             canvas->save();
208             canvas->translate(x, y);
209             SkPaint paint;
210             canvas->drawRect(*iter.get(), paint);
211             x += SkScalarCeilToScalar(iter.get()->width() + 10.f);
212             paint.setAntiAlias(true);
213             canvas->drawRect(*iter.get(), paint);
214             canvas->restore();
215 
216             y += SkScalarCeilToScalar(iter.get()->height() + 20.f);
217         }
218     }
219 
220 private:
221     SkTLList<SkPath> fPaths;
222     SkTLList<SkRect> fRects;
223 
224     typedef GM INHERITED;
225 };
226 
227 DEF_GM( return SkNEW(ConvexPolyEffect); )
228 }
229 
230 #endif
231