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