blob: ac8ec72d0895c2488108c5a7c4fbe73606a616d8 [file] [log] [blame]
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +00001
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
25namespace {
26extern const GrVertexAttrib kAttribs[] = {
27 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
28};
29}
30
31namespace skiagm {
32/**
33 * This GM directly exercises a GrEffect that draws convex polygons.
34 */
35class ConvexPolyEffect : public GM {
36public:
37 ConvexPolyEffect() {
38 this->setBGColor(0xFFFFFFFF);
39 }
40
41protected:
42 virtual SkString onShortName() SK_OVERRIDE {
43 return SkString("convex_poly_effect");
44 }
45
46 virtual SkISize onISize() SK_OVERRIDE {
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +000047 return make_isize(720, 800);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000048 }
49
50 virtual uint32_t onGetFlags() const SK_OVERRIDE {
51 // This is a GPU-specific GM.
52 return kGPUOnly_Flag;
53 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +000054
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000055 virtual void onOnceBeforeDraw() SK_OVERRIDE {
56 SkPath tri;
57 tri.moveTo(5.f, 5.f);
58 tri.lineTo(100.f, 20.f);
59 tri.lineTo(15.f, 100.f);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +000060
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000061 fPaths.addToTail(tri);
62 fPaths.addToTail(SkPath())->reverseAddPath(tri);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +000063
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000064 tri.close();
65 fPaths.addToTail(tri);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +000066
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000067 SkPath ngon;
68 static const SkScalar kRadius = 50.f;
69 const SkPoint center = { kRadius, kRadius };
70 for (int i = 0; i < GrConvexPolyEffect::kMaxEdges; ++i) {
71 SkScalar angle = 2 * SK_ScalarPI * i / GrConvexPolyEffect::kMaxEdges;
72 SkPoint point;
73 point.fY = SkScalarSinCos(angle, &point.fX);
74 point.scale(kRadius);
75 point = center + point;
76 if (0 == i) {
77 ngon.moveTo(point);
78 } else {
79 ngon.lineTo(point);
80 }
81 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +000082
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000083 fPaths.addToTail(ngon);
84 SkMatrix scaleM;
85 scaleM.setScale(1.1f, 0.4f);
86 ngon.transform(scaleM);
87 fPaths.addToTail(ngon);
skia.committer@gmail.comf0b0cda2014-02-09 03:02:01 +000088
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000089 // integer edges
90 fRects.addToTail(SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f));
91 // half-integer edges
92 fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f));
93 // vertically/horizontally thin rects that cover pixel centers
94 fRects.addToTail(SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f));
95 fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 0.75f));
96 // vertically/horizontally thin rects that don't cover pixel centers
97 fRects.addToTail(SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f));
98 fRects.addToTail(SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f));
99 // small in x and y
100 fRects.addToTail(SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f));
101 // inverted in x and y
102 fRects.addToTail(SkRect::MakeLTRB(100.f, 50.5f, 5.f, 0.5f));
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000103 }
104
105 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
106 SkBaseDevice* device = canvas->getTopDevice();
107 GrRenderTarget* rt = device->accessRenderTarget();
108 if (NULL == rt) {
109 return;
110 }
111 GrContext* context = rt->getContext();
112 if (NULL == context) {
113 return;
114 }
115
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000116 SkScalar y = 0;
117 for (SkTLList<SkPath>::Iter iter(fPaths, SkTLList<SkPath>::Iter::kHead_IterStart);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000118 NULL != iter.get();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000119 iter.next()) {
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000120 const SkPath* path = iter.get();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000121 SkScalar x = 0;
122
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000123 for (int et = 0; et < kGrEffectEdgeTypeCnt; ++et) {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000124 GrTestTarget tt;
125 context->getTestTarget(&tt);
126 if (NULL == tt.target()) {
127 SkDEBUGFAIL("Couldn't get Gr test target.");
128 return;
129 }
130 GrDrawState* drawState = tt.target()->drawState();
131 drawState->setVertexAttribs<kAttribs>(SK_ARRAY_COUNT(kAttribs));
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000132
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000133 SkMatrix m;
134 SkPath p;
135 m.setTranslate(x, y);
136 path->transform(m, &p);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000137
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000138 GrEffectEdgeType edgeType = (GrEffectEdgeType) et;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000139 SkAutoTUnref<GrEffectRef> effect(GrConvexPolyEffect::Create(edgeType, p));
140 if (!effect) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000141 continue;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000142 }
143 drawState->addCoverageEffect(effect, 1);
144 drawState->setIdentityViewMatrix();
145 drawState->setRenderTarget(rt);
146 drawState->setColor(0xff000000);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000147
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000148 SkPoint verts[4];
149 SkRect bounds = p.getBounds();
150 // Make sure any artifacts around the exterior of path are visible by using overly
151 // conservative bounding geometry.
152 bounds.outset(5.f, 5.f);
153 bounds.toQuad(verts);
154
155 tt.target()->setVertexSourceToArray(verts, 4);
156 tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer());
157 tt.target()->drawIndexed(kTriangleFan_GrPrimitiveType, 0, 0, 4, 6);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000158
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000159 x += SkScalarCeilToScalar(path->getBounds().width() + 10.f);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000160 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000161
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000162 // Draw AA and non AA paths using normal API for reference.
163 canvas->save();
164 canvas->translate(x, y);
165 SkPaint paint;
166 canvas->drawPath(*path, paint);
167 canvas->translate(path->getBounds().width() + 10.f, 0);
168 paint.setAntiAlias(true);
169 canvas->drawPath(*path, paint);
170 canvas->restore();
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000171
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000172 y += SkScalarCeilToScalar(path->getBounds().height() + 20.f);
173 }
174
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000175 for (SkTLList<SkRect>::Iter iter(fRects, SkTLList<SkRect>::Iter::kHead_IterStart);
176 NULL != iter.get();
177 iter.next()) {
178
179 SkScalar x = 0;
180
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000181 for (int et = 0; et < kGrEffectEdgeTypeCnt; ++et) {
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000182 GrTestTarget tt;
183 context->getTestTarget(&tt);
184 if (NULL == tt.target()) {
185 SkDEBUGFAIL("Couldn't get Gr test target.");
186 return;
187 }
188 SkRect rect = *iter.get();
189 rect.offset(x, y);
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000190 GrEffectEdgeType edgeType = (GrEffectEdgeType) et;
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000191 SkAutoTUnref<GrEffectRef> effect(GrConvexPolyEffect::Create(edgeType, rect));
192 if (!effect) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000193 continue;
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000194 }
195
196 GrDrawState* drawState = tt.target()->drawState();
197 drawState->setVertexAttribs<kAttribs>(SK_ARRAY_COUNT(kAttribs));
198 drawState->addCoverageEffect(effect, 1);
199 drawState->setIdentityViewMatrix();
200 drawState->setRenderTarget(rt);
201 drawState->setColor(0xff000000);
202
203 SkPoint verts[4];
204 SkRect bounds = rect;
205 bounds.outset(5.f, 5.f);
206 bounds.toQuad(verts);
207
208 tt.target()->setVertexSourceToArray(verts, 4);
209 tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer());
210 tt.target()->drawIndexed(kTriangleFan_GrPrimitiveType, 0, 0, 4, 6);
211
212 x += SkScalarCeilToScalar(rect.width() + 10.f);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000213 }
214
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000215 // Draw rect without and with AA using normal API for reference
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000216 canvas->save();
217 canvas->translate(x, y);
218 SkPaint paint;
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000219 canvas->drawRect(*iter.get(), paint);
220 x += SkScalarCeilToScalar(iter.get()->width() + 10.f);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000221 paint.setAntiAlias(true);
222 canvas->drawRect(*iter.get(), paint);
223 canvas->restore();
224
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000225 y += SkScalarCeilToScalar(iter.get()->height() + 20.f);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000226 }
227 }
228
229private:
230 SkTLList<SkPath> fPaths;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000231 SkTLList<SkRect> fRects;
skia.committer@gmail.comf0b0cda2014-02-09 03:02:01 +0000232
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000233 typedef GM INHERITED;
234};
235
236DEF_GM( return SkNEW(ConvexPolyEffect); )
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000237}
238
239#endif