OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 "GrAAFillRectBatch.h" | 8 #include "GrAAFillRectBatch.h" |
9 | 9 |
10 #include "GrBatch.h" | 10 #include "GrBatch.h" |
11 #include "GrColor.h" | 11 #include "GrColor.h" |
12 #include "GrDefaultGeoProcFactory.h" | 12 #include "GrDefaultGeoProcFactory.h" |
13 #include "GrResourceKey.h" | 13 #include "GrResourceKey.h" |
14 #include "GrResourceProvider.h" | 14 #include "GrResourceProvider.h" |
15 #include "GrTypes.h" | 15 #include "GrTypes.h" |
16 #include "SkMatrix.h" | 16 #include "SkMatrix.h" |
17 #include "SkRect.h" | 17 #include "SkRect.h" |
18 | 18 |
19 GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey); | 19 GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey); |
20 | 20 |
21 static void set_inset_fan(SkPoint* pts, size_t stride, | 21 static void set_inset_fan(SkPoint* pts, size_t stride, |
22 const SkRect& r, SkScalar dx, SkScalar dy) { | 22 const SkRect& r, SkScalar dx, SkScalar dy) { |
23 pts->setRectFan(r.fLeft + dx, r.fTop + dy, | 23 pts->setRectFan(r.fLeft + dx, r.fTop + dy, |
24 r.fRight - dx, r.fBottom - dy, stride); | 24 r.fRight - dx, r.fBottom - dy, stride); |
25 } | 25 } |
26 | 26 |
27 static const GrGeometryProcessor* create_fill_rect_gp(bool tweakAlphaForCoverage , | 27 /* |
28 const SkMatrix& viewMatrix , | 28 * To use this template, an implementation must define the following static func tions: |
bsalomon
2015/08/12 17:25:48
AAFillRectBatch is templated to optionally allow t
| |
29 bool usesLocalCoords, | 29 * A Geometry struct |
30 bool coverageIgnored) { | 30 * |
31 using namespace GrDefaultGeoProcFactory; | 31 * bool OnCanCombineLocalCoords(const SkMatrix& mine, const SkMatrix& theirs , |
bsalomon
2015/08/12 17:25:48
Why "On"?
| |
32 | 32 * bool usesLocalCoords) |
33 Color color(Color::kAttribute_Type); | 33 * |
34 Coverage::Type coverageType; | 34 * GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType() |
35 // TODO remove coverage if coverage is ignored | 35 * |
36 /*if (coverageIgnored) { | 36 * bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCoverage, |
37 coverageType = Coverage::kNone_Type; | 37 * bool usesLocalCoords) |
38 } else*/ if (tweakAlphaForCoverage) { | 38 * |
39 coverageType = Coverage::kSolid_Type; | 39 * void PostGenerateHook(intptr_t, size_t, SkPoint*, const Geometry&) {} |
bsalomon
2015/08/12 17:25:48
FillInAttributes?
VerticesWerePopulated?
Doc on w
| |
40 } else { | 40 */ |
41 coverageType = Coverage::kAttribute_Type; | 41 template <typename Base> |
bsalomon
2015/08/12 17:25:47
Base doesn't seem like the right name anymore
| |
42 } | |
43 Coverage coverage(coverageType); | |
44 LocalCoords localCoords(usesLocalCoords ? LocalCoords::kUsePosition_Type : | |
45 LocalCoords::kUnused_Type); | |
46 return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix); | |
47 } | |
48 | |
49 class AAFillRectBatch : public GrBatch { | 42 class AAFillRectBatch : public GrBatch { |
50 public: | 43 public: |
51 struct Geometry { | 44 typedef typename Base::Geometry Geometry; |
52 GrColor fColor; | |
53 SkMatrix fViewMatrix; | |
54 SkRect fRect; | |
55 SkRect fDevRect; | |
56 }; | |
57 | 45 |
58 static GrBatch* Create(GrColor color, | 46 static AAFillRectBatch* Create() { |
59 const SkMatrix& viewMatrix, | 47 return SkNEW(AAFillRectBatch); |
60 const SkRect& rect, | |
61 const SkRect& devRect) { | |
62 return SkNEW_ARGS(AAFillRectBatch, (color, viewMatrix, rect, devRect)); | |
63 } | 48 } |
64 | 49 |
65 const char* name() const override { return "AAFillRectBatch"; } | 50 const char* name() const override { return "AAFillRectBatch"; } |
66 | 51 |
67 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { | 52 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
68 // When this is called on a batch, there is only one geometry bundle | 53 // When this is called on a batch, there is only one geometry bundle |
69 out->setKnownFourComponents(fGeoData[0].fColor); | 54 out->setKnownFourComponents(fGeoData[0].fColor); |
70 } | 55 } |
71 | 56 |
72 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { | 57 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { |
(...skipping 11 matching lines...) Expand all Loading... | |
84 fBatch.fColorIgnored = !opt.readsColor(); | 69 fBatch.fColorIgnored = !opt.readsColor(); |
85 fBatch.fColor = fGeoData[0].fColor; | 70 fBatch.fColor = fGeoData[0].fColor; |
86 fBatch.fUsesLocalCoords = opt.readsLocalCoords(); | 71 fBatch.fUsesLocalCoords = opt.readsLocalCoords(); |
87 fBatch.fCoverageIgnored = !opt.readsCoverage(); | 72 fBatch.fCoverageIgnored = !opt.readsCoverage(); |
88 fBatch.fCanTweakAlphaForCoverage = opt.canTweakAlphaForCoverage(); | 73 fBatch.fCanTweakAlphaForCoverage = opt.canTweakAlphaForCoverage(); |
89 } | 74 } |
90 | 75 |
91 void generateGeometry(GrBatchTarget* batchTarget) override { | 76 void generateGeometry(GrBatchTarget* batchTarget) override { |
92 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); | 77 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); |
93 | 78 |
94 SkAutoTUnref<const GrGeometryProcessor> gp(create_fill_rect_gp(canTweakA lphaForCoverage, | 79 SkAutoTUnref<const GrGeometryProcessor> gp(CreateFillRectGP(canTweakAlph aForCoverage, |
95 this->vie wMatrix(), | 80 this->viewMa trix(), |
96 this->use sLocalCoords(), | 81 this->usesLo calCoords(), |
97 this->cov erageIgnored())); | 82 Base::LocalC oordsType(), |
83 this->covera geIgnored())); | |
98 if (!gp) { | 84 if (!gp) { |
99 SkDebugf("Couldn't create GrGeometryProcessor\n"); | 85 SkDebugf("Couldn't create GrGeometryProcessor\n"); |
100 return; | 86 return; |
101 } | 87 } |
102 | 88 |
103 batchTarget->initDraw(gp, this->pipeline()); | 89 batchTarget->initDraw(gp, this->pipeline()); |
104 | 90 |
105 size_t vertexStride = gp->getVertexStride(); | 91 size_t vertexStride = gp->getVertexStride(); |
106 SkASSERT(canTweakAlphaForCoverage ? | 92 SkASSERT(Base::StrideCheck(vertexStride, canTweakAlphaForCoverage, |
107 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) : | 93 this->usesLocalCoords())); |
108 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr)); | |
109 int instanceCount = fGeoData.count(); | 94 int instanceCount = fGeoData.count(); |
110 | 95 |
111 SkAutoTUnref<const GrIndexBuffer> indexBuffer(this->getIndexBuffer( | 96 SkAutoTUnref<const GrIndexBuffer> indexBuffer(this->getIndexBuffer( |
112 batchTarget->resourceProvider())); | 97 batchTarget->resourceProvider())); |
113 InstancedHelper helper; | 98 InstancedHelper helper; |
114 void* vertices = helper.init(batchTarget, kTriangles_GrPrimitiveType, ve rtexStride, | 99 void* vertices = helper.init(batchTarget, kTriangles_GrPrimitiveType, ve rtexStride, |
115 indexBuffer, kVertsPerAAFillRect, kIndicesP erAAFillRect, | 100 indexBuffer, kVertsPerAAFillRect, kIndicesP erAAFillRect, |
116 instanceCount); | 101 instanceCount); |
117 if (!vertices || !indexBuffer) { | 102 if (!vertices || !indexBuffer) { |
118 SkDebugf("Could not allocate vertices\n"); | 103 SkDebugf("Could not allocate vertices\n"); |
119 return; | 104 return; |
120 } | 105 } |
121 | 106 |
122 for (int i = 0; i < instanceCount; i++) { | 107 for (int i = 0; i < instanceCount; i++) { |
123 const Geometry& args = fGeoData[i]; | |
124 this->generateAAFillRectGeometry(vertices, | 108 this->generateAAFillRectGeometry(vertices, |
125 i * kVertsPerAAFillRect * vertexStr ide, | 109 i * kVertsPerAAFillRect * vertexStr ide, |
126 vertexStride, | 110 vertexStride, |
127 args.fColor, | 111 fGeoData[i], |
128 args.fViewMatrix, | |
129 args.fRect, | |
130 args.fDevRect, | |
131 canTweakAlphaForCoverage); | 112 canTweakAlphaForCoverage); |
132 } | 113 } |
133 | 114 |
134 helper.issueDraw(batchTarget); | 115 helper.issueDraw(batchTarget); |
135 } | 116 } |
136 | 117 |
137 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | 118 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
138 | 119 |
120 // to avoid even the initial copy of the struct, we have a getter for the fi rst item which | |
121 // is used to seed the batch with its initial geometry. After seeding, the client should call | |
122 // init() so the Batch can initialize itself | |
123 Geometry* geometry() { return &fGeoData[0]; } | |
124 void init() { | |
125 const Geometry& geo = fGeoData[0]; | |
126 this->setBounds(geo.fDevRect); | |
127 } | |
128 | |
129 | |
139 private: | 130 private: |
140 AAFillRectBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& rec t, | 131 AAFillRectBatch() { |
141 const SkRect& devRect) { | 132 this->initClassID<AAFillRectBatch<Base>>(); |
142 this->initClassID<AAFillRectBatch>(); | |
143 Geometry& geometry = fGeoData.push_back(); | |
144 geometry.fRect = rect; | |
145 geometry.fViewMatrix = viewMatrix; | |
146 geometry.fDevRect = devRect; | |
147 geometry.fColor = color; | |
148 | 133 |
149 this->setBounds(geometry.fDevRect); | 134 // Push back an initial geometry |
135 fGeoData.push_back(); | |
150 } | 136 } |
151 | 137 |
152 static const int kNumAAFillRectsInIndexBuffer = 256; | 138 static const int kNumAAFillRectsInIndexBuffer = 256; |
153 static const int kVertsPerAAFillRect = 8; | 139 static const int kVertsPerAAFillRect = 8; |
154 static const int kIndicesPerAAFillRect = 30; | 140 static const int kIndicesPerAAFillRect = 30; |
155 | 141 |
156 const GrIndexBuffer* getIndexBuffer(GrResourceProvider* resourceProvider) { | 142 const GrIndexBuffer* getIndexBuffer(GrResourceProvider* resourceProvider) { |
157 GR_DEFINE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey); | 143 GR_DEFINE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey); |
158 | 144 |
159 static const uint16_t gFillAARectIdx[] = { | 145 static const uint16_t gFillAARectIdx[] = { |
(...skipping 15 matching lines...) Expand all Loading... | |
175 bool colorIgnored() const { return fBatch.fColorIgnored; } | 161 bool colorIgnored() const { return fBatch.fColorIgnored; } |
176 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | 162 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } |
177 bool coverageIgnored() const { return fBatch.fCoverageIgnored; } | 163 bool coverageIgnored() const { return fBatch.fCoverageIgnored; } |
178 | 164 |
179 bool onCombineIfPossible(GrBatch* t) override { | 165 bool onCombineIfPossible(GrBatch* t) override { |
180 if (!this->pipeline()->isEqual(*t->pipeline())) { | 166 if (!this->pipeline()->isEqual(*t->pipeline())) { |
181 return false; | 167 return false; |
182 } | 168 } |
183 | 169 |
184 AAFillRectBatch* that = t->cast<AAFillRectBatch>(); | 170 AAFillRectBatch* that = t->cast<AAFillRectBatch>(); |
185 | 171 if (!Base::OnCanCombineLocalCoords(this->viewMatrix(), that->viewMatrix( ), |
186 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); | 172 this->usesLocalCoords())) { |
187 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses | |
188 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix | |
189 // using vertex attributes in these cases, but haven't investigated that | |
190 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) { | |
191 return false; | 173 return false; |
192 } | 174 } |
193 | 175 |
194 if (this->color() != that->color()) { | 176 if (this->color() != that->color()) { |
195 fBatch.fColor = GrColor_ILLEGAL; | 177 fBatch.fColor = GrColor_ILLEGAL; |
196 } | 178 } |
197 | 179 |
198 // In the event of two batches, one who can tweak, one who cannot, we ju st fall back to | 180 // In the event of two batches, one who can tweak, one who cannot, we ju st fall back to |
199 // not tweaking | 181 // not tweaking |
200 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage() ) { | 182 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage() ) { |
201 fBatch.fCanTweakAlphaForCoverage = false; | 183 fBatch.fCanTweakAlphaForCoverage = false; |
202 } | 184 } |
203 | 185 |
204 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; | 186 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; |
205 this->joinBounds(that->bounds()); | 187 this->joinBounds(that->bounds()); |
206 return true; | 188 return true; |
207 } | 189 } |
208 | 190 |
209 void generateAAFillRectGeometry(void* vertices, | 191 void generateAAFillRectGeometry(void* vertices, |
210 size_t offset, | 192 size_t offset, |
211 size_t vertexStride, | 193 size_t vertexStride, |
212 GrColor color, | 194 const Geometry& args, |
213 const SkMatrix& viewMatrix, | |
214 const SkRect& rect, | |
215 const SkRect& devRect, | |
216 bool tweakAlphaForCoverage) const { | 195 bool tweakAlphaForCoverage) const { |
217 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset; | 196 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset; |
218 | 197 |
219 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); | 198 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); |
220 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride); | 199 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride); |
221 | 200 |
222 SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1); | 201 SkScalar inset = SkMinScalar(args.fDevRect.width(), SK_Scalar1); |
223 inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height()); | 202 inset = SK_ScalarHalf * SkMinScalar(inset, args.fDevRect.height()); |
224 | 203 |
225 if (viewMatrix.rectStaysRect()) { | 204 if (args.fViewMatrix.rectStaysRect()) { |
226 set_inset_fan(fan0Pos, vertexStride, devRect, -SK_ScalarHalf, -SK_Sc alarHalf); | 205 set_inset_fan(fan0Pos, vertexStride, args.fDevRect, -SK_ScalarHalf, -SK_ScalarHalf); |
227 set_inset_fan(fan1Pos, vertexStride, devRect, inset, inset); | 206 set_inset_fan(fan1Pos, vertexStride, args.fDevRect, inset, inset); |
228 } else { | 207 } else { |
229 // compute transformed (1, 0) and (0, 1) vectors | 208 // compute transformed (1, 0) and (0, 1) vectors |
230 SkVector vec[2] = { | 209 SkVector vec[2] = { |
231 { viewMatrix[SkMatrix::kMScaleX], viewMatrix[SkMatrix::kMSkewY] }, | 210 { args.fViewMatrix[SkMatrix::kMScaleX], args.fViewMatrix[SkMatrix: :kMSkewY] }, |
232 { viewMatrix[SkMatrix::kMSkewX], viewMatrix[SkMatrix::kMScaleY] } | 211 { args.fViewMatrix[SkMatrix::kMSkewX], args.fViewMatrix[SkMatrix: :kMScaleY] } |
233 }; | 212 }; |
234 | 213 |
235 vec[0].normalize(); | 214 vec[0].normalize(); |
236 vec[0].scale(SK_ScalarHalf); | 215 vec[0].scale(SK_ScalarHalf); |
237 vec[1].normalize(); | 216 vec[1].normalize(); |
238 vec[1].scale(SK_ScalarHalf); | 217 vec[1].scale(SK_ScalarHalf); |
239 | 218 |
240 // create the rotated rect | 219 // create the rotated rect |
241 fan0Pos->setRectFan(rect.fLeft, rect.fTop, | 220 fan0Pos->setRectFan(args.fRect.fLeft, args.fRect.fTop, |
242 rect.fRight, rect.fBottom, vertexStride); | 221 args.fRect.fRight, args.fRect.fBottom, vertexStr ide); |
243 viewMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4); | 222 args.fViewMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4); |
244 | 223 |
245 // Now create the inset points and then outset the original | 224 // Now create the inset points and then outset the original |
246 // rotated points | 225 // rotated points |
247 | 226 |
248 // TL | 227 // TL |
249 *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) = | 228 *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) = |
250 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + v ec[1]; | 229 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + v ec[1]; |
251 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[ 1]; | 230 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[ 1]; |
252 // BL | 231 // BL |
253 *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) = | 232 *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) = |
254 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - v ec[1]; | 233 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - v ec[1]; |
255 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[ 1]; | 234 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[ 1]; |
256 // BR | 235 // BR |
257 *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) = | 236 *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) = |
258 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - v ec[1]; | 237 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - v ec[1]; |
259 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[ 1]; | 238 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[ 1]; |
260 // TR | 239 // TR |
261 *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) = | 240 *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) = |
262 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + v ec[1]; | 241 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + v ec[1]; |
263 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[ 1]; | 242 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[ 1]; |
264 } | 243 } |
265 | 244 |
245 Base::PostGenerateHook(verts, vertexStride, fan0Pos, args); | |
246 | |
266 // Make verts point to vertex color and then set all the color and cover age vertex attrs | 247 // Make verts point to vertex color and then set all the color and cover age vertex attrs |
267 // values. | 248 // values. |
268 verts += sizeof(SkPoint); | 249 verts += sizeof(SkPoint); |
269 for (int i = 0; i < 4; ++i) { | 250 for (int i = 0; i < 4; ++i) { |
270 if (tweakAlphaForCoverage) { | 251 if (tweakAlphaForCoverage) { |
271 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; | 252 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; |
272 } else { | 253 } else { |
273 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | 254 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = args.fCo lor; |
274 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrCo lor)) = 0; | 255 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrCo lor)) = 0; |
275 } | 256 } |
276 } | 257 } |
277 | 258 |
278 int scale; | 259 int scale; |
279 if (inset < SK_ScalarHalf) { | 260 if (inset < SK_ScalarHalf) { |
280 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)) ; | 261 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)) ; |
281 SkASSERT(scale >= 0 && scale <= 255); | 262 SkASSERT(scale >= 0 && scale <= 255); |
282 } else { | 263 } else { |
283 scale = 0xff; | 264 scale = 0xff; |
284 } | 265 } |
285 | 266 |
286 verts += 4 * vertexStride; | 267 verts += 4 * vertexStride; |
287 | 268 |
288 float innerCoverage = GrNormalizeByteToFloat(scale); | 269 float innerCoverage = GrNormalizeByteToFloat(scale); |
289 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale ); | 270 GrColor scaledColor = (0xff == scale) ? args.fColor : SkAlphaMulQ(args.f Color, scale); |
290 | 271 |
291 for (int i = 0; i < 4; ++i) { | 272 for (int i = 0; i < 4; ++i) { |
292 if (tweakAlphaForCoverage) { | 273 if (tweakAlphaForCoverage) { |
293 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledCo lor; | 274 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledCo lor; |
294 } else { | 275 } else { |
295 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | 276 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = args.fCo lor; |
296 *reinterpret_cast<float*>(verts + i * vertexStride + | 277 *reinterpret_cast<float*>(verts + i * vertexStride + |
297 sizeof(GrColor)) = innerCoverage; | 278 sizeof(GrColor)) = innerCoverage; |
298 } | 279 } |
299 } | 280 } |
300 } | 281 } |
301 | 282 |
283 static const GrGeometryProcessor* CreateFillRectGP( | |
284 bool tweakAlphaForCoverage, | |
285 const SkMatrix& viewMatrix, | |
286 bool usesLocalCoords, | |
287 GrDefaultGeoProcFactory::LocalCoords::T ype localCoordsType, | |
288 bool coverageIgnored) { | |
289 using namespace GrDefaultGeoProcFactory; | |
290 | |
291 Color color(Color::kAttribute_Type); | |
292 Coverage::Type coverageType; | |
293 // TODO remove coverage if coverage is ignored | |
294 /*if (coverageIgnored) { | |
295 coverageType = Coverage::kNone_Type; | |
296 } else*/ if (tweakAlphaForCoverage) { | |
297 coverageType = Coverage::kSolid_Type; | |
298 } else { | |
299 coverageType = Coverage::kAttribute_Type; | |
300 } | |
301 Coverage coverage(coverageType); | |
302 | |
303 // We assume the caller has inverted the viewmatrix | |
304 LocalCoords localCoords(usesLocalCoords ? localCoordsType : LocalCoords: :kUnused_Type); | |
305 if (LocalCoords::kHasExplicit_Type == localCoordsType) { | |
306 return GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkMatrix::I()); | |
307 } else { | |
308 return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix ); | |
309 } | |
310 } | |
311 | |
302 struct BatchTracker { | 312 struct BatchTracker { |
303 GrColor fColor; | 313 GrColor fColor; |
304 bool fUsesLocalCoords; | 314 bool fUsesLocalCoords; |
305 bool fColorIgnored; | 315 bool fColorIgnored; |
306 bool fCoverageIgnored; | 316 bool fCoverageIgnored; |
307 bool fCanTweakAlphaForCoverage; | 317 bool fCanTweakAlphaForCoverage; |
308 }; | 318 }; |
309 | 319 |
310 BatchTracker fBatch; | 320 BatchTracker fBatch; |
311 SkSTArray<1, Geometry, true> fGeoData; | 321 SkSTArray<1, Geometry, true> fGeoData; |
312 }; | 322 }; |
313 | 323 |
324 class AAFillRectBatchNoLocalMatrixImp { | |
325 public: | |
326 struct Geometry { | |
327 SkMatrix fViewMatrix; | |
328 SkRect fRect; | |
329 SkRect fDevRect; | |
330 GrColor fColor; | |
331 }; | |
332 | |
333 inline static bool OnCanCombineLocalCoords(const SkMatrix& mine, const SkMat rix& theirs, | |
334 bool usesLocalCoords) { | |
335 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses | |
336 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix | |
337 // using vertex attributes in these cases, but haven't investigated that | |
338 return !usesLocalCoords || mine.cheapEqualTo(theirs); | |
339 } | |
340 | |
341 inline static GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType() { | |
342 return GrDefaultGeoProcFactory::LocalCoords::kUsePosition_Type; | |
343 } | |
344 | |
345 inline static bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCov erage, | |
346 bool usesLocalCoords) { | |
347 return canTweakAlphaForCoverage ? | |
348 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) : | |
349 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr); | |
350 } | |
351 | |
352 inline static void PostGenerateHook(intptr_t, size_t, SkPoint*, const Geomet ry&) {} | |
353 }; | |
354 | |
355 class AAFillRectBatchLocalMatrixImp { | |
356 public: | |
357 struct Geometry { | |
358 SkMatrix fViewMatrix; | |
359 SkMatrix fLocalMatrix; | |
360 SkRect fRect; | |
361 SkRect fDevRect; | |
362 GrColor fColor; | |
363 }; | |
364 | |
365 inline static bool OnCanCombineLocalCoords(const SkMatrix& mine, const SkMat rix& theirs, | |
366 bool usesLocalCoords) { | |
367 return true; | |
368 } | |
369 | |
370 inline static GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType() { | |
371 return GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type; | |
372 } | |
373 | |
374 inline static bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCov erage, | |
375 bool usesLocalCoords) { | |
376 // Whomever created us should not have done so if there are no local coo rds | |
377 SkASSERT(usesLocalCoords); | |
378 return canTweakAlphaForCoverage ? | |
379 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLo calCoordAttr) : | |
380 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLo calCoordCoverage); | |
381 } | |
382 | |
383 inline static void PostGenerateHook(intptr_t vertices, size_t vertexStride, | |
384 SkPoint* fan0Pos, const Geometry& args) { | |
385 SkMatrix invViewMatrix; | |
386 if (!args.fViewMatrix.invert(&invViewMatrix)) { | |
387 SkASSERT(false); | |
388 invViewMatrix = SkMatrix::I(); | |
389 } | |
390 SkMatrix localCoordMatrix; | |
391 localCoordMatrix.setConcat(args.fLocalMatrix, invViewMatrix); | |
392 SkPoint* fan0Loc = reinterpret_cast<SkPoint*>(vertices + vertexStride - sizeof(SkPoint)); | |
393 localCoordMatrix.mapPointsWithStride(fan0Loc, fan0Pos, vertexStride, 8); | |
394 } | |
395 }; | |
396 | |
397 typedef AAFillRectBatch<AAFillRectBatchNoLocalMatrixImp> AAFillRectBatchNoLocalM atrix; | |
398 typedef AAFillRectBatch<AAFillRectBatchLocalMatrixImp> AAFillRectBatchLocalMatri x; | |
399 | |
314 namespace GrAAFillRectBatch { | 400 namespace GrAAFillRectBatch { |
315 | 401 |
316 GrBatch* Create(GrColor color, | 402 GrBatch* Create(GrColor color, |
317 const SkMatrix& viewMatrix, | 403 const SkMatrix& viewMatrix, |
318 const SkRect& rect, | 404 const SkRect& rect, |
319 const SkRect& devRect) { | 405 const SkRect& devRect) { |
320 return AAFillRectBatch::Create(color, viewMatrix, rect, devRect); | 406 AAFillRectBatchNoLocalMatrix* batch = AAFillRectBatchNoLocalMatrix::Create() ; |
407 AAFillRectBatchNoLocalMatrix::Geometry& geo = *batch->geometry(); | |
408 geo.fColor = color; | |
409 geo.fViewMatrix = viewMatrix; | |
410 geo.fRect = rect; | |
411 geo.fDevRect = devRect; | |
412 batch->init(); | |
413 return batch; | |
414 } | |
415 | |
416 GrBatch* Create(GrColor color, | |
417 const SkMatrix& viewMatrix, | |
418 const SkMatrix& localMatrix, | |
419 const SkRect& rect, | |
420 const SkRect& devRect) { | |
421 AAFillRectBatchLocalMatrix* batch = AAFillRectBatchLocalMatrix::Create(); | |
422 AAFillRectBatchLocalMatrix::Geometry& geo = *batch->geometry(); | |
423 geo.fColor = color; | |
424 geo.fViewMatrix = viewMatrix; | |
425 geo.fLocalMatrix = localMatrix; | |
426 geo.fRect = rect; | |
427 geo.fDevRect = devRect; | |
428 batch->init(); | |
429 return batch; | |
321 } | 430 } |
322 | 431 |
323 }; | 432 }; |
324 | 433 |
325 //////////////////////////////////////////////////////////////////////////////// /////////////////// | 434 //////////////////////////////////////////////////////////////////////////////// /////////////////// |
326 | 435 |
327 #ifdef GR_TEST_UTILS | 436 #ifdef GR_TEST_UTILS |
328 | 437 |
329 #include "GrBatchTest.h" | 438 #include "GrBatchTest.h" |
330 | 439 |
331 BATCH_TEST_DEFINE(AAFillRectBatch) { | 440 BATCH_TEST_DEFINE(AAFillRectBatch) { |
332 GrColor color = GrRandomColor(random); | 441 AAFillRectBatchNoLocalMatrix* batch = AAFillRectBatchNoLocalMatrix::Create() ; |
333 SkMatrix viewMatrix = GrTest::TestMatrix(random); | 442 AAFillRectBatchNoLocalMatrix::Geometry& geo = *batch->geometry(); |
334 SkRect rect = GrTest::TestRect(random); | 443 geo.fColor = GrRandomColor(random); |
335 SkRect devRect = GrTest::TestRect(random); | 444 geo.fViewMatrix = GrTest::TestMatrix(random); |
336 return AAFillRectBatch::Create(color, viewMatrix, rect, devRect); | 445 geo.fRect = GrTest::TestRect(random); |
446 geo.fDevRect = GrTest::TestRect(random); | |
447 batch->init(); | |
448 return batch; | |
449 } | |
450 | |
451 BATCH_TEST_DEFINE(AAFillRectBatchLocalMatrix) { | |
452 AAFillRectBatchLocalMatrix* batch = AAFillRectBatchLocalMatrix::Create(); | |
453 AAFillRectBatchLocalMatrix::Geometry& geo = *batch->geometry(); | |
454 geo.fColor = GrRandomColor(random); | |
455 geo.fViewMatrix = GrTest::TestMatrix(random); | |
456 geo.fLocalMatrix = GrTest::TestMatrix(random); | |
457 geo.fRect = GrTest::TestRect(random); | |
458 geo.fDevRect = GrTest::TestRect(random); | |
459 batch->init(); | |
460 return batch; | |
337 } | 461 } |
338 | 462 |
339 #endif | 463 #endif |
OLD | NEW |