blob: be469290457d844f42343fb22bad1135dd909d4a [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:
mtklein36352bf2015-03-25 18:17:31 -070035 SkString onShortName() 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
mtklein36352bf2015-03-25 18:17:31 -070057 SkISize onISize() override { return SkISize::Make(kImageWidth, kImageHeight); }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000058
mtklein36352bf2015-03-25 18:17:31 -070059 void onDraw(SkCanvas* canvas) override {
bsalomonb62da802015-01-31 07:51:14 -080060 GrContext* context = NULL;
bsalomon@google.com707bd602014-03-04 16:52:20 +000061#if SK_SUPPORT_GPU
reed@google.com9c135db2014-03-12 18:28:35 +000062 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
bsalomonb62da802015-01-31 07:51:14 -080063 context = rt ? rt->getContext() : NULL;
64#endif
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000065 if (kEffect_Type == fType && NULL == context) {
bsalomonb62da802015-01-31 07:51:14 -080066 this->drawGpuOnlyMessage(canvas);
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000067 return;
68 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000069
70 SkPaint paint;
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000071 if (kAA_Draw_Type == fType) {
72 paint.setAntiAlias(true);
73 }
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +000074
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000075 static const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX),
76 SkIntToScalar(kTileY));
77#ifdef SK_DEBUG
78 static const SkRect kMaxImageBound = SkRect::MakeWH(SkIntToScalar(kImageWidth),
79 SkIntToScalar(kImageHeight));
80#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000081
bsalomon@google.comb0ba39d2014-03-10 19:51:46 +000082#if SK_SUPPORT_GPU
joshualittb0a8a372014-09-23 09:50:21 -070083 int lastEdgeType = (kEffect_Type == fType) ? kLast_GrProcessorEdgeType: 0;
bsalomon@google.comb0ba39d2014-03-10 19:51:46 +000084#else
85 int lastEdgeType = 0;
86#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000087
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000088 int y = 1;
bsalomon@google.comb0ba39d2014-03-10 19:51:46 +000089 for (int et = 0; et <= lastEdgeType; ++et) {
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000090 int x = 1;
91 for (int curRRect = 0; curRRect < kNumRRects; ++curRRect) {
92 bool drew = true;
93#ifdef SK_DEBUG
94 SkASSERT(kMaxTileBound.contains(fRRects[curRRect].getBounds()));
95 SkRect imageSpaceBounds = fRRects[curRRect].getBounds();
96 imageSpaceBounds.offset(SkIntToScalar(x), SkIntToScalar(y));
97 SkASSERT(kMaxImageBound.contains(imageSpaceBounds));
98#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000099 canvas->save();
100 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000101 if (kEffect_Type == fType) {
bsalomon@google.com707bd602014-03-04 16:52:20 +0000102#if SK_SUPPORT_GPU
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000103 GrTestTarget tt;
104 context->getTestTarget(&tt);
105 if (NULL == tt.target()) {
106 SkDEBUGFAIL("Couldn't get Gr test target.");
107 return;
108 }
egdaniel8dd688b2015-01-22 10:16:09 -0800109 GrPipelineBuilder pipelineBuilder;
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000110
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000111 SkRRect rrect = fRRects[curRRect];
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000112 rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
joshualittb0a8a372014-09-23 09:50:21 -0700113 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
114 SkAutoTUnref<GrFragmentProcessor> fp(GrRRectEffect::Create(edgeType,
115 rrect));
116 if (fp) {
egdaniel8dd688b2015-01-22 10:16:09 -0800117 pipelineBuilder.addCoverageProcessor(fp);
118 pipelineBuilder.setRenderTarget(rt);
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000119
120 SkRect bounds = rrect.getBounds();
121 bounds.outset(2.f, 2.f);
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000122
joshualitt44701df2015-02-23 14:44:57 -0800123 tt.target()->drawSimpleRect(&pipelineBuilder,
124 0xff000000,
125 SkMatrix::I(),
joshualitt8059eb92014-12-29 15:10:07 -0800126 bounds);
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000127 } else {
128 drew = false;
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000129 }
bsalomon@google.com707bd602014-03-04 16:52:20 +0000130#endif
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000131 } else if (kBW_Clip_Type == fType || kAA_Clip_Type == fType) {
132 bool aaClip = (kAA_Clip_Type == fType);
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000133 canvas->clipRRect(fRRects[curRRect], SkRegion::kReplace_Op, aaClip);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000134 canvas->drawRect(kMaxTileBound, paint);
135 } else {
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000136 canvas->drawRRect(fRRects[curRRect], paint);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000137 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000138 canvas->restore();
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000139 if (drew) {
140 x = x + kTileX;
141 if (x > kImageWidth) {
142 x = 1;
143 y += kTileY;
144 }
145 }
146 }
147 if (x != 1) {
148 y += kTileY;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000149 }
150 }
151 }
152
153 void setUpRRects() {
skia.committer@gmail.com7a03d862012-12-18 02:03:03 +0000154 // 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 +0000155 // the screen in kTileX x kTileY tiles. The extra empty pixels on each side are for AA.
156
157 // simple cases
158 fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2));
159 fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2));
160 fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10);
commit-bot@chromium.orgc2f78242014-02-19 15:18:05 +0000161 fRRects[3].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 5);
162 // small circular corners are an interesting test case for gpu clipping
163 fRRects[4].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 1, 1);
164 fRRects[5].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.5f, 0.5f);
165 fRRects[6].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.2f, 0.2f);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000166
167 // The first complex case needs special handling since it is a square
168 fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2), gRadii[0]);
mike@reedtribe.orgf6100c82012-12-24 13:56:17 +0000169 for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000170 fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTileY-2), gRadii[i]);
171 }
172 }
173
174private:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000175 Type fType;
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000176
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000177 static const int kImageWidth = 640;
178 static const int kImageHeight = 480;
179
180 static const int kTileX = 80;
181 static const int kTileY = 40;
182
commit-bot@chromium.orgc2f78242014-02-19 15:18:05 +0000183 static const int kNumSimpleCases = 7;
commit-bot@chromium.org04eff722014-03-24 14:53:09 +0000184 static const int kNumComplexCases = 35;
robertphillips@google.com5683d422012-12-17 21:58:02 +0000185 static const SkVector gRadii[kNumComplexCases][4];
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000186
187 static const int kNumRRects = kNumSimpleCases + kNumComplexCases;
188 SkRRect fRRects[kNumRRects];
189
190 typedef GM INHERITED;
191};
192
193// Radii for the various test cases. Order is UL, UR, LR, LL
194const SkVector RRectGM::gRadii[kNumComplexCases][4] = {
195 // a circle
196 { { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY } },
197
198 // odd ball cases
199 { { 8, 8 }, { 32, 32 }, { 8, 8 }, { 32, 32 } },
200 { { 16, 8 }, { 8, 16 }, { 16, 8 }, { 8, 16 } },
201 { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 32, 32 } },
202
203 // UL
204 { { 30, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
205 { { 30, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
206 { { 15, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
207
208 // UR
209 { { 0, 0 }, { 30, 30 }, { 0, 0 }, { 0, 0 } },
210 { { 0, 0 }, { 30, 15 }, { 0, 0 }, { 0, 0 } },
211 { { 0, 0 }, { 15, 30 }, { 0, 0 }, { 0, 0 } },
212
213 // LR
214 { { 0, 0 }, { 0, 0 }, { 30, 30 }, { 0, 0 } },
215 { { 0, 0 }, { 0, 0 }, { 30, 15 }, { 0, 0 } },
216 { { 0, 0 }, { 0, 0 }, { 15, 30 }, { 0, 0 } },
217
218 // LL
219 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 30 } },
220 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 15 } },
221 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 30 } },
222
223 // over-sized radii
224 { { 0, 0 }, { 100, 400 }, { 0, 0 }, { 0, 0 } },
225 { { 0, 0 }, { 400, 400 }, { 0, 0 }, { 0, 0 } },
226 { { 400, 400 }, { 400, 400 }, { 400, 400 }, { 400, 400 } },
commit-bot@chromium.orgcb3672e2014-02-21 22:41:56 +0000227
228 // circular corner tabs
229 { { 0, 0 }, { 20, 20 }, { 20, 20 }, { 0, 0 } },
230 { { 20, 20 }, { 20, 20 }, { 0, 0 }, { 0, 0 } },
231 { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 20, 20 } },
232 { { 20, 20 }, { 0, 0 }, { 0, 0 }, { 20, 20 } },
commit-bot@chromium.orgc5c748c2014-03-11 15:54:51 +0000233
commit-bot@chromium.org04eff722014-03-24 14:53:09 +0000234 // small radius circular corner tabs
235 { { 0, 0 }, { 0.2f, 0.2f }, { 0.2f, 0.2f }, { 0, 0 } },
236 { { 0.3f, 0.3f }, { 0.3f, .3f }, { 0, 0 }, { 0, 0 } },
237
commit-bot@chromium.orgc5c748c2014-03-11 15:54:51 +0000238 // single circular corner cases
239 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 15 } },
240 { { 0, 0 }, { 0, 0 }, { 15, 15 }, { 0, 0 } },
241 { { 0, 0 }, { 15, 15 }, { 0, 0 }, { 0, 0 } },
242 { { 15, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
commit-bot@chromium.orgfa5edbe2014-03-13 18:01:05 +0000243
244 // nine patch elliptical
245 { { 5, 7 }, { 8, 7 }, { 8, 12 }, { 5, 12 } },
246 { { 0, 7 }, { 8, 7 }, { 8, 12 }, { 0, 12 } },
commit-bot@chromium.org04eff722014-03-24 14:53:09 +0000247
248 // nine patch elliptical, small radii
249 { { 0.4f, 7 }, { 8, 7 }, { 8, 12 }, { 0.4f, 12 } },
250 { { 0.4f, 0.4f }, { 8, 0.4f }, { 8, 12 }, { 0.4f, 12 } },
251 { { 20, 0.4f }, { 18, 0.4f }, { 18, 0.4f }, { 20, 0.4f } },
252 { { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f } },
253
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000254};
255
256///////////////////////////////////////////////////////////////////////////////
257
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000258DEF_GM( return new RRectGM(RRectGM::kAA_Draw_Type); )
259DEF_GM( return new RRectGM(RRectGM::kBW_Draw_Type); )
260DEF_GM( return new RRectGM(RRectGM::kAA_Clip_Type); )
261DEF_GM( return new RRectGM(RRectGM::kBW_Clip_Type); )
bsalomon@google.com707bd602014-03-04 16:52:20 +0000262#if SK_SUPPORT_GPU
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000263DEF_GM( return new RRectGM(RRectGM::kEffect_Type); )
bsalomon@google.com707bd602014-03-04 16:52:20 +0000264#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000265
266}