blob: e698e6bd34a75d16b4b56276afe03d133e751838 [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
joshualitt04194f32016-01-13 10:08:27 -080010#include "GrContext.h"
robertphillips391395d2016-03-02 09:26:36 -080011#include "GrDrawContextPriv.h"
joshualitt04194f32016-01-13 10:08:27 -080012#include "batches/GrDrawBatch.h"
13#include "batches/GrRectBatchFactory.h"
bsalomon@google.com707bd602014-03-04 16:52:20 +000014#include "effects/GrRRectEffect.h"
15#endif
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000016#include "SkDevice.h"
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000017#include "SkRRect.h"
18
19namespace skiagm {
20
21///////////////////////////////////////////////////////////////////////////////
22
23class RRectGM : public GM {
24public:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000025 enum Type {
26 kBW_Draw_Type,
27 kAA_Draw_Type,
28 kBW_Clip_Type,
29 kAA_Clip_Type,
30 kEffect_Type,
31 };
herbb10fe492016-01-08 13:48:43 -080032 RRectGM(Type type) : fType(type) { }
33
34protected:
35
36 void onOnceBeforeDraw() override {
caryclark65cdba62015-06-15 06:51:08 -070037 this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000038 this->setUpRRects();
39 }
40
mtklein36352bf2015-03-25 18:17:31 -070041 SkString onShortName() override {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000042 SkString name("rrect");
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000043 switch (fType) {
44 case kBW_Draw_Type:
45 name.append("_draw_bw");
46 break;
47 case kAA_Draw_Type:
48 name.append("_draw_aa");
49 break;
50 case kBW_Clip_Type:
51 name.append("_clip_bw");
52 break;
53 case kAA_Clip_Type:
54 name.append("_clip_aa");
55 break;
56 case kEffect_Type:
57 name.append("_effect");
58 break;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000059 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000060 return name;
61 }
62
mtklein36352bf2015-03-25 18:17:31 -070063 SkISize onISize() override { return SkISize::Make(kImageWidth, kImageHeight); }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000064
mtklein36352bf2015-03-25 18:17:31 -070065 void onDraw(SkCanvas* canvas) override {
halcanary96fcdcc2015-08-27 07:41:13 -070066 GrContext* context = nullptr;
bsalomon@google.com707bd602014-03-04 16:52:20 +000067#if SK_SUPPORT_GPU
reed@google.com9c135db2014-03-12 18:28:35 +000068 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
halcanary96fcdcc2015-08-27 07:41:13 -070069 context = rt ? rt->getContext() : nullptr;
joshualittc2eff2a2016-01-13 11:23:26 -080070 SkAutoTUnref<GrDrawContext> drawContext;
71 if (kEffect_Type == fType) {
72 if (!context) {
73 skiagm::GM::DrawGpuOnlyMessage(canvas);
74 return;
75 }
76
77 drawContext.reset(context->drawContext(rt));
78 if (!drawContext) {
79 return;
80 }
joshualitt04194f32016-01-13 10:08:27 -080081 }
bsalomonb62da802015-01-31 07:51:14 -080082#endif
halcanary96fcdcc2015-08-27 07:41:13 -070083 if (kEffect_Type == fType && nullptr == context) {
halcanary2a243382015-09-09 08:16:41 -070084 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000085 return;
86 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000087
88 SkPaint paint;
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000089 if (kAA_Draw_Type == fType) {
90 paint.setAntiAlias(true);
91 }
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +000092
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000093 static const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX),
94 SkIntToScalar(kTileY));
95#ifdef SK_DEBUG
96 static const SkRect kMaxImageBound = SkRect::MakeWH(SkIntToScalar(kImageWidth),
97 SkIntToScalar(kImageHeight));
98#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000099
bsalomon@google.comb0ba39d2014-03-10 19:51:46 +0000100#if SK_SUPPORT_GPU
joshualittb0a8a372014-09-23 09:50:21 -0700101 int lastEdgeType = (kEffect_Type == fType) ? kLast_GrProcessorEdgeType: 0;
bsalomon@google.comb0ba39d2014-03-10 19:51:46 +0000102#else
103 int lastEdgeType = 0;
104#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000105
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000106 int y = 1;
bsalomon@google.comb0ba39d2014-03-10 19:51:46 +0000107 for (int et = 0; et <= lastEdgeType; ++et) {
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000108 int x = 1;
109 for (int curRRect = 0; curRRect < kNumRRects; ++curRRect) {
110 bool drew = true;
111#ifdef SK_DEBUG
112 SkASSERT(kMaxTileBound.contains(fRRects[curRRect].getBounds()));
113 SkRect imageSpaceBounds = fRRects[curRRect].getBounds();
114 imageSpaceBounds.offset(SkIntToScalar(x), SkIntToScalar(y));
115 SkASSERT(kMaxImageBound.contains(imageSpaceBounds));
116#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000117 canvas->save();
118 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000119 if (kEffect_Type == fType) {
bsalomon@google.com707bd602014-03-04 16:52:20 +0000120#if SK_SUPPORT_GPU
egdaniel8dd688b2015-01-22 10:16:09 -0800121 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800122 pipelineBuilder.setXPFactory(
123 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000124
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000125 SkRRect rrect = fRRects[curRRect];
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000126 rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
joshualittb0a8a372014-09-23 09:50:21 -0700127 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
128 SkAutoTUnref<GrFragmentProcessor> fp(GrRRectEffect::Create(edgeType,
129 rrect));
130 if (fp) {
bsalomonac856c92015-08-27 06:30:17 -0700131 pipelineBuilder.addCoverageFragmentProcessor(fp);
egdaniel8dd688b2015-01-22 10:16:09 -0800132 pipelineBuilder.setRenderTarget(rt);
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000133
134 SkRect bounds = rrect.getBounds();
135 bounds.outset(2.f, 2.f);
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000136
joshualitt04194f32016-01-13 10:08:27 -0800137 SkAutoTUnref<GrDrawBatch> batch(
138 GrRectBatchFactory::CreateNonAAFill(0xff000000, SkMatrix::I(),
139 bounds, nullptr, nullptr));
robertphillips391395d2016-03-02 09:26:36 -0800140 drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder,
141 batch);
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000142 } else {
143 drew = false;
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000144 }
bsalomon@google.com707bd602014-03-04 16:52:20 +0000145#endif
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000146 } else if (kBW_Clip_Type == fType || kAA_Clip_Type == fType) {
147 bool aaClip = (kAA_Clip_Type == fType);
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000148 canvas->clipRRect(fRRects[curRRect], SkRegion::kReplace_Op, aaClip);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000149 canvas->drawRect(kMaxTileBound, paint);
150 } else {
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000151 canvas->drawRRect(fRRects[curRRect], paint);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000152 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000153 canvas->restore();
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000154 if (drew) {
155 x = x + kTileX;
156 if (x > kImageWidth) {
157 x = 1;
158 y += kTileY;
159 }
160 }
161 }
162 if (x != 1) {
163 y += kTileY;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000164 }
165 }
166 }
167
168 void setUpRRects() {
skia.committer@gmail.com7a03d862012-12-18 02:03:03 +0000169 // 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 +0000170 // the screen in kTileX x kTileY tiles. The extra empty pixels on each side are for AA.
171
172 // simple cases
173 fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2));
174 fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2));
175 fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10);
commit-bot@chromium.orgc2f78242014-02-19 15:18:05 +0000176 fRRects[3].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 5);
177 // small circular corners are an interesting test case for gpu clipping
178 fRRects[4].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 1, 1);
179 fRRects[5].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.5f, 0.5f);
180 fRRects[6].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.2f, 0.2f);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000181
182 // The first complex case needs special handling since it is a square
183 fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2), gRadii[0]);
mike@reedtribe.orgf6100c82012-12-24 13:56:17 +0000184 for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000185 fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTileY-2), gRadii[i]);
186 }
187 }
188
189private:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000190 Type fType;
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000191
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000192 static const int kImageWidth = 640;
193 static const int kImageHeight = 480;
194
195 static const int kTileX = 80;
196 static const int kTileY = 40;
197
commit-bot@chromium.orgc2f78242014-02-19 15:18:05 +0000198 static const int kNumSimpleCases = 7;
commit-bot@chromium.org04eff722014-03-24 14:53:09 +0000199 static const int kNumComplexCases = 35;
robertphillips@google.com5683d422012-12-17 21:58:02 +0000200 static const SkVector gRadii[kNumComplexCases][4];
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000201
202 static const int kNumRRects = kNumSimpleCases + kNumComplexCases;
203 SkRRect fRRects[kNumRRects];
204
205 typedef GM INHERITED;
206};
207
208// Radii for the various test cases. Order is UL, UR, LR, LL
209const SkVector RRectGM::gRadii[kNumComplexCases][4] = {
210 // a circle
211 { { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY } },
212
213 // odd ball cases
214 { { 8, 8 }, { 32, 32 }, { 8, 8 }, { 32, 32 } },
215 { { 16, 8 }, { 8, 16 }, { 16, 8 }, { 8, 16 } },
216 { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 32, 32 } },
217
218 // UL
219 { { 30, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
220 { { 30, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
221 { { 15, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
222
223 // UR
224 { { 0, 0 }, { 30, 30 }, { 0, 0 }, { 0, 0 } },
225 { { 0, 0 }, { 30, 15 }, { 0, 0 }, { 0, 0 } },
226 { { 0, 0 }, { 15, 30 }, { 0, 0 }, { 0, 0 } },
227
228 // LR
229 { { 0, 0 }, { 0, 0 }, { 30, 30 }, { 0, 0 } },
230 { { 0, 0 }, { 0, 0 }, { 30, 15 }, { 0, 0 } },
231 { { 0, 0 }, { 0, 0 }, { 15, 30 }, { 0, 0 } },
232
233 // LL
234 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 30 } },
235 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 15 } },
236 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 30 } },
237
238 // over-sized radii
239 { { 0, 0 }, { 100, 400 }, { 0, 0 }, { 0, 0 } },
240 { { 0, 0 }, { 400, 400 }, { 0, 0 }, { 0, 0 } },
241 { { 400, 400 }, { 400, 400 }, { 400, 400 }, { 400, 400 } },
commit-bot@chromium.orgcb3672e2014-02-21 22:41:56 +0000242
243 // circular corner tabs
244 { { 0, 0 }, { 20, 20 }, { 20, 20 }, { 0, 0 } },
245 { { 20, 20 }, { 20, 20 }, { 0, 0 }, { 0, 0 } },
246 { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 20, 20 } },
247 { { 20, 20 }, { 0, 0 }, { 0, 0 }, { 20, 20 } },
commit-bot@chromium.orgc5c748c2014-03-11 15:54:51 +0000248
commit-bot@chromium.org04eff722014-03-24 14:53:09 +0000249 // small radius circular corner tabs
250 { { 0, 0 }, { 0.2f, 0.2f }, { 0.2f, 0.2f }, { 0, 0 } },
251 { { 0.3f, 0.3f }, { 0.3f, .3f }, { 0, 0 }, { 0, 0 } },
252
commit-bot@chromium.orgc5c748c2014-03-11 15:54:51 +0000253 // single circular corner cases
254 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 15 } },
255 { { 0, 0 }, { 0, 0 }, { 15, 15 }, { 0, 0 } },
256 { { 0, 0 }, { 15, 15 }, { 0, 0 }, { 0, 0 } },
257 { { 15, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
commit-bot@chromium.orgfa5edbe2014-03-13 18:01:05 +0000258
259 // nine patch elliptical
260 { { 5, 7 }, { 8, 7 }, { 8, 12 }, { 5, 12 } },
261 { { 0, 7 }, { 8, 7 }, { 8, 12 }, { 0, 12 } },
commit-bot@chromium.org04eff722014-03-24 14:53:09 +0000262
263 // nine patch elliptical, small radii
264 { { 0.4f, 7 }, { 8, 7 }, { 8, 12 }, { 0.4f, 12 } },
265 { { 0.4f, 0.4f }, { 8, 0.4f }, { 8, 12 }, { 0.4f, 12 } },
266 { { 20, 0.4f }, { 18, 0.4f }, { 18, 0.4f }, { 20, 0.4f } },
267 { { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f } },
268
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000269};
270
271///////////////////////////////////////////////////////////////////////////////
272
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000273DEF_GM( return new RRectGM(RRectGM::kAA_Draw_Type); )
274DEF_GM( return new RRectGM(RRectGM::kBW_Draw_Type); )
275DEF_GM( return new RRectGM(RRectGM::kAA_Clip_Type); )
276DEF_GM( return new RRectGM(RRectGM::kBW_Clip_Type); )
bsalomon@google.com707bd602014-03-04 16:52:20 +0000277#if SK_SUPPORT_GPU
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000278DEF_GM( return new RRectGM(RRectGM::kEffect_Type); )
bsalomon@google.com707bd602014-03-04 16:52:20 +0000279#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000280
281}