blob: 4a1e29762bc18114d140f5f42b1d2890d602f9aa [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"
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +00009#include "GrTest.h"
10#include "SkDevice.h"
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000011#include "SkRRect.h"
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000012#include "effects/GrRRectEffect.h"
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000013
14namespace skiagm {
15
16///////////////////////////////////////////////////////////////////////////////
17
18class RRectGM : public GM {
19public:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000020 enum Type {
21 kBW_Draw_Type,
22 kAA_Draw_Type,
23 kBW_Clip_Type,
24 kAA_Clip_Type,
25 kEffect_Type,
26 };
27 RRectGM(Type type) : fType(type) {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000028 this->setBGColor(0xFFDDDDDD);
29 this->setUpRRects();
30 }
31
32protected:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000033 SkString onShortName() SK_OVERRIDE {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000034 SkString name("rrect");
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000035 switch (fType) {
36 case kBW_Draw_Type:
37 name.append("_draw_bw");
38 break;
39 case kAA_Draw_Type:
40 name.append("_draw_aa");
41 break;
42 case kBW_Clip_Type:
43 name.append("_clip_bw");
44 break;
45 case kAA_Clip_Type:
46 name.append("_clip_aa");
47 break;
48 case kEffect_Type:
49 name.append("_effect");
50 break;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000051 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000052 return name;
53 }
54
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000055 virtual SkISize onISize() SK_OVERRIDE { return make_isize(kImageWidth, kImageHeight); }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000056
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000057 virtual uint32_t onGetFlags() const SK_OVERRIDE {
58 if (kEffect_Type == fType) {
59 return kGPUOnly_Flag;
60 } else {
61 return 0;
62 }
63 }
64
65 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
66 SkBaseDevice* device = canvas->getTopDevice();
67 GrContext* context = NULL;
68 GrRenderTarget* rt = device->accessRenderTarget();
69 if (NULL != rt) {
70 context = rt->getContext();
71 }
72 if (kEffect_Type == fType && NULL == context) {
73 return;
74 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000075
76 SkPaint paint;
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000077 if (kAA_Draw_Type == fType) {
78 paint.setAntiAlias(true);
79 }
80
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000081 static const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX), SkIntToScalar(kTileY));
82
83 int curRRect = 0;
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000084 int numRRects = kNumRRects;
85 if (kEffect_Type == fType) {
86 numRRects *= GrRRectEffect::kEdgeTypeCnt;
87 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000088 for (int y = 1; y < kImageHeight; y += kTileY) {
89 for (int x = 1; x < kImageWidth; x += kTileX) {
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000090 if (curRRect >= numRRects) {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000091 break;
92 }
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000093 int rrectIdx = curRRect % kNumRRects;
94 SkASSERT(kMaxTileBound.contains(fRRects[rrectIdx].getBounds()));
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000095
96 canvas->save();
97 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000098 if (kEffect_Type == fType) {
99 GrTestTarget tt;
100 context->getTestTarget(&tt);
101 if (NULL == tt.target()) {
102 SkDEBUGFAIL("Couldn't get Gr test target.");
103 return;
104 }
105 GrDrawState* drawState = tt.target()->drawState();
106
107 SkRRect rrect = fRRects[rrectIdx];
108 rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
109 GrRRectEffect::EdgeType edgeType = (GrRRectEffect::EdgeType)
110 (curRRect / kNumRRects);
111 SkAutoTUnref<GrEffectRef> effect(GrRRectEffect::Create(edgeType, rrect));
112 if (effect) {
113 drawState->addCoverageEffect(effect);
114 drawState->setIdentityViewMatrix();
115 drawState->setRenderTarget(rt);
116 drawState->setColor(0xff000000);
117
118 SkRect bounds = rrect.getBounds();
119 bounds.outset(2.f, 2.f);
120
121 tt.target()->drawSimpleRect(bounds);
122 }
123 } else if (kBW_Clip_Type == fType || kAA_Clip_Type == fType) {
124 bool aaClip = (kAA_Clip_Type == fType);
125 canvas->clipRRect(fRRects[rrectIdx], SkRegion::kReplace_Op, aaClip);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000126 canvas->drawRect(kMaxTileBound, paint);
127 } else {
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000128 canvas->drawRRect(fRRects[rrectIdx], paint);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000129 }
130 ++curRRect;
131 canvas->restore();
132 }
133 }
134 }
135
136 void setUpRRects() {
skia.committer@gmail.com7a03d862012-12-18 02:03:03 +0000137 // 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 +0000138 // the screen in kTileX x kTileY tiles. The extra empty pixels on each side are for AA.
139
140 // simple cases
141 fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2));
142 fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2));
143 fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10);
commit-bot@chromium.orgc2f78242014-02-19 15:18:05 +0000144 fRRects[3].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 5);
145 // small circular corners are an interesting test case for gpu clipping
146 fRRects[4].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 1, 1);
147 fRRects[5].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.5f, 0.5f);
148 fRRects[6].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.2f, 0.2f);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000149
150 // The first complex case needs special handling since it is a square
151 fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2), gRadii[0]);
mike@reedtribe.orgf6100c82012-12-24 13:56:17 +0000152 for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000153 fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTileY-2), gRadii[i]);
154 }
155 }
156
157private:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000158 Type fType;
159
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000160 static const int kImageWidth = 640;
161 static const int kImageHeight = 480;
162
163 static const int kTileX = 80;
164 static const int kTileY = 40;
165
commit-bot@chromium.orgc2f78242014-02-19 15:18:05 +0000166 static const int kNumSimpleCases = 7;
commit-bot@chromium.orgcb3672e2014-02-21 22:41:56 +0000167 static const int kNumComplexCases = 23;
robertphillips@google.com5683d422012-12-17 21:58:02 +0000168 static const SkVector gRadii[kNumComplexCases][4];
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000169
170 static const int kNumRRects = kNumSimpleCases + kNumComplexCases;
171 SkRRect fRRects[kNumRRects];
172
173 typedef GM INHERITED;
174};
175
176// Radii for the various test cases. Order is UL, UR, LR, LL
177const SkVector RRectGM::gRadii[kNumComplexCases][4] = {
178 // a circle
179 { { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY } },
180
181 // odd ball cases
182 { { 8, 8 }, { 32, 32 }, { 8, 8 }, { 32, 32 } },
183 { { 16, 8 }, { 8, 16 }, { 16, 8 }, { 8, 16 } },
184 { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 32, 32 } },
185
186 // UL
187 { { 30, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
188 { { 30, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
189 { { 15, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
190
191 // UR
192 { { 0, 0 }, { 30, 30 }, { 0, 0 }, { 0, 0 } },
193 { { 0, 0 }, { 30, 15 }, { 0, 0 }, { 0, 0 } },
194 { { 0, 0 }, { 15, 30 }, { 0, 0 }, { 0, 0 } },
195
196 // LR
197 { { 0, 0 }, { 0, 0 }, { 30, 30 }, { 0, 0 } },
198 { { 0, 0 }, { 0, 0 }, { 30, 15 }, { 0, 0 } },
199 { { 0, 0 }, { 0, 0 }, { 15, 30 }, { 0, 0 } },
200
201 // LL
202 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 30 } },
203 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 15 } },
204 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 30 } },
205
206 // over-sized radii
207 { { 0, 0 }, { 100, 400 }, { 0, 0 }, { 0, 0 } },
208 { { 0, 0 }, { 400, 400 }, { 0, 0 }, { 0, 0 } },
209 { { 400, 400 }, { 400, 400 }, { 400, 400 }, { 400, 400 } },
commit-bot@chromium.orgcb3672e2014-02-21 22:41:56 +0000210
211 // circular corner tabs
212 { { 0, 0 }, { 20, 20 }, { 20, 20 }, { 0, 0 } },
213 { { 20, 20 }, { 20, 20 }, { 0, 0 }, { 0, 0 } },
214 { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 20, 20 } },
215 { { 20, 20 }, { 0, 0 }, { 0, 0 }, { 20, 20 } },
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000216};
217
218///////////////////////////////////////////////////////////////////////////////
219
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000220DEF_GM( return new RRectGM(RRectGM::kAA_Draw_Type); )
221DEF_GM( return new RRectGM(RRectGM::kBW_Draw_Type); )
222DEF_GM( return new RRectGM(RRectGM::kAA_Clip_Type); )
223DEF_GM( return new RRectGM(RRectGM::kBW_Clip_Type); )
224DEF_GM( return new RRectGM(RRectGM::kEffect_Type); )
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000225
226}