| 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 |