aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-01-30 14:28:39 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-01-30 14:28:39 +0000
commit9aed114505a06679bbc7fa836e224aae82b3e5f4 (patch)
treeee1219ba639247d97b3c86a02456f248229ca5c0 /src
parente5e3937a14c1ab2d02e646ae0a5e8d5a724a45a4 (diff)
Reland r3078 (original failures that led to revert were problems with the bot)
git-svn-id: http://skia.googlecode.com/svn/trunk@3101 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrAAConvexPathRenderer.cpp430
-rw-r--r--src/gpu/GrAddPathRenderers_default.cpp4
-rw-r--r--src/gpu/GrGLProgram.cpp31
3 files changed, 242 insertions, 223 deletions
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index 8cf6c77fcf..3b66004216 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -29,18 +29,28 @@ bool GrAAConvexPathRenderer::canDrawPath(const GrDrawTarget::Caps& targetCaps,
namespace {
-
struct Segment {
enum {
kLine,
kQuad
} fType;
- // line uses a, quad uses a and b (first point comes from prev. segment)
- GrPoint fA, fB;
- // normal to edge ending at a and b
- GrVec fANorm, fBNorm;
- // mid vector at a that splits angle with previous edge
- GrVec fPrevMid;
+ // line uses one pt, quad uses 2 pts
+ GrPoint fPts[2];
+ // normal to edge ending at each pt
+ GrVec fNorms[2];
+ // is the corner where the previous segment meets this segment
+ // sharp. If so, fMid is a normalized bisector facing outward.
+ GrVec fMid;
+
+ int countPoints() {
+ return (kLine == fType) ? 1 : 2;
+ }
+ const SkPoint& endPt() const {
+ return (kLine == fType) ? fPts[0] : fPts[1];
+ };
+ const SkPoint& endNorm() const {
+ return (kLine == fType) ? fNorms[0] : fNorms[1];
+ };
};
typedef SkTArray<Segment, true> SegmentArray;
@@ -50,7 +60,6 @@ bool is_path_degenerate(const GrPath& path) {
if (n < 3) {
return true;
}
-
// compute a line from the first two points that are not equal, look for
// a third pt that is off the line.
static const SkScalar TOL = (SK_Scalar1 / 16);
@@ -80,12 +89,84 @@ bool is_path_degenerate(const GrPath& path) {
return true;
}
+void center_of_mass(const SegmentArray& segments, SkPoint* c) {
+ GrScalar area = 0;
+ SkPoint center;
+ center.set(0, 0);
+ int count = segments.count();
+ for (int i = 0; i < count; ++i) {
+ const SkPoint& pi = segments[i].endPt();
+ int j = (i + 1) % count;
+ const SkPoint& pj = segments[j].endPt();
+ GrScalar t = GrMul(pi.fX, pj.fY) - GrMul(pj.fX, pi.fY);
+ area += t;
+ center.fX += (pi.fX + pj.fX) * t;
+ center.fY += (pi.fY + pj.fY) * t;
+ }
+ area *= 3;
+ area = GrScalarDiv(GR_Scalar1, area);
+ center.fX = GrScalarMul(center.fX, area);
+ center.fY = GrScalarMul(center.fY, area);
+ *c = center;
+}
+
+void compute_vectors(SegmentArray* segments,
+ SkPoint* fanPt,
+ int* vCount,
+ int* iCount) {
+ center_of_mass(*segments, fanPt);
+ int count = segments->count();
+
+ // figure out which way the normals should point
+ GrPoint::Side normSide;
+ fanPt->distanceToLineBetweenSqd((*segments)[0].endPt(),
+ (*segments)[1].endPt(),
+ &normSide);
+
+ *vCount = 0;
+ *iCount = 0;
+ // compute normals at all points
+ for (int a = 0; a < count; ++a) {
+ const Segment& sega = (*segments)[a];
+ int b = (a + 1) % count;
+ Segment& segb = (*segments)[b];
+
+ const GrPoint* prevPt = &sega.endPt();
+ int n = segb.countPoints();
+ for (int p = 0; p < n; ++p) {
+ segb.fNorms[p] = segb.fPts[p] - *prevPt;
+ segb.fNorms[p].normalize();
+ segb.fNorms[p].setOrthog(segb.fNorms[p], normSide);
+ prevPt = &segb.fPts[p];
+ }
+ if (Segment::kLine == segb.fType) {
+ *vCount += 5;
+ *iCount += 9;
+ } else {
+ *vCount += 6;
+ *iCount += 12;
+ }
+ }
+
+ // compute mid-vectors where segments meet. TODO: Detect shallow corners
+ // and leave out the wedges and close gaps by stitching segments together.
+ for (int a = 0; a < count; ++a) {
+ const Segment& sega = (*segments)[a];
+ int b = (a + 1) % count;
+ Segment& segb = (*segments)[b];
+ segb.fMid = segb.fNorms[0] + sega.endNorm();
+ segb.fMid.normalize();
+ // corner wedges
+ *vCount += 4;
+ *iCount += 6;
+ }
+}
+
bool get_segments(const GrPath& path,
SegmentArray* segments,
- int* quadCnt,
- int* lineCnt) {
- *quadCnt = 0;
- *lineCnt = 0;
+ SkPoint* fanPt,
+ int* vCount,
+ int* iCount) {
SkPath::Iter iter(path, true);
// This renderer overemphasises very thin path regions. We use the distance
// to the path from the sample to compute coverage. Every pixel intersected
@@ -104,16 +185,14 @@ bool get_segments(const GrPath& path,
case kLine_PathCmd: {
segments->push_back();
segments->back().fType = Segment::kLine;
- segments->back().fA = pts[1];
- ++(*lineCnt);
+ segments->back().fPts[0] = pts[1];
break;
}
case kQuadratic_PathCmd:
segments->push_back();
segments->back().fType = Segment::kQuad;
- segments->back().fA = pts[1];
- segments->back().fB = pts[2];
- ++(*quadCnt);
+ segments->back().fPts[0] = pts[1];
+ segments->back().fPts[1] = pts[2];
break;
case kCubic_PathCmd: {
SkSTArray<15, SkPoint, true> quads;
@@ -122,14 +201,13 @@ bool get_segments(const GrPath& path,
for (int q = 0; q < count; q += 3) {
segments->push_back();
segments->back().fType = Segment::kQuad;
- segments->back().fA = quads[q + 1];
- segments->back().fB = quads[q + 2];
- ++(*quadCnt);
+ segments->back().fPts[0] = quads[q + 1];
+ segments->back().fPts[1] = quads[q + 2];
}
break;
};
case kEnd_PathCmd:
- GrAssert(*quadCnt + *lineCnt == segments->count());
+ compute_vectors(segments, fanPt, vCount, iCount);
return true;
default:
break;
@@ -139,201 +217,139 @@ bool get_segments(const GrPath& path,
struct QuadVertex {
GrPoint fPos;
- union {
- GrPoint fQuadUV;
- GrScalar fEdge[4];
- };
+ GrPoint fUV;
+ GrScalar fD0;
+ GrScalar fD1;
};
-
-void get_counts(int quadCount, int lineCount, int* vCount, int* iCount) {
- *vCount = 9 * lineCount + 11 * quadCount;
- *iCount = 15 * lineCount + 24 * quadCount;
-}
-
-// This macro can be defined for visual debugging purposes. It exagerates the AA
-// smear at the edges by increasing the size of the extruded geometry used for
-// AA. However, the coverage value computed in the shader will still go to zero
-// at distance > .5 outside the curves. So, the shader code has be modified as
-// well to stretch out the AA smear.
-//#define STRETCH_AA
-#define STRETCH_FACTOR (20 * SK_Scalar1)
-
-void create_vertices(SegmentArray* segments,
- const GrPoint& fanPt,
- QuadVertex* verts,
- uint16_t* idxs) {
- int count = segments->count();
- GrAssert(count > 1);
- int prevS = count - 1;
- const Segment& lastSeg = (*segments)[prevS];
-
- // walk the segments and compute normals to each edge and
- // bisectors at vertices. The loop relies on having the end point and normal
- // from previous segment so we first compute that. Also, we determine
- // whether normals point left or right to face outside the path.
- GrVec prevPt;
- GrPoint prevPrevPt;
- GrVec prevNorm;
- if (Segment::kLine == lastSeg.fType) {
- prevPt = lastSeg.fA;
- const Segment& secondLastSeg = (*segments)[prevS - 1];
- prevPrevPt = (Segment::kLine == secondLastSeg.fType) ?
- secondLastSeg.fA :
- secondLastSeg.fB;
- } else {
- prevPt = lastSeg.fB;
- prevPrevPt = lastSeg.fA;
- }
- GrVec::Side outside;
- // we will compute our edge vectors so that they are pointing along the
- // direction in which we are iterating the path. So here we take an opposite
- // vector and get the side that the fan pt lies relative to it.
- fanPt.distanceToLineBetweenSqd(prevPrevPt, prevPt, &outside);
- prevNorm = prevPt - prevPrevPt;
- prevNorm.normalize();
- prevNorm.setOrthog(prevNorm, outside);
-#ifdef STRETCH_AA
- prevNorm.scale(STRETCH_FACTOR);
-#endif
-
- // compute the normals and bisectors
- for (int s = 0; s < count; ++s, ++prevS) {
- Segment& curr = (*segments)[s];
-
- GrVec currVec = curr.fA - prevPt;
- currVec.normalize();
- curr.fANorm.setOrthog(currVec, outside);
-#ifdef STRETCH_AA
- curr.fANorm.scale(STRETCH_FACTOR);
-#endif
- curr.fPrevMid = prevNorm + curr.fANorm;
- curr.fPrevMid.normalize();
-#ifdef STRETCH_AA
- curr.fPrevMid.scale(STRETCH_FACTOR);
-#endif
- if (Segment::kLine == curr.fType) {
- prevPt = curr.fA;
- prevNorm = curr.fANorm;
- } else {
- currVec = curr.fB - curr.fA;
- currVec.normalize();
- curr.fBNorm.setOrthog(currVec, outside);
-#ifdef STRETCH_AA
- curr.fBNorm.scale(STRETCH_FACTOR);
-#endif
- prevPt = curr.fB;
- prevNorm = curr.fBNorm;
- }
- }
-
- // compute the vertices / indices
- if (Segment::kLine == lastSeg.fType) {
- prevPt = lastSeg.fA;
- prevNorm = lastSeg.fANorm;
- } else {
- prevPt = lastSeg.fB;
- prevNorm = lastSeg.fBNorm;
- }
+
+void create_vertices(const SegmentArray& segments,
+ const SkPoint& fanPt,
+ QuadVertex* verts,
+ uint16_t* idxs) {
int v = 0;
int i = 0;
- for (int s = 0; s < count; ++s, ++prevS) {
- Segment& curr = (*segments)[s];
- verts[v + 0].fPos = prevPt;
- verts[v + 1].fPos = prevPt + prevNorm;
- verts[v + 2].fPos = prevPt + curr.fPrevMid;
- verts[v + 3].fPos = prevPt + curr.fANorm;
- verts[v + 0].fQuadUV.set(0, 0);
- verts[v + 1].fQuadUV.set(0, -SK_Scalar1);
- verts[v + 2].fQuadUV.set(0, -SK_Scalar1);
- verts[v + 3].fQuadUV.set(0, -SK_Scalar1);
+ int count = segments.count();
+ for (int a = 0; a < count; ++a) {
+ const Segment& sega = segments[a];
+ int b = (a + 1) % count;
+ const Segment& segb = segments[b];
+
+ // FIXME: These tris are inset in the 1 unit arc around the corner
+ verts[v + 0].fPos = sega.endPt();
+ verts[v + 1].fPos = verts[v + 0].fPos + sega.endNorm();
+ verts[v + 2].fPos = verts[v + 0].fPos + segb.fMid;
+ verts[v + 3].fPos = verts[v + 0].fPos + segb.fNorms[0];
+ verts[v + 0].fUV.set(0,0);
+ verts[v + 1].fUV.set(0,-SK_Scalar1);
+ verts[v + 2].fUV.set(0,-SK_Scalar1);
+ verts[v + 3].fUV.set(0,-SK_Scalar1);
+ verts[v + 0].fD0 = verts[v + 0].fD1 = -SK_Scalar1;
+ verts[v + 1].fD0 = verts[v + 1].fD1 = -SK_Scalar1;
+ verts[v + 2].fD0 = verts[v + 2].fD1 = -SK_Scalar1;
+ verts[v + 3].fD0 = verts[v + 3].fD1 = -SK_Scalar1;
+
idxs[i + 0] = v + 0;
- idxs[i + 1] = v + 1;
- idxs[i + 2] = v + 2;
+ idxs[i + 1] = v + 2;
+ idxs[i + 2] = v + 1;
idxs[i + 3] = v + 0;
- idxs[i + 4] = v + 2;
- idxs[i + 5] = v + 3;
-
+ idxs[i + 4] = v + 3;
+ idxs[i + 5] = v + 2;
+
v += 4;
i += 6;
- if (Segment::kLine == curr.fType) {
+ if (Segment::kLine == segb.fType) {
verts[v + 0].fPos = fanPt;
- verts[v + 1].fPos = prevPt;
- verts[v + 2].fPos = curr.fA;
- verts[v + 3].fPos = prevPt + curr.fANorm;
- verts[v + 4].fPos = curr.fA + curr.fANorm;
- GrScalar lineC = -curr.fANorm.dot(curr.fA);
- GrScalar fanDist = curr.fANorm.dot(fanPt) - lineC;
- verts[v + 0].fQuadUV.set(0, SkScalarAbs(fanDist));
- verts[v + 1].fQuadUV.set(0, 0);
- verts[v + 2].fQuadUV.set(0, 0);
- verts[v + 3].fQuadUV.set(0, -GR_Scalar1);
- verts[v + 4].fQuadUV.set(0, -GR_Scalar1);
+ verts[v + 1].fPos = sega.endPt();
+ verts[v + 2].fPos = segb.fPts[0];
+
+ verts[v + 3].fPos = verts[v + 1].fPos + segb.fNorms[0];
+ verts[v + 4].fPos = verts[v + 2].fPos + segb.fNorms[0];
+
+ // we draw the line edge as a degenerate quad (u is 0, v is the
+ // signed distance to the edge)
+ GrScalar dist = fanPt.distanceToLineBetween(verts[v + 1].fPos,
+ verts[v + 2].fPos);
+ verts[v + 0].fUV.set(0, dist);
+ verts[v + 1].fUV.set(0, 0);
+ verts[v + 2].fUV.set(0, 0);
+ verts[v + 3].fUV.set(0, -SK_Scalar1);
+ verts[v + 4].fUV.set(0, -SK_Scalar1);
+
+ verts[v + 0].fD0 = verts[v + 0].fD1 = -SK_Scalar1;
+ verts[v + 1].fD0 = verts[v + 1].fD1 = -SK_Scalar1;
+ verts[v + 2].fD0 = verts[v + 2].fD1 = -SK_Scalar1;
+ verts[v + 3].fD0 = verts[v + 3].fD1 = -SK_Scalar1;
+ verts[v + 4].fD0 = verts[v + 4].fD1 = -SK_Scalar1;
idxs[i + 0] = v + 0;
- idxs[i + 1] = v + 1;
- idxs[i + 2] = v + 2;
- idxs[i + 3] = v + 1;
- idxs[i + 4] = v + 3;
- idxs[i + 5] = v + 4;
- idxs[i + 6] = v + 1;
- idxs[i + 7] = v + 4;
+ idxs[i + 1] = v + 2;
+ idxs[i + 2] = v + 1;
+
+ idxs[i + 3] = v + 3;
+ idxs[i + 4] = v + 1;
+ idxs[i + 5] = v + 2;
+
+ idxs[i + 6] = v + 4;
+ idxs[i + 7] = v + 3;
idxs[i + 8] = v + 2;
- i += 9;
v += 5;
-
- prevPt = curr.fA;
- prevNorm = curr.fANorm;
+ i += 9;
} else {
- GrVec splitVec = curr.fANorm + curr.fBNorm;
- splitVec.normalize();
-#ifdef STRETCH_AA
- splitVec.scale(STRETCH_FACTOR);
-#endif
-
- verts[v + 0].fPos = prevPt;
- verts[v + 1].fPos = curr.fA;
- verts[v + 2].fPos = curr.fB;
- verts[v + 3].fPos = fanPt;
- verts[v + 4].fPos = prevPt + curr.fANorm;
- verts[v + 5].fPos = curr.fA + splitVec;
- verts[v + 6].fPos = curr.fB + curr.fBNorm;
-
- verts[v + 0].fQuadUV.set(0, 0);
- verts[v + 1].fQuadUV.set(GR_ScalarHalf, 0);
- verts[v + 2].fQuadUV.set(GR_Scalar1, GR_Scalar1);
+ GrPoint qpts[] = {sega.endPt(), segb.fPts[0], segb.fPts[1]};
+
+ GrVec midVec = segb.fNorms[0] + segb.fNorms[1];
+ midVec.normalize();
+
+ verts[v + 0].fPos = fanPt;
+ verts[v + 1].fPos = qpts[0];
+ verts[v + 2].fPos = qpts[2];
+ verts[v + 3].fPos = qpts[0] + segb.fNorms[0];
+ verts[v + 4].fPos = qpts[2] + segb.fNorms[1];
+ verts[v + 5].fPos = qpts[1] + midVec;
+
+ GrScalar c = segb.fNorms[0].dot(qpts[0]);
+ verts[v + 0].fD0 = -segb.fNorms[0].dot(fanPt) + c;
+ verts[v + 1].fD0 = 0.f;
+ verts[v + 2].fD0 = -segb.fNorms[0].dot(qpts[2]) + c;
+ verts[v + 3].fD0 = -GR_ScalarMax/100;
+ verts[v + 4].fD0 = -GR_ScalarMax/100;
+ verts[v + 5].fD0 = -GR_ScalarMax/100;
+
+ c = segb.fNorms[1].dot(qpts[2]);
+ verts[v + 0].fD1 = -segb.fNorms[1].dot(fanPt) + c;
+ verts[v + 1].fD1 = -segb.fNorms[1].dot(qpts[0]) + c;
+ verts[v + 2].fD1 = 0.f;
+ verts[v + 3].fD1 = -GR_ScalarMax/100;
+ verts[v + 4].fD1 = -GR_ScalarMax/100;
+ verts[v + 5].fD1 = -GR_ScalarMax/100;
+
GrMatrix toUV;
- GrPoint pts[] = {prevPt, curr.fA, curr.fB};
- GrPathUtils::quadDesignSpaceToUVCoordsMatrix(pts, &toUV);
- toUV.mapPointsWithStride(&verts[v + 3].fQuadUV,
- &verts[v + 3].fPos,
- sizeof(QuadVertex), 4);
-
- idxs[i + 0] = v + 3;
- idxs[i + 1] = v + 0;
- idxs[i + 2] = v + 1;
- idxs[i + 3] = v + 3;
- idxs[i + 4] = v + 1;
- idxs[i + 5] = v + 2;
- idxs[i + 6] = v + 0;
- idxs[i + 7] = v + 4;
- idxs[i + 8] = v + 1;
- idxs[i + 9] = v + 4;
- idxs[i + 10] = v + 1;
- idxs[i + 11] = v + 5;
- idxs[i + 12] = v + 5;
- idxs[i + 13] = v + 1;
- idxs[i + 14] = v + 2;
- idxs[i + 15] = v + 5;
- idxs[i + 16] = v + 2;
- idxs[i + 17] = v + 6;
-
- i += 18;
- v += 7;
- prevPt = curr.fB;
- prevNorm = curr.fBNorm;
+ GrPathUtils::quadDesignSpaceToUVCoordsMatrix(qpts, &toUV);
+ toUV.mapPointsWithStride(&verts[v].fUV,
+ &verts[v].fPos,
+ sizeof(QuadVertex),
+ 6);
+
+ idxs[i + 0] = v + 3;
+ idxs[i + 1] = v + 1;
+ idxs[i + 2] = v + 2;
+ idxs[i + 3] = v + 4;
+ idxs[i + 4] = v + 3;
+ idxs[i + 5] = v + 2;
+
+ idxs[i + 6] = v + 5;
+ idxs[i + 7] = v + 3;
+ idxs[i + 8] = v + 4;
+
+ idxs[i + 9] = v + 0;
+ idxs[i + 10] = v + 2;
+ idxs[i + 11] = v + 1;
+
+ v += 6;
+ i += 12;
}
}
}
@@ -357,13 +373,9 @@ void GrAAConvexPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
}
drawState->setViewMatrix(GrMatrix::I());
-
SkPath path;
fPath->transform(vm, &path);
- SkPoint fanPt = {path.getBounds().centerX(),
- path.getBounds().centerY()};
-
GrVertexLayout layout = 0;
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
if ((1 << s) & stageMask) {
@@ -375,15 +387,13 @@ void GrAAConvexPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
QuadVertex *verts;
uint16_t* idxs;
- int nQuads;
- int nLines;
+ int vCount;
+ int iCount;
SegmentArray segments;
- if (!get_segments(path, &segments, &nQuads, &nLines)) {
+ SkPoint fanPt;
+ if (!get_segments(path, &segments, &fanPt, &vCount, &iCount)) {
return;
}
- int vCount;
- int iCount;
- get_counts(nQuads, nLines, &vCount, &iCount);
if (!fTarget->reserveVertexSpace(layout,
vCount,
@@ -395,7 +405,7 @@ void GrAAConvexPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
return;
}
- create_vertices(&segments, fanPt, verts, idxs);
+ create_vertices(segments, fanPt, verts, idxs);
drawState->setVertexEdgeType(GrDrawState::kQuad_EdgeType);
fTarget->drawIndexed(kTriangles_PrimitiveType,
diff --git a/src/gpu/GrAddPathRenderers_default.cpp b/src/gpu/GrAddPathRenderers_default.cpp
index 37c388e6bd..af22e935e1 100644
--- a/src/gpu/GrAddPathRenderers_default.cpp
+++ b/src/gpu/GrAddPathRenderers_default.cpp
@@ -18,9 +18,7 @@ void GrPathRenderer::AddPathRenderers(GrContext* ctx,
if (GrPathRenderer* pr = GrAAHairLinePathRenderer::Create(ctx)) {
chain->addPathRenderer(pr)->unref();
}
- // Disabled for now. Need to fix issue where some hairlines don't
- // wind up going to the hairline renderer and get rendered by this
- // PR looking speckly.
+ // Disabled for now.
//chain->addPathRenderer(new GrAAConvexPathRenderer())->unref();
}
}
diff --git a/src/gpu/GrGLProgram.cpp b/src/gpu/GrGLProgram.cpp
index ce5a284710..610446d615 100644
--- a/src/gpu/GrGLProgram.cpp
+++ b/src/gpu/GrGLProgram.cpp
@@ -528,23 +528,34 @@ void GrGLProgram::genEdgeCoverage(const GrGLInterface* gl,
if (GrDrawState::kHairLine_EdgeType == fProgramDesc.fVertexEdgeType) {
segments->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), %s.xyz));\n", fsName);
segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
+ } else if (GrDrawState::kQuad_EdgeType == fProgramDesc.fVertexEdgeType) {
+ segments->fFSCode.appendf("\tfloat edgeAlpha;\n");
+ // keep the derivative instructions outside the conditional
+ segments->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
+ segments->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
+ segments->fFSCode.appendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName);
+ // today we know z and w are in device space. We could use derivatives
+ segments->fFSCode.appendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName);
+ segments->fFSCode.append ("\t} else {\n");
+ segments->fFSCode.appendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
+ "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n",
+ fsName, fsName);
+ segments->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
+ segments->fFSCode.appendf("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n"
+ "\t}\n");
+ if (gl->supportsES2()) {
+ segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
+ }
} else {
- GrAssert(GrDrawState::kHairQuad_EdgeType == fProgramDesc.fVertexEdgeType ||
- GrDrawState::kQuad_EdgeType == fProgramDesc.fVertexEdgeType);
- // for now we know we're not in perspective, so we could compute this
- // per-quadratic rather than per pixel
+ GrAssert(GrDrawState::kHairQuad_EdgeType == fProgramDesc.fVertexEdgeType);
segments->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
segments->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
segments->fFSCode.appendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
"\t 2.0*%s.x*duvdy.x - duvdy.y);\n",
fsName, fsName);
segments->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
- if (GrDrawState::kQuad_EdgeType == fProgramDesc.fVertexEdgeType) {
- segments->fFSCode.append("\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n");
- } else {
- segments->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
- segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
- }
+ segments->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
+ segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
if (gl->supportsES2()) {
segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
}