| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 "GrOvalRenderer.h" | 8 #include "GrOvalRenderer.h" |
| 9 | 9 |
| 10 #include "GrBatchFlushState.h" | 10 #include "GrBatchFlushState.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 return m.isSimilarity(); | 55 return m.isSimilarity(); |
| 56 } | 56 } |
| 57 | 57 |
| 58 } | 58 } |
| 59 | 59 |
| 60 /////////////////////////////////////////////////////////////////////////////// | 60 /////////////////////////////////////////////////////////////////////////////// |
| 61 | 61 |
| 62 /** | 62 /** |
| 63 * The output of this effect is a modulation of the input color and coverage for
a circle. It | 63 * The output of this effect is a modulation of the input color and coverage for
a circle. It |
| 64 * operates in a space normalized by the circle radius (outer radius in the case
of a stroke) | 64 * operates in a space normalized by the circle radius (outer radius in the case
of a stroke) |
| 65 * with origin at the circle center. Two vertex attributes are used: | 65 * with origin at the circle center. Three vertex attributes are used: |
| 66 * vec2f : position in device space of the bounding geometry vertices | 66 * vec2f : position in device space of the bounding geometry vertices |
| 67 * vec4ub: color |
| 67 * vec4f : (p.xy, outerRad, innerRad) | 68 * vec4f : (p.xy, outerRad, innerRad) |
| 68 * p is the position in the normalized space. | 69 * p is the position in the normalized space. |
| 69 * outerRad is the outerRadius in device space. | 70 * outerRad is the outerRadius in device space. |
| 70 * innerRad is the innerRadius in normalized space (ignored if not s
troking). | 71 * innerRad is the innerRadius in normalized space (ignored if not s
troking). |
| 71 */ | 72 */ |
| 72 | 73 |
| 73 class CircleEdgeEffect : public GrGeometryProcessor { | 74 class CircleGeometryProcessor : public GrGeometryProcessor { |
| 74 public: | 75 public: |
| 75 static GrGeometryProcessor* Create(GrColor color, bool stroke, const SkMatri
x& localMatrix, | 76 CircleGeometryProcessor(bool stroke, const SkMatrix& localMatrix) : fLocalMa
trix(localMatrix){ |
| 76 bool usesLocalCoords) { | 77 this->initClassID<CircleGeometryProcessor>(); |
| 77 return new CircleEdgeEffect(color, stroke, localMatrix, usesLocalCoords)
; | 78 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe
rtexAttribType, |
| 79 kHigh_GrSLPrecision)); |
| 80 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexA
ttribType)); |
| 81 fInCircleEdge = &this->addVertexAttrib(Attribute("inCircleEdge", |
| 82 kVec4f_GrVertexAttribTy
pe)); |
| 83 fStroke = stroke; |
| 78 } | 84 } |
| 79 | 85 |
| 80 const Attribute* inPosition() const { return fInPosition; } | 86 const Attribute* inPosition() const { return fInPosition; } |
| 81 const Attribute* inColor() const { return fInColor; } | 87 const Attribute* inColor() const { return fInColor; } |
| 82 const Attribute* inCircleEdge() const { return fInCircleEdge; } | 88 const Attribute* inCircleEdge() const { return fInCircleEdge; } |
| 83 GrColor color() const { return fColor; } | |
| 84 bool colorIgnored() const { return GrColor_ILLEGAL == fColor; } | |
| 85 const SkMatrix& localMatrix() const { return fLocalMatrix; } | 89 const SkMatrix& localMatrix() const { return fLocalMatrix; } |
| 86 bool usesLocalCoords() const { return fUsesLocalCoords; } | 90 virtual ~CircleGeometryProcessor() {} |
| 87 virtual ~CircleEdgeEffect() {} | |
| 88 | 91 |
| 89 const char* name() const override { return "CircleEdge"; } | 92 const char* name() const override { return "CircleEdge"; } |
| 90 | 93 |
| 91 inline bool isStroked() const { return fStroke; } | |
| 92 | |
| 93 class GLSLProcessor : public GrGLSLGeometryProcessor { | 94 class GLSLProcessor : public GrGLSLGeometryProcessor { |
| 94 public: | 95 public: |
| 95 GLSLProcessor() {} | 96 GLSLProcessor() {} |
| 96 | 97 |
| 97 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ | 98 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ |
| 98 const CircleEdgeEffect& ce = args.fGP.cast<CircleEdgeEffect>(); | 99 const CircleGeometryProcessor& cgp = args.fGP.cast<CircleGeometryPro
cessor>(); |
| 99 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; | 100 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; |
| 100 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; | 101 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; |
| 101 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; | 102 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
| 102 | 103 |
| 103 // emit attributes | 104 // emit attributes |
| 104 varyingHandler->emitAttributes(ce); | 105 varyingHandler->emitAttributes(cgp); |
| 105 | 106 |
| 106 GrGLSLVertToFrag v(kVec4f_GrSLType); | 107 GrGLSLVertToFrag v(kVec4f_GrSLType); |
| 107 varyingHandler->addVarying("CircleEdge", &v); | 108 varyingHandler->addVarying("CircleEdge", &v); |
| 108 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), ce.inCircleEdge()->f
Name); | 109 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), cgp.inCircleEdge()->
fName); |
| 109 | 110 |
| 110 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; | 111 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; |
| 111 // setup pass through color | 112 // setup pass through color |
| 112 if (!ce.colorIgnored()) { | 113 varyingHandler->addPassThroughAttribute(cgp.inColor(), args.fOutputC
olor); |
| 113 varyingHandler->addPassThroughAttribute(ce.inColor(), args.fOutp
utColor); | |
| 114 } | |
| 115 | 114 |
| 116 // Setup position | 115 // Setup position |
| 117 this->setupPosition(vertBuilder, gpArgs, ce.inPosition()->fName); | 116 this->setupPosition(vertBuilder, gpArgs, cgp.inPosition()->fName); |
| 118 | 117 |
| 119 // emit transforms | 118 // emit transforms |
| 120 this->emitTransforms(vertBuilder, | 119 this->emitTransforms(vertBuilder, |
| 121 varyingHandler, | 120 varyingHandler, |
| 122 uniformHandler, | 121 uniformHandler, |
| 123 gpArgs->fPositionVar, | 122 gpArgs->fPositionVar, |
| 124 ce.inPosition()->fName, | 123 cgp.inPosition()->fName, |
| 125 ce.localMatrix(), | 124 cgp.localMatrix(), |
| 126 args.fTransformsIn, | 125 args.fTransformsIn, |
| 127 args.fTransformsOut); | 126 args.fTransformsOut); |
| 128 | 127 |
| 129 fragBuilder->codeAppendf("float d = length(%s.xy);", v.fsIn()); | 128 fragBuilder->codeAppendf("float d = length(%s.xy);", v.fsIn()); |
| 130 fragBuilder->codeAppendf("float edgeAlpha = clamp(%s.z * (1.0 - d),
0.0, 1.0);", | 129 fragBuilder->codeAppendf("float edgeAlpha = clamp(%s.z * (1.0 - d),
0.0, 1.0);", |
| 131 v.fsIn()); | 130 v.fsIn()); |
| 132 if (ce.isStroked()) { | 131 if (cgp.fStroke) { |
| 133 fragBuilder->codeAppendf("float innerAlpha = clamp(%s.z * (d - %
s.w), 0.0, 1.0);", | 132 fragBuilder->codeAppendf("float innerAlpha = clamp(%s.z * (d - %
s.w), 0.0, 1.0);", |
| 134 v.fsIn(), v.fsIn()); | 133 v.fsIn(), v.fsIn()); |
| 135 fragBuilder->codeAppend("edgeAlpha *= innerAlpha;"); | 134 fragBuilder->codeAppend("edgeAlpha *= innerAlpha;"); |
| 136 } | 135 } |
| 137 | 136 |
| 138 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera
ge); | 137 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera
ge); |
| 139 } | 138 } |
| 140 | 139 |
| 141 static void GenKey(const GrGeometryProcessor& gp, | 140 static void GenKey(const GrGeometryProcessor& gp, |
| 142 const GrGLSLCaps&, | 141 const GrGLSLCaps&, |
| 143 GrProcessorKeyBuilder* b) { | 142 GrProcessorKeyBuilder* b) { |
| 144 const CircleEdgeEffect& ce = gp.cast<CircleEdgeEffect>(); | 143 const CircleGeometryProcessor& cgp = gp.cast<CircleGeometryProcessor
>(); |
| 145 uint16_t key = ce.isStroked() ? 0x1 : 0x0; | 144 uint16_t key = cgp.fStroke ? 0x1 : 0x0; |
| 146 key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0
x2 : 0x0; | 145 key |= cgp.localMatrix().hasPerspective() ? 0x2 : 0x0; |
| 147 key |= ce.colorIgnored() ? 0x4 : 0x0; | |
| 148 b->add32(key); | 146 b->add32(key); |
| 149 } | 147 } |
| 150 | 148 |
| 151 void setData(const GrGLSLProgramDataManager& pdman, | 149 void setData(const GrGLSLProgramDataManager& pdman, |
| 152 const GrPrimitiveProcessor& gp) override { | 150 const GrPrimitiveProcessor& gp) override { |
| 153 } | 151 } |
| 154 | 152 |
| 155 void setTransformData(const GrPrimitiveProcessor& primProc, | 153 void setTransformData(const GrPrimitiveProcessor& primProc, |
| 156 const GrGLSLProgramDataManager& pdman, | 154 const GrGLSLProgramDataManager& pdman, |
| 157 int index, | 155 int index, |
| 158 const SkTArray<const GrCoordTransform*, true>& tra
nsforms) override { | 156 const SkTArray<const GrCoordTransform*, true>& tra
nsforms) override { |
| 159 this->setTransformDataHelper<CircleEdgeEffect>(primProc, pdman, inde
x, transforms); | 157 this->setTransformDataHelper<CircleGeometryProcessor>(primProc, pdma
n, index, |
| 158 transforms); |
| 160 } | 159 } |
| 161 | 160 |
| 162 private: | 161 private: |
| 163 typedef GrGLSLGeometryProcessor INHERITED; | 162 typedef GrGLSLGeometryProcessor INHERITED; |
| 164 }; | 163 }; |
| 165 | 164 |
| 166 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override { | 165 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override { |
| 167 GLSLProcessor::GenKey(*this, caps, b); | 166 GLSLProcessor::GenKey(*this, caps, b); |
| 168 } | 167 } |
| 169 | 168 |
| 170 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri
de { | 169 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri
de { |
| 171 return new GLSLProcessor(); | 170 return new GLSLProcessor(); |
| 172 } | 171 } |
| 173 | 172 |
| 174 private: | 173 private: |
| 175 CircleEdgeEffect(GrColor color, bool stroke, const SkMatrix& localMatrix, bo
ol usesLocalCoords) | 174 SkMatrix fLocalMatrix; |
| 176 : fColor(color) | |
| 177 , fLocalMatrix(localMatrix) | |
| 178 , fUsesLocalCoords(usesLocalCoords) { | |
| 179 this->initClassID<CircleEdgeEffect>(); | |
| 180 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe
rtexAttribType, | |
| 181 kHigh_GrSLPrecision)); | |
| 182 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexA
ttribType)); | |
| 183 fInCircleEdge = &this->addVertexAttrib(Attribute("inCircleEdge", | |
| 184 kVec4f_GrVertexAttrib
Type)); | |
| 185 fStroke = stroke; | |
| 186 } | |
| 187 | |
| 188 GrColor fColor; | |
| 189 SkMatrix fLocalMatrix; | |
| 190 const Attribute* fInPosition; | 175 const Attribute* fInPosition; |
| 191 const Attribute* fInColor; | 176 const Attribute* fInColor; |
| 192 const Attribute* fInCircleEdge; | 177 const Attribute* fInCircleEdge; |
| 193 bool fStroke; | 178 bool fStroke; |
| 194 bool fUsesLocalCoords; | |
| 195 | 179 |
| 196 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; | 180 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; |
| 197 | 181 |
| 198 typedef GrGeometryProcessor INHERITED; | 182 typedef GrGeometryProcessor INHERITED; |
| 199 }; | 183 }; |
| 200 | 184 |
| 201 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleEdgeEffect); | 185 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleGeometryProcessor); |
| 202 | 186 |
| 203 const GrGeometryProcessor* CircleEdgeEffect::TestCreate(GrProcessorTestData* d)
{ | 187 const GrGeometryProcessor* CircleGeometryProcessor::TestCreate(GrProcessorTestDa
ta* d) { |
| 204 return CircleEdgeEffect::Create(GrRandomColor(d->fRandom), | 188 return new CircleGeometryProcessor(d->fRandom->nextBool(), GrTest::TestMatri
x(d->fRandom)); |
| 205 d->fRandom->nextBool(), | |
| 206 GrTest::TestMatrix(d->fRandom), | |
| 207 d->fRandom->nextBool()); | |
| 208 } | 189 } |
| 209 | 190 |
| 210 /////////////////////////////////////////////////////////////////////////////// | 191 /////////////////////////////////////////////////////////////////////////////// |
| 211 | 192 |
| 212 /** | 193 /** |
| 213 * The output of this effect is a modulation of the input color and coverage for
an axis-aligned | 194 * The output of this effect is a modulation of the input color and coverage for
an axis-aligned |
| 214 * ellipse, specified as a 2D offset from center, and the reciprocals of the out
er and inner radii, | 195 * ellipse, specified as a 2D offset from center, and the reciprocals of the out
er and inner radii, |
| 215 * in both x and y directions. | 196 * in both x and y directions. |
| 216 * | 197 * |
| 217 * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0. | 198 * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0. |
| 218 */ | 199 */ |
| 219 | 200 |
| 220 class EllipseEdgeEffect : public GrGeometryProcessor { | 201 class EllipseGeometryProcessor : public GrGeometryProcessor { |
| 221 public: | 202 public: |
| 222 static GrGeometryProcessor* Create(GrColor color, bool stroke, const SkMatri
x& localMatrix, | 203 EllipseGeometryProcessor(bool stroke, const SkMatrix& localMatrix) |
| 223 bool usesLocalCoords) { | 204 : fLocalMatrix(localMatrix) { |
| 224 return new EllipseEdgeEffect(color, stroke, localMatrix, usesLocalCoords
); | 205 this->initClassID<EllipseGeometryProcessor>(); |
| 206 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe
rtexAttribType)); |
| 207 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexA
ttribType)); |
| 208 fInEllipseOffset = &this->addVertexAttrib(Attribute("inEllipseOffset", |
| 209 kVec2f_GrVertexAttri
bType)); |
| 210 fInEllipseRadii = &this->addVertexAttrib(Attribute("inEllipseRadii", |
| 211 kVec4f_GrVertexAttrib
Type)); |
| 212 fStroke = stroke; |
| 225 } | 213 } |
| 226 | 214 |
| 227 virtual ~EllipseEdgeEffect() {} | 215 virtual ~EllipseGeometryProcessor() {} |
| 228 | 216 |
| 229 const char* name() const override { return "EllipseEdge"; } | 217 const char* name() const override { return "EllipseEdge"; } |
| 230 | 218 |
| 231 const Attribute* inPosition() const { return fInPosition; } | 219 const Attribute* inPosition() const { return fInPosition; } |
| 232 const Attribute* inColor() const { return fInColor; } | 220 const Attribute* inColor() const { return fInColor; } |
| 233 const Attribute* inEllipseOffset() const { return fInEllipseOffset; } | 221 const Attribute* inEllipseOffset() const { return fInEllipseOffset; } |
| 234 const Attribute* inEllipseRadii() const { return fInEllipseRadii; } | 222 const Attribute* inEllipseRadii() const { return fInEllipseRadii; } |
| 235 GrColor color() const { return fColor; } | |
| 236 bool colorIgnored() const { return GrColor_ILLEGAL == fColor; } | |
| 237 const SkMatrix& localMatrix() const { return fLocalMatrix; } | 223 const SkMatrix& localMatrix() const { return fLocalMatrix; } |
| 238 bool usesLocalCoords() const { return fUsesLocalCoords; } | |
| 239 | |
| 240 inline bool isStroked() const { return fStroke; } | |
| 241 | 224 |
| 242 class GLSLProcessor : public GrGLSLGeometryProcessor { | 225 class GLSLProcessor : public GrGLSLGeometryProcessor { |
| 243 public: | 226 public: |
| 244 GLSLProcessor() {} | 227 GLSLProcessor() {} |
| 245 | 228 |
| 246 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ | 229 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ |
| 247 const EllipseEdgeEffect& ee = args.fGP.cast<EllipseEdgeEffect>(); | 230 const EllipseGeometryProcessor& egp = args.fGP.cast<EllipseGeometryP
rocessor>(); |
| 248 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; | 231 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; |
| 249 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; | 232 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; |
| 250 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; | 233 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
| 251 | 234 |
| 252 // emit attributes | 235 // emit attributes |
| 253 varyingHandler->emitAttributes(ee); | 236 varyingHandler->emitAttributes(egp); |
| 254 | 237 |
| 255 GrGLSLVertToFrag ellipseOffsets(kVec2f_GrSLType); | 238 GrGLSLVertToFrag ellipseOffsets(kVec2f_GrSLType); |
| 256 varyingHandler->addVarying("EllipseOffsets", &ellipseOffsets); | 239 varyingHandler->addVarying("EllipseOffsets", &ellipseOffsets); |
| 257 vertBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(), | 240 vertBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(), |
| 258 ee.inEllipseOffset()->fName); | 241 egp.inEllipseOffset()->fName); |
| 259 | 242 |
| 260 GrGLSLVertToFrag ellipseRadii(kVec4f_GrSLType); | 243 GrGLSLVertToFrag ellipseRadii(kVec4f_GrSLType); |
| 261 varyingHandler->addVarying("EllipseRadii", &ellipseRadii); | 244 varyingHandler->addVarying("EllipseRadii", &ellipseRadii); |
| 262 vertBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), | 245 vertBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), |
| 263 ee.inEllipseRadii()->fName); | 246 egp.inEllipseRadii()->fName); |
| 264 | 247 |
| 265 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; | 248 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; |
| 266 // setup pass through color | 249 // setup pass through color |
| 267 if (!ee.colorIgnored()) { | 250 varyingHandler->addPassThroughAttribute(egp.inColor(), args.fOutputC
olor); |
| 268 varyingHandler->addPassThroughAttribute(ee.inColor(), args.fOutp
utColor); | |
| 269 } | |
| 270 | 251 |
| 271 // Setup position | 252 // Setup position |
| 272 this->setupPosition(vertBuilder, gpArgs, ee.inPosition()->fName); | 253 this->setupPosition(vertBuilder, gpArgs, egp.inPosition()->fName); |
| 273 | 254 |
| 274 // emit transforms | 255 // emit transforms |
| 275 this->emitTransforms(vertBuilder, | 256 this->emitTransforms(vertBuilder, |
| 276 varyingHandler, | 257 varyingHandler, |
| 277 uniformHandler, | 258 uniformHandler, |
| 278 gpArgs->fPositionVar, | 259 gpArgs->fPositionVar, |
| 279 ee.inPosition()->fName, | 260 egp.inPosition()->fName, |
| 280 ee.localMatrix(), | 261 egp.localMatrix(), |
| 281 args.fTransformsIn, | 262 args.fTransformsIn, |
| 282 args.fTransformsOut); | 263 args.fTransformsOut); |
| 283 | 264 |
| 284 // for outer curve | 265 // for outer curve |
| 285 fragBuilder->codeAppendf("vec2 scaledOffset = %s*%s.xy;", ellipseOff
sets.fsIn(), | 266 fragBuilder->codeAppendf("vec2 scaledOffset = %s*%s.xy;", ellipseOff
sets.fsIn(), |
| 286 ellipseRadii.fsIn()); | 267 ellipseRadii.fsIn()); |
| 287 fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset
) - 1.0;"); | 268 fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset
) - 1.0;"); |
| 288 fragBuilder->codeAppendf("vec2 grad = 2.0*scaledOffset*%s.xy;", elli
pseRadii.fsIn()); | 269 fragBuilder->codeAppendf("vec2 grad = 2.0*scaledOffset*%s.xy;", elli
pseRadii.fsIn()); |
| 289 fragBuilder->codeAppend("float grad_dot = dot(grad, grad);"); | 270 fragBuilder->codeAppend("float grad_dot = dot(grad, grad);"); |
| 290 | 271 |
| 291 // avoid calling inversesqrt on zero. | 272 // avoid calling inversesqrt on zero. |
| 292 fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); | 273 fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); |
| 293 fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); | 274 fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); |
| 294 fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0.
0, 1.0);"); | 275 fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0.
0, 1.0);"); |
| 295 | 276 |
| 296 // for inner curve | 277 // for inner curve |
| 297 if (ee.isStroked()) { | 278 if (egp.fStroke) { |
| 298 fragBuilder->codeAppendf("scaledOffset = %s*%s.zw;", | 279 fragBuilder->codeAppendf("scaledOffset = %s*%s.zw;", |
| 299 ellipseOffsets.fsIn(), ellipseRadii.fsI
n()); | 280 ellipseOffsets.fsIn(), ellipseRadii.fsI
n()); |
| 300 fragBuilder->codeAppend("test = dot(scaledOffset, scaledOffset)
- 1.0;"); | 281 fragBuilder->codeAppend("test = dot(scaledOffset, scaledOffset)
- 1.0;"); |
| 301 fragBuilder->codeAppendf("grad = 2.0*scaledOffset*%s.zw;", | 282 fragBuilder->codeAppendf("grad = 2.0*scaledOffset*%s.zw;", |
| 302 ellipseRadii.fsIn()); | 283 ellipseRadii.fsIn()); |
| 303 fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));"
); | 284 fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));"
); |
| 304 fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0
, 1.0);"); | 285 fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0
, 1.0);"); |
| 305 } | 286 } |
| 306 | 287 |
| 307 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera
ge); | 288 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera
ge); |
| 308 } | 289 } |
| 309 | 290 |
| 310 static void GenKey(const GrGeometryProcessor& gp, | 291 static void GenKey(const GrGeometryProcessor& gp, |
| 311 const GrGLSLCaps&, | 292 const GrGLSLCaps&, |
| 312 GrProcessorKeyBuilder* b) { | 293 GrProcessorKeyBuilder* b) { |
| 313 const EllipseEdgeEffect& ee = gp.cast<EllipseEdgeEffect>(); | 294 const EllipseGeometryProcessor& egp = gp.cast<EllipseGeometryProcess
or>(); |
| 314 uint16_t key = ee.isStroked() ? 0x1 : 0x0; | 295 uint16_t key = egp.fStroke ? 0x1 : 0x0; |
| 315 key |= ee.usesLocalCoords() && ee.localMatrix().hasPerspective() ? 0
x2 : 0x0; | 296 key |= egp.localMatrix().hasPerspective() ? 0x2 : 0x0; |
| 316 key |= ee.colorIgnored() ? 0x4 : 0x0; | |
| 317 b->add32(key); | 297 b->add32(key); |
| 318 } | 298 } |
| 319 | 299 |
| 320 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitivePro
cessor& gp) override { | 300 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitivePro
cessor& gp) override { |
| 321 } | 301 } |
| 322 | 302 |
| 323 void setTransformData(const GrPrimitiveProcessor& primProc, | 303 void setTransformData(const GrPrimitiveProcessor& primProc, |
| 324 const GrGLSLProgramDataManager& pdman, | 304 const GrGLSLProgramDataManager& pdman, |
| 325 int index, | 305 int index, |
| 326 const SkTArray<const GrCoordTransform*, true>& tra
nsforms) override { | 306 const SkTArray<const GrCoordTransform*, true>& tra
nsforms) override { |
| 327 this->setTransformDataHelper<EllipseEdgeEffect>(primProc, pdman, ind
ex, transforms); | 307 this->setTransformDataHelper<EllipseGeometryProcessor>(primProc, pdm
an, index, |
| 308 transforms); |
| 328 } | 309 } |
| 329 | 310 |
| 330 private: | 311 private: |
| 331 typedef GrGLSLGeometryProcessor INHERITED; | 312 typedef GrGLSLGeometryProcessor INHERITED; |
| 332 }; | 313 }; |
| 333 | 314 |
| 334 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override { | 315 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override { |
| 335 GLSLProcessor::GenKey(*this, caps, b); | 316 GLSLProcessor::GenKey(*this, caps, b); |
| 336 } | 317 } |
| 337 | 318 |
| 338 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri
de { | 319 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri
de { |
| 339 return new GLSLProcessor(); | 320 return new GLSLProcessor(); |
| 340 } | 321 } |
| 341 | 322 |
| 342 private: | 323 private: |
| 343 EllipseEdgeEffect(GrColor color, bool stroke, const SkMatrix& localMatrix, | |
| 344 bool usesLocalCoords) | |
| 345 : fColor(color) | |
| 346 , fLocalMatrix(localMatrix) | |
| 347 , fUsesLocalCoords(usesLocalCoords) { | |
| 348 this->initClassID<EllipseEdgeEffect>(); | |
| 349 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe
rtexAttribType)); | |
| 350 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexA
ttribType)); | |
| 351 fInEllipseOffset = &this->addVertexAttrib(Attribute("inEllipseOffset", | |
| 352 kVec2f_GrVertexAttri
bType)); | |
| 353 fInEllipseRadii = &this->addVertexAttrib(Attribute("inEllipseRadii", | |
| 354 kVec4f_GrVertexAttrib
Type)); | |
| 355 fStroke = stroke; | |
| 356 } | |
| 357 | |
| 358 const Attribute* fInPosition; | 324 const Attribute* fInPosition; |
| 359 const Attribute* fInColor; | 325 const Attribute* fInColor; |
| 360 const Attribute* fInEllipseOffset; | 326 const Attribute* fInEllipseOffset; |
| 361 const Attribute* fInEllipseRadii; | 327 const Attribute* fInEllipseRadii; |
| 362 GrColor fColor; | |
| 363 SkMatrix fLocalMatrix; | 328 SkMatrix fLocalMatrix; |
| 364 bool fStroke; | 329 bool fStroke; |
| 365 bool fUsesLocalCoords; | |
| 366 | 330 |
| 367 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; | 331 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; |
| 368 | 332 |
| 369 typedef GrGeometryProcessor INHERITED; | 333 typedef GrGeometryProcessor INHERITED; |
| 370 }; | 334 }; |
| 371 | 335 |
| 372 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(EllipseEdgeEffect); | 336 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(EllipseGeometryProcessor); |
| 373 | 337 |
| 374 const GrGeometryProcessor* EllipseEdgeEffect::TestCreate(GrProcessorTestData* d)
{ | 338 const GrGeometryProcessor* EllipseGeometryProcessor::TestCreate(GrProcessorTestD
ata* d) { |
| 375 return EllipseEdgeEffect::Create(GrRandomColor(d->fRandom), | 339 return new EllipseGeometryProcessor(d->fRandom->nextBool(), GrTest::TestMatr
ix(d->fRandom)); |
| 376 d->fRandom->nextBool(), | |
| 377 GrTest::TestMatrix(d->fRandom), | |
| 378 d->fRandom->nextBool()); | |
| 379 } | 340 } |
| 380 | 341 |
| 381 /////////////////////////////////////////////////////////////////////////////// | 342 /////////////////////////////////////////////////////////////////////////////// |
| 382 | 343 |
| 383 /** | 344 /** |
| 384 * The output of this effect is a modulation of the input color and coverage for
an ellipse, | 345 * The output of this effect is a modulation of the input color and coverage for
an ellipse, |
| 385 * specified as a 2D offset from center for both the outer and inner paths (if s
troked). The | 346 * specified as a 2D offset from center for both the outer and inner paths (if s
troked). The |
| 386 * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge c
orrected by | 347 * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge c
orrected by |
| 387 * using differentials. | 348 * using differentials. |
| 388 * | 349 * |
| 389 * The result is device-independent and can be used with any affine matrix. | 350 * The result is device-independent and can be used with any affine matrix. |
| 390 */ | 351 */ |
| 391 | 352 |
| 392 class DIEllipseEdgeEffect : public GrGeometryProcessor { | 353 enum class DIEllipseStyle { kStroke = 0, kHairline, kFill }; |
| 354 |
| 355 class DIEllipseGeometryProcessor : public GrGeometryProcessor { |
| 393 public: | 356 public: |
| 394 enum Mode { kStroke = 0, kHairline, kFill }; | 357 DIEllipseGeometryProcessor(const SkMatrix& viewMatrix, DIEllipseStyle style) |
| 395 | 358 : fViewMatrix(viewMatrix) { |
| 396 static GrGeometryProcessor* Create(GrColor color, const SkMatrix& viewMatrix
, Mode mode, | 359 this->initClassID<DIEllipseGeometryProcessor>(); |
| 397 bool usesLocalCoords) { | 360 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe
rtexAttribType, |
| 398 return new DIEllipseEdgeEffect(color, viewMatrix, mode, usesLocalCoords)
; | 361 kHigh_GrSLPrecision)); |
| 362 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexA
ttribType)); |
| 363 fInEllipseOffsets0 = &this->addVertexAttrib(Attribute("inEllipseOffsets0
", |
| 364 kVec2f_GrVertexAtt
ribType)); |
| 365 fInEllipseOffsets1 = &this->addVertexAttrib(Attribute("inEllipseOffsets1
", |
| 366 kVec2f_GrVertexAtt
ribType)); |
| 367 fStyle = style; |
| 399 } | 368 } |
| 400 | 369 |
| 401 virtual ~DIEllipseEdgeEffect() {} | 370 |
| 371 virtual ~DIEllipseGeometryProcessor() {} |
| 402 | 372 |
| 403 const char* name() const override { return "DIEllipseEdge"; } | 373 const char* name() const override { return "DIEllipseEdge"; } |
| 404 | 374 |
| 405 const Attribute* inPosition() const { return fInPosition; } | 375 const Attribute* inPosition() const { return fInPosition; } |
| 406 const Attribute* inColor() const { return fInColor; } | 376 const Attribute* inColor() const { return fInColor; } |
| 407 const Attribute* inEllipseOffsets0() const { return fInEllipseOffsets0; } | 377 const Attribute* inEllipseOffsets0() const { return fInEllipseOffsets0; } |
| 408 const Attribute* inEllipseOffsets1() const { return fInEllipseOffsets1; } | 378 const Attribute* inEllipseOffsets1() const { return fInEllipseOffsets1; } |
| 409 GrColor color() const { return fColor; } | |
| 410 bool colorIgnored() const { return GrColor_ILLEGAL == fColor; } | |
| 411 const SkMatrix& viewMatrix() const { return fViewMatrix; } | 379 const SkMatrix& viewMatrix() const { return fViewMatrix; } |
| 412 bool usesLocalCoords() const { return fUsesLocalCoords; } | 380 |
| 413 | |
| 414 inline Mode getMode() const { return fMode; } | |
| 415 | |
| 416 class GLSLProcessor : public GrGLSLGeometryProcessor { | 381 class GLSLProcessor : public GrGLSLGeometryProcessor { |
| 417 public: | 382 public: |
| 418 GLSLProcessor() | 383 GLSLProcessor() |
| 419 : fViewMatrix(SkMatrix::InvalidMatrix()) {} | 384 : fViewMatrix(SkMatrix::InvalidMatrix()) {} |
| 420 | 385 |
| 421 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { | 386 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { |
| 422 const DIEllipseEdgeEffect& ee = args.fGP.cast<DIEllipseEdgeEffect>()
; | 387 const DIEllipseGeometryProcessor& diegp = args.fGP.cast<DIEllipseGeo
metryProcessor>(); |
| 423 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; | 388 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; |
| 424 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; | 389 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; |
| 425 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; | 390 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
| 426 | 391 |
| 427 // emit attributes | 392 // emit attributes |
| 428 varyingHandler->emitAttributes(ee); | 393 varyingHandler->emitAttributes(diegp); |
| 429 | 394 |
| 430 GrGLSLVertToFrag offsets0(kVec2f_GrSLType); | 395 GrGLSLVertToFrag offsets0(kVec2f_GrSLType); |
| 431 varyingHandler->addVarying("EllipseOffsets0", &offsets0); | 396 varyingHandler->addVarying("EllipseOffsets0", &offsets0); |
| 432 vertBuilder->codeAppendf("%s = %s;", offsets0.vsOut(), | 397 vertBuilder->codeAppendf("%s = %s;", offsets0.vsOut(), |
| 433 ee.inEllipseOffsets0()->fName); | 398 diegp.inEllipseOffsets0()->fName); |
| 434 | 399 |
| 435 GrGLSLVertToFrag offsets1(kVec2f_GrSLType); | 400 GrGLSLVertToFrag offsets1(kVec2f_GrSLType); |
| 436 varyingHandler->addVarying("EllipseOffsets1", &offsets1); | 401 varyingHandler->addVarying("EllipseOffsets1", &offsets1); |
| 437 vertBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), | 402 vertBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), |
| 438 ee.inEllipseOffsets1()->fName); | 403 diegp.inEllipseOffsets1()->fName); |
| 439 | 404 |
| 440 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; | 405 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; |
| 441 // setup pass through color | 406 varyingHandler->addPassThroughAttribute(diegp.inColor(), args.fOutpu
tColor); |
| 442 if (!ee.colorIgnored()) { | |
| 443 varyingHandler->addPassThroughAttribute(ee.inColor(), args.fOutp
utColor); | |
| 444 } | |
| 445 | 407 |
| 446 // Setup position | 408 // Setup position |
| 447 this->setupPosition(vertBuilder, | 409 this->setupPosition(vertBuilder, |
| 448 uniformHandler, | 410 uniformHandler, |
| 449 gpArgs, | 411 gpArgs, |
| 450 ee.inPosition()->fName, | 412 diegp.inPosition()->fName, |
| 451 ee.viewMatrix(), | 413 diegp.viewMatrix(), |
| 452 &fViewMatrixUniform); | 414 &fViewMatrixUniform); |
| 453 | 415 |
| 454 // emit transforms | 416 // emit transforms |
| 455 this->emitTransforms(vertBuilder, | 417 this->emitTransforms(vertBuilder, |
| 456 varyingHandler, | 418 varyingHandler, |
| 457 uniformHandler, | 419 uniformHandler, |
| 458 gpArgs->fPositionVar, | 420 gpArgs->fPositionVar, |
| 459 ee.inPosition()->fName, | 421 diegp.inPosition()->fName, |
| 460 args.fTransformsIn, | 422 args.fTransformsIn, |
| 461 args.fTransformsOut); | 423 args.fTransformsOut); |
| 462 | 424 |
| 463 SkAssertResult(fragBuilder->enableFeature( | 425 SkAssertResult(fragBuilder->enableFeature( |
| 464 GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeatur
e)); | 426 GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeatur
e)); |
| 465 // for outer curve | 427 // for outer curve |
| 466 fragBuilder->codeAppendf("vec2 scaledOffset = %s.xy;", offsets0.fsIn
()); | 428 fragBuilder->codeAppendf("vec2 scaledOffset = %s.xy;", offsets0.fsIn
()); |
| 467 fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset
) - 1.0;"); | 429 fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset
) - 1.0;"); |
| 468 fragBuilder->codeAppendf("vec2 duvdx = dFdx(%s);", offsets0.fsIn()); | 430 fragBuilder->codeAppendf("vec2 duvdx = dFdx(%s);", offsets0.fsIn()); |
| 469 fragBuilder->codeAppendf("vec2 duvdy = dFdy(%s);", offsets0.fsIn()); | 431 fragBuilder->codeAppendf("vec2 duvdy = dFdy(%s);", offsets0.fsIn()); |
| 470 fragBuilder->codeAppendf("vec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s
.y*duvdx.y," | 432 fragBuilder->codeAppendf("vec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s
.y*duvdx.y," |
| 471 " 2.0*%s.x*duvdy.x + 2.0*%s
.y*duvdy.y);", | 433 " 2.0*%s.x*duvdy.x + 2.0*%s
.y*duvdy.y);", |
| 472 offsets0.fsIn(), offsets0.fsIn(), offsets0.
fsIn(), offsets0.fsIn()); | 434 offsets0.fsIn(), offsets0.fsIn(), offsets0.
fsIn(), |
| 435 offsets0.fsIn()); |
| 473 | 436 |
| 474 fragBuilder->codeAppend("float grad_dot = dot(grad, grad);"); | 437 fragBuilder->codeAppend("float grad_dot = dot(grad, grad);"); |
| 475 // avoid calling inversesqrt on zero. | 438 // avoid calling inversesqrt on zero. |
| 476 fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); | 439 fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); |
| 477 fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); | 440 fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); |
| 478 if (kHairline == ee.getMode()) { | 441 if (DIEllipseStyle::kHairline == diegp.fStyle) { |
| 479 // can probably do this with one step | 442 // can probably do this with one step |
| 480 fragBuilder->codeAppend("float edgeAlpha = clamp(1.0-test*invlen
, 0.0, 1.0);"); | 443 fragBuilder->codeAppend("float edgeAlpha = clamp(1.0-test*invlen
, 0.0, 1.0);"); |
| 481 fragBuilder->codeAppend("edgeAlpha *= clamp(1.0+test*invlen, 0.0
, 1.0);"); | 444 fragBuilder->codeAppend("edgeAlpha *= clamp(1.0+test*invlen, 0.0
, 1.0);"); |
| 482 } else { | 445 } else { |
| 483 fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen
, 0.0, 1.0);"); | 446 fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen
, 0.0, 1.0);"); |
| 484 } | 447 } |
| 485 | 448 |
| 486 // for inner curve | 449 // for inner curve |
| 487 if (kStroke == ee.getMode()) { | 450 if (DIEllipseStyle::kStroke == diegp.fStyle) { |
| 488 fragBuilder->codeAppendf("scaledOffset = %s.xy;", offsets1.fsIn(
)); | 451 fragBuilder->codeAppendf("scaledOffset = %s.xy;", offsets1.fsIn(
)); |
| 489 fragBuilder->codeAppend("test = dot(scaledOffset, scaledOffset)
- 1.0;"); | 452 fragBuilder->codeAppend("test = dot(scaledOffset, scaledOffset)
- 1.0;"); |
| 490 fragBuilder->codeAppendf("duvdx = dFdx(%s);", offsets1.fsIn()); | 453 fragBuilder->codeAppendf("duvdx = dFdx(%s);", offsets1.fsIn()); |
| 491 fragBuilder->codeAppendf("duvdy = dFdy(%s);", offsets1.fsIn()); | 454 fragBuilder->codeAppendf("duvdy = dFdy(%s);", offsets1.fsIn()); |
| 492 fragBuilder->codeAppendf("grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.
y*duvdx.y," | 455 fragBuilder->codeAppendf("grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.
y*duvdx.y," |
| 493 " 2.0*%s.x*duvdy.x + 2.0*%s.
y*duvdy.y);", | 456 " 2.0*%s.x*duvdy.x + 2.0*%s.
y*duvdy.y);", |
| 494 offsets1.fsIn(), offsets1.fsIn(), offse
ts1.fsIn(), | 457 offsets1.fsIn(), offsets1.fsIn(), offse
ts1.fsIn(), |
| 495 offsets1.fsIn()); | 458 offsets1.fsIn()); |
| 496 fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));"
); | 459 fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));"
); |
| 497 fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0
, 1.0);"); | 460 fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0
, 1.0);"); |
| 498 } | 461 } |
| 499 | 462 |
| 500 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera
ge); | 463 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera
ge); |
| 501 } | 464 } |
| 502 | 465 |
| 503 static void GenKey(const GrGeometryProcessor& gp, | 466 static void GenKey(const GrGeometryProcessor& gp, |
| 504 const GrGLSLCaps&, | 467 const GrGLSLCaps&, |
| 505 GrProcessorKeyBuilder* b) { | 468 GrProcessorKeyBuilder* b) { |
| 506 const DIEllipseEdgeEffect& ellipseEffect = gp.cast<DIEllipseEdgeEffe
ct>(); | 469 const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryP
rocessor>(); |
| 507 uint16_t key = ellipseEffect.getMode(); | 470 uint16_t key = static_cast<uint16_t>(diegp.fStyle); |
| 508 key |= ellipseEffect.colorIgnored() << 9; | 471 key |= ComputePosKey(diegp.viewMatrix()) << 10; |
| 509 key |= ComputePosKey(ellipseEffect.viewMatrix()) << 10; | |
| 510 b->add32(key); | 472 b->add32(key); |
| 511 } | 473 } |
| 512 | 474 |
| 513 void setData(const GrGLSLProgramDataManager& pdman, | 475 void setData(const GrGLSLProgramDataManager& pdman, |
| 514 const GrPrimitiveProcessor& gp) override { | 476 const GrPrimitiveProcessor& gp) override { |
| 515 const DIEllipseEdgeEffect& dee = gp.cast<DIEllipseEdgeEffect>(); | 477 const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryP
rocessor>(); |
| 516 | 478 |
| 517 if (!dee.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dee.
viewMatrix())) { | 479 if (!diegp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(di
egp.viewMatrix())) { |
| 518 fViewMatrix = dee.viewMatrix(); | 480 fViewMatrix = diegp.viewMatrix(); |
| 519 float viewMatrix[3 * 3]; | 481 float viewMatrix[3 * 3]; |
| 520 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); | 482 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); |
| 521 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); | 483 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); |
| 522 } | 484 } |
| 523 } | 485 } |
| 524 | 486 |
| 525 private: | 487 private: |
| 526 SkMatrix fViewMatrix; | 488 SkMatrix fViewMatrix; |
| 527 UniformHandle fViewMatrixUniform; | 489 UniformHandle fViewMatrixUniform; |
| 528 | 490 |
| 529 typedef GrGLSLGeometryProcessor INHERITED; | 491 typedef GrGLSLGeometryProcessor INHERITED; |
| 530 }; | 492 }; |
| 531 | 493 |
| 532 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override { | 494 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override { |
| 533 GLSLProcessor::GenKey(*this, caps, b); | 495 GLSLProcessor::GenKey(*this, caps, b); |
| 534 } | 496 } |
| 535 | 497 |
| 536 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri
de { | 498 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri
de { |
| 537 return new GLSLProcessor(); | 499 return new GLSLProcessor(); |
| 538 } | 500 } |
| 539 | 501 |
| 540 private: | 502 private: |
| 541 DIEllipseEdgeEffect(GrColor color, const SkMatrix& viewMatrix, Mode mode, | |
| 542 bool usesLocalCoords) | |
| 543 : fColor(color) | |
| 544 , fViewMatrix(viewMatrix) | |
| 545 , fUsesLocalCoords(usesLocalCoords) { | |
| 546 this->initClassID<DIEllipseEdgeEffect>(); | |
| 547 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe
rtexAttribType, | |
| 548 kHigh_GrSLPrecision)); | |
| 549 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexA
ttribType)); | |
| 550 fInEllipseOffsets0 = &this->addVertexAttrib(Attribute("inEllipseOffsets0
", | |
| 551 kVec2f_GrVertexAtt
ribType)); | |
| 552 fInEllipseOffsets1 = &this->addVertexAttrib(Attribute("inEllipseOffsets1
", | |
| 553 kVec2f_GrVertexAtt
ribType)); | |
| 554 fMode = mode; | |
| 555 } | |
| 556 | |
| 557 const Attribute* fInPosition; | 503 const Attribute* fInPosition; |
| 558 const Attribute* fInColor; | 504 const Attribute* fInColor; |
| 559 const Attribute* fInEllipseOffsets0; | 505 const Attribute* fInEllipseOffsets0; |
| 560 const Attribute* fInEllipseOffsets1; | 506 const Attribute* fInEllipseOffsets1; |
| 561 GrColor fColor; | 507 SkMatrix fViewMatrix; |
| 562 SkMatrix fViewMatrix; | 508 DIEllipseStyle fStyle; |
| 563 Mode fMode; | |
| 564 bool fUsesLocalCoords; | |
| 565 | 509 |
| 566 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; | 510 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; |
| 567 | 511 |
| 568 typedef GrGeometryProcessor INHERITED; | 512 typedef GrGeometryProcessor INHERITED; |
| 569 }; | 513 }; |
| 570 | 514 |
| 571 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseEdgeEffect); | 515 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseGeometryProcessor); |
| 572 | 516 |
| 573 const GrGeometryProcessor* DIEllipseEdgeEffect::TestCreate(GrProcessorTestData*
d) { | 517 const GrGeometryProcessor* DIEllipseGeometryProcessor::TestCreate(GrProcessorTes
tData* d) { |
| 574 return DIEllipseEdgeEffect::Create(GrRandomColor(d->fRandom), | 518 return new DIEllipseGeometryProcessor(GrTest::TestMatrix(d->fRandom), |
| 575 GrTest::TestMatrix(d->fRandom), | 519 (DIEllipseStyle)(d->fRandom->nextRange
U(0,2))); |
| 576 (Mode)(d->fRandom->nextRangeU(0,2)), | |
| 577 d->fRandom->nextBool()); | |
| 578 } | 520 } |
| 579 | 521 |
| 580 /////////////////////////////////////////////////////////////////////////////// | 522 /////////////////////////////////////////////////////////////////////////////// |
| 581 | 523 |
| 582 GrDrawBatch* GrOvalRenderer::CreateOvalBatch(GrColor color, | 524 GrDrawBatch* GrOvalRenderer::CreateOvalBatch(GrColor color, |
| 583 const SkMatrix& viewMatrix, | 525 const SkMatrix& viewMatrix, |
| 584 const SkRect& oval, | 526 const SkRect& oval, |
| 585 const SkStrokeRec& stroke, | 527 const SkStrokeRec& stroke, |
| 586 GrShaderCaps* shaderCaps) { | 528 GrShaderCaps* shaderCaps) { |
| 587 // we can draw circles | 529 // we can draw circles |
| (...skipping 14 matching lines...) Expand all Loading... |
| 602 return nullptr; | 544 return nullptr; |
| 603 } | 545 } |
| 604 | 546 |
| 605 /////////////////////////////////////////////////////////////////////////////// | 547 /////////////////////////////////////////////////////////////////////////////// |
| 606 | 548 |
| 607 class CircleBatch : public GrVertexBatch { | 549 class CircleBatch : public GrVertexBatch { |
| 608 public: | 550 public: |
| 609 DEFINE_BATCH_CLASS_ID | 551 DEFINE_BATCH_CLASS_ID |
| 610 | 552 |
| 611 struct Geometry { | 553 struct Geometry { |
| 612 SkMatrix fViewMatrix; | |
| 613 SkRect fDevBounds; | 554 SkRect fDevBounds; |
| 614 SkScalar fInnerRadius; | 555 SkScalar fInnerRadius; |
| 615 SkScalar fOuterRadius; | 556 SkScalar fOuterRadius; |
| 616 GrColor fColor; | 557 GrColor fColor; |
| 617 bool fStroke; | |
| 618 }; | 558 }; |
| 619 | 559 |
| 620 static GrDrawBatch* Create(const Geometry& geometry) { return new CircleBatc
h(geometry); } | 560 CircleBatch(const Geometry& geometry, const SkMatrix& viewMatrix, bool strok
ed) |
| 621 | 561 : INHERITED(ClassID()) |
| 562 , fStroked(stroked) |
| 563 , fViewMatrixIfUsingLocalCoords(viewMatrix) { |
| 564 fGeoData.push_back(geometry); |
| 565 this->setBounds(geometry.fDevBounds); |
| 566 } |
| 622 const char* name() const override { return "CircleBatch"; } | 567 const char* name() const override { return "CircleBatch"; } |
| 623 | 568 |
| 624 SkString dumpInfo() const override { | 569 SkString dumpInfo() const override { |
| 625 SkString string; | 570 SkString string; |
| 626 for (int i = 0; i < fGeoData.count(); ++i) { | 571 for (int i = 0; i < fGeoData.count(); ++i) { |
| 627 string.appendf("Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.
2f]," | 572 string.appendf("Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.
2f]," |
| 628 "InnerRad: %.2f, OuterRad: %.2f\n", | 573 "InnerRad: %.2f, OuterRad: %.2f\n", |
| 629 fGeoData[i].fColor, | 574 fGeoData[i].fColor, |
| 630 fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds.
fTop, | 575 fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds.
fTop, |
| 631 fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds
.fBottom, | 576 fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds
.fBottom, |
| 632 fGeoData[i].fInnerRadius, | 577 fGeoData[i].fInnerRadius, |
| 633 fGeoData[i].fOuterRadius); | 578 fGeoData[i].fOuterRadius); |
| 634 } | 579 } |
| 635 string.append(INHERITED::dumpInfo()); | 580 string.append(INHERITED::dumpInfo()); |
| 636 return string; | 581 return string; |
| 637 } | 582 } |
| 638 | 583 |
| 639 void computePipelineOptimizations(GrInitInvariantOutput* color, | 584 void computePipelineOptimizations(GrInitInvariantOutput* color, |
| 640 GrInitInvariantOutput* coverage, | 585 GrInitInvariantOutput* coverage, |
| 641 GrBatchToXPOverrides* overrides) const ove
rride { | 586 GrBatchToXPOverrides* overrides) const ove
rride { |
| 642 // When this is called on a batch, there is only one geometry bundle | 587 // When this is called on a batch, there is only one geometry bundle |
| 643 color->setKnownFourComponents(fGeoData[0].fColor); | 588 color->setKnownFourComponents(fGeoData[0].fColor); |
| 644 coverage->setUnknownSingleComponent(); | 589 coverage->setUnknownSingleComponent(); |
| 645 } | 590 } |
| 646 | 591 |
| 647 private: | 592 private: |
| 648 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { | 593 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { |
| 649 // Handle any color overrides | 594 // Handle any overrides that affect our GP. |
| 650 if (!overrides.readsColor()) { | 595 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); |
| 651 fGeoData[0].fColor = GrColor_ILLEGAL; | 596 if (!overrides.readsLocalCoords()) { |
| 597 fViewMatrixIfUsingLocalCoords.reset(); |
| 652 } | 598 } |
| 653 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); | |
| 654 | |
| 655 // setup batch properties | |
| 656 fBatch.fColorIgnored = !overrides.readsColor(); | |
| 657 fBatch.fColor = fGeoData[0].fColor; | |
| 658 fBatch.fStroke = fGeoData[0].fStroke; | |
| 659 fBatch.fUsesLocalCoords = overrides.readsLocalCoords(); | |
| 660 fBatch.fCoverageIgnored = !overrides.readsCoverage(); | |
| 661 } | 599 } |
| 662 | 600 |
| 663 void onPrepareDraws(Target* target) const override { | 601 void onPrepareDraws(Target* target) const override { |
| 664 SkMatrix invert; | 602 SkMatrix localMatrix; |
| 665 if (!this->viewMatrix().invert(&invert)) { | 603 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { |
| 666 return; | 604 return; |
| 667 } | 605 } |
| 668 | 606 |
| 669 // Setup geometry processor | 607 // Setup geometry processor |
| 670 SkAutoTUnref<GrGeometryProcessor> gp(CircleEdgeEffect::Create(this->colo
r(), | 608 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(fStroke
d, localMatrix)); |
| 671 this->stro
ke(), | |
| 672 invert, | |
| 673 this->uses
LocalCoords())); | |
| 674 | 609 |
| 675 target->initDraw(gp, this->pipeline()); | 610 target->initDraw(gp, this->pipeline()); |
| 676 | 611 |
| 677 int instanceCount = fGeoData.count(); | 612 int instanceCount = fGeoData.count(); |
| 678 size_t vertexStride = gp->getVertexStride(); | 613 size_t vertexStride = gp->getVertexStride(); |
| 679 SkASSERT(vertexStride == sizeof(CircleVertex)); | 614 SkASSERT(vertexStride == sizeof(CircleVertex)); |
| 680 QuadHelper helper; | 615 QuadHelper helper; |
| 681 CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(target
, vertexStride, | 616 CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(target
, vertexStride, |
| 682 instan
ceCount)); | 617 instan
ceCount)); |
| 683 if (!verts) { | 618 if (!verts) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 verts[3].fColor = color; | 652 verts[3].fColor = color; |
| 718 verts[3].fOffset = SkPoint::Make(1, -1); | 653 verts[3].fOffset = SkPoint::Make(1, -1); |
| 719 verts[3].fOuterRadius = outerRadius; | 654 verts[3].fOuterRadius = outerRadius; |
| 720 verts[3].fInnerRadius = innerRadius; | 655 verts[3].fInnerRadius = innerRadius; |
| 721 | 656 |
| 722 verts += kVerticesPerQuad; | 657 verts += kVerticesPerQuad; |
| 723 } | 658 } |
| 724 helper.recordDraw(target); | 659 helper.recordDraw(target); |
| 725 } | 660 } |
| 726 | 661 |
| 727 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
| 728 | |
| 729 CircleBatch(const Geometry& geometry) : INHERITED(ClassID()) { | |
| 730 fGeoData.push_back(geometry); | |
| 731 | |
| 732 this->setBounds(geometry.fDevBounds); | |
| 733 } | |
| 734 | |
| 735 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | 662 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
| 736 CircleBatch* that = t->cast<CircleBatch>(); | 663 CircleBatch* that = t->cast<CircleBatch>(); |
| 737 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), | 664 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), |
| 738 that->bounds(), caps)) { | 665 that->bounds(), caps)) { |
| 739 return false; | 666 return false; |
| 740 } | 667 } |
| 741 | 668 |
| 742 if (this->stroke() != that->stroke()) { | 669 if (this->fStroked != that->fStroked) { |
| 743 return false; | 670 return false; |
| 744 } | 671 } |
| 745 | 672 |
| 746 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); | 673 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing
LocalCoords)) { |
| 747 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi
ewMatrix())) { | |
| 748 return false; | 674 return false; |
| 749 } | 675 } |
| 750 | 676 |
| 751 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin())
; | 677 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); |
| 752 this->joinBounds(that->bounds()); | 678 this->joinBounds(that->bounds()); |
| 753 return true; | 679 return true; |
| 754 } | 680 } |
| 755 | 681 |
| 756 GrColor color() const { return fBatch.fColor; } | 682 bool fStroked; |
| 757 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | 683 SkMatrix fViewMatrixIfUsingLocalCoords; |
| 758 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | |
| 759 bool stroke() const { return fBatch.fStroke; } | |
| 760 | |
| 761 struct BatchTracker { | |
| 762 GrColor fColor; | |
| 763 bool fStroke; | |
| 764 bool fUsesLocalCoords; | |
| 765 bool fColorIgnored; | |
| 766 bool fCoverageIgnored; | |
| 767 }; | |
| 768 | |
| 769 BatchTracker fBatch; | |
| 770 SkSTArray<1, Geometry, true> fGeoData; | 684 SkSTArray<1, Geometry, true> fGeoData; |
| 771 | 685 |
| 772 typedef GrVertexBatch INHERITED; | 686 typedef GrVertexBatch INHERITED; |
| 773 }; | 687 }; |
| 774 | 688 |
| 775 static GrDrawBatch* create_circle_batch(GrColor color, | 689 static GrDrawBatch* create_circle_batch(GrColor color, |
| 776 const SkMatrix& viewMatrix, | 690 const SkMatrix& viewMatrix, |
| 777 const SkRect& circle, | 691 const SkRect& circle, |
| 778 const SkStrokeRec& stroke) { | 692 const SkStrokeRec& stroke) { |
| 779 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); | 693 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 803 } | 717 } |
| 804 | 718 |
| 805 // The radii are outset for two reasons. First, it allows the shader to simp
ly perform simpler | 719 // The radii are outset for two reasons. First, it allows the shader to simp
ly perform simpler |
| 806 // computation because the computed alpha is zero, rather than 50%, at the r
adius. | 720 // computation because the computed alpha is zero, rather than 50%, at the r
adius. |
| 807 // Second, the outer radius is used to compute the verts of the bounding box
that is rendered | 721 // Second, the outer radius is used to compute the verts of the bounding box
that is rendered |
| 808 // and the outset ensures the box will cover all partially covered by the ci
rcle. | 722 // and the outset ensures the box will cover all partially covered by the ci
rcle. |
| 809 outerRadius += SK_ScalarHalf; | 723 outerRadius += SK_ScalarHalf; |
| 810 innerRadius -= SK_ScalarHalf; | 724 innerRadius -= SK_ScalarHalf; |
| 811 | 725 |
| 812 CircleBatch::Geometry geometry; | 726 CircleBatch::Geometry geometry; |
| 813 geometry.fViewMatrix = viewMatrix; | |
| 814 geometry.fColor = color; | 727 geometry.fColor = color; |
| 815 geometry.fInnerRadius = innerRadius; | 728 geometry.fInnerRadius = innerRadius; |
| 816 geometry.fOuterRadius = outerRadius; | 729 geometry.fOuterRadius = outerRadius; |
| 817 geometry.fStroke = isStrokeOnly && innerRadius > 0; | |
| 818 geometry.fDevBounds = SkRect::MakeLTRB(center.fX - outerRadius, center.fY -
outerRadius, | 730 geometry.fDevBounds = SkRect::MakeLTRB(center.fX - outerRadius, center.fY -
outerRadius, |
| 819 center.fX + outerRadius, center.fY +
outerRadius); | 731 center.fX + outerRadius, center.fY +
outerRadius); |
| 820 | 732 |
| 821 return CircleBatch::Create(geometry); | 733 return new CircleBatch(geometry, viewMatrix, isStrokeOnly && innerRadius > 0
); |
| 822 } | 734 } |
| 823 | 735 |
| 824 GrDrawBatch* GrOvalRenderer::CreateCircleBatch(GrColor color, | 736 GrDrawBatch* GrOvalRenderer::CreateCircleBatch(GrColor color, |
| 825 const SkMatrix& viewMatrix, | 737 const SkMatrix& viewMatrix, |
| 826 const SkRect& circle, | 738 const SkRect& circle, |
| 827 const SkStrokeRec& stroke) { | 739 const SkStrokeRec& stroke) { |
| 828 return create_circle_batch(color, viewMatrix, circle, stroke); | 740 return create_circle_batch(color, viewMatrix, circle, stroke); |
| 829 } | 741 } |
| 830 | 742 |
| 831 /////////////////////////////////////////////////////////////////////////////// | 743 /////////////////////////////////////////////////////////////////////////////// |
| 832 | 744 |
| 833 class EllipseBatch : public GrVertexBatch { | 745 class EllipseBatch : public GrVertexBatch { |
| 834 public: | 746 public: |
| 835 DEFINE_BATCH_CLASS_ID | 747 DEFINE_BATCH_CLASS_ID |
| 836 | 748 |
| 837 struct Geometry { | 749 struct Geometry { |
| 838 SkMatrix fViewMatrix; | |
| 839 SkRect fDevBounds; | 750 SkRect fDevBounds; |
| 840 SkScalar fXRadius; | 751 SkScalar fXRadius; |
| 841 SkScalar fYRadius; | 752 SkScalar fYRadius; |
| 842 SkScalar fInnerXRadius; | 753 SkScalar fInnerXRadius; |
| 843 SkScalar fInnerYRadius; | 754 SkScalar fInnerYRadius; |
| 844 GrColor fColor; | 755 GrColor fColor; |
| 845 bool fStroke; | |
| 846 }; | 756 }; |
| 847 | 757 |
| 848 static GrDrawBatch* Create(const Geometry& geometry) { return new EllipseBat
ch(geometry); } | 758 EllipseBatch(const Geometry& geometry, const SkMatrix& viewMatrix, bool stro
ked) |
| 759 : INHERITED(ClassID()) |
| 760 , fStroked(stroked) |
| 761 , fViewMatrixIfUsingLocalCoords(viewMatrix) { |
| 762 fGeoData.push_back(geometry); |
| 763 this->setBounds(geometry.fDevBounds); |
| 764 } |
| 849 | 765 |
| 850 const char* name() const override { return "EllipseBatch"; } | 766 const char* name() const override { return "EllipseBatch"; } |
| 851 | 767 |
| 852 void computePipelineOptimizations(GrInitInvariantOutput* color, | 768 void computePipelineOptimizations(GrInitInvariantOutput* color, |
| 853 GrInitInvariantOutput* coverage, | 769 GrInitInvariantOutput* coverage, |
| 854 GrBatchToXPOverrides* overrides) const ove
rride { | 770 GrBatchToXPOverrides* overrides) const ove
rride { |
| 855 // When this is called on a batch, there is only one geometry bundle | 771 // When this is called on a batch, there is only one geometry bundle |
| 856 color->setKnownFourComponents(fGeoData[0].fColor); | 772 color->setKnownFourComponents(fGeoData[0].fColor); |
| 857 coverage->setUnknownSingleComponent(); | 773 coverage->setUnknownSingleComponent(); |
| 858 } | 774 } |
| 859 | 775 |
| 860 private: | 776 private: |
| 861 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { | 777 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { |
| 862 // Handle any color overrides | 778 // Handle any overrides that affect our GP. |
| 863 if (!overrides.readsCoverage()) { | 779 if (!overrides.readsCoverage()) { |
| 864 fGeoData[0].fColor = GrColor_ILLEGAL; | 780 fGeoData[0].fColor = GrColor_ILLEGAL; |
| 865 } | 781 } |
| 866 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); | 782 if (!overrides.readsLocalCoords()) { |
| 867 | 783 fViewMatrixIfUsingLocalCoords.reset(); |
| 868 // setup batch properties | 784 } |
| 869 fBatch.fColorIgnored = !overrides.readsColor(); | |
| 870 fBatch.fColor = fGeoData[0].fColor; | |
| 871 fBatch.fStroke = fGeoData[0].fStroke; | |
| 872 fBatch.fUsesLocalCoords = overrides.readsLocalCoords(); | |
| 873 fBatch.fCoverageIgnored = !overrides.readsCoverage(); | |
| 874 } | 785 } |
| 875 | 786 |
| 876 void onPrepareDraws(Target* target) const override { | 787 void onPrepareDraws(Target* target) const override { |
| 877 SkMatrix invert; | 788 SkMatrix localMatrix; |
| 878 if (!this->viewMatrix().invert(&invert)) { | 789 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { |
| 879 return; | 790 return; |
| 880 } | 791 } |
| 881 | 792 |
| 882 // Setup geometry processor | 793 // Setup geometry processor |
| 883 SkAutoTUnref<GrGeometryProcessor> gp(EllipseEdgeEffect::Create(this->col
or(), | 794 SkAutoTUnref<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStrok
ed, localMatrix)); |
| 884 this->str
oke(), | |
| 885 invert, | |
| 886 this->use
sLocalCoords())); | |
| 887 | 795 |
| 888 target->initDraw(gp, this->pipeline()); | 796 target->initDraw(gp, this->pipeline()); |
| 889 | 797 |
| 890 int instanceCount = fGeoData.count(); | 798 int instanceCount = fGeoData.count(); |
| 891 QuadHelper helper; | 799 QuadHelper helper; |
| 892 size_t vertexStride = gp->getVertexStride(); | 800 size_t vertexStride = gp->getVertexStride(); |
| 893 SkASSERT(vertexStride == sizeof(EllipseVertex)); | 801 SkASSERT(vertexStride == sizeof(EllipseVertex)); |
| 894 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>( | 802 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>( |
| 895 helper.init(target, vertexStride, instanceCount)); | 803 helper.init(target, vertexStride, instanceCount)); |
| 896 if (!verts) { | 804 if (!verts) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 verts[3].fColor = color; | 843 verts[3].fColor = color; |
| 936 verts[3].fOffset = SkPoint::Make(xRadius, -yRadius); | 844 verts[3].fOffset = SkPoint::Make(xRadius, -yRadius); |
| 937 verts[3].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); | 845 verts[3].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); |
| 938 verts[3].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip)
; | 846 verts[3].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip)
; |
| 939 | 847 |
| 940 verts += kVerticesPerQuad; | 848 verts += kVerticesPerQuad; |
| 941 } | 849 } |
| 942 helper.recordDraw(target); | 850 helper.recordDraw(target); |
| 943 } | 851 } |
| 944 | 852 |
| 945 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
| 946 | |
| 947 EllipseBatch(const Geometry& geometry) : INHERITED(ClassID()) { | |
| 948 fGeoData.push_back(geometry); | |
| 949 | |
| 950 this->setBounds(geometry.fDevBounds); | |
| 951 } | |
| 952 | |
| 953 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | 853 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
| 954 EllipseBatch* that = t->cast<EllipseBatch>(); | 854 EllipseBatch* that = t->cast<EllipseBatch>(); |
| 955 | 855 |
| 956 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), | 856 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), |
| 957 that->bounds(), caps)) { | 857 that->bounds(), caps)) { |
| 958 return false; | 858 return false; |
| 959 } | 859 } |
| 960 | 860 |
| 961 if (this->stroke() != that->stroke()) { | 861 if (fStroked != that->fStroked) { |
| 962 return false; | 862 return false; |
| 963 } | 863 } |
| 964 | 864 |
| 965 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); | 865 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing
LocalCoords)) { |
| 966 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi
ewMatrix())) { | |
| 967 return false; | 866 return false; |
| 968 } | 867 } |
| 969 | 868 |
| 970 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin())
; | 869 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); |
| 971 this->joinBounds(that->bounds()); | 870 this->joinBounds(that->bounds()); |
| 972 return true; | 871 return true; |
| 973 } | 872 } |
| 974 | 873 |
| 975 GrColor color() const { return fBatch.fColor; } | |
| 976 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | |
| 977 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | |
| 978 bool stroke() const { return fBatch.fStroke; } | |
| 979 | 874 |
| 980 struct BatchTracker { | 875 bool fStroked; |
| 981 GrColor fColor; | 876 SkMatrix fViewMatrixIfUsingLocalCoords; |
| 982 bool fStroke; | |
| 983 bool fUsesLocalCoords; | |
| 984 bool fColorIgnored; | |
| 985 bool fCoverageIgnored; | |
| 986 }; | |
| 987 | |
| 988 BatchTracker fBatch; | |
| 989 SkSTArray<1, Geometry, true> fGeoData; | 877 SkSTArray<1, Geometry, true> fGeoData; |
| 990 | 878 |
| 991 typedef GrVertexBatch INHERITED; | 879 typedef GrVertexBatch INHERITED; |
| 992 }; | 880 }; |
| 993 | 881 |
| 994 static GrDrawBatch* create_ellipse_batch(GrColor color, | 882 static GrDrawBatch* create_ellipse_batch(GrColor color, |
| 995 const SkMatrix& viewMatrix, | 883 const SkMatrix& viewMatrix, |
| 996 const SkRect& ellipse, | 884 const SkRect& ellipse, |
| 997 const SkStrokeRec& stroke) { | 885 const SkStrokeRec& stroke) { |
| 998 SkASSERT(viewMatrix.rectStaysRect()); | 886 SkASSERT(viewMatrix.rectStaysRect()); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1051 yRadius += scaledStroke.fY; | 939 yRadius += scaledStroke.fY; |
| 1052 } | 940 } |
| 1053 | 941 |
| 1054 // We've extended the outer x radius out half a pixel to antialias. | 942 // We've extended the outer x radius out half a pixel to antialias. |
| 1055 // This will also expand the rect so all the pixels will be captured. | 943 // This will also expand the rect so all the pixels will be captured. |
| 1056 // TODO: Consider if we should use sqrt(2)/2 instead | 944 // TODO: Consider if we should use sqrt(2)/2 instead |
| 1057 xRadius += SK_ScalarHalf; | 945 xRadius += SK_ScalarHalf; |
| 1058 yRadius += SK_ScalarHalf; | 946 yRadius += SK_ScalarHalf; |
| 1059 | 947 |
| 1060 EllipseBatch::Geometry geometry; | 948 EllipseBatch::Geometry geometry; |
| 1061 geometry.fViewMatrix = viewMatrix; | |
| 1062 geometry.fColor = color; | 949 geometry.fColor = color; |
| 1063 geometry.fXRadius = xRadius; | 950 geometry.fXRadius = xRadius; |
| 1064 geometry.fYRadius = yRadius; | 951 geometry.fYRadius = yRadius; |
| 1065 geometry.fInnerXRadius = innerXRadius; | 952 geometry.fInnerXRadius = innerXRadius; |
| 1066 geometry.fInnerYRadius = innerYRadius; | 953 geometry.fInnerYRadius = innerYRadius; |
| 1067 geometry.fStroke = isStrokeOnly && innerXRadius > 0 && innerYRadius > 0; | |
| 1068 geometry.fDevBounds = SkRect::MakeLTRB(center.fX - xRadius, center.fY - yRad
ius, | 954 geometry.fDevBounds = SkRect::MakeLTRB(center.fX - xRadius, center.fY - yRad
ius, |
| 1069 center.fX + xRadius, center.fY + yRad
ius); | 955 center.fX + xRadius, center.fY + yRad
ius); |
| 1070 | 956 |
| 1071 return EllipseBatch::Create(geometry); | 957 return new EllipseBatch(geometry, viewMatrix, |
| 958 isStrokeOnly && innerXRadius > 0 && innerYRadius > 0
); |
| 1072 } | 959 } |
| 1073 | 960 |
| 1074 GrDrawBatch* GrOvalRenderer::CreateEllipseBatch(GrColor color, | 961 GrDrawBatch* GrOvalRenderer::CreateEllipseBatch(GrColor color, |
| 1075 const SkMatrix& viewMatrix, | 962 const SkMatrix& viewMatrix, |
| 1076 const SkRect& ellipse, | 963 const SkRect& ellipse, |
| 1077 const SkStrokeRec& stroke) { | 964 const SkStrokeRec& stroke) { |
| 1078 return create_ellipse_batch(color, viewMatrix, ellipse, stroke); | 965 return create_ellipse_batch(color, viewMatrix, ellipse, stroke); |
| 1079 } | 966 } |
| 1080 | 967 |
| 1081 ////////////////////////////////////////////////////////////////////////////////
///////////////// | 968 ////////////////////////////////////////////////////////////////////////////////
///////////////// |
| 1082 | 969 |
| 1083 class DIEllipseBatch : public GrVertexBatch { | 970 class DIEllipseBatch : public GrVertexBatch { |
| 1084 public: | 971 public: |
| 1085 DEFINE_BATCH_CLASS_ID | 972 DEFINE_BATCH_CLASS_ID |
| 1086 | 973 |
| 1087 struct Geometry { | 974 struct Geometry { |
| 1088 SkMatrix fViewMatrix; | 975 SkMatrix fViewMatrix; |
| 1089 SkRect fBounds; | 976 SkRect fBounds; |
| 1090 SkScalar fXRadius; | 977 SkScalar fXRadius; |
| 1091 SkScalar fYRadius; | 978 SkScalar fYRadius; |
| 1092 SkScalar fInnerXRadius; | 979 SkScalar fInnerXRadius; |
| 1093 SkScalar fInnerYRadius; | 980 SkScalar fInnerYRadius; |
| 1094 SkScalar fGeoDx; | 981 SkScalar fGeoDx; |
| 1095 SkScalar fGeoDy; | 982 SkScalar fGeoDy; |
| 1096 GrColor fColor; | 983 GrColor fColor; |
| 1097 DIEllipseEdgeEffect::Mode fMode; | 984 DIEllipseStyle fStyle; |
| 1098 }; | 985 }; |
| 1099 | 986 |
| 1100 static GrDrawBatch* Create(const Geometry& geometry, const SkRect& bounds) { | 987 static GrDrawBatch* Create(const Geometry& geometry, const SkRect& bounds) { |
| 1101 return new DIEllipseBatch(geometry, bounds); | 988 return new DIEllipseBatch(geometry, bounds); |
| 1102 } | 989 } |
| 1103 | 990 |
| 1104 const char* name() const override { return "DIEllipseBatch"; } | 991 const char* name() const override { return "DIEllipseBatch"; } |
| 1105 | 992 |
| 1106 void computePipelineOptimizations(GrInitInvariantOutput* color, | 993 void computePipelineOptimizations(GrInitInvariantOutput* color, |
| 1107 GrInitInvariantOutput* coverage, | 994 GrInitInvariantOutput* coverage, |
| 1108 GrBatchToXPOverrides* overrides) const ove
rride { | 995 GrBatchToXPOverrides* overrides) const ove
rride { |
| 1109 // When this is called on a batch, there is only one geometry bundle | 996 // When this is called on a batch, there is only one geometry bundle |
| 1110 color->setKnownFourComponents(fGeoData[0].fColor); | 997 color->setKnownFourComponents(fGeoData[0].fColor); |
| 1111 coverage->setUnknownSingleComponent(); | 998 coverage->setUnknownSingleComponent(); |
| 1112 } | 999 } |
| 1113 | 1000 |
| 1114 private: | 1001 private: |
| 1115 | 1002 |
| 1116 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { | 1003 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { |
| 1117 // Handle any color overrides | 1004 // Handle any overrides that affect our GP. |
| 1118 if (!overrides.readsColor()) { | |
| 1119 fGeoData[0].fColor = GrColor_ILLEGAL; | |
| 1120 } | |
| 1121 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); | 1005 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); |
| 1122 | 1006 fUsesLocalCoords = overrides.readsLocalCoords(); |
| 1123 // setup batch properties | |
| 1124 fBatch.fColorIgnored = !overrides.readsColor(); | |
| 1125 fBatch.fColor = fGeoData[0].fColor; | |
| 1126 fBatch.fMode = fGeoData[0].fMode; | |
| 1127 fBatch.fUsesLocalCoords = overrides.readsLocalCoords(); | |
| 1128 fBatch.fCoverageIgnored = !overrides.readsCoverage(); | |
| 1129 } | 1007 } |
| 1130 | 1008 |
| 1131 void onPrepareDraws(Target* target) const override { | 1009 void onPrepareDraws(Target* target) const override { |
| 1132 // Setup geometry processor | 1010 // Setup geometry processor |
| 1133 SkAutoTUnref<GrGeometryProcessor> gp(DIEllipseEdgeEffect::Create(this->c
olor(), | 1011 SkAutoTUnref<GrGeometryProcessor> gp(new DIEllipseGeometryProcessor(this
->viewMatrix(), |
| 1134 this->v
iewMatrix(), | 1012 this
->style())); |
| 1135 this->m
ode(), | |
| 1136 this->u
sesLocalCoords())); | |
| 1137 | 1013 |
| 1138 target->initDraw(gp, this->pipeline()); | 1014 target->initDraw(gp, this->pipeline()); |
| 1139 | 1015 |
| 1140 int instanceCount = fGeoData.count(); | 1016 int instanceCount = fGeoData.count(); |
| 1141 size_t vertexStride = gp->getVertexStride(); | 1017 size_t vertexStride = gp->getVertexStride(); |
| 1142 SkASSERT(vertexStride == sizeof(DIEllipseVertex)); | 1018 SkASSERT(vertexStride == sizeof(DIEllipseVertex)); |
| 1143 QuadHelper helper; | 1019 QuadHelper helper; |
| 1144 DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>( | 1020 DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>( |
| 1145 helper.init(target, vertexStride, instanceCount)); | 1021 helper.init(target, vertexStride, instanceCount)); |
| 1146 if (!verts) { | 1022 if (!verts) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1180 | 1056 |
| 1181 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); | 1057 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); |
| 1182 verts[3].fColor = color; | 1058 verts[3].fColor = color; |
| 1183 verts[3].fOuterOffset = SkPoint::Make(1.0f + offsetDx, -1.0f - offse
tDy); | 1059 verts[3].fOuterOffset = SkPoint::Make(1.0f + offsetDx, -1.0f - offse
tDy); |
| 1184 verts[3].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, -inner
RatioY - offsetDy); | 1060 verts[3].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, -inner
RatioY - offsetDy); |
| 1185 | 1061 |
| 1186 verts += kVerticesPerQuad; | 1062 verts += kVerticesPerQuad; |
| 1187 } | 1063 } |
| 1188 helper.recordDraw(target); | 1064 helper.recordDraw(target); |
| 1189 } | 1065 } |
| 1190 | 1066 |
| 1191 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
| 1192 | |
| 1193 DIEllipseBatch(const Geometry& geometry, const SkRect& bounds) : INHERITED(C
lassID()) { | 1067 DIEllipseBatch(const Geometry& geometry, const SkRect& bounds) : INHERITED(C
lassID()) { |
| 1194 fGeoData.push_back(geometry); | 1068 fGeoData.push_back(geometry); |
| 1195 | 1069 |
| 1196 this->setBounds(bounds); | 1070 this->setBounds(bounds); |
| 1197 } | 1071 } |
| 1198 | 1072 |
| 1199 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | 1073 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
| 1200 DIEllipseBatch* that = t->cast<DIEllipseBatch>(); | 1074 DIEllipseBatch* that = t->cast<DIEllipseBatch>(); |
| 1201 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), | 1075 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), |
| 1202 that->bounds(), caps)) { | 1076 that->bounds(), caps)) { |
| 1203 return false; | 1077 return false; |
| 1204 } | 1078 } |
| 1205 | 1079 |
| 1206 if (this->mode() != that->mode()) { | 1080 if (this->style() != that->style()) { |
| 1207 return false; | 1081 return false; |
| 1208 } | 1082 } |
| 1209 | 1083 |
| 1210 // TODO rewrite to allow positioning on CPU | 1084 // TODO rewrite to allow positioning on CPU |
| 1211 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { | 1085 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { |
| 1212 return false; | 1086 return false; |
| 1213 } | 1087 } |
| 1214 | 1088 |
| 1215 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin())
; | 1089 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); |
| 1216 this->joinBounds(that->bounds()); | 1090 this->joinBounds(that->bounds()); |
| 1217 return true; | 1091 return true; |
| 1218 } | 1092 } |
| 1219 | 1093 |
| 1220 GrColor color() const { return fBatch.fColor; } | |
| 1221 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | |
| 1222 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | 1094 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } |
| 1223 DIEllipseEdgeEffect::Mode mode() const { return fBatch.fMode; } | 1095 DIEllipseStyle style() const { return fGeoData[0].fStyle; } |
| 1224 | 1096 |
| 1225 struct BatchTracker { | 1097 bool fUsesLocalCoords; |
| 1226 GrColor fColor; | |
| 1227 DIEllipseEdgeEffect::Mode fMode; | |
| 1228 bool fUsesLocalCoords; | |
| 1229 bool fColorIgnored; | |
| 1230 bool fCoverageIgnored; | |
| 1231 }; | |
| 1232 | |
| 1233 BatchTracker fBatch; | |
| 1234 SkSTArray<1, Geometry, true> fGeoData; | 1098 SkSTArray<1, Geometry, true> fGeoData; |
| 1235 | 1099 |
| 1236 typedef GrVertexBatch INHERITED; | 1100 typedef GrVertexBatch INHERITED; |
| 1237 }; | 1101 }; |
| 1238 | 1102 |
| 1239 static GrDrawBatch* create_diellipse_batch(GrColor color, | 1103 static GrDrawBatch* create_diellipse_batch(GrColor color, |
| 1240 const SkMatrix& viewMatrix, | 1104 const SkMatrix& viewMatrix, |
| 1241 const SkRect& ellipse, | 1105 const SkRect& ellipse, |
| 1242 const SkStrokeRec& stroke) { | 1106 const SkStrokeRec& stroke) { |
| 1243 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); | 1107 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); |
| 1244 SkScalar xRadius = SkScalarHalf(ellipse.width()); | 1108 SkScalar xRadius = SkScalarHalf(ellipse.width()); |
| 1245 SkScalar yRadius = SkScalarHalf(ellipse.height()); | 1109 SkScalar yRadius = SkScalarHalf(ellipse.height()); |
| 1246 | 1110 |
| 1247 SkStrokeRec::Style style = stroke.getStyle(); | 1111 SkStrokeRec::Style style = stroke.getStyle(); |
| 1248 DIEllipseEdgeEffect::Mode mode = (SkStrokeRec::kStroke_Style == style) ? | 1112 DIEllipseStyle dieStyle = (SkStrokeRec::kStroke_Style == style) ? |
| 1249 DIEllipseEdgeEffect::kStroke : | 1113 DIEllipseStyle::kStroke : |
| 1250 (SkStrokeRec::kHairline_Style == style) ? | 1114 (SkStrokeRec::kHairline_Style == style) ? |
| 1251 DIEllipseEdgeEffect::kHairline : DIEllipseEd
geEffect::kFill; | 1115 DIEllipseStyle::kHairline : DIEllipseSty
le::kFill; |
| 1252 | 1116 |
| 1253 SkScalar innerXRadius = 0; | 1117 SkScalar innerXRadius = 0; |
| 1254 SkScalar innerYRadius = 0; | 1118 SkScalar innerYRadius = 0; |
| 1255 if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != sty
le) { | 1119 if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != sty
le) { |
| 1256 SkScalar strokeWidth = stroke.getWidth(); | 1120 SkScalar strokeWidth = stroke.getWidth(); |
| 1257 | 1121 |
| 1258 if (SkScalarNearlyZero(strokeWidth)) { | 1122 if (SkScalarNearlyZero(strokeWidth)) { |
| 1259 strokeWidth = SK_ScalarHalf; | 1123 strokeWidth = SK_ScalarHalf; |
| 1260 } else { | 1124 } else { |
| 1261 strokeWidth *= SK_ScalarHalf; | 1125 strokeWidth *= SK_ScalarHalf; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1275 | 1139 |
| 1276 // set inner radius (if needed) | 1140 // set inner radius (if needed) |
| 1277 if (SkStrokeRec::kStroke_Style == style) { | 1141 if (SkStrokeRec::kStroke_Style == style) { |
| 1278 innerXRadius = xRadius - strokeWidth; | 1142 innerXRadius = xRadius - strokeWidth; |
| 1279 innerYRadius = yRadius - strokeWidth; | 1143 innerYRadius = yRadius - strokeWidth; |
| 1280 } | 1144 } |
| 1281 | 1145 |
| 1282 xRadius += strokeWidth; | 1146 xRadius += strokeWidth; |
| 1283 yRadius += strokeWidth; | 1147 yRadius += strokeWidth; |
| 1284 } | 1148 } |
| 1285 if (DIEllipseEdgeEffect::kStroke == mode) { | 1149 if (DIEllipseStyle::kStroke == dieStyle) { |
| 1286 mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect::kSt
roke : | 1150 dieStyle = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseStyle ::kSt
roke : |
| 1287 DIEllipseEdgeEffect::kFi
ll; | 1151 DIEllipseStyle ::kFi
ll; |
| 1288 } | 1152 } |
| 1289 | 1153 |
| 1290 // This expands the outer rect so that after CTM we end up with a half-pixel
border | 1154 // This expands the outer rect so that after CTM we end up with a half-pixel
border |
| 1291 SkScalar a = viewMatrix[SkMatrix::kMScaleX]; | 1155 SkScalar a = viewMatrix[SkMatrix::kMScaleX]; |
| 1292 SkScalar b = viewMatrix[SkMatrix::kMSkewX]; | 1156 SkScalar b = viewMatrix[SkMatrix::kMSkewX]; |
| 1293 SkScalar c = viewMatrix[SkMatrix::kMSkewY]; | 1157 SkScalar c = viewMatrix[SkMatrix::kMSkewY]; |
| 1294 SkScalar d = viewMatrix[SkMatrix::kMScaleY]; | 1158 SkScalar d = viewMatrix[SkMatrix::kMScaleY]; |
| 1295 SkScalar geoDx = SK_ScalarHalf / SkScalarSqrt(a*a + c*c); | 1159 SkScalar geoDx = SK_ScalarHalf / SkScalarSqrt(a*a + c*c); |
| 1296 SkScalar geoDy = SK_ScalarHalf / SkScalarSqrt(b*b + d*d); | 1160 SkScalar geoDy = SK_ScalarHalf / SkScalarSqrt(b*b + d*d); |
| 1297 | 1161 |
| 1298 DIEllipseBatch::Geometry geometry; | 1162 DIEllipseBatch::Geometry geometry; |
| 1299 geometry.fViewMatrix = viewMatrix; | 1163 geometry.fViewMatrix = viewMatrix; |
| 1300 geometry.fColor = color; | 1164 geometry.fColor = color; |
| 1301 geometry.fXRadius = xRadius; | 1165 geometry.fXRadius = xRadius; |
| 1302 geometry.fYRadius = yRadius; | 1166 geometry.fYRadius = yRadius; |
| 1303 geometry.fInnerXRadius = innerXRadius; | 1167 geometry.fInnerXRadius = innerXRadius; |
| 1304 geometry.fInnerYRadius = innerYRadius; | 1168 geometry.fInnerYRadius = innerYRadius; |
| 1305 geometry.fGeoDx = geoDx; | 1169 geometry.fGeoDx = geoDx; |
| 1306 geometry.fGeoDy = geoDy; | 1170 geometry.fGeoDy = geoDy; |
| 1307 geometry.fMode = mode; | 1171 geometry.fStyle = dieStyle; |
| 1308 geometry.fBounds = SkRect::MakeLTRB(center.fX - xRadius - geoDx, center.fY -
yRadius - geoDy, | 1172 geometry.fBounds = SkRect::MakeLTRB(center.fX - xRadius - geoDx, center.fY -
yRadius - geoDy, |
| 1309 center.fX + xRadius + geoDx, center.fY +
yRadius + geoDy); | 1173 center.fX + xRadius + geoDx, center.fY +
yRadius + geoDy); |
| 1310 | 1174 |
| 1311 SkRect devBounds = geometry.fBounds; | 1175 SkRect devBounds = geometry.fBounds; |
| 1312 viewMatrix.mapRect(&devBounds); | 1176 viewMatrix.mapRect(&devBounds); |
| 1313 return DIEllipseBatch::Create(geometry, devBounds); | 1177 return DIEllipseBatch::Create(geometry, devBounds); |
| 1314 } | 1178 } |
| 1315 | 1179 |
| 1316 GrDrawBatch* GrOvalRenderer::CreateDIEllipseBatch(GrColor color, | 1180 GrDrawBatch* GrOvalRenderer::CreateDIEllipseBatch(GrColor color, |
| 1317 const SkMatrix& viewMatrix, | 1181 const SkMatrix& viewMatrix, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1363 } | 1227 } |
| 1364 } | 1228 } |
| 1365 | 1229 |
| 1366 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 1230 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 1367 | 1231 |
| 1368 class RRectCircleRendererBatch : public GrVertexBatch { | 1232 class RRectCircleRendererBatch : public GrVertexBatch { |
| 1369 public: | 1233 public: |
| 1370 DEFINE_BATCH_CLASS_ID | 1234 DEFINE_BATCH_CLASS_ID |
| 1371 | 1235 |
| 1372 struct Geometry { | 1236 struct Geometry { |
| 1373 SkMatrix fViewMatrix; | |
| 1374 SkRect fDevBounds; | 1237 SkRect fDevBounds; |
| 1375 SkScalar fInnerRadius; | 1238 SkScalar fInnerRadius; |
| 1376 SkScalar fOuterRadius; | 1239 SkScalar fOuterRadius; |
| 1377 GrColor fColor; | 1240 GrColor fColor; |
| 1378 bool fStroke; | |
| 1379 }; | 1241 }; |
| 1380 | 1242 |
| 1381 static GrDrawBatch* Create(const Geometry& geometry) { | 1243 RRectCircleRendererBatch(const Geometry& geometry, const SkMatrix& viewMatri
x, bool stroked) |
| 1382 return new RRectCircleRendererBatch(geometry); | 1244 : INHERITED(ClassID()) |
| 1245 , fStroked(stroked) |
| 1246 , fViewMatrixIfUsingLocalCoords(viewMatrix) { |
| 1247 fGeoData.push_back(geometry); |
| 1248 |
| 1249 this->setBounds(geometry.fDevBounds); |
| 1383 } | 1250 } |
| 1384 | 1251 |
| 1385 const char* name() const override { return "RRectCircleBatch"; } | 1252 const char* name() const override { return "RRectCircleBatch"; } |
| 1386 | 1253 |
| 1387 void computePipelineOptimizations(GrInitInvariantOutput* color, | 1254 void computePipelineOptimizations(GrInitInvariantOutput* color, |
| 1388 GrInitInvariantOutput* coverage, | 1255 GrInitInvariantOutput* coverage, |
| 1389 GrBatchToXPOverrides* overrides) const ove
rride { | 1256 GrBatchToXPOverrides* overrides) const ove
rride { |
| 1390 // When this is called on a batch, there is only one geometry bundle | 1257 // When this is called on a batch, there is only one geometry bundle |
| 1391 color->setKnownFourComponents(fGeoData[0].fColor); | 1258 color->setKnownFourComponents(fGeoData[0].fColor); |
| 1392 coverage->setUnknownSingleComponent(); | 1259 coverage->setUnknownSingleComponent(); |
| 1393 } | 1260 } |
| 1394 | 1261 |
| 1395 private: | 1262 private: |
| 1396 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { | 1263 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { |
| 1397 // Handle any color overrides | 1264 // Handle any overrides that affect our GP. |
| 1398 if (!overrides.readsColor()) { | 1265 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); |
| 1399 fGeoData[0].fColor = GrColor_ILLEGAL; | 1266 if (!overrides.readsLocalCoords()) { |
| 1267 fViewMatrixIfUsingLocalCoords.reset(); |
| 1400 } | 1268 } |
| 1401 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); | |
| 1402 | |
| 1403 // setup batch properties | |
| 1404 fBatch.fColorIgnored = !overrides.readsColor(); | |
| 1405 fBatch.fColor = fGeoData[0].fColor; | |
| 1406 fBatch.fStroke = fGeoData[0].fStroke; | |
| 1407 fBatch.fUsesLocalCoords = overrides.readsLocalCoords(); | |
| 1408 fBatch.fCoverageIgnored = !overrides.readsCoverage(); | |
| 1409 } | 1269 } |
| 1410 | 1270 |
| 1411 void onPrepareDraws(Target* target) const override { | 1271 void onPrepareDraws(Target* target) const override { |
| 1412 // reset to device coordinates | 1272 // Invert the view matrix as a local matrix (if any other processors req
uire coords). |
| 1413 SkMatrix invert; | 1273 SkMatrix localMatrix; |
| 1414 if (!this->viewMatrix().invert(&invert)) { | 1274 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { |
| 1415 SkDebugf("Failed to invert\n"); | |
| 1416 return; | 1275 return; |
| 1417 } | 1276 } |
| 1418 | 1277 |
| 1419 // Setup geometry processor | 1278 // Setup geometry processor |
| 1420 SkAutoTUnref<GrGeometryProcessor> gp(CircleEdgeEffect::Create(this->colo
r(), | 1279 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(fStroke
d, localMatrix)); |
| 1421 this->stro
ke(), | |
| 1422 invert, | |
| 1423 this->uses
LocalCoords())); | |
| 1424 | 1280 |
| 1425 target->initDraw(gp, this->pipeline()); | 1281 target->initDraw(gp, this->pipeline()); |
| 1426 | 1282 |
| 1427 int instanceCount = fGeoData.count(); | 1283 int instanceCount = fGeoData.count(); |
| 1428 size_t vertexStride = gp->getVertexStride(); | 1284 size_t vertexStride = gp->getVertexStride(); |
| 1429 SkASSERT(vertexStride == sizeof(CircleVertex)); | 1285 SkASSERT(vertexStride == sizeof(CircleVertex)); |
| 1430 | 1286 |
| 1431 // drop out the middle quad if we're stroked | 1287 // drop out the middle quad if we're stroked |
| 1432 int indicesPerInstance = this->stroke() ? kIndicesPerStrokeRRect : kIndi
cesPerRRect; | 1288 int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPer
RRect; |
| 1433 SkAutoTUnref<const GrIndexBuffer> indexBuffer( | 1289 SkAutoTUnref<const GrIndexBuffer> indexBuffer( |
| 1434 ref_rrect_index_buffer(this->stroke(), target->resourceProvider())); | 1290 ref_rrect_index_buffer(fStroked, target->resourceProvider())); |
| 1435 | 1291 |
| 1436 InstancedHelper helper; | 1292 InstancedHelper helper; |
| 1437 CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(target
, | 1293 CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(target
, |
| 1438 kTriangles_GrPrimitiveType, vertexStride, indexBuffer, kVertsPerRRec
t, | 1294 kTriangles_GrPrimitiveType, vertexStride, indexBuffer, kVertsPerRRec
t, |
| 1439 indicesPerInstance, instanceCount)); | 1295 indicesPerInstance, instanceCount)); |
| 1440 if (!verts || !indexBuffer) { | 1296 if (!verts || !indexBuffer) { |
| 1441 SkDebugf("Could not allocate vertices\n"); | 1297 SkDebugf("Could not allocate vertices\n"); |
| 1442 return; | 1298 return; |
| 1443 } | 1299 } |
| 1444 | 1300 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1487 verts->fOffset = SkPoint::Make(1, yOuterRadii[i]); | 1343 verts->fOffset = SkPoint::Make(1, yOuterRadii[i]); |
| 1488 verts->fOuterRadius = outerRadius; | 1344 verts->fOuterRadius = outerRadius; |
| 1489 verts->fInnerRadius = innerRadius; | 1345 verts->fInnerRadius = innerRadius; |
| 1490 verts++; | 1346 verts++; |
| 1491 } | 1347 } |
| 1492 } | 1348 } |
| 1493 | 1349 |
| 1494 helper.recordDraw(target); | 1350 helper.recordDraw(target); |
| 1495 } | 1351 } |
| 1496 | 1352 |
| 1497 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
| 1498 | |
| 1499 RRectCircleRendererBatch(const Geometry& geometry) : INHERITED(ClassID()) { | |
| 1500 fGeoData.push_back(geometry); | |
| 1501 | |
| 1502 this->setBounds(geometry.fDevBounds); | |
| 1503 } | |
| 1504 | |
| 1505 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | 1353 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
| 1506 RRectCircleRendererBatch* that = t->cast<RRectCircleRendererBatch>(); | 1354 RRectCircleRendererBatch* that = t->cast<RRectCircleRendererBatch>(); |
| 1507 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), | 1355 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), |
| 1508 that->bounds(), caps)) { | 1356 that->bounds(), caps)) { |
| 1509 return false; | 1357 return false; |
| 1510 } | 1358 } |
| 1511 | 1359 |
| 1512 if (this->stroke() != that->stroke()) { | 1360 if (fStroked != that->fStroked) { |
| 1513 return false; | 1361 return false; |
| 1514 } | 1362 } |
| 1515 | 1363 |
| 1516 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); | 1364 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing
LocalCoords)) { |
| 1517 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi
ewMatrix())) { | |
| 1518 return false; | 1365 return false; |
| 1519 } | 1366 } |
| 1520 | 1367 |
| 1521 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin())
; | 1368 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); |
| 1522 this->joinBounds(that->bounds()); | 1369 this->joinBounds(that->bounds()); |
| 1523 return true; | 1370 return true; |
| 1524 } | 1371 } |
| 1525 | 1372 |
| 1526 GrColor color() const { return fBatch.fColor; } | 1373 bool fStroked; |
| 1527 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | 1374 SkMatrix fViewMatrixIfUsingLocalCoords; |
| 1528 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | |
| 1529 bool stroke() const { return fBatch.fStroke; } | |
| 1530 | |
| 1531 struct BatchTracker { | |
| 1532 GrColor fColor; | |
| 1533 bool fStroke; | |
| 1534 bool fUsesLocalCoords; | |
| 1535 bool fColorIgnored; | |
| 1536 bool fCoverageIgnored; | |
| 1537 }; | |
| 1538 | |
| 1539 BatchTracker fBatch; | |
| 1540 SkSTArray<1, Geometry, true> fGeoData; | 1375 SkSTArray<1, Geometry, true> fGeoData; |
| 1541 | 1376 |
| 1542 typedef GrVertexBatch INHERITED; | 1377 typedef GrVertexBatch INHERITED; |
| 1543 }; | 1378 }; |
| 1544 | 1379 |
| 1545 class RRectEllipseRendererBatch : public GrVertexBatch { | 1380 class RRectEllipseRendererBatch : public GrVertexBatch { |
| 1546 public: | 1381 public: |
| 1547 DEFINE_BATCH_CLASS_ID | 1382 DEFINE_BATCH_CLASS_ID |
| 1548 | 1383 |
| 1549 struct Geometry { | 1384 struct Geometry { |
| 1550 SkMatrix fViewMatrix; | |
| 1551 SkRect fDevBounds; | 1385 SkRect fDevBounds; |
| 1552 SkScalar fXRadius; | 1386 SkScalar fXRadius; |
| 1553 SkScalar fYRadius; | 1387 SkScalar fYRadius; |
| 1554 SkScalar fInnerXRadius; | 1388 SkScalar fInnerXRadius; |
| 1555 SkScalar fInnerYRadius; | 1389 SkScalar fInnerYRadius; |
| 1556 GrColor fColor; | 1390 GrColor fColor; |
| 1557 bool fStroke; | |
| 1558 }; | 1391 }; |
| 1559 | 1392 |
| 1560 static GrDrawBatch* Create(const Geometry& geometry) { | 1393 RRectEllipseRendererBatch(const Geometry& geometry, const SkMatrix& viewMatr
ix, bool stroked) |
| 1561 return new RRectEllipseRendererBatch(geometry); | 1394 : INHERITED(ClassID()) |
| 1395 , fStroked(stroked) |
| 1396 , fViewMatrixIfUsingLocalCoords(viewMatrix) { |
| 1397 fGeoData.push_back(geometry); |
| 1398 this->setBounds(geometry.fDevBounds); |
| 1562 } | 1399 } |
| 1563 | 1400 |
| 1564 const char* name() const override { return "RRectEllipseRendererBatch"; } | 1401 const char* name() const override { return "RRectEllipseRendererBatch"; } |
| 1565 | 1402 |
| 1566 void computePipelineOptimizations(GrInitInvariantOutput* color, | 1403 void computePipelineOptimizations(GrInitInvariantOutput* color, |
| 1567 GrInitInvariantOutput* coverage, | 1404 GrInitInvariantOutput* coverage, |
| 1568 GrBatchToXPOverrides* overrides) const ove
rride { | 1405 GrBatchToXPOverrides* overrides) const ove
rride { |
| 1569 // When this is called on a batch, there is only one geometry bundle | 1406 // When this is called on a batch, there is only one geometry bundle |
| 1570 color->setKnownFourComponents(fGeoData[0].fColor); | 1407 color->setKnownFourComponents(fGeoData[0].fColor); |
| 1571 coverage->setUnknownSingleComponent(); | 1408 coverage->setUnknownSingleComponent(); |
| 1572 } | 1409 } |
| 1573 | 1410 |
| 1574 private: | 1411 private: |
| 1575 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { | 1412 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { |
| 1576 // Handle any color overrides | 1413 // Handle overrides that affect our GP. |
| 1577 if (!overrides.readsColor()) { | 1414 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); |
| 1578 fGeoData[0].fColor = GrColor_ILLEGAL; | 1415 if (!overrides.readsLocalCoords()) { |
| 1416 fViewMatrixIfUsingLocalCoords.reset(); |
| 1579 } | 1417 } |
| 1580 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); | |
| 1581 | |
| 1582 // setup batch properties | |
| 1583 fBatch.fColorIgnored = !overrides.readsColor(); | |
| 1584 fBatch.fColor = fGeoData[0].fColor; | |
| 1585 fBatch.fStroke = fGeoData[0].fStroke; | |
| 1586 fBatch.fUsesLocalCoords = overrides.readsLocalCoords(); | |
| 1587 fBatch.fCoverageIgnored = !overrides.readsCoverage(); | |
| 1588 } | 1418 } |
| 1589 | 1419 |
| 1590 void onPrepareDraws(Target* target) const override { | 1420 void onPrepareDraws(Target* target) const override { |
| 1591 // reset to device coordinates | 1421 SkMatrix localMatrix; |
| 1592 SkMatrix invert; | 1422 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { |
| 1593 if (!this->viewMatrix().invert(&invert)) { | |
| 1594 SkDebugf("Failed to invert\n"); | |
| 1595 return; | 1423 return; |
| 1596 } | 1424 } |
| 1597 | 1425 |
| 1598 // Setup geometry processor | 1426 // Setup geometry processor |
| 1599 SkAutoTUnref<GrGeometryProcessor> gp(EllipseEdgeEffect::Create(this->col
or(), | 1427 SkAutoTUnref<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStrok
ed, localMatrix)); |
| 1600 this->str
oke(), | |
| 1601 invert, | |
| 1602 this->use
sLocalCoords())); | |
| 1603 | 1428 |
| 1604 target->initDraw(gp, this->pipeline()); | 1429 target->initDraw(gp, this->pipeline()); |
| 1605 | 1430 |
| 1606 int instanceCount = fGeoData.count(); | 1431 int instanceCount = fGeoData.count(); |
| 1607 size_t vertexStride = gp->getVertexStride(); | 1432 size_t vertexStride = gp->getVertexStride(); |
| 1608 SkASSERT(vertexStride == sizeof(EllipseVertex)); | 1433 SkASSERT(vertexStride == sizeof(EllipseVertex)); |
| 1609 | 1434 |
| 1610 // drop out the middle quad if we're stroked | 1435 // drop out the middle quad if we're stroked |
| 1611 int indicesPerInstance = this->stroke() ? kIndicesPerStrokeRRect : kIndi
cesPerRRect; | 1436 int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPer
RRect; |
| 1612 SkAutoTUnref<const GrIndexBuffer> indexBuffer( | 1437 SkAutoTUnref<const GrIndexBuffer> indexBuffer( |
| 1613 ref_rrect_index_buffer(this->stroke(), target->resourceProvider())); | 1438 ref_rrect_index_buffer(fStroked, target->resourceProvider())); |
| 1614 | 1439 |
| 1615 InstancedHelper helper; | 1440 InstancedHelper helper; |
| 1616 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>( | 1441 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>( |
| 1617 helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexB
uffer, | 1442 helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexB
uffer, |
| 1618 kVertsPerRRect, indicesPerInstance, instanceCount)); | 1443 kVertsPerRRect, indicesPerInstance, instanceCount)); |
| 1619 if (!verts || !indexBuffer) { | 1444 if (!verts || !indexBuffer) { |
| 1620 SkDebugf("Could not allocate vertices\n"); | 1445 SkDebugf("Could not allocate vertices\n"); |
| 1621 return; | 1446 return; |
| 1622 } | 1447 } |
| 1623 | 1448 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1677 verts->fColor = color; | 1502 verts->fColor = color; |
| 1678 verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]); | 1503 verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]); |
| 1679 verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); | 1504 verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); |
| 1680 verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadReci
p); | 1505 verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadReci
p); |
| 1681 verts++; | 1506 verts++; |
| 1682 } | 1507 } |
| 1683 } | 1508 } |
| 1684 helper.recordDraw(target); | 1509 helper.recordDraw(target); |
| 1685 } | 1510 } |
| 1686 | 1511 |
| 1687 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
| 1688 | |
| 1689 RRectEllipseRendererBatch(const Geometry& geometry) : INHERITED(ClassID()) { | |
| 1690 fGeoData.push_back(geometry); | |
| 1691 | |
| 1692 this->setBounds(geometry.fDevBounds); | |
| 1693 } | |
| 1694 | |
| 1695 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | 1512 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
| 1696 RRectEllipseRendererBatch* that = t->cast<RRectEllipseRendererBatch>(); | 1513 RRectEllipseRendererBatch* that = t->cast<RRectEllipseRendererBatch>(); |
| 1697 | 1514 |
| 1698 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), | 1515 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), |
| 1699 that->bounds(), caps)) { | 1516 that->bounds(), caps)) { |
| 1700 return false; | 1517 return false; |
| 1701 } | 1518 } |
| 1702 | 1519 |
| 1703 if (this->stroke() != that->stroke()) { | 1520 if (fStroked != that->fStroked) { |
| 1704 return false; | 1521 return false; |
| 1705 } | 1522 } |
| 1706 | 1523 |
| 1707 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); | 1524 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing
LocalCoords)) { |
| 1708 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi
ewMatrix())) { | |
| 1709 return false; | 1525 return false; |
| 1710 } | 1526 } |
| 1711 | 1527 |
| 1712 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin())
; | 1528 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); |
| 1713 this->joinBounds(that->bounds()); | 1529 this->joinBounds(that->bounds()); |
| 1714 return true; | 1530 return true; |
| 1715 } | 1531 } |
| 1716 | 1532 |
| 1717 GrColor color() const { return fBatch.fColor; } | 1533 bool fStroked; |
| 1718 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | 1534 SkMatrix fViewMatrixIfUsingLocalCoords; |
| 1719 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | 1535 SkSTArray<1, Geometry, true> fGeoData; |
| 1720 bool stroke() const { return fBatch.fStroke; } | |
| 1721 | |
| 1722 struct BatchTracker { | |
| 1723 GrColor fColor; | |
| 1724 bool fStroke; | |
| 1725 bool fUsesLocalCoords; | |
| 1726 bool fColorIgnored; | |
| 1727 bool fCoverageIgnored; | |
| 1728 }; | |
| 1729 | |
| 1730 BatchTracker fBatch; | |
| 1731 SkSTArray<1, Geometry, true> fGeoData; | |
| 1732 | 1536 |
| 1733 typedef GrVertexBatch INHERITED; | 1537 typedef GrVertexBatch INHERITED; |
| 1734 }; | 1538 }; |
| 1735 | 1539 |
| 1736 static GrDrawBatch* create_rrect_batch(GrColor color, | 1540 static GrDrawBatch* create_rrect_batch(GrColor color, |
| 1737 const SkMatrix& viewMatrix, | 1541 const SkMatrix& viewMatrix, |
| 1738 const SkRRect& rrect, | 1542 const SkRRect& rrect, |
| 1739 const SkStrokeRec& stroke) { | 1543 const SkStrokeRec& stroke) { |
| 1740 SkASSERT(viewMatrix.rectStaysRect()); | 1544 SkASSERT(viewMatrix.rectStaysRect()); |
| 1741 SkASSERT(rrect.isSimple()); | 1545 SkASSERT(rrect.isSimple()); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1814 // Second, the outer radius is used to compute the verts of the bounding
box that is | 1618 // Second, the outer radius is used to compute the verts of the bounding
box that is |
| 1815 // rendered and the outset ensures the box will cover all partially cove
red by the rrect | 1619 // rendered and the outset ensures the box will cover all partially cove
red by the rrect |
| 1816 // corners. | 1620 // corners. |
| 1817 outerRadius += SK_ScalarHalf; | 1621 outerRadius += SK_ScalarHalf; |
| 1818 innerRadius -= SK_ScalarHalf; | 1622 innerRadius -= SK_ScalarHalf; |
| 1819 | 1623 |
| 1820 // Expand the rect so all the pixels will be captured. | 1624 // Expand the rect so all the pixels will be captured. |
| 1821 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); | 1625 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); |
| 1822 | 1626 |
| 1823 RRectCircleRendererBatch::Geometry geometry; | 1627 RRectCircleRendererBatch::Geometry geometry; |
| 1824 geometry.fViewMatrix = viewMatrix; | |
| 1825 geometry.fColor = color; | 1628 geometry.fColor = color; |
| 1826 geometry.fInnerRadius = innerRadius; | 1629 geometry.fInnerRadius = innerRadius; |
| 1827 geometry.fOuterRadius = outerRadius; | 1630 geometry.fOuterRadius = outerRadius; |
| 1828 geometry.fStroke = isStrokeOnly; | |
| 1829 geometry.fDevBounds = bounds; | 1631 geometry.fDevBounds = bounds; |
| 1830 | 1632 |
| 1831 return RRectCircleRendererBatch::Create(geometry); | 1633 return new RRectCircleRendererBatch(geometry, viewMatrix, isStrokeOnly); |
| 1832 // otherwise we use the ellipse renderer | 1634 // otherwise we use the ellipse renderer |
| 1833 } else { | 1635 } else { |
| 1834 SkScalar innerXRadius = 0.0f; | 1636 SkScalar innerXRadius = 0.0f; |
| 1835 SkScalar innerYRadius = 0.0f; | 1637 SkScalar innerYRadius = 0.0f; |
| 1836 if (hasStroke) { | 1638 if (hasStroke) { |
| 1837 if (SkScalarNearlyZero(scaledStroke.length())) { | 1639 if (SkScalarNearlyZero(scaledStroke.length())) { |
| 1838 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); | 1640 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); |
| 1839 } else { | 1641 } else { |
| 1840 scaledStroke.scale(SK_ScalarHalf); | 1642 scaledStroke.scale(SK_ScalarHalf); |
| 1841 } | 1643 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1862 yRadius += scaledStroke.fY; | 1664 yRadius += scaledStroke.fY; |
| 1863 bounds.outset(scaledStroke.fX, scaledStroke.fY); | 1665 bounds.outset(scaledStroke.fX, scaledStroke.fY); |
| 1864 } | 1666 } |
| 1865 | 1667 |
| 1866 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); | 1668 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); |
| 1867 | 1669 |
| 1868 // Expand the rect so all the pixels will be captured. | 1670 // Expand the rect so all the pixels will be captured. |
| 1869 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); | 1671 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); |
| 1870 | 1672 |
| 1871 RRectEllipseRendererBatch::Geometry geometry; | 1673 RRectEllipseRendererBatch::Geometry geometry; |
| 1872 geometry.fViewMatrix = viewMatrix; | |
| 1873 geometry.fColor = color; | 1674 geometry.fColor = color; |
| 1874 geometry.fXRadius = xRadius; | 1675 geometry.fXRadius = xRadius; |
| 1875 geometry.fYRadius = yRadius; | 1676 geometry.fYRadius = yRadius; |
| 1876 geometry.fInnerXRadius = innerXRadius; | 1677 geometry.fInnerXRadius = innerXRadius; |
| 1877 geometry.fInnerYRadius = innerYRadius; | 1678 geometry.fInnerYRadius = innerYRadius; |
| 1878 geometry.fStroke = isStrokeOnly; | |
| 1879 geometry.fDevBounds = bounds; | 1679 geometry.fDevBounds = bounds; |
| 1880 | 1680 |
| 1881 return RRectEllipseRendererBatch::Create(geometry); | 1681 return new RRectEllipseRendererBatch(geometry, viewMatrix, isStrokeOnly)
; |
| 1882 } | 1682 } |
| 1883 } | 1683 } |
| 1884 | 1684 |
| 1885 GrDrawBatch* GrOvalRenderer::CreateRRectBatch(GrColor color, | 1685 GrDrawBatch* GrOvalRenderer::CreateRRectBatch(GrColor color, |
| 1886 const SkMatrix& viewMatrix, | 1686 const SkMatrix& viewMatrix, |
| 1887 const SkRRect& rrect, | 1687 const SkRRect& rrect, |
| 1888 const SkStrokeRec& stroke, | 1688 const SkStrokeRec& stroke, |
| 1889 GrShaderCaps* shaderCaps) { | 1689 GrShaderCaps* shaderCaps) { |
| 1890 if (rrect.isOval()) { | 1690 if (rrect.isOval()) { |
| 1891 return CreateOvalBatch(color, viewMatrix, rrect.getBounds(), stroke, sha
derCaps); | 1691 return CreateOvalBatch(color, viewMatrix, rrect.getBounds(), stroke, sha
derCaps); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1924 } | 1724 } |
| 1925 | 1725 |
| 1926 DRAW_BATCH_TEST_DEFINE(RRectBatch) { | 1726 DRAW_BATCH_TEST_DEFINE(RRectBatch) { |
| 1927 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); | 1727 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); |
| 1928 GrColor color = GrRandomColor(random); | 1728 GrColor color = GrRandomColor(random); |
| 1929 const SkRRect& rrect = GrTest::TestRRectSimple(random); | 1729 const SkRRect& rrect = GrTest::TestRRectSimple(random); |
| 1930 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra
ndom)); | 1730 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra
ndom)); |
| 1931 } | 1731 } |
| 1932 | 1732 |
| 1933 #endif | 1733 #endif |
| OLD | NEW |