| 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 "GrProcessor.h" | 10 #include "GrProcessor.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 | 46 |
| 47 inline bool circle_stays_circle(const SkMatrix& m) { | 47 inline bool circle_stays_circle(const SkMatrix& m) { |
| 48 return m.isSimilarity(); | 48 return m.isSimilarity(); |
| 49 } | 49 } |
| 50 | 50 |
| 51 } | 51 } |
| 52 | 52 |
| 53 /////////////////////////////////////////////////////////////////////////////// | 53 /////////////////////////////////////////////////////////////////////////////// |
| 54 | 54 |
| 55 /** | 55 /** |
| 56 * The output of this effect is a modulation of the input color and coverage for
a circle, | 56 * The output of this effect is a modulation of the input color and coverage for
a circle. It |
| 57 * specified as offset_x, offset_y (both from center point), outer radius and in
ner radius. | 57 * operates in a space normalized by the circle radius (outer radius in the case
of a stroke) |
| 58 * with origin at the circle center. Two vertex attributes are used: |
| 59 * vec2f : position in device space of the bounding geometry vertices |
| 60 * vec4f : (p.xy, outerRad, innerRad) |
| 61 * p is the position in the normalized space. |
| 62 * outerRad is the outerRadius in device space. |
| 63 * innerRad is the innerRadius in normalized space (ignored if not s
troking). |
| 58 */ | 64 */ |
| 59 | 65 |
| 60 class CircleEdgeEffect : public GrGeometryProcessor { | 66 class CircleEdgeEffect : public GrGeometryProcessor { |
| 61 public: | 67 public: |
| 62 static GrGeometryProcessor* Create(GrColor color, bool stroke) { | 68 static GrGeometryProcessor* Create(GrColor color, bool stroke) { |
| 63 return SkNEW_ARGS(CircleEdgeEffect, (color, stroke)); | 69 return SkNEW_ARGS(CircleEdgeEffect, (color, stroke)); |
| 64 } | 70 } |
| 65 | 71 |
| 66 const GrAttribute* inPosition() const { return fInPosition; } | 72 const GrAttribute* inPosition() const { return fInPosition; } |
| 67 const GrAttribute* inCircleEdge() const { return fInCircleEdge; } | 73 const GrAttribute* inCircleEdge() const { return fInCircleEdge; } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 87 // setup coord outputs | 93 // setup coord outputs |
| 88 vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ce.i
nPosition()->fName); | 94 vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ce.i
nPosition()->fName); |
| 89 vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ce.inPo
sition()->fName); | 95 vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ce.inPo
sition()->fName); |
| 90 | 96 |
| 91 // setup position varying | 97 // setup position varying |
| 92 vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPositi
on(), | 98 vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPositi
on(), |
| 93 vsBuilder->uViewM(), ce.inPosition()->fName); | 99 vsBuilder->uViewM(), ce.inPosition()->fName); |
| 94 | 100 |
| 95 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilde
r(); | 101 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilde
r(); |
| 96 fsBuilder->codeAppendf("float d = length(%s.xy);", v.fsIn()); | 102 fsBuilder->codeAppendf("float d = length(%s.xy);", v.fsIn()); |
| 97 fsBuilder->codeAppendf("float edgeAlpha = clamp(%s.z - d, 0.0, 1.0);
", v.fsIn()); | 103 fsBuilder->codeAppendf("float edgeAlpha = clamp(%s.z * (1.0 - d), 0.
0, 1.0);", v.fsIn()); |
| 98 if (ce.isStroked()) { | 104 if (ce.isStroked()) { |
| 99 fsBuilder->codeAppendf("float innerAlpha = clamp(d - %s.w, 0.0,
1.0);", | 105 fsBuilder->codeAppendf("float innerAlpha = clamp(%s.z * (d - %s.
w), 0.0, 1.0);", |
| 100 v.fsIn()); | 106 v.fsIn(), v.fsIn()); |
| 101 fsBuilder->codeAppend("edgeAlpha *= innerAlpha;"); | 107 fsBuilder->codeAppend("edgeAlpha *= innerAlpha;"); |
| 102 } | 108 } |
| 103 | 109 |
| 104 fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage
); | 110 fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage
); |
| 105 } | 111 } |
| 106 | 112 |
| 107 static void GenKey(const GrGeometryProcessor& processor, | 113 static void GenKey(const GrGeometryProcessor& processor, |
| 108 const GrBatchTracker&, | 114 const GrBatchTracker&, |
| 109 const GrGLCaps&, | 115 const GrGLCaps&, |
| 110 GrProcessorKeyBuilder* b) { | 116 GrProcessorKeyBuilder* b) { |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 | 573 |
| 568 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); | 574 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); |
| 569 SkASSERT(gp->getVertexStride() == sizeof(CircleVertex)); | 575 SkASSERT(gp->getVertexStride() == sizeof(CircleVertex)); |
| 570 if (!geo.succeeded()) { | 576 if (!geo.succeeded()) { |
| 571 SkDebugf("Failed to get space for vertices!\n"); | 577 SkDebugf("Failed to get space for vertices!\n"); |
| 572 return; | 578 return; |
| 573 } | 579 } |
| 574 | 580 |
| 575 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); | 581 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); |
| 576 | 582 |
| 577 // The radii are outset for two reasons. First, it allows the shader to simp
ly perform | 583 // The radii are outset for two reasons. First, it allows the shader to simp
ly perform simpler |
| 578 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is use
d to compute the | 584 // computation because the computed alpha is zero, rather than 50%, at the r
adius. |
| 579 // verts of the bounding box that is rendered and the outset ensures the box
will cover all | 585 // Second, the outer radius is used to compute the verts of the bounding box
that is rendered |
| 580 // pixels partially covered by the circle. | 586 // and the outset ensures the box will cover all partially covered by the ci
rcle. |
| 581 outerRadius += SK_ScalarHalf; | 587 outerRadius += SK_ScalarHalf; |
| 582 innerRadius -= SK_ScalarHalf; | 588 innerRadius -= SK_ScalarHalf; |
| 583 | 589 |
| 584 SkRect bounds = SkRect::MakeLTRB( | 590 SkRect bounds = SkRect::MakeLTRB( |
| 585 center.fX - outerRadius, | 591 center.fX - outerRadius, |
| 586 center.fY - outerRadius, | 592 center.fY - outerRadius, |
| 587 center.fX + outerRadius, | 593 center.fX + outerRadius, |
| 588 center.fY + outerRadius | 594 center.fY + outerRadius |
| 589 ); | 595 ); |
| 590 | 596 |
| 597 // The inner radius in the vertex data must be specified in normalized space
. |
| 598 innerRadius = innerRadius / outerRadius; |
| 591 verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); | 599 verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); |
| 592 verts[0].fOffset = SkPoint::Make(-outerRadius, -outerRadius); | 600 verts[0].fOffset = SkPoint::Make(-1, -1); |
| 593 verts[0].fOuterRadius = outerRadius; | 601 verts[0].fOuterRadius = outerRadius; |
| 594 verts[0].fInnerRadius = innerRadius; | 602 verts[0].fInnerRadius = innerRadius; |
| 595 | 603 |
| 596 verts[1].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); | 604 verts[1].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); |
| 597 verts[1].fOffset = SkPoint::Make(-outerRadius, outerRadius); | 605 verts[1].fOffset = SkPoint::Make(-1, 1); |
| 598 verts[1].fOuterRadius = outerRadius; | 606 verts[1].fOuterRadius = outerRadius; |
| 599 verts[1].fInnerRadius = innerRadius; | 607 verts[1].fInnerRadius = innerRadius; |
| 600 | 608 |
| 601 verts[2].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); | 609 verts[2].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); |
| 602 verts[2].fOffset = SkPoint::Make(outerRadius, outerRadius); | 610 verts[2].fOffset = SkPoint::Make(1, 1); |
| 603 verts[2].fOuterRadius = outerRadius; | 611 verts[2].fOuterRadius = outerRadius; |
| 604 verts[2].fInnerRadius = innerRadius; | 612 verts[2].fInnerRadius = innerRadius; |
| 605 | 613 |
| 606 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); | 614 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); |
| 607 verts[3].fOffset = SkPoint::Make(outerRadius, -outerRadius); | 615 verts[3].fOffset = SkPoint::Make(1, -1); |
| 608 verts[3].fOuterRadius = outerRadius; | 616 verts[3].fOuterRadius = outerRadius; |
| 609 verts[3].fInnerRadius = innerRadius; | 617 verts[3].fInnerRadius = innerRadius; |
| 610 | 618 |
| 611 target->setIndexSourceToBuffer(context->getGpu()->getQuadIndexBuffer()); | 619 target->setIndexSourceToBuffer(context->getGpu()->getQuadIndexBuffer()); |
| 612 target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 4, 6,
&bounds); | 620 target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 4, 6,
&bounds); |
| 613 target->resetIndexSource(); | 621 target->resetIndexSource(); |
| 614 } | 622 } |
| 615 | 623 |
| 616 /////////////////////////////////////////////////////////////////////////////// | 624 /////////////////////////////////////////////////////////////////////////////// |
| 617 | 625 |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1082 | 1090 |
| 1083 GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStrid
e(), 0); | 1091 GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStrid
e(), 0); |
| 1084 SkASSERT(effect->getVertexStride() == sizeof(CircleVertex)); | 1092 SkASSERT(effect->getVertexStride() == sizeof(CircleVertex)); |
| 1085 if (!geo.succeeded()) { | 1093 if (!geo.succeeded()) { |
| 1086 SkDebugf("Failed to get space for vertices!\n"); | 1094 SkDebugf("Failed to get space for vertices!\n"); |
| 1087 return false; | 1095 return false; |
| 1088 } | 1096 } |
| 1089 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); | 1097 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); |
| 1090 | 1098 |
| 1091 // The radii are outset for two reasons. First, it allows the shader to
simply perform | 1099 // The radii are outset for two reasons. First, it allows the shader to
simply perform |
| 1092 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is
used to compute the | 1100 // simpler computation because the computed alpha is zero, rather than 5
0%, at the radius. |
| 1093 // verts of the bounding box that is rendered and the outset ensures the
box will cover all | 1101 // Second, the outer radius is used to compute the verts of the bounding
box that is |
| 1094 // pixels partially covered by the circle. | 1102 // rendered and the outset ensures the box will cover all partially cove
red by the rrect |
| 1103 // corners. |
| 1095 outerRadius += SK_ScalarHalf; | 1104 outerRadius += SK_ScalarHalf; |
| 1096 innerRadius -= SK_ScalarHalf; | 1105 innerRadius -= SK_ScalarHalf; |
| 1097 | 1106 |
| 1098 // Expand the rect so all the pixels will be captured. | 1107 // Expand the rect so all the pixels will be captured. |
| 1099 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); | 1108 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); |
| 1100 | 1109 |
| 1101 SkScalar yCoords[4] = { | 1110 SkScalar yCoords[4] = { |
| 1102 bounds.fTop, | 1111 bounds.fTop, |
| 1103 bounds.fTop + outerRadius, | 1112 bounds.fTop + outerRadius, |
| 1104 bounds.fBottom - outerRadius, | 1113 bounds.fBottom - outerRadius, |
| 1105 bounds.fBottom | 1114 bounds.fBottom |
| 1106 }; | 1115 }; |
| 1107 SkScalar yOuterRadii[4] = { | 1116 SkScalar yOuterRadii[4] = {-1, 0, 0, 1 }; |
| 1108 -outerRadius, | 1117 // The inner radius in the vertex data must be specified in normalized s
pace. |
| 1109 0, | 1118 innerRadius = innerRadius / outerRadius; |
| 1110 0, | |
| 1111 outerRadius | |
| 1112 }; | |
| 1113 for (int i = 0; i < 4; ++i) { | 1119 for (int i = 0; i < 4; ++i) { |
| 1114 verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]); | 1120 verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]); |
| 1115 verts->fOffset = SkPoint::Make(-outerRadius, yOuterRadii[i]); | 1121 verts->fOffset = SkPoint::Make(-1, yOuterRadii[i]); |
| 1116 verts->fOuterRadius = outerRadius; | 1122 verts->fOuterRadius = outerRadius; |
| 1117 verts->fInnerRadius = innerRadius; | 1123 verts->fInnerRadius = innerRadius; |
| 1118 verts++; | 1124 verts++; |
| 1119 | 1125 |
| 1120 verts->fPos = SkPoint::Make(bounds.fLeft + outerRadius, yCoords[i]); | 1126 verts->fPos = SkPoint::Make(bounds.fLeft + outerRadius, yCoords[i]); |
| 1121 verts->fOffset = SkPoint::Make(0, yOuterRadii[i]); | 1127 verts->fOffset = SkPoint::Make(0, yOuterRadii[i]); |
| 1122 verts->fOuterRadius = outerRadius; | 1128 verts->fOuterRadius = outerRadius; |
| 1123 verts->fInnerRadius = innerRadius; | 1129 verts->fInnerRadius = innerRadius; |
| 1124 verts++; | 1130 verts++; |
| 1125 | 1131 |
| 1126 verts->fPos = SkPoint::Make(bounds.fRight - outerRadius, yCoords[i])
; | 1132 verts->fPos = SkPoint::Make(bounds.fRight - outerRadius, yCoords[i])
; |
| 1127 verts->fOffset = SkPoint::Make(0, yOuterRadii[i]); | 1133 verts->fOffset = SkPoint::Make(0, yOuterRadii[i]); |
| 1128 verts->fOuterRadius = outerRadius; | 1134 verts->fOuterRadius = outerRadius; |
| 1129 verts->fInnerRadius = innerRadius; | 1135 verts->fInnerRadius = innerRadius; |
| 1130 verts++; | 1136 verts++; |
| 1131 | 1137 |
| 1132 verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); | 1138 verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); |
| 1133 verts->fOffset = SkPoint::Make(outerRadius, yOuterRadii[i]); | 1139 verts->fOffset = SkPoint::Make(1, yOuterRadii[i]); |
| 1134 verts->fOuterRadius = outerRadius; | 1140 verts->fOuterRadius = outerRadius; |
| 1135 verts->fInnerRadius = innerRadius; | 1141 verts->fInnerRadius = innerRadius; |
| 1136 verts++; | 1142 verts++; |
| 1137 } | 1143 } |
| 1138 | 1144 |
| 1139 // drop out the middle quad if we're stroked | 1145 // drop out the middle quad if we're stroked |
| 1140 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : | 1146 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : |
| 1141 SK_ARRAY_COUNT(gRRectIndices); | 1147 SK_ARRAY_COUNT(gRRectIndices); |
| 1142 target->setIndexSourceToBuffer(indexBuffer); | 1148 target->setIndexSourceToBuffer(indexBuffer); |
| 1143 target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 1
6, indexCnt, | 1149 target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 1
6, indexCnt, |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1247 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : | 1253 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : |
| 1248 SK_ARRAY_COUNT(gRRectIndices); | 1254 SK_ARRAY_COUNT(gRRectIndices); |
| 1249 target->setIndexSourceToBuffer(indexBuffer); | 1255 target->setIndexSourceToBuffer(indexBuffer); |
| 1250 target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 1
6, indexCnt, | 1256 target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 1
6, indexCnt, |
| 1251 &bounds); | 1257 &bounds); |
| 1252 } | 1258 } |
| 1253 | 1259 |
| 1254 target->resetIndexSource(); | 1260 target->resetIndexSource(); |
| 1255 return true; | 1261 return true; |
| 1256 } | 1262 } |
| OLD | NEW |