blob: dfeebf3dd89e6d74973c151cf97969cc4e79a974 [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"
Mike Klein33d20552017-03-22 13:47:51 -04009#include "sk_tool_utils.h"
bsalomon@google.com707bd602014-03-04 16:52:20 +000010#if SK_SUPPORT_GPU
joshualitt04194f32016-01-13 10:08:27 -080011#include "GrContext.h"
Brian Osman11052242016-10-27 14:47:55 -040012#include "GrRenderTargetContextPriv.h"
bsalomon@google.com707bd602014-03-04 16:52:20 +000013#include "effects/GrRRectEffect.h"
Brian Salomon89527432016-12-16 09:52:16 -050014#include "ops/GrDrawOp.h"
Brian Salomonbaaf4392017-06-15 09:59:23 -040015#include "ops/GrRectOpFactory.h"
bsalomon@google.com707bd602014-03-04 16:52:20 +000016#endif
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 {
Brian Osman11052242016-10-27 14:47:55 -040066 GrRenderTargetContext* renderTargetContext =
67 canvas->internal_private_accessTopLayerRenderTargetContext();
68 if (kEffect_Type == fType && !renderTargetContext) {
halcanary2a243382015-09-09 08:16:41 -070069 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000070 return;
71 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000072
73 SkPaint paint;
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +000074 if (kAA_Draw_Type == fType) {
75 paint.setAntiAlias(true);
76 }
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +000077
mtkleindbfd7ab2016-09-01 11:24:54 -070078 const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX),
79 SkIntToScalar(kTileY));
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000080#ifdef SK_DEBUG
mtkleindbfd7ab2016-09-01 11:24:54 -070081 const SkRect kMaxImageBound = SkRect::MakeWH(SkIntToScalar(kImageWidth),
82 SkIntToScalar(kImageHeight));
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000083#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000084
bsalomon@google.comb0ba39d2014-03-10 19:51:46 +000085#if SK_SUPPORT_GPU
Ethan Nicholas1706f842017-11-10 11:58:19 -050086 int lastEdgeType = (kEffect_Type == fType) ? (int) GrClipEdgeType::kLast: 0;
bsalomon@google.comb0ba39d2014-03-10 19:51:46 +000087#else
88 int lastEdgeType = 0;
89#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +000090
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000091 int y = 1;
bsalomon@google.comb0ba39d2014-03-10 19:51:46 +000092 for (int et = 0; et <= lastEdgeType; ++et) {
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +000093 int x = 1;
94 for (int curRRect = 0; curRRect < kNumRRects; ++curRRect) {
95 bool drew = true;
96#ifdef SK_DEBUG
97 SkASSERT(kMaxTileBound.contains(fRRects[curRRect].getBounds()));
98 SkRect imageSpaceBounds = fRRects[curRRect].getBounds();
99 imageSpaceBounds.offset(SkIntToScalar(x), SkIntToScalar(y));
100 SkASSERT(kMaxImageBound.contains(imageSpaceBounds));
101#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000102 canvas->save();
103 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000104 if (kEffect_Type == fType) {
bsalomon@google.com707bd602014-03-04 16:52:20 +0000105#if SK_SUPPORT_GPU
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000106 SkRRect rrect = fRRects[curRRect];
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000107 rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500108 GrClipEdgeType edgeType = (GrClipEdgeType) et;
Brian Salomon14471772017-12-05 10:35:15 -0500109 const auto& caps = *renderTargetContext->caps()->shaderCaps();
110 auto fp = GrRRectEffect::Make(edgeType, rrect, caps);
joshualittb0a8a372014-09-23 09:50:21 -0700111 if (fp) {
Brian Salomon82f44312017-01-11 13:42:54 -0500112 GrPaint grPaint;
113 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
robertphillips28a838e2016-06-23 14:07:00 -0700114 grPaint.addCoverageFragmentProcessor(std::move(fp));
Brian Salomonac70f842017-05-08 10:43:33 -0400115 grPaint.setColor4f(GrColor4f(0, 0, 0, 1.f));
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000116
117 SkRect bounds = rrect.getBounds();
118 bounds.outset(2.f, 2.f);
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000119
Brian Salomonac70f842017-05-08 10:43:33 -0400120 renderTargetContext->priv().testingOnly_addDrawOp(
Brian Salomonbaaf4392017-06-15 09:59:23 -0400121 GrRectOpFactory::MakeNonAAFill(std::move(grPaint),
122 SkMatrix::I(), bounds,
123 GrAAType::kNone));
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000124 } else {
125 drew = false;
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000126 }
bsalomon@google.com707bd602014-03-04 16:52:20 +0000127#endif
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000128 } else if (kBW_Clip_Type == fType || kAA_Clip_Type == fType) {
129 bool aaClip = (kAA_Clip_Type == fType);
reed66998382016-09-21 11:15:07 -0700130 canvas->clipRRect(fRRects[curRRect], aaClip);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000131 canvas->drawRect(kMaxTileBound, paint);
132 } else {
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000133 canvas->drawRRect(fRRects[curRRect], paint);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000134 }
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000135 canvas->restore();
commit-bot@chromium.orgbfce48e2014-03-10 19:33:16 +0000136 if (drew) {
137 x = x + kTileX;
138 if (x > kImageWidth) {
139 x = 1;
140 y += kTileY;
141 }
142 }
143 }
144 if (x != 1) {
145 y += kTileY;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000146 }
147 }
148 }
149
150 void setUpRRects() {
skia.committer@gmail.com7a03d862012-12-18 02:03:03 +0000151 // 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 +0000152 // the screen in kTileX x kTileY tiles. The extra empty pixels on each side are for AA.
153
154 // simple cases
155 fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2));
156 fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2));
157 fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10);
commit-bot@chromium.orgc2f78242014-02-19 15:18:05 +0000158 fRRects[3].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 5);
159 // small circular corners are an interesting test case for gpu clipping
160 fRRects[4].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 1, 1);
161 fRRects[5].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.5f, 0.5f);
162 fRRects[6].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.2f, 0.2f);
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000163
164 // The first complex case needs special handling since it is a square
165 fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2), gRadii[0]);
mike@reedtribe.orgf6100c82012-12-24 13:56:17 +0000166 for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) {
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000167 fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTileY-2), gRadii[i]);
168 }
169 }
170
171private:
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000172 Type fType;
skia.committer@gmail.comf1f66c02014-03-05 03:02:06 +0000173
mtkleindbfd7ab2016-09-01 11:24:54 -0700174 static constexpr int kImageWidth = 640;
175 static constexpr int kImageHeight = 480;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000176
mtkleindbfd7ab2016-09-01 11:24:54 -0700177 static constexpr int kTileX = 80;
178 static constexpr int kTileY = 40;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000179
mtkleindbfd7ab2016-09-01 11:24:54 -0700180 static constexpr int kNumSimpleCases = 7;
181 static constexpr int kNumComplexCases = 35;
robertphillips@google.com5683d422012-12-17 21:58:02 +0000182 static const SkVector gRadii[kNumComplexCases][4];
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000183
mtkleindbfd7ab2016-09-01 11:24:54 -0700184 static constexpr int kNumRRects = kNumSimpleCases + kNumComplexCases;
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000185 SkRRect fRRects[kNumRRects];
186
187 typedef GM INHERITED;
188};
189
190// Radii for the various test cases. Order is UL, UR, LR, LL
191const SkVector RRectGM::gRadii[kNumComplexCases][4] = {
192 // a circle
193 { { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY } },
194
195 // odd ball cases
196 { { 8, 8 }, { 32, 32 }, { 8, 8 }, { 32, 32 } },
197 { { 16, 8 }, { 8, 16 }, { 16, 8 }, { 8, 16 } },
198 { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 32, 32 } },
199
200 // UL
201 { { 30, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
202 { { 30, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
203 { { 15, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
204
205 // UR
206 { { 0, 0 }, { 30, 30 }, { 0, 0 }, { 0, 0 } },
207 { { 0, 0 }, { 30, 15 }, { 0, 0 }, { 0, 0 } },
208 { { 0, 0 }, { 15, 30 }, { 0, 0 }, { 0, 0 } },
209
210 // LR
211 { { 0, 0 }, { 0, 0 }, { 30, 30 }, { 0, 0 } },
212 { { 0, 0 }, { 0, 0 }, { 30, 15 }, { 0, 0 } },
213 { { 0, 0 }, { 0, 0 }, { 15, 30 }, { 0, 0 } },
214
215 // LL
216 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 30 } },
217 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 15 } },
218 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 30 } },
219
220 // over-sized radii
221 { { 0, 0 }, { 100, 400 }, { 0, 0 }, { 0, 0 } },
222 { { 0, 0 }, { 400, 400 }, { 0, 0 }, { 0, 0 } },
223 { { 400, 400 }, { 400, 400 }, { 400, 400 }, { 400, 400 } },
commit-bot@chromium.orgcb3672e2014-02-21 22:41:56 +0000224
225 // circular corner tabs
226 { { 0, 0 }, { 20, 20 }, { 20, 20 }, { 0, 0 } },
227 { { 20, 20 }, { 20, 20 }, { 0, 0 }, { 0, 0 } },
228 { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 20, 20 } },
229 { { 20, 20 }, { 0, 0 }, { 0, 0 }, { 20, 20 } },
commit-bot@chromium.orgc5c748c2014-03-11 15:54:51 +0000230
commit-bot@chromium.org04eff722014-03-24 14:53:09 +0000231 // small radius circular corner tabs
232 { { 0, 0 }, { 0.2f, 0.2f }, { 0.2f, 0.2f }, { 0, 0 } },
233 { { 0.3f, 0.3f }, { 0.3f, .3f }, { 0, 0 }, { 0, 0 } },
234
commit-bot@chromium.orgc5c748c2014-03-11 15:54:51 +0000235 // single circular corner cases
236 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 15 } },
237 { { 0, 0 }, { 0, 0 }, { 15, 15 }, { 0, 0 } },
238 { { 0, 0 }, { 15, 15 }, { 0, 0 }, { 0, 0 } },
239 { { 15, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
commit-bot@chromium.orgfa5edbe2014-03-13 18:01:05 +0000240
241 // nine patch elliptical
242 { { 5, 7 }, { 8, 7 }, { 8, 12 }, { 5, 12 } },
243 { { 0, 7 }, { 8, 7 }, { 8, 12 }, { 0, 12 } },
commit-bot@chromium.org04eff722014-03-24 14:53:09 +0000244
245 // nine patch elliptical, small radii
246 { { 0.4f, 7 }, { 8, 7 }, { 8, 12 }, { 0.4f, 12 } },
247 { { 0.4f, 0.4f }, { 8, 0.4f }, { 8, 12 }, { 0.4f, 12 } },
248 { { 20, 0.4f }, { 18, 0.4f }, { 18, 0.4f }, { 20, 0.4f } },
249 { { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f } },
250
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000251};
252
253///////////////////////////////////////////////////////////////////////////////
254
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000255DEF_GM( return new RRectGM(RRectGM::kAA_Draw_Type); )
256DEF_GM( return new RRectGM(RRectGM::kBW_Draw_Type); )
257DEF_GM( return new RRectGM(RRectGM::kAA_Clip_Type); )
258DEF_GM( return new RRectGM(RRectGM::kBW_Clip_Type); )
bsalomon@google.com707bd602014-03-04 16:52:20 +0000259#if SK_SUPPORT_GPU
commit-bot@chromium.orgfbde87f2014-03-04 16:25:34 +0000260DEF_GM( return new RRectGM(RRectGM::kEffect_Type); )
bsalomon@google.com707bd602014-03-04 16:52:20 +0000261#endif
robertphillips@google.com4e18c7a2012-12-17 21:48:19 +0000262
263}