blob: 52df12a4ffd4ffe73353ecb5399aa9e527a05938 [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"
Brian Salomonc7fe0f72018-05-11 10:14:21 -04009#include "GrCaps.h"
joshualitt04194f32016-01-13 10:08:27 -080010#include "GrContext.h"
Brian Osman11052242016-10-27 14:47:55 -040011#include "GrRenderTargetContextPriv.h"
bsalomon@google.com707bd602014-03-04 16:52:20 +000012#include "effects/GrRRectEffect.h"
Brian Salomon89527432016-12-16 09:52:16 -050013#include "ops/GrDrawOp.h"
Michael Ludwig72ab3462018-12-10 12:43:36 -050014#include "ops/GrFillRectOp.h"
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000015#include "SkRRect.h"
16
17namespace skiagm {
18
19///////////////////////////////////////////////////////////////////////////////
20
21class RRectGM : public GM {
22public:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000023 enum Type {
24 kBW_Draw_Type,
25 kAA_Draw_Type,
26 kBW_Clip_Type,
27 kAA_Clip_Type,
28 kEffect_Type,
29 };
herbb10fe492016-01-08 13:48:43 -080030 RRectGM(Type type) : fType(type) { }
31
32protected:
33
34 void onOnceBeforeDraw() override {
Mike Kleind46dce32018-08-16 10:17:03 -040035 this->setBGColor(0xFFDDDDDD);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000036 this->setUpRRects();
37 }
38
mtklein36352bf2015-03-25 18:17:31 -070039 SkString onShortName() override {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000040 SkString name("rrect");
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000041 switch (fType) {
42 case kBW_Draw_Type:
43 name.append("_draw_bw");
44 break;
45 case kAA_Draw_Type:
46 name.append("_draw_aa");
47 break;
48 case kBW_Clip_Type:
49 name.append("_clip_bw");
50 break;
51 case kAA_Clip_Type:
52 name.append("_clip_aa");
53 break;
54 case kEffect_Type:
55 name.append("_effect");
56 break;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000057 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000058 return name;
59 }
60
mtklein36352bf2015-03-25 18:17:31 -070061 SkISize onISize() override { return SkISize::Make(kImageWidth, kImageHeight); }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000062
Chris Dalton50e24d72019-02-07 16:20:09 -070063 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
Brian Osman11052242016-10-27 14:47:55 -040064 GrRenderTargetContext* renderTargetContext =
65 canvas->internal_private_accessTopLayerRenderTargetContext();
Robert Phillips7c525e62018-06-12 10:11:12 -040066 GrContext* context = canvas->getGrContext();
Chris Dalton50e24d72019-02-07 16:20:09 -070067 if (kEffect_Type == fType && (!renderTargetContext || !context)) {
68 *errorMsg = kErrorMsg_DrawSkippedGpuOnly;
69 return DrawResult::kSkip;
Robert Phillips7c525e62018-06-12 10:11:12 -040070 }
71
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000072 SkPaint paint;
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000073 if (kAA_Draw_Type == fType) {
74 paint.setAntiAlias(true);
75 }
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +000076
mtkleindbfd7ab2016-09-01 11:24:54 -070077 const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX),
78 SkIntToScalar(kTileY));
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000079#ifdef SK_DEBUG
mtkleindbfd7ab2016-09-01 11:24:54 -070080 const SkRect kMaxImageBound = SkRect::MakeWH(SkIntToScalar(kImageWidth),
81 SkIntToScalar(kImageHeight));
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000082#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000083
Ethan Nicholas1706f842017-11-10 11:58:19 -050084 int lastEdgeType = (kEffect_Type == fType) ? (int) GrClipEdgeType::kLast: 0;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000085
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000086 int y = 1;
bsalomon@google.comb0ba39d2014-03-10 19:51:46 +000087 for (int et = 0; et <= lastEdgeType; ++et) {
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000088 int x = 1;
89 for (int curRRect = 0; curRRect < kNumRRects; ++curRRect) {
90 bool drew = true;
91#ifdef SK_DEBUG
92 SkASSERT(kMaxTileBound.contains(fRRects[curRRect].getBounds()));
93 SkRect imageSpaceBounds = fRRects[curRRect].getBounds();
94 imageSpaceBounds.offset(SkIntToScalar(x), SkIntToScalar(y));
95 SkASSERT(kMaxImageBound.contains(imageSpaceBounds));
96#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000097 canvas->save();
98 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000099 if (kEffect_Type == fType) {
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000100 SkRRect rrect = fRRects[curRRect];
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000101 rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500102 GrClipEdgeType edgeType = (GrClipEdgeType) et;
Ethan Nicholaseace9352018-10-15 20:09:54 +0000103 const auto& caps = *renderTargetContext->caps()->shaderCaps();
104 auto fp = GrRRectEffect::Make(edgeType, rrect, caps);
joshualittb0a8a372014-09-23 09:50:21 -0700105 if (fp) {
Brian Salomon82f44312017-01-11 13:42:54 -0500106 GrPaint grPaint;
107 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
robertphillips28a838e2016-06-23 14:07:00 -0700108 grPaint.addCoverageFragmentProcessor(std::move(fp));
Brian Osmancb3d0872018-10-16 15:19:28 -0400109 grPaint.setColor4f({ 0, 0, 0, 1.f });
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000110
111 SkRect bounds = rrect.getBounds();
112 bounds.outset(2.f, 2.f);
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000113
Brian Salomonac70f842017-05-08 10:43:33 -0400114 renderTargetContext->priv().testingOnly_addDrawOp(
Michael Ludwig72ab3462018-12-10 12:43:36 -0500115 GrFillRectOp::Make(context, std::move(grPaint), GrAAType::kNone,
116 SkMatrix::I(), bounds));
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000117 } else {
118 drew = false;
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000119 }
120 } else if (kBW_Clip_Type == fType || kAA_Clip_Type == fType) {
121 bool aaClip = (kAA_Clip_Type == fType);
reed66998382016-09-21 11:15:07 -0700122 canvas->clipRRect(fRRects[curRRect], aaClip);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000123 canvas->drawRect(kMaxTileBound, paint);
124 } else {
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000125 canvas->drawRRect(fRRects[curRRect], paint);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000126 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000127 canvas->restore();
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000128 if (drew) {
129 x = x + kTileX;
130 if (x > kImageWidth) {
131 x = 1;
132 y += kTileY;
133 }
134 }
135 }
136 if (x != 1) {
137 y += kTileY;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000138 }
139 }
Chris Dalton50e24d72019-02-07 16:20:09 -0700140 return DrawResult::kOk;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000141 }
142
143 void setUpRRects() {
skia.committer@gmail.com7a03d862012-12-18 02:03:03 +0000144 // 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 +0000145 // the screen in kTileX x kTileY tiles. The extra empty pixels on each side are for AA.
146
147 // simple cases
148 fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2));
149 fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2));
150 fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10);
commit-bot@chromium.orgc2f78242014-02-19 15:18:05 +0000151 fRRects[3].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 5);
152 // small circular corners are an interesting test case for gpu clipping
153 fRRects[4].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 1, 1);
154 fRRects[5].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.5f, 0.5f);
155 fRRects[6].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.2f, 0.2f);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000156
157 // The first complex case needs special handling since it is a square
158 fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2), gRadii[0]);
mike@reedtribe.orgf6100c82012-12-24 13:56:17 +0000159 for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000160 fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTileY-2), gRadii[i]);
161 }
162 }
163
164private:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000165 Type fType;
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000166
mtkleindbfd7ab2016-09-01 11:24:54 -0700167 static constexpr int kImageWidth = 640;
168 static constexpr int kImageHeight = 480;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000169
mtkleindbfd7ab2016-09-01 11:24:54 -0700170 static constexpr int kTileX = 80;
171 static constexpr int kTileY = 40;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000172
mtkleindbfd7ab2016-09-01 11:24:54 -0700173 static constexpr int kNumSimpleCases = 7;
174 static constexpr int kNumComplexCases = 35;
robertphillips@google.com5683d422012-12-17 21:58:02 +0000175 static const SkVector gRadii[kNumComplexCases][4];
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000176
mtkleindbfd7ab2016-09-01 11:24:54 -0700177 static constexpr int kNumRRects = kNumSimpleCases + kNumComplexCases;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000178 SkRRect fRRects[kNumRRects];
179
180 typedef GM INHERITED;
181};
182
183// Radii for the various test cases. Order is UL, UR, LR, LL
184const SkVector RRectGM::gRadii[kNumComplexCases][4] = {
185 // a circle
186 { { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY } },
187
188 // odd ball cases
189 { { 8, 8 }, { 32, 32 }, { 8, 8 }, { 32, 32 } },
190 { { 16, 8 }, { 8, 16 }, { 16, 8 }, { 8, 16 } },
191 { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 32, 32 } },
192
193 // UL
194 { { 30, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
195 { { 30, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
196 { { 15, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
197
198 // UR
199 { { 0, 0 }, { 30, 30 }, { 0, 0 }, { 0, 0 } },
200 { { 0, 0 }, { 30, 15 }, { 0, 0 }, { 0, 0 } },
201 { { 0, 0 }, { 15, 30 }, { 0, 0 }, { 0, 0 } },
202
203 // LR
204 { { 0, 0 }, { 0, 0 }, { 30, 30 }, { 0, 0 } },
205 { { 0, 0 }, { 0, 0 }, { 30, 15 }, { 0, 0 } },
206 { { 0, 0 }, { 0, 0 }, { 15, 30 }, { 0, 0 } },
207
208 // LL
209 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 30 } },
210 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 15 } },
211 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 30 } },
212
213 // over-sized radii
214 { { 0, 0 }, { 100, 400 }, { 0, 0 }, { 0, 0 } },
215 { { 0, 0 }, { 400, 400 }, { 0, 0 }, { 0, 0 } },
216 { { 400, 400 }, { 400, 400 }, { 400, 400 }, { 400, 400 } },
commit-bot@chromium.orgcb3672e2014-02-21 22:41:56 +0000217
218 // circular corner tabs
219 { { 0, 0 }, { 20, 20 }, { 20, 20 }, { 0, 0 } },
220 { { 20, 20 }, { 20, 20 }, { 0, 0 }, { 0, 0 } },
221 { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 20, 20 } },
222 { { 20, 20 }, { 0, 0 }, { 0, 0 }, { 20, 20 } },
commit-bot@chromium.orgc5c748c2014-03-11 15:54:51 +0000223
commit-bot@chromium.org04eff722014-03-24 14:53:09 +0000224 // small radius circular corner tabs
225 { { 0, 0 }, { 0.2f, 0.2f }, { 0.2f, 0.2f }, { 0, 0 } },
226 { { 0.3f, 0.3f }, { 0.3f, .3f }, { 0, 0 }, { 0, 0 } },
227
commit-bot@chromium.orgc5c748c2014-03-11 15:54:51 +0000228 // single circular corner cases
229 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 15 } },
230 { { 0, 0 }, { 0, 0 }, { 15, 15 }, { 0, 0 } },
231 { { 0, 0 }, { 15, 15 }, { 0, 0 }, { 0, 0 } },
232 { { 15, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
commit-bot@chromium.orgfa5edbe2014-03-13 18:01:05 +0000233
234 // nine patch elliptical
235 { { 5, 7 }, { 8, 7 }, { 8, 12 }, { 5, 12 } },
236 { { 0, 7 }, { 8, 7 }, { 8, 12 }, { 0, 12 } },
commit-bot@chromium.org04eff722014-03-24 14:53:09 +0000237
238 // nine patch elliptical, small radii
239 { { 0.4f, 7 }, { 8, 7 }, { 8, 12 }, { 0.4f, 12 } },
240 { { 0.4f, 0.4f }, { 8, 0.4f }, { 8, 12 }, { 0.4f, 12 } },
241 { { 20, 0.4f }, { 18, 0.4f }, { 18, 0.4f }, { 20, 0.4f } },
242 { { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f } },
243
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000244};
245
246///////////////////////////////////////////////////////////////////////////////
247
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000248DEF_GM( return new RRectGM(RRectGM::kAA_Draw_Type); )
249DEF_GM( return new RRectGM(RRectGM::kBW_Draw_Type); )
250DEF_GM( return new RRectGM(RRectGM::kAA_Clip_Type); )
251DEF_GM( return new RRectGM(RRectGM::kBW_Clip_Type); )
252DEF_GM( return new RRectGM(RRectGM::kEffect_Type); )
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000253
254}