diff options
author | jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-09-04 16:40:37 +0000 |
---|---|---|
committer | jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-09-04 16:40:37 +0000 |
commit | 059a5a339b14b6fe4f942d57387fba7a9e1fea06 (patch) | |
tree | 8ec193c39d1ae45b0ec8ab3f5c6134cc141e5ccc /src/gpu | |
parent | 14486ea9e3f770363bb7db27dc7d0033f3cba013 (diff) |
Reverting r11075.
git-svn-id: http://skia.googlecode.com/svn/trunk@11080 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrOvalRenderer.cpp | 296 |
1 files changed, 14 insertions, 282 deletions
diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp index c036ca1c6a..6965f9e580 100644 --- a/src/gpu/GrOvalRenderer.cpp +++ b/src/gpu/GrOvalRenderer.cpp @@ -37,12 +37,6 @@ struct EllipseVertex { GrPoint fInnerRadii; }; -struct DIEllipseVertex { - GrPoint fPos; - GrPoint fOuterOffset; - GrPoint fInnerOffset; -}; - inline bool circle_stays_circle(const SkMatrix& m) { return m.isSimilarity(); } @@ -298,157 +292,6 @@ GrEffectRef* EllipseEdgeEffect::TestCreate(SkMWCRandom* random, /////////////////////////////////////////////////////////////////////////////// -/** - * The output of this effect is a modulation of the input color and coverage for an ellipse, - * specified as a 2D offset from center for both the outer and inner paths (if stroked). The - * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge corrected by - * using differentials. - * - * The result is device-independent and can be used with any affine matrix. - */ - -class DIEllipseEdgeEffect : public GrEffect { -public: - enum Mode { kStroke = 0, kHairline, kFill }; - - static GrEffectRef* Create(Mode mode) { - GR_CREATE_STATIC_EFFECT(gEllipseStrokeEdge, DIEllipseEdgeEffect, (kStroke)); - GR_CREATE_STATIC_EFFECT(gEllipseHairlineEdge, DIEllipseEdgeEffect, (kHairline)); - GR_CREATE_STATIC_EFFECT(gEllipseFillEdge, DIEllipseEdgeEffect, (kFill)); - - if (kStroke == mode) { - gEllipseStrokeEdge->ref(); - return gEllipseStrokeEdge; - } else if (kHairline == mode) { - gEllipseHairlineEdge->ref(); - return gEllipseHairlineEdge; - } else { - gEllipseFillEdge->ref(); - return gEllipseFillEdge; - } - } - - virtual void getConstantColorComponents(GrColor* color, - uint32_t* validFlags) const SK_OVERRIDE { - *validFlags = 0; - } - - virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { - return GrTBackendEffectFactory<DIEllipseEdgeEffect>::getInstance(); - } - - virtual ~DIEllipseEdgeEffect() {} - - static const char* Name() { return "DIEllipseEdge"; } - - inline Mode getMode() const { return fMode; } - - class GLEffect : public GrGLEffect { - public: - GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) - : INHERITED (factory) {} - - virtual void emitCode(GrGLShaderBuilder* builder, - const GrDrawEffect& drawEffect, - EffectKey key, - const char* outputColor, - const char* inputColor, - const TextureSamplerArray& samplers) SK_OVERRIDE { - GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); - SkASSERT(NULL != vertexBuilder); - - const DIEllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<DIEllipseEdgeEffect>(); - - const char *vsOffsetName, *fsOffsetName; - - vertexBuilder->addVarying(kVec4f_GrSLType, "EllipseOffsets", &vsOffsetName, &fsOffsetName); - const SkString* attr0Name = - vertexBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName, attr0Name->c_str()); - - // for outer curve - builder->fsCodeAppendf("\tvec2 scaledOffset = %s.xy;\n", fsOffsetName); - builder->fsCodeAppend("\tfloat test = dot(scaledOffset, scaledOffset) - 1.0;\n"); - builder->fsCodeAppendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsOffsetName); - builder->fsCodeAppendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsOffsetName); - builder->fsCodeAppendf("\tvec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,\n" - "\t 2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);\n", - fsOffsetName, fsOffsetName, fsOffsetName, fsOffsetName); - - builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n"); - // we need to clamp the length^2 of the gradiant vector to a non-zero value, because - // on the Nexus 4 the undefined result of inversesqrt(0) drops out an entire tile - // TODO: restrict this to Adreno-only - builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n"); - builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n"); - if (kHairline == ellipseEffect.getMode()) { - // can probably do this with one step - builder->fsCodeAppend("\tfloat edgeAlpha = clamp(1.0-test*invlen, 0.0, 1.0);\n"); - builder->fsCodeAppend("\tedgeAlpha *= clamp(1.0+test*invlen, 0.0, 1.0);\n"); - } else { - builder->fsCodeAppend("\tfloat edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);\n"); - } - - // for inner curve - if (kStroke == ellipseEffect.getMode()) { - builder->fsCodeAppendf("\tscaledOffset = %s.wz;\n", fsOffsetName); - builder->fsCodeAppend("\ttest = dot(scaledOffset, scaledOffset) - 1.0;\n"); - builder->fsCodeAppendf("\tduvdx = dFdx(%s.wz);\n", fsOffsetName); - builder->fsCodeAppendf("\tduvdy = dFdy(%s.wz);\n", fsOffsetName); - builder->fsCodeAppendf("\tgrad = vec2(2.0*%s.w*duvdx.x + 2.0*%s.z*duvdx.y,\n" - "\t 2.0*%s.w*duvdy.x + 2.0*%s.z*duvdy.y);\n", - fsOffsetName, fsOffsetName, fsOffsetName, fsOffsetName); - builder->fsCodeAppend("\tinvlen = inversesqrt(dot(grad, grad));\n"); - builder->fsCodeAppend("\tedgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);\n"); - } - - SkString modulate; - GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); - } - - static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { - const DIEllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<DIEllipseEdgeEffect>(); - - return ellipseEffect.getMode(); - } - - virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE { - } - - private: - typedef GrGLEffect INHERITED; - }; - -private: - DIEllipseEdgeEffect(Mode mode) : GrEffect() { - this->addVertexAttrib(kVec4f_GrSLType); - fMode = mode; - } - - virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { - const DIEllipseEdgeEffect& eee = CastEffect<DIEllipseEdgeEffect>(other); - return eee.fMode == fMode; - } - - Mode fMode; - - GR_DECLARE_EFFECT_TEST; - - typedef GrEffect INHERITED; -}; - -GR_DEFINE_EFFECT_TEST(DIEllipseEdgeEffect); - -GrEffectRef* DIEllipseEdgeEffect::TestCreate(SkMWCRandom* random, - GrContext* context, - const GrDrawTargetCaps&, - GrTexture* textures[]) { - return DIEllipseEdgeEffect::Create((Mode)(random->nextRangeU(0,2))); -} - -/////////////////////////////////////////////////////////////////////////////// - void GrOvalRenderer::reset() { GrSafeSetNull(fRRectIndexBuffer); } @@ -466,12 +309,11 @@ bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bo if (SkScalarNearlyEqual(oval.width(), oval.height()) && circle_stays_circle(vm)) { this->drawCircle(target, useAA, oval, stroke); - // if we have shader derivative support, render as device-independent - } else if (target->caps()->shaderDerivativeSupport()) { - return this->drawDIEllipse(target, useAA, oval, stroke); - // otherwise axis-aligned ellipses only + + // and axis-aligned ellipses only } else if (vm.rectStaysRect()) { return this->drawEllipse(target, useAA, oval, stroke); + } else { return false; } @@ -479,6 +321,8 @@ bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bo return true; } +namespace { + /////////////////////////////////////////////////////////////////////////////// // position + edge @@ -487,6 +331,8 @@ extern const GrVertexAttrib gCircleVertexAttribs[] = { {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} }; +}; + void GrOvalRenderer::drawCircle(GrDrawTarget* target, bool useAA, const SkRect& circle, @@ -578,17 +424,15 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target, /////////////////////////////////////////////////////////////////////////////// -// position + offset + 1/radii +namespace { + +// position + edge extern const GrVertexAttrib gEllipseVertexAttribs[] = { {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}, {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding} }; -// position + offsets -extern const GrVertexAttrib gDIEllipseVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}, }; bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, @@ -625,8 +469,8 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, SkStrokeRec::Style style = stroke.getStyle(); bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style); - SkScalar innerXRadius = 0; - SkScalar innerYRadius = 0; + SkScalar innerXRadius = 0.0f; + SkScalar innerYRadius = 0.0f; if (SkStrokeRec::kFill_Style != style) { if (SkScalarNearlyZero(scaledStroke.length())) { scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); @@ -723,118 +567,6 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, return true; } -bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, - bool useAA, - const SkRect& ellipse, - const SkStrokeRec& stroke) -{ - GrDrawState* drawState = target->drawState(); - const SkMatrix& vm = drawState->getViewMatrix(); - - GrPoint center = GrPoint::Make(ellipse.centerX(), ellipse.centerY()); - SkScalar xRadius = SkScalarHalf(ellipse.width()); - SkScalar yRadius = SkScalarHalf(ellipse.height()); - - SkStrokeRec::Style style = stroke.getStyle(); - DIEllipseEdgeEffect::Mode mode = (SkStrokeRec::kStroke_Style == style) ? - DIEllipseEdgeEffect::kStroke : - (SkStrokeRec::kHairline_Style == style) ? - DIEllipseEdgeEffect::kHairline : DIEllipseEdgeEffect::kFill; - - SkScalar innerXRadius = 0; - SkScalar innerYRadius = 0; - if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != style) { - SkScalar strokeWidth = stroke.getWidth(); - - if (SkScalarNearlyZero(strokeWidth)) { - strokeWidth = SK_ScalarHalf; - } else { - strokeWidth *= SK_ScalarHalf; - } - - // we only handle thick strokes for near-circular ellipses - if (strokeWidth > SK_ScalarHalf && - (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) { - return false; - } - - // we don't handle it if curvature of the stroke is less than curvature of the ellipse - if (strokeWidth*(yRadius*yRadius) < (strokeWidth*strokeWidth)*xRadius || - strokeWidth*(xRadius*xRadius) < (strokeWidth*strokeWidth)*yRadius) { - return false; - } - - // set inner radius (if needed) - if (SkStrokeRec::kStroke_Style == style) { - innerXRadius = xRadius - strokeWidth; - innerYRadius = yRadius - strokeWidth; - } - - xRadius += strokeWidth; - yRadius += strokeWidth; - } - if (DIEllipseEdgeEffect::kStroke == mode) { - mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect::kStroke : - DIEllipseEdgeEffect::kFill; - } - SkScalar innerRatioX = SkScalarDiv(xRadius, innerXRadius); - SkScalar innerRatioY = SkScalarDiv(yRadius, innerYRadius); - - drawState->setVertexAttribs<gDIEllipseVertexAttribs>(SK_ARRAY_COUNT(gDIEllipseVertexAttribs)); - SkASSERT(sizeof(DIEllipseVertex) == drawState->getVertexSize()); - - GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); - if (!geo.succeeded()) { - GrPrintf("Failed to get space for vertices!\n"); - return false; - } - - DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(geo.vertices()); - - GrEffectRef* effect = DIEllipseEdgeEffect::Create(mode); - - static const int kEllipseOffsetAttrIndex = 1; - drawState->addCoverageEffect(effect, kEllipseOffsetAttrIndex)->unref(); - - // This expands the outer rect so that after CTM we end up with a half-pixel border - SkScalar a = vm[SkMatrix::kMScaleX]; - SkScalar b = vm[SkMatrix::kMSkewX]; - SkScalar c = vm[SkMatrix::kMSkewY]; - SkScalar d = vm[SkMatrix::kMScaleY]; - SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c)); - SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d)); - // This adjusts the "radius" to include the half-pixel border - SkScalar offsetDx = SkScalarDiv(geoDx, xRadius); - SkScalar offsetDy = SkScalarDiv(geoDy, yRadius); - - SkRect bounds = SkRect::MakeLTRB( - center.fX - xRadius - geoDx, - center.fY - yRadius - geoDy, - center.fX + xRadius + geoDx, - center.fY + yRadius + geoDy - ); - - verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); - verts[0].fOuterOffset = SkPoint::Make(-1.0f - offsetDx, -1.0f - offsetDy); - verts[0].fInnerOffset = SkPoint::Make(-innerRatioX - offsetDx, -innerRatioY - offsetDy); - - verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); - verts[1].fOuterOffset = SkPoint::Make(1.0f + offsetDx, -1.0f - offsetDy); - verts[1].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, -innerRatioY - offsetDy); - - verts[2].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); - verts[2].fOuterOffset = SkPoint::Make(-1.0f - offsetDx, 1.0f + offsetDy); - verts[2].fInnerOffset = SkPoint::Make(-innerRatioX - offsetDx, innerRatioY + offsetDy); - - verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); - verts[3].fOuterOffset = SkPoint::Make(1.0f + offsetDx, 1.0f + offsetDy); - verts[3].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, innerRatioY + offsetDy); - - target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds); - - return true; -} - /////////////////////////////////////////////////////////////////////////////// static const uint16_t gRRectIndices[] = { @@ -961,7 +693,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b bounds.outset(halfWidth, halfWidth); } - isStroked = (isStroked && innerRadius > 0); + isStroked = (isStroked && innerRadius > 0); GrEffectRef* effect = CircleEdgeEffect::Create(isStroked); static const int kCircleEdgeAttrIndex = 1; @@ -1057,7 +789,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b bounds.outset(scaledStroke.fX, scaledStroke.fY); } - isStroked = (isStroked && innerXRadius > 0 && innerYRadius > 0); + isStroked = (isStroked && innerXRadius > 0 && innerYRadius > 0); GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0); if (!geo.succeeded()) { |