3 * Copyright 2014 Google Inc.
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
9 // This test only works with the GPU backend.
15 #include "GrContext.h"
16 #include "GrPathUtils.h"
18 #include "SkColorPriv.h"
20 #include "SkGeometry.h"
23 #include "effects/GrConvexPolyEffect.h"
27 * This GM directly exercises a GrProcessor that draws convex polygons.
29 class ConvexPolyEffect : public GM {
32 this->setBGColor(0xFFFFFFFF);
36 virtual SkString onShortName() SK_OVERRIDE {
37 return SkString("convex_poly_effect");
40 virtual SkISize onISize() SK_OVERRIDE {
41 return SkISize::Make(720, 800);
44 virtual uint32_t onGetFlags() const SK_OVERRIDE {
45 // This is a GPU-specific GM.
49 virtual void onOnceBeforeDraw() SK_OVERRIDE {
52 tri.lineTo(100.f, 20.f);
53 tri.lineTo(15.f, 100.f);
55 fPaths.addToTail(tri);
56 fPaths.addToTail(SkPath())->reverseAddPath(tri);
59 fPaths.addToTail(tri);
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;
67 point.fY = SkScalarSinCos(angle, &point.fX);
69 point = center + point;
77 fPaths.addToTail(ngon);
79 scaleM.setScale(1.1f, 0.4f);
80 ngon.transform(scaleM);
81 fPaths.addToTail(ngon);
84 fRects.addToTail(SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f));
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));
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));
99 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
100 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
104 GrContext* context = rt->getContext();
105 if (NULL == context) {
110 for (SkTLList<SkPath>::Iter iter(fPaths, SkTLList<SkPath>::Iter::kHead_IterStart);
113 const SkPath* path = iter.get();
116 for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
118 context->getTestTarget(&tt);
119 if (NULL == tt.target()) {
120 SkDEBUGFAIL("Couldn't get Gr test target.");
123 GrDrawState* drawState = tt.target()->drawState();
127 m.setTranslate(x, y);
128 path->transform(m, &p);
130 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
131 SkAutoTUnref<GrFragmentProcessor> fp(GrConvexPolyEffect::Create(edgeType, p));
135 drawState->addCoverageProcessor(fp);
136 drawState->setIdentityViewMatrix();
137 drawState->setRenderTarget(rt);
138 drawState->setColor(0xff000000);
141 GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, 0);
142 SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices());
145 SkRect bounds = p.getBounds();
146 // Make sure any artifacts around the exterior of path are visible by using overly
147 // conservative bounding geometry.
148 bounds.outset(5.f, 5.f);
149 bounds.toQuad(verts);
151 //tt.target()->setVertexSourceToArray(verts, 4);
152 tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer());
153 tt.target()->drawIndexed(kTriangleFan_GrPrimitiveType, 0, 0, 4, 6);
155 x += SkScalarCeilToScalar(path->getBounds().width() + 10.f);
158 // Draw AA and non AA paths using normal API for reference.
160 canvas->translate(x, y);
162 canvas->drawPath(*path, paint);
163 canvas->translate(path->getBounds().width() + 10.f, 0);
164 paint.setAntiAlias(true);
165 canvas->drawPath(*path, paint);
168 y += SkScalarCeilToScalar(path->getBounds().height() + 20.f);
171 for (SkTLList<SkRect>::Iter iter(fRects, SkTLList<SkRect>::Iter::kHead_IterStart);
177 for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
179 context->getTestTarget(&tt);
180 if (NULL == tt.target()) {
181 SkDEBUGFAIL("Couldn't get Gr test target.");
184 SkRect rect = *iter.get();
186 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
187 SkAutoTUnref<GrFragmentProcessor> fp(GrConvexPolyEffect::Create(edgeType, rect));
192 GrDrawState* drawState = tt.target()->drawState();
193 drawState->addCoverageProcessor(fp);
194 drawState->setIdentityViewMatrix();
195 drawState->setRenderTarget(rt);
196 drawState->setColor(0xff000000);
199 GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, 0);
200 SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices());
203 SkRect bounds = rect;
204 bounds.outset(5.f, 5.f);
205 bounds.toQuad(verts);
207 //tt.target()->setVertexSourceToArray(verts, 4);
208 tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer());
209 tt.target()->drawIndexed(kTriangleFan_GrPrimitiveType, 0, 0, 4, 6);
211 x += SkScalarCeilToScalar(rect.width() + 10.f);
214 // Draw rect without and with AA using normal API for reference
216 canvas->translate(x, y);
218 canvas->drawRect(*iter.get(), paint);
219 x += SkScalarCeilToScalar(iter.get()->width() + 10.f);
220 paint.setAntiAlias(true);
221 canvas->drawRect(*iter.get(), paint);
224 y += SkScalarCeilToScalar(iter.get()->height() + 20.f);
229 SkTLList<SkPath> fPaths;
230 SkTLList<SkRect> fRects;
232 typedef GM INHERITED;
235 DEF_GM( return SkNEW(ConvexPolyEffect); )