| Index: src/gpu/GrOvalRenderer.cpp
|
| diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp
|
| index eac6fb4a3af5b2b3a3cb1ffba7659548ed4d7be4..b9a806c9e19bfe63ee7ea2a290efff2ac6061ce8 100644
|
| --- a/src/gpu/GrOvalRenderer.cpp
|
| +++ b/src/gpu/GrOvalRenderer.cpp
|
| @@ -53,8 +53,14 @@ inline bool circle_stays_circle(const SkMatrix& m) {
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| /**
|
| - * The output of this effect is a modulation of the input color and coverage for a circle,
|
| - * specified as offset_x, offset_y (both from center point), outer radius and inner radius.
|
| + * The output of this effect is a modulation of the input color and coverage for a circle. It
|
| + * operates in a space normalized by the circle radius (outer radius in the case of a stroke)
|
| + * with origin at the circle center. Two vertex attributes are used:
|
| + * vec2f : position in device space of the bounding geometry vertices
|
| + * vec4f : (p.xy, outerRad, innerRad)
|
| + * p is the position in the normalized space.
|
| + * outerRad is the outerRadius in device space.
|
| + * innerRad is the innerRadius in normalized space (ignored if not stroking).
|
| */
|
|
|
| class CircleEdgeEffect : public GrGeometryProcessor {
|
| @@ -94,10 +100,10 @@ public:
|
|
|
| GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
|
| fsBuilder->codeAppendf("float d = length(%s.xy);", v.fsIn());
|
| - fsBuilder->codeAppendf("float edgeAlpha = clamp(%s.z - d, 0.0, 1.0);", v.fsIn());
|
| + fsBuilder->codeAppendf("float edgeAlpha = clamp(%s.z * (1.0 - d), 0.0, 1.0);", v.fsIn());
|
| if (ce.isStroked()) {
|
| - fsBuilder->codeAppendf("float innerAlpha = clamp(d - %s.w, 0.0, 1.0);",
|
| - v.fsIn());
|
| + fsBuilder->codeAppendf("float innerAlpha = clamp(%s.z * (d - %s.w), 0.0, 1.0);",
|
| + v.fsIn(), v.fsIn());
|
| fsBuilder->codeAppend("edgeAlpha *= innerAlpha;");
|
| }
|
|
|
| @@ -574,10 +580,10 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
|
|
|
| CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
|
|
|
| - // The radii are outset for two reasons. First, it allows the shader to simply perform
|
| - // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
|
| - // verts of the bounding box that is rendered and the outset ensures the box will cover all
|
| - // pixels partially covered by the circle.
|
| + // The radii are outset for two reasons. First, it allows the shader to simply perform simpler
|
| + // computation because the computed alpha is zero, rather than 50%, at the radius.
|
| + // Second, the outer radius is used to compute the verts of the bounding box that is rendered
|
| + // and the outset ensures the box will cover all partially covered by the circle.
|
| outerRadius += SK_ScalarHalf;
|
| innerRadius -= SK_ScalarHalf;
|
|
|
| @@ -588,23 +594,25 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
|
| center.fY + outerRadius
|
| );
|
|
|
| + // The inner radius in the vertex data must be specified in normalized space.
|
| + innerRadius = innerRadius / outerRadius;
|
| verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop);
|
| - verts[0].fOffset = SkPoint::Make(-outerRadius, -outerRadius);
|
| + verts[0].fOffset = SkPoint::Make(-1, -1);
|
| verts[0].fOuterRadius = outerRadius;
|
| verts[0].fInnerRadius = innerRadius;
|
|
|
| verts[1].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom);
|
| - verts[1].fOffset = SkPoint::Make(-outerRadius, outerRadius);
|
| + verts[1].fOffset = SkPoint::Make(-1, 1);
|
| verts[1].fOuterRadius = outerRadius;
|
| verts[1].fInnerRadius = innerRadius;
|
|
|
| verts[2].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
|
| - verts[2].fOffset = SkPoint::Make(outerRadius, outerRadius);
|
| + verts[2].fOffset = SkPoint::Make(1, 1);
|
| verts[2].fOuterRadius = outerRadius;
|
| verts[2].fInnerRadius = innerRadius;
|
|
|
| verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fTop);
|
| - verts[3].fOffset = SkPoint::Make(outerRadius, -outerRadius);
|
| + verts[3].fOffset = SkPoint::Make(1, -1);
|
| verts[3].fOuterRadius = outerRadius;
|
| verts[3].fInnerRadius = innerRadius;
|
|
|
| @@ -1089,9 +1097,10 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target,
|
| CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
|
|
|
| // The radii are outset for two reasons. First, it allows the shader to simply perform
|
| - // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
|
| - // verts of the bounding box that is rendered and the outset ensures the box will cover all
|
| - // pixels partially covered by the circle.
|
| + // simpler computation because the computed alpha is zero, rather than 50%, at the radius.
|
| + // Second, the outer radius is used to compute the verts of the bounding box that is
|
| + // rendered and the outset ensures the box will cover all partially covered by the rrect
|
| + // corners.
|
| outerRadius += SK_ScalarHalf;
|
| innerRadius -= SK_ScalarHalf;
|
|
|
| @@ -1104,15 +1113,12 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target,
|
| bounds.fBottom - outerRadius,
|
| bounds.fBottom
|
| };
|
| - SkScalar yOuterRadii[4] = {
|
| - -outerRadius,
|
| - 0,
|
| - 0,
|
| - outerRadius
|
| - };
|
| + SkScalar yOuterRadii[4] = {-1, 0, 0, 1 };
|
| + // The inner radius in the vertex data must be specified in normalized space.
|
| + innerRadius = innerRadius / outerRadius;
|
| for (int i = 0; i < 4; ++i) {
|
| verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]);
|
| - verts->fOffset = SkPoint::Make(-outerRadius, yOuterRadii[i]);
|
| + verts->fOffset = SkPoint::Make(-1, yOuterRadii[i]);
|
| verts->fOuterRadius = outerRadius;
|
| verts->fInnerRadius = innerRadius;
|
| verts++;
|
| @@ -1130,7 +1136,7 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target,
|
| verts++;
|
|
|
| verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]);
|
| - verts->fOffset = SkPoint::Make(outerRadius, yOuterRadii[i]);
|
| + verts->fOffset = SkPoint::Make(1, yOuterRadii[i]);
|
| verts->fOuterRadius = outerRadius;
|
| verts->fInnerRadius = innerRadius;
|
| verts++;
|
|
|