aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrOvalRenderer.cpp
diff options
context:
space:
mode:
authorGravatar jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-09-04 16:40:37 +0000
committerGravatar jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-09-04 16:40:37 +0000
commit059a5a339b14b6fe4f942d57387fba7a9e1fea06 (patch)
tree8ec193c39d1ae45b0ec8ab3f5c6134cc141e5ccc /src/gpu/GrOvalRenderer.cpp
parent14486ea9e3f770363bb7db27dc7d0033f3cba013 (diff)
Reverting r11075.
git-svn-id: http://skia.googlecode.com/svn/trunk@11080 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu/GrOvalRenderer.cpp')
-rw-r--r--src/gpu/GrOvalRenderer.cpp296
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()) {