blob: 63b6dbc4275cf9fcae9cece0150952e8950de94a [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
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000016#include "SkRRect.h"
17
18namespace skiagm {
19
20///////////////////////////////////////////////////////////////////////////////
21
22class RRectGM : public GM {
23public:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000024 enum Type {
25 kBW_Draw_Type,
26 kAA_Draw_Type,
27 kBW_Clip_Type,
28 kAA_Clip_Type,
29 kEffect_Type,
30 };
herbb10fe492016-01-08 13:48:43 -080031 RRectGM(Type type) : fType(type) { }
32
33protected:
34
35 void onOnceBeforeDraw() override {
caryclark65cdba62015-06-15 06:51:08 -070036 this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000037 this->setUpRRects();
38 }
39
mtklein36352bf2015-03-25 18:17:31 -070040 SkString onShortName() override {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000041 SkString name("rrect");
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000042 switch (fType) {
43 case kBW_Draw_Type:
44 name.append("_draw_bw");
45 break;
46 case kAA_Draw_Type:
47 name.append("_draw_aa");
48 break;
49 case kBW_Clip_Type:
50 name.append("_clip_bw");
51 break;
52 case kAA_Clip_Type:
53 name.append("_clip_aa");
54 break;
55 case kEffect_Type:
56 name.append("_effect");
57 break;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000058 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000059 return name;
60 }
61
mtklein36352bf2015-03-25 18:17:31 -070062 SkISize onISize() override { return SkISize::Make(kImageWidth, kImageHeight); }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000063
mtklein36352bf2015-03-25 18:17:31 -070064 void onDraw(SkCanvas* canvas) override {
robertphillips175dd9b2016-04-28 14:32:04 -070065 GrDrawContext* drawContext = canvas->internal_private_accessTopLayerDrawContext();
66 if (kEffect_Type == fType && !drawContext) {
halcanary2a243382015-09-09 08:16:41 -070067 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000068 return;
69 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000070
71 SkPaint paint;
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000072 if (kAA_Draw_Type == fType) {
73 paint.setAntiAlias(true);
74 }
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +000075
mtkleindbfd7ab2016-09-01 11:24:54 -070076 const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX),
77 SkIntToScalar(kTileY));
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000078#ifdef SK_DEBUG
mtkleindbfd7ab2016-09-01 11:24:54 -070079 const SkRect kMaxImageBound = SkRect::MakeWH(SkIntToScalar(kImageWidth),
80 SkIntToScalar(kImageHeight));
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000081#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000082
bsalomon@google.comb0ba39d2014-03-10 19:51:46 +000083#if SK_SUPPORT_GPU
joshualittb0a8a372014-09-23 09:50:21 -070084 int lastEdgeType = (kEffect_Type == fType) ? kLast_GrProcessorEdgeType: 0;
bsalomon@google.comb0ba39d2014-03-10 19:51:46 +000085#else
86 int lastEdgeType = 0;
87#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000088
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000089 int y = 1;
bsalomon@google.comb0ba39d2014-03-10 19:51:46 +000090 for (int et = 0; et <= lastEdgeType; ++et) {
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000091 int x = 1;
92 for (int curRRect = 0; curRRect < kNumRRects; ++curRRect) {
93 bool drew = true;
94#ifdef SK_DEBUG
95 SkASSERT(kMaxTileBound.contains(fRRects[curRRect].getBounds()));
96 SkRect imageSpaceBounds = fRRects[curRRect].getBounds();
97 imageSpaceBounds.offset(SkIntToScalar(x), SkIntToScalar(y));
98 SkASSERT(kMaxImageBound.contains(imageSpaceBounds));
99#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000100 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
robertphillips28a838e2016-06-23 14:07:00 -0700104 GrPaint grPaint;
105 grPaint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000106
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000107 SkRRect rrect = fRRects[curRRect];
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000108 rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
joshualittb0a8a372014-09-23 09:50:21 -0700109 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
bungeman06ca8ec2016-06-09 08:01:03 -0700110 sk_sp<GrFragmentProcessor> fp(GrRRectEffect::Make(edgeType, rrect));
joshualittb0a8a372014-09-23 09:50:21 -0700111 if (fp) {
robertphillips28a838e2016-06-23 14:07:00 -0700112 grPaint.addCoverageFragmentProcessor(std::move(fp));
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000113
114 SkRect bounds = rrect.getBounds();
115 bounds.outset(2.f, 2.f);
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000116
joshualitt04194f32016-01-13 10:08:27 -0800117 SkAutoTUnref<GrDrawBatch> batch(
118 GrRectBatchFactory::CreateNonAAFill(0xff000000, SkMatrix::I(),
119 bounds, nullptr, nullptr));
robertphillips28a838e2016-06-23 14:07:00 -0700120 drawContext->drawContextPriv().testingOnly_drawBatch(grPaint, batch);
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000121 } else {
122 drew = false;
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000123 }
bsalomon@google.com707bd602014-03-04 16:52:20 +0000124#endif
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000125 } else if (kBW_Clip_Type == fType || kAA_Clip_Type == fType) {
126 bool aaClip = (kAA_Clip_Type == fType);
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000127 canvas->clipRRect(fRRects[curRRect], SkRegion::kReplace_Op, aaClip);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000128 canvas->drawRect(kMaxTileBound, paint);
129 } else {
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000130 canvas->drawRRect(fRRects[curRRect], paint);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000131 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000132 canvas->restore();
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000133 if (drew) {
134 x = x + kTileX;
135 if (x > kImageWidth) {
136 x = 1;
137 y += kTileY;
138 }
139 }
140 }
141 if (x != 1) {
142 y += kTileY;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000143 }
144 }
145 }
146
147 void setUpRRects() {
skia.committer@gmail.com7a03d862012-12-18 02:03:03 +0000148 // 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 +0000149 // the screen in kTileX x kTileY tiles. The extra empty pixels on each side are for AA.
150
151 // simple cases
152 fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2));
153 fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2));
154 fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10);
commit-bot@chromium.orgc2f78242014-02-19 15:18:05 +0000155 fRRects[3].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 5);
156 // small circular corners are an interesting test case for gpu clipping
157 fRRects[4].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 1, 1);
158 fRRects[5].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.5f, 0.5f);
159 fRRects[6].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.2f, 0.2f);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000160
161 // The first complex case needs special handling since it is a square
162 fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2), gRadii[0]);
mike@reedtribe.orgf6100c82012-12-24 13:56:17 +0000163 for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000164 fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTileY-2), gRadii[i]);
165 }
166 }
167
168private:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000169 Type fType;
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000170
mtkleindbfd7ab2016-09-01 11:24:54 -0700171 static constexpr int kImageWidth = 640;
172 static constexpr int kImageHeight = 480;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000173
mtkleindbfd7ab2016-09-01 11:24:54 -0700174 static constexpr int kTileX = 80;
175 static constexpr int kTileY = 40;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000176
mtkleindbfd7ab2016-09-01 11:24:54 -0700177 static constexpr int kNumSimpleCases = 7;
178 static constexpr int kNumComplexCases = 35;
robertphillips@google.com5683d422012-12-17 21:58:02 +0000179 static const SkVector gRadii[kNumComplexCases][4];
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000180
mtkleindbfd7ab2016-09-01 11:24:54 -0700181 static constexpr int kNumRRects = kNumSimpleCases + kNumComplexCases;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000182 SkRRect fRRects[kNumRRects];
183
184 typedef GM INHERITED;
185};
186
187// Radii for the various test cases. Order is UL, UR, LR, LL
188const SkVector RRectGM::gRadii[kNumComplexCases][4] = {
189 // a circle
190 { { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY } },
191
192 // odd ball cases
193 { { 8, 8 }, { 32, 32 }, { 8, 8 }, { 32, 32 } },
194 { { 16, 8 }, { 8, 16 }, { 16, 8 }, { 8, 16 } },
195 { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 32, 32 } },
196
197 // UL
198 { { 30, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
199 { { 30, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
200 { { 15, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
201
202 // UR
203 { { 0, 0 }, { 30, 30 }, { 0, 0 }, { 0, 0 } },
204 { { 0, 0 }, { 30, 15 }, { 0, 0 }, { 0, 0 } },
205 { { 0, 0 }, { 15, 30 }, { 0, 0 }, { 0, 0 } },
206
207 // LR
208 { { 0, 0 }, { 0, 0 }, { 30, 30 }, { 0, 0 } },
209 { { 0, 0 }, { 0, 0 }, { 30, 15 }, { 0, 0 } },
210 { { 0, 0 }, { 0, 0 }, { 15, 30 }, { 0, 0 } },
211
212 // LL
213 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 30 } },
214 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 15 } },
215 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 30 } },
216
217 // over-sized radii
218 { { 0, 0 }, { 100, 400 }, { 0, 0 }, { 0, 0 } },
219 { { 0, 0 }, { 400, 400 }, { 0, 0 }, { 0, 0 } },
220 { { 400, 400 }, { 400, 400 }, { 400, 400 }, { 400, 400 } },
commit-bot@chromium.orgcb3672e2014-02-21 22:41:56 +0000221
222 // circular corner tabs
223 { { 0, 0 }, { 20, 20 }, { 20, 20 }, { 0, 0 } },
224 { { 20, 20 }, { 20, 20 }, { 0, 0 }, { 0, 0 } },
225 { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 20, 20 } },
226 { { 20, 20 }, { 0, 0 }, { 0, 0 }, { 20, 20 } },
commit-bot@chromium.orgc5c748c2014-03-11 15:54:51 +0000227
commit-bot@chromium.org04eff722014-03-24 14:53:09 +0000228 // small radius circular corner tabs
229 { { 0, 0 }, { 0.2f, 0.2f }, { 0.2f, 0.2f }, { 0, 0 } },
230 { { 0.3f, 0.3f }, { 0.3f, .3f }, { 0, 0 }, { 0, 0 } },
231
commit-bot@chromium.orgc5c748c2014-03-11 15:54:51 +0000232 // single circular corner cases
233 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 15 } },
234 { { 0, 0 }, { 0, 0 }, { 15, 15 }, { 0, 0 } },
235 { { 0, 0 }, { 15, 15 }, { 0, 0 }, { 0, 0 } },
236 { { 15, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
commit-bot@chromium.orgfa5edbe2014-03-13 18:01:05 +0000237
238 // nine patch elliptical
239 { { 5, 7 }, { 8, 7 }, { 8, 12 }, { 5, 12 } },
240 { { 0, 7 }, { 8, 7 }, { 8, 12 }, { 0, 12 } },
commit-bot@chromium.org04eff722014-03-24 14:53:09 +0000241
242 // nine patch elliptical, small radii
243 { { 0.4f, 7 }, { 8, 7 }, { 8, 12 }, { 0.4f, 12 } },
244 { { 0.4f, 0.4f }, { 8, 0.4f }, { 8, 12 }, { 0.4f, 12 } },
245 { { 20, 0.4f }, { 18, 0.4f }, { 18, 0.4f }, { 20, 0.4f } },
246 { { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f } },
247
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000248};
249
250///////////////////////////////////////////////////////////////////////////////
251
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000252DEF_GM( return new RRectGM(RRectGM::kAA_Draw_Type); )
253DEF_GM( return new RRectGM(RRectGM::kBW_Draw_Type); )
254DEF_GM( return new RRectGM(RRectGM::kAA_Clip_Type); )
255DEF_GM( return new RRectGM(RRectGM::kBW_Clip_Type); )
bsalomon@google.com707bd602014-03-04 16:52:20 +0000256#if SK_SUPPORT_GPU
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000257DEF_GM( return new RRectGM(RRectGM::kEffect_Type); )
bsalomon@google.com707bd602014-03-04 16:52:20 +0000258#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000259
260}