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 "GrBatchFlushState.h" | 10 #include "GrBatchFlushState.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 kIndicesPerAAFillRect, kNumAAFillRectsInIndexBuffer, kVertsPerAAFillRect
, | 44 kIndicesPerAAFillRect, kNumAAFillRectsInIndexBuffer, kVertsPerAAFillRect
, |
45 gAAFillRectIndexBufferKey); | 45 gAAFillRectIndexBufferKey); |
46 } | 46 } |
47 | 47 |
48 /* | 48 /* |
49 * AAFillRectBatch is templated to optionally allow the insertion of an addition
al | 49 * AAFillRectBatch is templated to optionally allow the insertion of an addition
al |
50 * attribute for explicit local coordinates. | 50 * attribute for explicit local coordinates. |
51 * To use this template, an implementation must define the following static func
tions: | 51 * To use this template, an implementation must define the following static func
tions: |
52 * A Geometry struct | 52 * A Geometry struct |
53 * | 53 * |
54 * bool CanCombineLocalCoords(const SkMatrix& mine, const SkMatrix& theirs, | 54 * bool CanCombine(const Geometry& mine, const Geometry& theirs, |
55 * bool usesLocalCoords) | 55 * const GrPipelineOptimizations&) |
56 * | 56 * |
57 * GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType() | 57 * const GrGeometryProcessor* CreateGP(const Geometry& seedGeometry, |
| 58 * const GrPipelineOptimizations& opts) |
58 * | 59 * |
59 * bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCoverage, | 60 * Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo, |
60 * bool usesLocalCoords) | 61 * const GrPipelineOptimizations& opts) |
61 * | |
62 * void FillInAttributes(intptr_t startVertex, size_t vertexStride, | |
63 * SkPoint* fan0Position, const Geometry&) | |
64 */ | 62 */ |
65 template <typename Base> | 63 template <typename Base> |
66 class AAFillRectBatch : public GrVertexBatch { | 64 class AAFillRectBatch : public GrVertexBatch { |
67 public: | 65 public: |
68 typedef typename Base::Geometry Geometry; | 66 typedef typename Base::Geometry Geometry; |
69 | 67 |
70 static AAFillRectBatch* Create() { | 68 static AAFillRectBatch* Create() { |
71 return SkNEW(AAFillRectBatch); | 69 return SkNEW(AAFillRectBatch); |
72 } | 70 } |
73 | 71 |
74 const char* name() const override { return "AAFillRectBatch"; } | 72 const char* name() const override { return "AAFillRectBatch"; } |
75 | 73 |
76 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { | 74 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
77 // When this is called on a batch, there is only one geometry bundle | 75 // When this is called on a batch, there is only one geometry bundle |
78 out->setKnownFourComponents(fGeoData[0].fColor); | 76 out->setKnownFourComponents(fGeoData[0].fColor); |
79 } | 77 } |
80 | 78 |
81 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { | 79 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { |
82 out->setUnknownSingleComponent(); | 80 out->setUnknownSingleComponent(); |
83 } | 81 } |
84 | 82 |
85 void initBatchTracker(const GrPipelineOptimizations& opt) override { | 83 void initBatchTracker(const GrPipelineOptimizations& opt) override { |
86 // Handle any color overrides | |
87 if (!opt.readsColor()) { | |
88 fGeoData[0].fColor = GrColor_ILLEGAL; | |
89 } | |
90 opt.getOverrideColorIfSet(&fGeoData[0].fColor); | 84 opt.getOverrideColorIfSet(&fGeoData[0].fColor); |
91 | 85 fOpts = opt; |
92 // setup batch properties | |
93 fBatch.fColorIgnored = !opt.readsColor(); | |
94 fBatch.fColor = fGeoData[0].fColor; | |
95 fBatch.fUsesLocalCoords = opt.readsLocalCoords(); | |
96 fBatch.fCoverageIgnored = !opt.readsCoverage(); | |
97 fBatch.fCanTweakAlphaForCoverage = opt.canTweakAlphaForCoverage(); | |
98 } | 86 } |
99 | 87 |
100 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | 88 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
101 | 89 |
102 // to avoid even the initial copy of the struct, we have a getter for the fi
rst item which | 90 // to avoid even the initial copy of the struct, we have a getter for the fi
rst item which |
103 // is used to seed the batch with its initial geometry. After seeding, the
client should call | 91 // is used to seed the batch with its initial geometry. After seeding, the
client should call |
104 // init() so the Batch can initialize itself | 92 // init() so the Batch can initialize itself |
105 Geometry* geometry() { return &fGeoData[0]; } | 93 Geometry* geometry() { return &fGeoData[0]; } |
106 void init() { | 94 void init() { |
107 const Geometry& geo = fGeoData[0]; | 95 const Geometry& geo = fGeoData[0]; |
108 this->setBounds(geo.fDevRect); | 96 this->setBounds(geo.fDevRect); |
109 } | 97 } |
110 | 98 |
111 private: | 99 private: |
112 AAFillRectBatch() { | 100 AAFillRectBatch() { |
113 this->initClassID<AAFillRectBatch<Base>>(); | 101 this->initClassID<AAFillRectBatch<Base>>(); |
114 | 102 |
115 // Push back an initial geometry | 103 // Push back an initial geometry |
116 fGeoData.push_back(); | 104 fGeoData.push_back(); |
117 } | 105 } |
118 | 106 |
119 GrColor color() const { return fBatch.fColor; } | |
120 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | |
121 bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCover
age; } | |
122 bool colorIgnored() const { return fBatch.fColorIgnored; } | |
123 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | |
124 bool coverageIgnored() const { return fBatch.fCoverageIgnored; } | |
125 | |
126 void onPrepareDraws(Target* target) override { | 107 void onPrepareDraws(Target* target) override { |
127 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); | 108 SkAutoTUnref<const GrGeometryProcessor> gp(Base::CreateGP(this->seedGeom
etry(), fOpts)); |
128 | |
129 SkAutoTUnref<const GrGeometryProcessor> gp(CreateFillRectGP(canTweakAlph
aForCoverage, | |
130 this->viewMa
trix(), | |
131 this->usesLo
calCoords(), | |
132 Base::LocalC
oordsType(), | |
133 this->covera
geIgnored())); | |
134 if (!gp) { | 109 if (!gp) { |
135 SkDebugf("Couldn't create GrGeometryProcessor\n"); | 110 SkDebugf("Couldn't create GrGeometryProcessor\n"); |
136 return; | 111 return; |
137 } | 112 } |
138 | 113 |
139 target->initDraw(gp, this->pipeline()); | 114 target->initDraw(gp, this->pipeline()); |
140 | 115 |
141 size_t vertexStride = gp->getVertexStride(); | 116 size_t vertexStride = gp->getVertexStride(); |
142 SkASSERT(Base::StrideCheck(vertexStride, canTweakAlphaForCoverage, | |
143 this->usesLocalCoords())); | |
144 int instanceCount = fGeoData.count(); | 117 int instanceCount = fGeoData.count(); |
145 | 118 |
146 SkAutoTUnref<const GrIndexBuffer> indexBuffer(get_index_buffer(target->r
esourceProvider())); | 119 SkAutoTUnref<const GrIndexBuffer> indexBuffer(get_index_buffer(target->r
esourceProvider())); |
147 InstancedHelper helper; | 120 InstancedHelper helper; |
148 void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexS
tride, | 121 void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexS
tride, |
149 indexBuffer, kVertsPerAAFillRect, kIndicesP
erAAFillRect, | 122 indexBuffer, kVertsPerAAFillRect, kIndicesP
erAAFillRect, |
150 instanceCount); | 123 instanceCount); |
151 if (!vertices || !indexBuffer) { | 124 if (!vertices || !indexBuffer) { |
152 SkDebugf("Could not allocate vertices\n"); | 125 SkDebugf("Could not allocate vertices\n"); |
153 return; | 126 return; |
154 } | 127 } |
155 | 128 |
156 for (int i = 0; i < instanceCount; i++) { | 129 for (int i = 0; i < instanceCount; i++) { |
157 this->generateAAFillRectGeometry(vertices, | 130 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + |
158 i * kVertsPerAAFillRect * vertexStr
ide, | 131 i * kVertsPerAAFillRect * vertexStride; |
159 vertexStride, | 132 Base::Tesselate(verts, vertexStride, fGeoData[i], fOpts); |
160 fGeoData[i], | |
161 canTweakAlphaForCoverage); | |
162 } | 133 } |
163 helper.recordDraw(target); | 134 helper.recordDraw(target); |
164 } | 135 } |
165 | 136 |
| 137 const Geometry& seedGeometry() const { return fGeoData[0]; } |
| 138 |
166 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | 139 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
167 AAFillRectBatch* that = t->cast<AAFillRectBatch>(); | 140 AAFillRectBatch* that = t->cast<AAFillRectBatch>(); |
168 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), | 141 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), |
169 that->bounds(), caps)) { | 142 that->bounds(), caps)) { |
170 return false; | 143 return false; |
171 } | 144 } |
172 | 145 |
173 if (!Base::CanCombineLocalCoords(this->viewMatrix(), that->viewMatrix(), | 146 if (!Base::CanCombine(this->seedGeometry(), that->seedGeometry(), fOpts)
) { |
174 this->usesLocalCoords())) { | |
175 return false; | 147 return false; |
176 } | 148 } |
177 | 149 |
178 if (this->color() != that->color()) { | |
179 fBatch.fColor = GrColor_ILLEGAL; | |
180 } | |
181 | |
182 // In the event of two batches, one who can tweak, one who cannot, we ju
st fall back to | 150 // In the event of two batches, one who can tweak, one who cannot, we ju
st fall back to |
183 // not tweaking | 151 // not tweaking |
184 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage()
) { | 152 if (fOpts.canTweakAlphaForCoverage() && !that->fOpts.canTweakAlphaForCov
erage()) { |
185 fBatch.fCanTweakAlphaForCoverage = false; | 153 fOpts = that->fOpts; |
186 } | 154 } |
187 | 155 |
188 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin())
; | 156 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin())
; |
189 this->joinBounds(that->bounds()); | 157 this->joinBounds(that->bounds()); |
190 return true; | 158 return true; |
191 } | 159 } |
192 | 160 |
193 void generateAAFillRectGeometry(void* vertices, | 161 GrPipelineOptimizations fOpts; |
194 size_t offset, | 162 SkSTArray<1, Geometry, true> fGeoData; |
195 size_t vertexStride, | 163 }; |
196 const Geometry& args, | |
197 bool tweakAlphaForCoverage) const { | |
198 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset; | |
199 | 164 |
200 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); | 165 static const GrGeometryProcessor* create_fill_rect_gp( |
201 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride); | 166 const SkMatrix& viewMatrix, |
| 167 const GrPipelineOptimizations& opts, |
| 168 GrDefaultGeoProcFactory::LocalCoords::Typ
e localCoordsType) { |
| 169 using namespace GrDefaultGeoProcFactory; |
202 | 170 |
203 SkScalar inset = SkMinScalar(args.fDevRect.width(), SK_Scalar1); | 171 Color color(Color::kAttribute_Type); |
204 inset = SK_ScalarHalf * SkMinScalar(inset, args.fDevRect.height()); | 172 Coverage::Type coverageType; |
| 173 // TODO remove coverage if coverage is ignored |
| 174 /*if (coverageIgnored) { |
| 175 coverageType = Coverage::kNone_Type; |
| 176 } else*/ if (opts.canTweakAlphaForCoverage()) { |
| 177 coverageType = Coverage::kSolid_Type; |
| 178 } else { |
| 179 coverageType = Coverage::kAttribute_Type; |
| 180 } |
| 181 Coverage coverage(coverageType); |
205 | 182 |
206 if (args.fViewMatrix.rectStaysRect()) { | 183 // We assume the caller has inverted the viewmatrix |
207 set_inset_fan(fan0Pos, vertexStride, args.fDevRect, -SK_ScalarHalf,
-SK_ScalarHalf); | 184 if (LocalCoords::kHasExplicit_Type == localCoordsType) { |
208 set_inset_fan(fan1Pos, vertexStride, args.fDevRect, inset, inset); | 185 LocalCoords localCoords(localCoordsType); |
| 186 return GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkM
atrix::I()); |
| 187 } else { |
| 188 LocalCoords localCoords(opts.readsLocalCoords() ? localCoordsType : |
| 189 LocalCoords::kUnused_T
ype); |
| 190 return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix); |
| 191 } |
| 192 } |
| 193 |
| 194 static void generate_aa_fill_rect_geometry(intptr_t verts, |
| 195 size_t vertexStride, |
| 196 GrColor color, |
| 197 const SkMatrix& viewMatrix, |
| 198 const SkRect& rect, |
| 199 const SkRect& devRect, |
| 200 const GrPipelineOptimizations& opts, |
| 201 const SkMatrix* localMatrix) { |
| 202 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); |
| 203 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride); |
| 204 |
| 205 SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1); |
| 206 inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height()); |
| 207 |
| 208 if (viewMatrix.rectStaysRect()) { |
| 209 set_inset_fan(fan0Pos, vertexStride, devRect, -SK_ScalarHalf, -SK_Scalar
Half); |
| 210 set_inset_fan(fan1Pos, vertexStride, devRect, inset, inset); |
| 211 } else { |
| 212 // compute transformed (1, 0) and (0, 1) vectors |
| 213 SkVector vec[2] = { |
| 214 { viewMatrix[SkMatrix::kMScaleX], viewMatrix[SkMatrix::kMSkewY] }, |
| 215 { viewMatrix[SkMatrix::kMSkewX], viewMatrix[SkMatrix::kMScaleY] } |
| 216 }; |
| 217 |
| 218 vec[0].normalize(); |
| 219 vec[0].scale(SK_ScalarHalf); |
| 220 vec[1].normalize(); |
| 221 vec[1].scale(SK_ScalarHalf); |
| 222 |
| 223 // create the rotated rect |
| 224 fan0Pos->setRectFan(rect.fLeft, rect.fTop, |
| 225 rect.fRight, rect.fBottom, vertexStride); |
| 226 viewMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4); |
| 227 |
| 228 // Now create the inset points and then outset the original |
| 229 // rotated points |
| 230 |
| 231 // TL |
| 232 *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) = |
| 233 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + vec[1
]; |
| 234 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[1]; |
| 235 // BL |
| 236 *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) = |
| 237 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - vec[1
]; |
| 238 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[1]; |
| 239 // BR |
| 240 *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) = |
| 241 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - vec[1
]; |
| 242 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[1]; |
| 243 // TR |
| 244 *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) = |
| 245 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + vec[1
]; |
| 246 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[1]; |
| 247 } |
| 248 |
| 249 if (localMatrix) { |
| 250 SkMatrix invViewMatrix; |
| 251 if (!viewMatrix.invert(&invViewMatrix)) { |
| 252 SkASSERT(false); |
| 253 invViewMatrix = SkMatrix::I(); |
| 254 } |
| 255 SkMatrix localCoordMatrix; |
| 256 localCoordMatrix.setConcat(*localMatrix, invViewMatrix); |
| 257 SkPoint* fan0Loc = reinterpret_cast<SkPoint*>(verts + sizeof(SkPoint) +
sizeof(GrColor)); |
| 258 localCoordMatrix.mapPointsWithStride(fan0Loc, fan0Pos, vertexStride, 8); |
| 259 } |
| 260 |
| 261 bool tweakAlphaForCoverage = opts.canTweakAlphaForCoverage(); |
| 262 |
| 263 // Make verts point to vertex color and then set all the color and coverage
vertex attrs |
| 264 // values. |
| 265 verts += sizeof(SkPoint); |
| 266 |
| 267 // The coverage offset is always the last vertex attribute |
| 268 intptr_t coverageOffset = vertexStride - sizeof(GrColor) - sizeof(SkPoint); |
| 269 for (int i = 0; i < 4; ++i) { |
| 270 if (tweakAlphaForCoverage) { |
| 271 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; |
209 } else { | 272 } else { |
210 // compute transformed (1, 0) and (0, 1) vectors | 273 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; |
211 SkVector vec[2] = { | 274 *reinterpret_cast<float*>(verts + i * vertexStride + coverageOffset)
= 0; |
212 { args.fViewMatrix[SkMatrix::kMScaleX], args.fViewMatrix[SkMatrix:
:kMSkewY] }, | |
213 { args.fViewMatrix[SkMatrix::kMSkewX], args.fViewMatrix[SkMatrix:
:kMScaleY] } | |
214 }; | |
215 | |
216 vec[0].normalize(); | |
217 vec[0].scale(SK_ScalarHalf); | |
218 vec[1].normalize(); | |
219 vec[1].scale(SK_ScalarHalf); | |
220 | |
221 // create the rotated rect | |
222 fan0Pos->setRectFan(args.fRect.fLeft, args.fRect.fTop, | |
223 args.fRect.fRight, args.fRect.fBottom, vertexStr
ide); | |
224 args.fViewMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4); | |
225 | |
226 // Now create the inset points and then outset the original | |
227 // rotated points | |
228 | |
229 // TL | |
230 *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) = | |
231 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + v
ec[1]; | |
232 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[
1]; | |
233 // BL | |
234 *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) = | |
235 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - v
ec[1]; | |
236 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[
1]; | |
237 // BR | |
238 *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) = | |
239 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - v
ec[1]; | |
240 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[
1]; | |
241 // TR | |
242 *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) = | |
243 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + v
ec[1]; | |
244 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[
1]; | |
245 } | |
246 | |
247 Base::FillInAttributes(verts, vertexStride, fan0Pos, args); | |
248 | |
249 // Make verts point to vertex color and then set all the color and cover
age vertex attrs | |
250 // values. | |
251 verts += sizeof(SkPoint); | |
252 | |
253 // The coverage offset is always the last vertex attribute | |
254 intptr_t coverageOffset = vertexStride - sizeof(GrColor) - sizeof(SkPoin
t); | |
255 for (int i = 0; i < 4; ++i) { | |
256 if (tweakAlphaForCoverage) { | |
257 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; | |
258 } else { | |
259 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = args.fCo
lor; | |
260 *reinterpret_cast<float*>(verts + i * vertexStride + coverageOff
set) = 0; | |
261 } | |
262 } | |
263 | |
264 int scale; | |
265 if (inset < SK_ScalarHalf) { | |
266 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf))
; | |
267 SkASSERT(scale >= 0 && scale <= 255); | |
268 } else { | |
269 scale = 0xff; | |
270 } | |
271 | |
272 verts += 4 * vertexStride; | |
273 | |
274 float innerCoverage = GrNormalizeByteToFloat(scale); | |
275 GrColor scaledColor = (0xff == scale) ? args.fColor : SkAlphaMulQ(args.f
Color, scale); | |
276 | |
277 for (int i = 0; i < 4; ++i) { | |
278 if (tweakAlphaForCoverage) { | |
279 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledCo
lor; | |
280 } else { | |
281 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = args.fCo
lor; | |
282 *reinterpret_cast<float*>(verts + i * vertexStride + | |
283 coverageOffset) = innerCoverage; | |
284 } | |
285 } | 275 } |
286 } | 276 } |
287 | 277 |
288 static const GrGeometryProcessor* CreateFillRectGP( | 278 int scale; |
289 bool tweakAlphaForCoverage, | 279 if (inset < SK_ScalarHalf) { |
290 const SkMatrix& viewMatrix, | 280 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); |
291 bool usesLocalCoords, | 281 SkASSERT(scale >= 0 && scale <= 255); |
292 GrDefaultGeoProcFactory::LocalCoords::T
ype localCoordsType, | 282 } else { |
293 bool coverageIgnored) { | 283 scale = 0xff; |
294 using namespace GrDefaultGeoProcFactory; | 284 } |
295 | 285 |
296 Color color(Color::kAttribute_Type); | 286 verts += 4 * vertexStride; |
297 Coverage::Type coverageType; | 287 |
298 // TODO remove coverage if coverage is ignored | 288 float innerCoverage = GrNormalizeByteToFloat(scale); |
299 /*if (coverageIgnored) { | 289 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); |
300 coverageType = Coverage::kNone_Type; | 290 |
301 } else*/ if (tweakAlphaForCoverage) { | 291 for (int i = 0; i < 4; ++i) { |
302 coverageType = Coverage::kSolid_Type; | 292 if (tweakAlphaForCoverage) { |
| 293 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; |
303 } else { | 294 } else { |
304 coverageType = Coverage::kAttribute_Type; | 295 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; |
305 } | 296 *reinterpret_cast<float*>(verts + i * vertexStride + |
306 Coverage coverage(coverageType); | 297 coverageOffset) = innerCoverage; |
307 | |
308 // We assume the caller has inverted the viewmatrix | |
309 if (LocalCoords::kHasExplicit_Type == localCoordsType) { | |
310 LocalCoords localCoords(localCoordsType); | |
311 return GrDefaultGeoProcFactory::Create(color, coverage, localCoords,
SkMatrix::I()); | |
312 } else { | |
313 LocalCoords localCoords(usesLocalCoords ? localCoordsType : LocalCoo
rds::kUnused_Type); | |
314 return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix
); | |
315 } | 298 } |
316 } | 299 } |
317 | 300 } |
318 struct BatchTracker { | |
319 GrColor fColor; | |
320 bool fUsesLocalCoords; | |
321 bool fColorIgnored; | |
322 bool fCoverageIgnored; | |
323 bool fCanTweakAlphaForCoverage; | |
324 }; | |
325 | |
326 BatchTracker fBatch; | |
327 SkSTArray<1, Geometry, true> fGeoData; | |
328 }; | |
329 | 301 |
330 class AAFillRectBatchNoLocalMatrixImp { | 302 class AAFillRectBatchNoLocalMatrixImp { |
331 public: | 303 public: |
332 struct Geometry { | 304 struct Geometry { |
333 SkMatrix fViewMatrix; | 305 SkMatrix fViewMatrix; |
334 SkRect fRect; | 306 SkRect fRect; |
335 SkRect fDevRect; | 307 SkRect fDevRect; |
336 GrColor fColor; | 308 GrColor fColor; |
337 }; | 309 }; |
338 | 310 |
339 inline static bool CanCombineLocalCoords(const SkMatrix& mine, const SkMatri
x& theirs, | 311 inline static bool CanCombine(const Geometry& mine, const Geometry& theirs, |
340 bool usesLocalCoords) { | 312 const GrPipelineOptimizations& opts) { |
341 // We apply the viewmatrix to the rect points on the cpu. However, if t
he pipeline uses | 313 // We apply the viewmatrix to the rect points on the cpu. However, if t
he pipeline uses |
342 // local coords then we won't be able to batch. We could actually uploa
d the viewmatrix | 314 // local coords then we won't be able to batch. We could actually uploa
d the viewmatrix |
343 // using vertex attributes in these cases, but haven't investigated that | 315 // using vertex attributes in these cases, but haven't investigated that |
344 return !usesLocalCoords || mine.cheapEqualTo(theirs); | 316 return !opts.readsLocalCoords() || mine.fViewMatrix.cheapEqualTo(theirs.
fViewMatrix); |
345 } | 317 } |
346 | 318 |
347 inline static GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType() { | 319 inline static const GrGeometryProcessor* CreateGP(const Geometry& geo, |
348 return GrDefaultGeoProcFactory::LocalCoords::kUsePosition_Type; | 320 const GrPipelineOptimizati
ons& opts) { |
| 321 const GrGeometryProcessor* gp = |
| 322 create_fill_rect_gp(geo.fViewMatrix, opts, |
| 323 GrDefaultGeoProcFactory::LocalCoords::kUsePo
sition_Type); |
| 324 |
| 325 SkASSERT(opts.canTweakAlphaForCoverage() ? |
| 326 gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::Positi
onColorAttr) : |
| 327 gp->getVertexStride() == |
| 328 sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAt
tr)); |
| 329 return gp; |
349 } | 330 } |
350 | 331 |
351 inline static bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCov
erage, | 332 inline static void Tesselate(intptr_t vertices, size_t vertexStride, const G
eometry& geo, |
352 bool usesLocalCoords) { | 333 const GrPipelineOptimizations& opts) { |
353 return canTweakAlphaForCoverage ? | 334 generate_aa_fill_rect_geometry(vertices, vertexStride, |
354 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt
tr) : | 335 geo.fColor, geo.fViewMatrix, geo.fRect, g
eo.fDevRect, opts, |
355 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo
verageAttr); | 336 NULL); |
356 } | 337 } |
357 | |
358 inline static void FillInAttributes(intptr_t, size_t, SkPoint*, const Geomet
ry&) {} | |
359 }; | 338 }; |
360 | 339 |
361 class AAFillRectBatchLocalMatrixImp { | 340 class AAFillRectBatchLocalMatrixImp { |
362 public: | 341 public: |
363 struct Geometry { | 342 struct Geometry { |
364 SkMatrix fViewMatrix; | 343 SkMatrix fViewMatrix; |
365 SkMatrix fLocalMatrix; | 344 SkMatrix fLocalMatrix; |
366 SkRect fRect; | 345 SkRect fRect; |
367 SkRect fDevRect; | 346 SkRect fDevRect; |
368 GrColor fColor; | 347 GrColor fColor; |
369 }; | 348 }; |
370 | 349 |
371 inline static bool CanCombineLocalCoords(const SkMatrix& mine, const SkMatri
x& theirs, | 350 inline static bool CanCombine(const Geometry& mine, const Geometry& theirs, |
372 bool usesLocalCoords) { | 351 const GrPipelineOptimizations&) { |
373 return true; | 352 return true; |
374 } | 353 } |
375 | 354 |
376 inline static GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType() { | 355 inline static const GrGeometryProcessor* CreateGP(const Geometry& geo, |
377 return GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type; | 356 const GrPipelineOptimizati
ons& opts) { |
| 357 const GrGeometryProcessor* gp = |
| 358 create_fill_rect_gp(geo.fViewMatrix, opts, |
| 359 GrDefaultGeoProcFactory::LocalCoords::kHasEx
plicit_Type); |
| 360 |
| 361 SkASSERT(opts.canTweakAlphaForCoverage() ? |
| 362 gp->getVertexStride() == |
| 363 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoord
Attr) : |
| 364 gp->getVertexStride() == |
| 365 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoord
Coverage)); |
| 366 return gp; |
378 } | 367 } |
379 | 368 |
380 inline static bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCov
erage, | 369 inline static void Tesselate(intptr_t vertices, size_t vertexStride, const G
eometry& geo, |
381 bool usesLocalCoords) { | 370 const GrPipelineOptimizations& opts) { |
382 // Whomever created us should not have done so if there are no local coo
rds | 371 generate_aa_fill_rect_geometry(vertices, vertexStride, |
383 return canTweakAlphaForCoverage ? | 372 geo.fColor, geo.fViewMatrix, geo.fRect, g
eo.fDevRect, opts, |
384 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLo
calCoordAttr) : | 373 &geo.fLocalMatrix); |
385 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLo
calCoordCoverage); | |
386 } | |
387 | |
388 inline static void FillInAttributes(intptr_t vertices, size_t vertexStride, | |
389 SkPoint* fan0Pos, const Geometry& args)
{ | |
390 SkMatrix invViewMatrix; | |
391 if (!args.fViewMatrix.invert(&invViewMatrix)) { | |
392 SkASSERT(false); | |
393 invViewMatrix = SkMatrix::I(); | |
394 } | |
395 SkMatrix localCoordMatrix; | |
396 localCoordMatrix.setConcat(args.fLocalMatrix, invViewMatrix); | |
397 SkPoint* fan0Loc = reinterpret_cast<SkPoint*>(vertices + sizeof(SkPoint)
+ sizeof(GrColor)); | |
398 localCoordMatrix.mapPointsWithStride(fan0Loc, fan0Pos, vertexStride, 8); | |
399 } | 374 } |
400 }; | 375 }; |
401 | 376 |
402 typedef AAFillRectBatch<AAFillRectBatchNoLocalMatrixImp> AAFillRectBatchNoLocalM
atrix; | 377 typedef AAFillRectBatch<AAFillRectBatchNoLocalMatrixImp> AAFillRectBatchNoLocalM
atrix; |
403 typedef AAFillRectBatch<AAFillRectBatchLocalMatrixImp> AAFillRectBatchLocalMatri
x; | 378 typedef AAFillRectBatch<AAFillRectBatchLocalMatrixImp> AAFillRectBatchLocalMatri
x; |
404 | 379 |
405 namespace GrAAFillRectBatch { | 380 namespace GrAAFillRectBatch { |
406 | 381 |
407 GrDrawBatch* Create(GrColor color, | 382 GrDrawBatch* Create(GrColor color, |
408 const SkMatrix& viewMatrix, | 383 const SkMatrix& viewMatrix, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 DRAW_BATCH_TEST_DEFINE(AAFillRectBatchLocalMatrix) { | 428 DRAW_BATCH_TEST_DEFINE(AAFillRectBatchLocalMatrix) { |
454 GrColor color = GrRandomColor(random); | 429 GrColor color = GrRandomColor(random); |
455 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); | 430 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); |
456 SkMatrix localMatrix = GrTest::TestMatrix(random); | 431 SkMatrix localMatrix = GrTest::TestMatrix(random); |
457 SkRect rect = GrTest::TestRect(random); | 432 SkRect rect = GrTest::TestRect(random); |
458 SkRect devRect = GrTest::TestRect(random); | 433 SkRect devRect = GrTest::TestRect(random); |
459 return GrAAFillRectBatch::Create(color, viewMatrix, localMatrix, rect, devRe
ct); | 434 return GrAAFillRectBatch::Create(color, viewMatrix, localMatrix, rect, devRe
ct); |
460 } | 435 } |
461 | 436 |
462 #endif | 437 #endif |
OLD | NEW |