OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "gm.h" | 8 #include "gm.h" |
| 9 #include "GrTest.h" |
| 10 #include "SkDevice.h" |
9 #include "SkRRect.h" | 11 #include "SkRRect.h" |
| 12 #include "effects/GrRRectEffect.h" |
10 | 13 |
11 namespace skiagm { | 14 namespace skiagm { |
12 | 15 |
13 /////////////////////////////////////////////////////////////////////////////// | 16 /////////////////////////////////////////////////////////////////////////////// |
14 | 17 |
15 class RRectGM : public GM { | 18 class RRectGM : public GM { |
16 public: | 19 public: |
17 RRectGM(bool doAA, bool doClip) : fDoAA(doAA), fDoClip(doClip) { | 20 enum Type { |
| 21 kBW_Draw_Type, |
| 22 kAA_Draw_Type, |
| 23 kBW_Clip_Type, |
| 24 kAA_Clip_Type, |
| 25 kEffect_Type, |
| 26 }; |
| 27 RRectGM(Type type) : fType(type) { |
18 this->setBGColor(0xFFDDDDDD); | 28 this->setBGColor(0xFFDDDDDD); |
19 this->setUpRRects(); | 29 this->setUpRRects(); |
20 } | 30 } |
21 | 31 |
22 protected: | 32 protected: |
23 SkString onShortName() { | 33 SkString onShortName() SK_OVERRIDE { |
24 SkString name("rrect"); | 34 SkString name("rrect"); |
25 if (fDoClip) { | 35 switch (fType) { |
26 name.append("_clip"); | 36 case kBW_Draw_Type: |
| 37 name.append("_draw_bw"); |
| 38 break; |
| 39 case kAA_Draw_Type: |
| 40 name.append("_draw_aa"); |
| 41 break; |
| 42 case kBW_Clip_Type: |
| 43 name.append("_clip_bw"); |
| 44 break; |
| 45 case kAA_Clip_Type: |
| 46 name.append("_clip_aa"); |
| 47 break; |
| 48 case kEffect_Type: |
| 49 name.append("_effect"); |
| 50 break; |
27 } | 51 } |
28 if (fDoAA) { | |
29 name.append("_aa"); | |
30 } else { | |
31 name.append("_bw"); | |
32 } | |
33 | |
34 return name; | 52 return name; |
35 } | 53 } |
36 | 54 |
37 virtual SkISize onISize() { return make_isize(kImageWidth, kImageHeight); } | 55 virtual SkISize onISize() SK_OVERRIDE { return make_isize(kImageWidth, kImag
eHeight); } |
38 | 56 |
39 virtual void onDraw(SkCanvas* canvas) { | 57 virtual uint32_t onGetFlags() const SK_OVERRIDE { |
| 58 if (kEffect_Type == fType) { |
| 59 return kGPUOnly_Flag; |
| 60 } else { |
| 61 return 0; |
| 62 } |
| 63 } |
| 64 |
| 65 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { |
| 66 SkBaseDevice* device = canvas->getTopDevice(); |
| 67 GrContext* context = NULL; |
| 68 GrRenderTarget* rt = device->accessRenderTarget(); |
| 69 if (NULL != rt) { |
| 70 context = rt->getContext(); |
| 71 } |
| 72 if (kEffect_Type == fType && NULL == context) { |
| 73 return; |
| 74 } |
40 | 75 |
41 SkPaint paint; | 76 SkPaint paint; |
42 // when clipping the AA is pushed into the clip operation | 77 if (kAA_Draw_Type == fType) { |
43 paint.setAntiAlias(fDoClip ? false : fDoAA); | 78 paint.setAntiAlias(true); |
44 | 79 } |
| 80 |
45 static const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX)
, SkIntToScalar(kTileY)); | 81 static const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX)
, SkIntToScalar(kTileY)); |
46 | 82 |
47 int curRRect = 0; | 83 int curRRect = 0; |
| 84 int numRRects = kNumRRects; |
| 85 if (kEffect_Type == fType) { |
| 86 numRRects *= GrRRectEffect::kEdgeTypeCnt; |
| 87 } |
48 for (int y = 1; y < kImageHeight; y += kTileY) { | 88 for (int y = 1; y < kImageHeight; y += kTileY) { |
49 for (int x = 1; x < kImageWidth; x += kTileX) { | 89 for (int x = 1; x < kImageWidth; x += kTileX) { |
50 if (curRRect >= kNumRRects) { | 90 if (curRRect >= numRRects) { |
51 break; | 91 break; |
52 } | 92 } |
53 SkASSERT(kMaxTileBound.contains(fRRects[curRRect].getBounds())); | 93 int rrectIdx = curRRect % kNumRRects; |
| 94 SkASSERT(kMaxTileBound.contains(fRRects[rrectIdx].getBounds())); |
54 | 95 |
55 canvas->save(); | 96 canvas->save(); |
56 canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); | 97 canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); |
57 if (fDoClip) { | 98 if (kEffect_Type == fType) { |
58 canvas->clipRRect(fRRects[curRRect], SkRegion::kReplace_
Op, fDoAA); | 99 GrTestTarget tt; |
| 100 context->getTestTarget(&tt); |
| 101 if (NULL == tt.target()) { |
| 102 SkDEBUGFAIL("Couldn't get Gr test target."); |
| 103 return; |
| 104 } |
| 105 GrDrawState* drawState = tt.target()->drawState(); |
| 106 |
| 107 SkRRect rrect = fRRects[rrectIdx]; |
| 108 rrect.offset(SkIntToScalar(x), SkIntToScalar(y)); |
| 109 GrRRectEffect::EdgeType edgeType = (GrRRectEffect::EdgeT
ype) |
| 110 (curRRect / kNumRRec
ts); |
| 111 SkAutoTUnref<GrEffectRef> effect(GrRRectEffect::Create(e
dgeType, rrect)); |
| 112 if (effect) { |
| 113 drawState->addCoverageEffect(effect); |
| 114 drawState->setIdentityViewMatrix(); |
| 115 drawState->setRenderTarget(rt); |
| 116 drawState->setColor(0xff000000); |
| 117 |
| 118 SkRect bounds = rrect.getBounds(); |
| 119 bounds.outset(2.f, 2.f); |
| 120 |
| 121 tt.target()->drawSimpleRect(bounds); |
| 122 } |
| 123 } else if (kBW_Clip_Type == fType || kAA_Clip_Type == fType)
{ |
| 124 bool aaClip = (kAA_Clip_Type == fType); |
| 125 canvas->clipRRect(fRRects[rrectIdx], SkRegion::kReplace_
Op, aaClip); |
59 canvas->drawRect(kMaxTileBound, paint); | 126 canvas->drawRect(kMaxTileBound, paint); |
60 } else { | 127 } else { |
61 canvas->drawRRect(fRRects[curRRect], paint); | 128 canvas->drawRRect(fRRects[rrectIdx], paint); |
62 } | 129 } |
63 ++curRRect; | 130 ++curRRect; |
64 canvas->restore(); | 131 canvas->restore(); |
65 } | 132 } |
66 } | 133 } |
67 } | 134 } |
68 | 135 |
69 void setUpRRects() { | 136 void setUpRRects() { |
70 // each RRect must fit in a 0x0 -> (kTileX-2)x(kTileY-2) block. These wi
ll be tiled across | 137 // each RRect must fit in a 0x0 -> (kTileX-2)x(kTileY-2) block. These wi
ll be tiled across |
71 // the screen in kTileX x kTileY tiles. The extra empty pixels on each s
ide are for AA. | 138 // the screen in kTileX x kTileY tiles. The extra empty pixels on each s
ide are for AA. |
72 | 139 |
73 // simple cases | 140 // simple cases |
74 fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2)); | 141 fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2)); |
75 fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2)); | 142 fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2)); |
76 fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10); | 143 fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10); |
77 fRRects[3].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 5); | 144 fRRects[3].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 5); |
78 // small circular corners are an interesting test case for gpu clipping | 145 // small circular corners are an interesting test case for gpu clipping |
79 fRRects[4].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 1, 1); | 146 fRRects[4].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 1, 1); |
80 fRRects[5].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.5f, 0.5f); | 147 fRRects[5].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.5f, 0.5f); |
81 fRRects[6].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.2f, 0.2f); | 148 fRRects[6].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.2f, 0.2f); |
82 | 149 |
83 // The first complex case needs special handling since it is a square | 150 // The first complex case needs special handling since it is a square |
84 fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2)
, gRadii[0]); | 151 fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2)
, gRadii[0]); |
85 for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) { | 152 for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) { |
86 fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTi
leY-2), gRadii[i]); | 153 fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTi
leY-2), gRadii[i]); |
87 } | 154 } |
88 } | 155 } |
89 | 156 |
90 private: | 157 private: |
91 bool fDoAA; | 158 Type fType; |
92 bool fDoClip; // use clipRRect & drawRect instead of drawRRect | 159 |
93 | |
94 static const int kImageWidth = 640; | 160 static const int kImageWidth = 640; |
95 static const int kImageHeight = 480; | 161 static const int kImageHeight = 480; |
96 | 162 |
97 static const int kTileX = 80; | 163 static const int kTileX = 80; |
98 static const int kTileY = 40; | 164 static const int kTileY = 40; |
99 | 165 |
100 static const int kNumSimpleCases = 7; | 166 static const int kNumSimpleCases = 7; |
101 static const int kNumComplexCases = 23; | 167 static const int kNumComplexCases = 23; |
102 static const SkVector gRadii[kNumComplexCases][4]; | 168 static const SkVector gRadii[kNumComplexCases][4]; |
103 | 169 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 | 210 |
145 // circular corner tabs | 211 // circular corner tabs |
146 { { 0, 0 }, { 20, 20 }, { 20, 20 }, { 0, 0 } }, | 212 { { 0, 0 }, { 20, 20 }, { 20, 20 }, { 0, 0 } }, |
147 { { 20, 20 }, { 20, 20 }, { 0, 0 }, { 0, 0 } }, | 213 { { 20, 20 }, { 20, 20 }, { 0, 0 }, { 0, 0 } }, |
148 { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 20, 20 } }, | 214 { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 20, 20 } }, |
149 { { 20, 20 }, { 0, 0 }, { 0, 0 }, { 20, 20 } }, | 215 { { 20, 20 }, { 0, 0 }, { 0, 0 }, { 20, 20 } }, |
150 }; | 216 }; |
151 | 217 |
152 /////////////////////////////////////////////////////////////////////////////// | 218 /////////////////////////////////////////////////////////////////////////////// |
153 | 219 |
154 DEF_GM( return new RRectGM(false, false); ) | 220 DEF_GM( return new RRectGM(RRectGM::kAA_Draw_Type); ) |
155 DEF_GM( return new RRectGM(true, false); ) | 221 DEF_GM( return new RRectGM(RRectGM::kBW_Draw_Type); ) |
156 DEF_GM( return new RRectGM(false, true); ) | 222 DEF_GM( return new RRectGM(RRectGM::kAA_Clip_Type); ) |
157 DEF_GM( return new RRectGM(true, true); ) | 223 DEF_GM( return new RRectGM(RRectGM::kBW_Clip_Type); ) |
| 224 DEF_GM( return new RRectGM(RRectGM::kEffect_Type); ) |
158 | 225 |
159 } | 226 } |
OLD | NEW |