Index: src/gpu/GrAAHairLinePathRenderer.cpp |
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp |
index c1f951ab7f91832d95ece209f71b377794c68e48..d39090f3225deb43a21f41f6dd6928ce05452245 100644 |
--- a/src/gpu/GrAAHairLinePathRenderer.cpp |
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp |
@@ -29,14 +29,19 @@ namespace { |
static const int kVertsPerQuad = 5; |
static const int kIdxsPerQuad = 9; |
-static const int kVertsPerLineSeg = 4; |
-static const int kIdxsPerLineSeg = 6; |
+static const int kVertsPerLineSeg = 6; |
+static const int kIdxsPerLineSeg = 12; |
static const int kNumQuadsInIdxBuffer = 256; |
static const size_t kQuadIdxSBufize = kIdxsPerQuad * |
sizeof(uint16_t) * |
kNumQuadsInIdxBuffer; |
+static const int kNumLineSegsInIdxBuffer = 256; |
+static const size_t kLineSegIdxSBufize = kIdxsPerLineSeg * |
+ sizeof(uint16_t) * |
+ kNumLineSegsInIdxBuffer; |
+ |
bool push_quad_index_data(GrIndexBuffer* qIdxBuffer) { |
uint16_t* data = (uint16_t*) qIdxBuffer->lock(); |
bool tempData = NULL == data; |
@@ -78,13 +83,53 @@ bool push_quad_index_data(GrIndexBuffer* qIdxBuffer) { |
return true; |
} |
} |
+ |
+bool push_line_index_data(GrIndexBuffer* qIdxBuffer) { |
+ uint16_t* data = (uint16_t*) qIdxBuffer->lock(); |
+ bool tempData = NULL == data; |
+ if (tempData) { |
+ data = SkNEW_ARRAY(uint16_t, kNumLineSegsInIdxBuffer * kIdxsPerLineSeg); |
+ } |
+ for (int i = 0; i < kNumLineSegsInIdxBuffer; ++i) { |
+ // Each line segment is rendered as two quads, with alpha = 1 along the |
+ // spine of the segment, and alpha = 0 along the outer edges, represented |
+ // horizontally like (i.e. the line equation is t*(p1-p0) + p0) |
+ // |
+ // p4 p5 |
+ // p0 p1 |
+ // p2 p3 |
+ // |
+ // Each is drawn as four triangles specified by these 12 indices: |
+ int baseIdx = i * kIdxsPerLineSeg; |
+ uint16_t baseVert = (uint16_t)(i * kVertsPerLineSeg); |
+ data[0 + baseIdx] = baseVert + 0; // p0 |
+ data[1 + baseIdx] = baseVert + 1; // p1 |
+ data[2 + baseIdx] = baseVert + 2; // p2 |
+ |
+ data[3 + baseIdx] = baseVert + 2; // p2 |
+ data[4 + baseIdx] = baseVert + 1; // p1 |
+ data[5 + baseIdx] = baseVert + 3; // p3 |
+ |
+ data[6 + baseIdx] = baseVert + 0; // p0 |
+ data[7 + baseIdx] = baseVert + 5; // p5 |
+ data[8 + baseIdx] = baseVert + 1; // p1 |
+ |
+ data[9 + baseIdx] = baseVert + 0; // p0 |
+ data[10+ baseIdx] = baseVert + 4; // p4 |
+ data[11+ baseIdx] = baseVert + 5; // p5 |
+ } |
+ if (tempData) { |
+ bool ret = qIdxBuffer->updateData(data, kLineSegIdxSBufize); |
+ delete[] data; |
+ return ret; |
+ } else { |
+ qIdxBuffer->unlock(); |
+ return true; |
+ } |
+} |
} |
GrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) { |
- const GrIndexBuffer* lIdxBuffer = context->getQuadIndexBuffer(); |
- if (NULL == lIdxBuffer) { |
- return NULL; |
- } |
GrGpu* gpu = context->getGpu(); |
GrIndexBuffer* qIdxBuf = gpu->createIndexBuffer(kQuadIdxSBufize, false); |
SkAutoTUnref<GrIndexBuffer> qIdxBuffer(qIdxBuf); |
@@ -92,8 +137,14 @@ GrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) { |
!push_quad_index_data(qIdxBuf)) { |
return NULL; |
} |
+ GrIndexBuffer* lIdxBuf = gpu->createIndexBuffer(kLineSegIdxSBufize, false); |
+ SkAutoTUnref<GrIndexBuffer> lIdxBuffer(lIdxBuf); |
+ if (NULL == lIdxBuf || |
+ !push_line_index_data(lIdxBuf)) { |
+ return NULL; |
+ } |
return SkNEW_ARGS(GrAAHairLinePathRenderer, |
- (context, lIdxBuffer, qIdxBuf)); |
+ (context, lIdxBuf, qIdxBuf)); |
} |
GrAAHairLinePathRenderer::GrAAHairLinePathRenderer( |
@@ -435,11 +486,7 @@ int generate_lines_and_quads(const SkPath& path, |
struct Vertex { |
GrPoint fPos; |
union { |
- struct { |
- SkScalar fA; |
- SkScalar fB; |
- SkScalar fC; |
- } fLine; |
+ SkScalar fCoverage; |
bsalomon
2013/08/07 20:59:57
fLineCoverage? or...
struct {
SkScalar fCoverage
jvanverth1
2013/08/07 21:15:04
Done.
|
struct { |
SkScalar fK; |
SkScalar fL; |
@@ -661,17 +708,17 @@ void add_line(const SkPoint p[2], |
if (orthVec.setLength(SK_Scalar1)) { |
orthVec.setOrthog(orthVec); |
- SkScalar lineC = -(a.dot(orthVec)); |
for (int i = 0; i < kVertsPerLineSeg; ++i) { |
- (*vert)[i].fPos = (i < 2) ? a : b; |
- if (0 == i || 3 == i) { |
+ (*vert)[i].fPos = (i & 0x1) ? b : a; |
+ if (i & 0x2) { |
+ (*vert)[i].fPos += orthVec; |
+ (*vert)[i].fCoverage = 0; |
+ } else if (i & 0x4) { |
(*vert)[i].fPos -= orthVec; |
+ (*vert)[i].fCoverage = 0; |
} else { |
- (*vert)[i].fPos += orthVec; |
+ (*vert)[i].fCoverage= SK_Scalar1; |
} |
- (*vert)[i].fLine.fA = orthVec.fX; |
- (*vert)[i].fLine.fB = orthVec.fY; |
- (*vert)[i].fLine.fC = lineC; |
} |
if (NULL != toSrc) { |
toSrc->mapPointsWithStride(&(*vert)->fPos, |
@@ -684,6 +731,8 @@ void add_line(const SkPoint p[2], |
(*vert)[1].fPos.set(SK_ScalarMax, SK_ScalarMax); |
(*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax); |
(*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax); |
+ (*vert)[4].fPos.set(SK_ScalarMax, SK_ScalarMax); |
+ (*vert)[5].fPos.set(SK_ScalarMax, SK_ScalarMax); |
} |
*vert += kVertsPerLineSeg; |
@@ -936,7 +985,7 @@ GrEffectRef* HairQuadEdgeEffect::TestCreate(SkMWCRandom* random, |
/** |
* The output of this effect is a 1-pixel wide line. |
- * Input is 2D implicit device coord line eq (a*x + b*y +c = 0). 4th component unused. |
+ * Input is 2D offset vector from the line. 3rd and 4th components unused. |
*/ |
class HairLineEdgeEffect : public GrEffect { |
public: |
@@ -978,9 +1027,7 @@ public: |
builder->addVarying(kVec4f_GrSLType, "HairLineEdge", &vsName, &fsName); |
- builder->fsCodeAppendf("\t\tedgeAlpha = abs(dot(vec3(%s.xy,1), %s.xyz));\n", |
- builder->fragmentPosition(), fsName); |
- builder->fsCodeAppendf("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); |
+ builder->fsCodeAppendf("\t\tedgeAlpha = %s.x;\n", fsName); |
SkString modulate; |
GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); |
@@ -1194,10 +1241,9 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, |
GrDrawState::AutoRestoreEffects are(drawState); |
target->setIndexSourceToBuffer(fLinesIndexBuffer); |
int lines = 0; |
- int nBufLines = fLinesIndexBuffer->maxQuads(); |
drawState->addCoverageEffect(hairLineEffect, kEdgeAttrIndex)->unref(); |
while (lines < lineCnt) { |
- int n = GrMin(lineCnt - lines, nBufLines); |
+ int n = GrMin(lineCnt - lines, kNumLineSegsInIdxBuffer); |
target->drawIndexed(kTriangles_GrPrimitiveType, |
kVertsPerLineSeg*lines, // startV |
0, // startI |