Chromium Code Reviews| Index: src/gpu/GrOvalRenderer.cpp |
| =================================================================== |
| --- src/gpu/GrOvalRenderer.cpp (revision 8596) |
| +++ src/gpu/GrOvalRenderer.cpp (working copy) |
| @@ -21,19 +21,18 @@ |
| namespace { |
| struct CircleVertex { |
| - GrPoint fPos; |
| - GrPoint fCenter; |
| + GrPoint fPos; |
| + GrPoint fOffset; |
| SkScalar fOuterRadius; |
| SkScalar fInnerRadius; |
| }; |
| struct EllipseVertex { |
| - GrPoint fPos; |
| - GrPoint fCenter; |
| + GrPoint fPos; |
| SkScalar fOuterXRadius; |
| - SkScalar fOuterXYRatio; |
| SkScalar fInnerXRadius; |
| - SkScalar fInnerXYRatio; |
| + GrPoint fOuterOffset; |
| + GrPoint fInnerOffset; |
| }; |
| inline bool circle_stays_circle(const SkMatrix& m) { |
| @@ -46,8 +45,7 @@ |
| /** |
| * The output of this effect is a modulation of the input color and coverage for a circle, |
| - * specified as center_x, center_y, x_radius, inner radius and outer radius in window space |
| - * (y-down). |
| + * specified as offset_x, offset_y (both from center point), outer radius and inner radius. |
| */ |
| class CircleEdgeEffect : public GrEffect { |
| @@ -102,13 +100,13 @@ |
| builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); |
| builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); |
| - builder->fsCodeAppendf("\tfloat d = distance(%s.xy, %s.xy);\n", |
| - builder->fragmentPosition(), fsName); |
| + builder->fsCodeAppendf("\tfloat d = length(%s.xy);\n", fsName); |
| builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0);\n", fsName); |
| if (circleEffect.isStroked()) { |
| builder->fsCodeAppendf("\tfloat innerAlpha = clamp(d - %s.w, 0.0, 1.0);\n", fsName); |
| builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n"); |
| } |
| + |
| SkString modulate; |
| GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); |
| builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); |
| @@ -158,7 +156,7 @@ |
| /** |
| * The output of this effect is a modulation of the input color and coverage for an axis-aligned |
| - * ellipse, specified as center_x, center_y, x_radius, x_radius/y_radius in window space (y-down). |
| + * ellipse, specified as outer and inner radii, and outer and inner offsets from center. |
| */ |
| class EllipseEdgeEffect : public GrEffect { |
| @@ -207,37 +205,31 @@ |
| const TextureSamplerArray& samplers) SK_OVERRIDE { |
| const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<EllipseEdgeEffect>(); |
| - const char *vsCenterName, *fsCenterName; |
| - const char *vsEdgeName, *fsEdgeName; |
| + const char *vsRadiiName, *fsRadiiName; |
| + const char *vsOffsetsName, *fsOffsetsName; |
| - builder->addVarying(kVec2f_GrSLType, "EllipseCenter", &vsCenterName, &fsCenterName); |
| + builder->addVarying(kVec2f_GrSLType, "EllipseRadii", &vsRadiiName, &fsRadiiName); |
| const SkString* attr0Name = |
| builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); |
| - builder->vsCodeAppendf("\t%s = %s;\n", vsCenterName, attr0Name->c_str()); |
| + builder->vsCodeAppendf("\t%s = %s;\n", vsRadiiName, attr0Name->c_str()); |
| - builder->addVarying(kVec4f_GrSLType, "EllipseEdge", &vsEdgeName, &fsEdgeName); |
| + builder->addVarying(kVec4f_GrSLType, "EllipseOffsets", &vsOffsetsName, &fsOffsetsName); |
| const SkString* attr1Name = |
| builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); |
| - builder->vsCodeAppendf("\t%s = %s;\n", vsEdgeName, attr1Name->c_str()); |
| + builder->vsCodeAppendf("\t%s = %s;\n", vsOffsetsName, attr1Name->c_str()); |
| - // translate to origin |
| - builder->fsCodeAppendf("\tvec2 outerOffset = (%s.xy - %s.xy);\n", |
| - builder->fragmentPosition(), fsCenterName); |
| - builder->fsCodeAppend("\tvec2 innerOffset = outerOffset;\n"); |
| - // scale y by xRadius/yRadius |
| - builder->fsCodeAppendf("\touterOffset.y *= %s.y;\n", fsEdgeName); |
| - builder->fsCodeAppend("\tfloat dOuter = length(outerOffset);\n"); |
| + // get length of offset |
| + builder->fsCodeAppendf("\tfloat dOuter = length(%s.xy);\n", fsOffsetsName); |
| // compare outer lengths against xOuterRadius |
| builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.x-dOuter, 0.0, 1.0);\n", |
| - fsEdgeName); |
| + fsRadiiName); |
| if (ellipseEffect.isStroked()) { |
| - builder->fsCodeAppendf("\tinnerOffset.y *= %s.w;\n", fsEdgeName); |
| - builder->fsCodeAppend("\tfloat dInner = length(innerOffset);\n"); |
| + builder->fsCodeAppendf("\tfloat dInner = length(%s.zw);\n", fsOffsetsName); |
| // compare inner lengths against xInnerRadius |
| - builder->fsCodeAppendf("\tfloat innerAlpha = clamp(dInner-%s.z, 0.0, 1.0);\n", |
| - fsEdgeName); |
| + builder->fsCodeAppendf("\tfloat innerAlpha = clamp(dInner-%s.y, 0.0, 1.0);\n", |
| + fsRadiiName); |
| builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n"); |
| } |
| @@ -384,12 +376,6 @@ |
| outerRadius += SK_ScalarHalf; |
| innerRadius -= SK_ScalarHalf; |
| - for (int i = 0; i < 4; ++i) { |
| - verts[i].fCenter = center; |
| - verts[i].fOuterRadius = outerRadius; |
| - verts[i].fInnerRadius = innerRadius; |
| - } |
| - |
| SkRect bounds = SkRect::MakeLTRB( |
| center.fX - outerRadius, |
| center.fY - outerRadius, |
| @@ -398,9 +384,24 @@ |
| ); |
| verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); |
| + verts[0].fOffset = SkPoint::Make(-outerRadius, -outerRadius); |
| + verts[0].fOuterRadius = outerRadius; |
| + verts[0].fInnerRadius = innerRadius; |
| + |
| verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); |
| + verts[1].fOffset = SkPoint::Make(outerRadius, -outerRadius); |
| + verts[1].fOuterRadius = outerRadius; |
| + verts[1].fInnerRadius = innerRadius; |
| + |
| verts[2].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); |
| + verts[2].fOffset = SkPoint::Make(-outerRadius, outerRadius); |
| + verts[2].fOuterRadius = outerRadius; |
| + verts[2].fInnerRadius = innerRadius; |
| + |
| verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); |
| + verts[3].fOffset = SkPoint::Make(outerRadius, outerRadius); |
| + verts[3].fOuterRadius = outerRadius; |
| + verts[3].fInnerRadius = innerRadius; |
| target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds); |
| } |
| @@ -495,30 +496,46 @@ |
| SkScalar outerRatio = SkScalarDiv(xRadius, yRadius); |
| - for (int i = 0; i < 4; ++i) { |
| - verts[i].fCenter = center; |
| - verts[i].fOuterXRadius = xRadius + 0.5f; |
| - verts[i].fOuterXYRatio = outerRatio; |
| - verts[i].fInnerXRadius = innerXRadius - 0.5f; |
| - verts[i].fInnerXYRatio = innerRatio; |
| - } |
| + // We've extended the outer x radius out half a pixel to antialias. |
| + // This will also expand the rect so all the pixels will be captured. |
| + xRadius += SK_ScalarHalf; |
| + yRadius += SK_ScalarHalf; |
| + innerXRadius -= SK_ScalarHalf; |
| - SkScalar L = -xRadius; |
| - SkScalar R = +xRadius; |
| - SkScalar T = -yRadius; |
| - SkScalar B = +yRadius; |
| + SkRect bounds = SkRect::MakeLTRB( |
| + center.fX - xRadius, |
| + center.fY - yRadius, |
| + center.fX + xRadius, |
| + center.fY + yRadius |
| + ); |
| - // We've extended the outer x radius out half a pixel to antialias. |
| - // Expand the drawn rect here so all the pixels will be captured. |
| - L += center.fX - SK_ScalarHalf; |
| - R += center.fX + SK_ScalarHalf; |
| - T += center.fY - SK_ScalarHalf; |
| - B += center.fY + SK_ScalarHalf; |
| + // The offsets are created by scaling the y radius by the appropriate ratio. This way we end up |
| + // with a circle equation which can be checked quickly in the shader. We need one offset for |
| + // outer and one for inner because they have different scale factors -- otherwise we end up with |
| + // non-uniform strokes. |
| + verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); |
| + verts[0].fOuterXRadius = xRadius; |
| + verts[0].fInnerXRadius = innerXRadius; |
| + verts[0].fOuterOffset = SkPoint::Make(-xRadius, -outerRatio*yRadius); |
| + verts[0].fInnerOffset = SkPoint::Make(-xRadius, -innerRatio*yRadius); |
| - verts[0].fPos = SkPoint::Make(L, T); |
| - verts[1].fPos = SkPoint::Make(R, T); |
| - verts[2].fPos = SkPoint::Make(L, B); |
| - verts[3].fPos = SkPoint::Make(R, B); |
| + verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); |
| + verts[1].fOuterXRadius = xRadius; |
| + verts[1].fInnerXRadius = innerXRadius; |
| + verts[1].fOuterOffset = SkPoint::Make(xRadius, -outerRatio*yRadius); |
| + verts[1].fInnerOffset = SkPoint::Make(xRadius, -innerRatio*yRadius); |
| - target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4); |
| + verts[2].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); |
| + verts[2].fOuterXRadius = xRadius; |
| + verts[2].fInnerXRadius = innerXRadius; |
| + verts[2].fOuterOffset = SkPoint::Make(-xRadius, outerRatio*yRadius); |
| + verts[2].fInnerOffset = SkPoint::Make(-xRadius, innerRatio*yRadius); |
| + |
| + verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); |
| + verts[3].fOuterXRadius = xRadius; |
| + verts[3].fInnerXRadius = innerXRadius; |
| + verts[3].fOuterOffset = SkPoint::Make(xRadius, outerRatio*yRadius); |
| + verts[3].fInnerOffset = SkPoint::Make(xRadius, innerRatio*yRadius); |
| + |
|
robertphillips
2013/04/10 23:18:39
For the rect edge passing the bounds actually slow
|
| + target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds); |
| } |