blob: 7bc7c199b0a35098a9a82b534bde15f50cf3ff7b [file] [log] [blame]
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +00001/*
2 * Copyright 2012 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#include "gm.h"
bsalomon@google.com707bd602014-03-04 16:52:20 +00009#if SK_SUPPORT_GPU
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000010#include "GrTest.h"
bsalomon@google.com707bd602014-03-04 16:52:20 +000011#include "effects/GrRRectEffect.h"
12#endif
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000013#include "SkDevice.h"
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000014#include "SkRRect.h"
15
16namespace skiagm {
17
18///////////////////////////////////////////////////////////////////////////////
19
20class RRectGM : public GM {
21public:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000022 enum Type {
23 kBW_Draw_Type,
24 kAA_Draw_Type,
25 kBW_Clip_Type,
26 kAA_Clip_Type,
27 kEffect_Type,
28 };
29 RRectGM(Type type) : fType(type) {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000030 this->setBGColor(0xFFDDDDDD);
31 this->setUpRRects();
32 }
33
34protected:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000035 SkString onShortName() SK_OVERRIDE {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000036 SkString name("rrect");
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000037 switch (fType) {
38 case kBW_Draw_Type:
39 name.append("_draw_bw");
40 break;
41 case kAA_Draw_Type:
42 name.append("_draw_aa");
43 break;
44 case kBW_Clip_Type:
45 name.append("_clip_bw");
46 break;
47 case kAA_Clip_Type:
48 name.append("_clip_aa");
49 break;
50 case kEffect_Type:
51 name.append("_effect");
52 break;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000053 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000054 return name;
55 }
56
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000057 virtual SkISize onISize() SK_OVERRIDE { return make_isize(kImageWidth, kImageHeight); }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000058
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000059 virtual uint32_t onGetFlags() const SK_OVERRIDE {
60 if (kEffect_Type == fType) {
61 return kGPUOnly_Flag;
62 } else {
63 return 0;
64 }
65 }
66
67 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
bsalomon@google.com707bd602014-03-04 16:52:20 +000068 int numRRects = kNumRRects;
69#if SK_SUPPORT_GPU
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000070 SkBaseDevice* device = canvas->getTopDevice();
71 GrContext* context = NULL;
72 GrRenderTarget* rt = device->accessRenderTarget();
73 if (NULL != rt) {
74 context = rt->getContext();
75 }
76 if (kEffect_Type == fType && NULL == context) {
77 return;
78 }
bsalomon@google.com707bd602014-03-04 16:52:20 +000079 if (kEffect_Type == fType) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000080 numRRects *= kGrEffectEdgeTypeCnt;
bsalomon@google.com707bd602014-03-04 16:52:20 +000081 }
82#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000083
84 SkPaint paint;
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000085 if (kAA_Draw_Type == fType) {
86 paint.setAntiAlias(true);
87 }
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +000088
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000089 static const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX), SkIntToScalar(kTileY));
90
91 int curRRect = 0;
92 for (int y = 1; y < kImageHeight; y += kTileY) {
93 for (int x = 1; x < kImageWidth; x += kTileX) {
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000094 if (curRRect >= numRRects) {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000095 break;
96 }
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000097 int rrectIdx = curRRect % kNumRRects;
98 SkASSERT(kMaxTileBound.contains(fRRects[rrectIdx].getBounds()));
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000099
100 canvas->save();
101 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000102 if (kEffect_Type == fType) {
bsalomon@google.com707bd602014-03-04 16:52:20 +0000103#if SK_SUPPORT_GPU
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000104 GrTestTarget tt;
105 context->getTestTarget(&tt);
106 if (NULL == tt.target()) {
107 SkDEBUGFAIL("Couldn't get Gr test target.");
108 return;
109 }
110 GrDrawState* drawState = tt.target()->drawState();
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000111
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000112 SkRRect rrect = fRRects[rrectIdx];
113 rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000114 GrEffectEdgeType edgeType = (GrEffectEdgeType) (curRRect / kNumRRects);
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000115 SkAutoTUnref<GrEffectRef> effect(GrRRectEffect::Create(edgeType, rrect));
116 if (effect) {
117 drawState->addCoverageEffect(effect);
118 drawState->setIdentityViewMatrix();
119 drawState->setRenderTarget(rt);
120 drawState->setColor(0xff000000);
121
122 SkRect bounds = rrect.getBounds();
123 bounds.outset(2.f, 2.f);
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000124
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000125 tt.target()->drawSimpleRect(bounds);
126 }
bsalomon@google.com707bd602014-03-04 16:52:20 +0000127#endif
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000128 } else if (kBW_Clip_Type == fType || kAA_Clip_Type == fType) {
129 bool aaClip = (kAA_Clip_Type == fType);
130 canvas->clipRRect(fRRects[rrectIdx], SkRegion::kReplace_Op, aaClip);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000131 canvas->drawRect(kMaxTileBound, paint);
132 } else {
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000133 canvas->drawRRect(fRRects[rrectIdx], paint);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000134 }
135 ++curRRect;
136 canvas->restore();
137 }
138 }
139 }
140
141 void setUpRRects() {
skia.committer@gmail.com7a03d862012-12-18 02:03:03 +0000142 // each RRect must fit in a 0x0 -> (kTileX-2)x(kTileY-2) block. These will be tiled across
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000143 // the screen in kTileX x kTileY tiles. The extra empty pixels on each side are for AA.
144
145 // simple cases
146 fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2));
147 fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2));
148 fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10);
commit-bot@chromium.orgc2f78242014-02-19 15:18:05 +0000149 fRRects[3].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 5);
150 // small circular corners are an interesting test case for gpu clipping
151 fRRects[4].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 1, 1);
152 fRRects[5].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.5f, 0.5f);
153 fRRects[6].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.2f, 0.2f);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000154
155 // The first complex case needs special handling since it is a square
156 fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2), gRadii[0]);
mike@reedtribe.orgf6100c82012-12-24 13:56:17 +0000157 for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000158 fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTileY-2), gRadii[i]);
159 }
160 }
161
162private:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000163 Type fType;
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000164
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000165 static const int kImageWidth = 640;
166 static const int kImageHeight = 480;
167
168 static const int kTileX = 80;
169 static const int kTileY = 40;
170
commit-bot@chromium.orgc2f78242014-02-19 15:18:05 +0000171 static const int kNumSimpleCases = 7;
commit-bot@chromium.orgcb3672e2014-02-21 22:41:56 +0000172 static const int kNumComplexCases = 23;
robertphillips@google.com5683d422012-12-17 21:58:02 +0000173 static const SkVector gRadii[kNumComplexCases][4];
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000174
175 static const int kNumRRects = kNumSimpleCases + kNumComplexCases;
176 SkRRect fRRects[kNumRRects];
177
178 typedef GM INHERITED;
179};
180
181// Radii for the various test cases. Order is UL, UR, LR, LL
182const SkVector RRectGM::gRadii[kNumComplexCases][4] = {
183 // a circle
184 { { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY } },
185
186 // odd ball cases
187 { { 8, 8 }, { 32, 32 }, { 8, 8 }, { 32, 32 } },
188 { { 16, 8 }, { 8, 16 }, { 16, 8 }, { 8, 16 } },
189 { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 32, 32 } },
190
191 // UL
192 { { 30, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
193 { { 30, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
194 { { 15, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
195
196 // UR
197 { { 0, 0 }, { 30, 30 }, { 0, 0 }, { 0, 0 } },
198 { { 0, 0 }, { 30, 15 }, { 0, 0 }, { 0, 0 } },
199 { { 0, 0 }, { 15, 30 }, { 0, 0 }, { 0, 0 } },
200
201 // LR
202 { { 0, 0 }, { 0, 0 }, { 30, 30 }, { 0, 0 } },
203 { { 0, 0 }, { 0, 0 }, { 30, 15 }, { 0, 0 } },
204 { { 0, 0 }, { 0, 0 }, { 15, 30 }, { 0, 0 } },
205
206 // LL
207 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 30 } },
208 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 15 } },
209 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 30 } },
210
211 // over-sized radii
212 { { 0, 0 }, { 100, 400 }, { 0, 0 }, { 0, 0 } },
213 { { 0, 0 }, { 400, 400 }, { 0, 0 }, { 0, 0 } },
214 { { 400, 400 }, { 400, 400 }, { 400, 400 }, { 400, 400 } },
commit-bot@chromium.orgcb3672e2014-02-21 22:41:56 +0000215
216 // circular corner tabs
217 { { 0, 0 }, { 20, 20 }, { 20, 20 }, { 0, 0 } },
218 { { 20, 20 }, { 20, 20 }, { 0, 0 }, { 0, 0 } },
219 { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 20, 20 } },
220 { { 20, 20 }, { 0, 0 }, { 0, 0 }, { 20, 20 } },
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000221};
222
223///////////////////////////////////////////////////////////////////////////////
224
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000225DEF_GM( return new RRectGM(RRectGM::kAA_Draw_Type); )
226DEF_GM( return new RRectGM(RRectGM::kBW_Draw_Type); )
227DEF_GM( return new RRectGM(RRectGM::kAA_Clip_Type); )
228DEF_GM( return new RRectGM(RRectGM::kBW_Clip_Type); )
bsalomon@google.com707bd602014-03-04 16:52:20 +0000229#if SK_SUPPORT_GPU
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000230DEF_GM( return new RRectGM(RRectGM::kEffect_Type); )
bsalomon@google.com707bd602014-03-04 16:52:20 +0000231#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000232
233}