Chromium Code Reviews| 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 |