Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(220)

Unified Diff: src/gpu/GrAAHairLinePathRenderer.cpp

Issue 18258005: Add implicit hairline conic rendering to GPU (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/core/SkGeometry.cpp ('K') | « src/gpu/GrAAHairLinePathRenderer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrAAHairLinePathRenderer.cpp
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index 51bff1efc361dfdb33d7509c94b48198c88bbb7a..52317431004471510f2996d883d7b18da687b06d 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -30,6 +30,9 @@ namespace {
static const int kVertsPerQuad = 5;
static const int kIdxsPerQuad = 9;
+static const int kVertsPerConic = 5;
+static const int kIdxsPerConic = 9;
+
static const int kVertsPerLineSeg = 4;
static const int kIdxsPerLineSeg = 6;
@@ -37,6 +40,10 @@ static const int kNumQuadsInIdxBuffer = 256;
static const size_t kQuadIdxSBufize = kIdxsPerQuad *
sizeof(uint16_t) *
kNumQuadsInIdxBuffer;
+static const int kNumConicsInIdxBuffer = 256;
+static const size_t kConicIdxSBufize = kIdxsPerConic *
+ sizeof(uint16_t) *
+ kNumConicsInIdxBuffer;
bool push_quad_index_data(GrIndexBuffer* qIdxBuffer) {
uint16_t* data = (uint16_t*) qIdxBuffer->lock();
@@ -93,23 +100,32 @@ GrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) {
!push_quad_index_data(qIdxBuf)) {
return NULL;
}
+ GrIndexBuffer* cIdxBuf = gpu->createIndexBuffer(kConicIdxSBufize, false);
+ if (NULL == cIdxBuf ||
+ !push_quad_index_data(cIdxBuf)) {
bsalomon 2013/07/10 15:14:36 can't we just use one idx buffer then?
egdaniel 2013/07/10 20:34:18 I'm assuming you mean for the quad and conic corre
+ return NULL;
+ }
return SkNEW_ARGS(GrAAHairLinePathRenderer,
- (context, lIdxBuffer, qIdxBuf));
+ (context, lIdxBuffer, qIdxBuf, cIdxBuf));
}
GrAAHairLinePathRenderer::GrAAHairLinePathRenderer(
const GrContext* context,
const GrIndexBuffer* linesIndexBuffer,
- const GrIndexBuffer* quadsIndexBuffer) {
+ const GrIndexBuffer* quadsIndexBuffer,
+ const GrIndexBuffer* conicIndexBuffer) {
fLinesIndexBuffer = linesIndexBuffer;
linesIndexBuffer->ref();
fQuadsIndexBuffer = quadsIndexBuffer;
quadsIndexBuffer->ref();
+ fConicsIndexBuffer = conicIndexBuffer;
+ conicIndexBuffer->ref();
}
GrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() {
fLinesIndexBuffer->unref();
fQuadsIndexBuffer->unref();
+ fConicsIndexBuffer->unref();
}
namespace {
@@ -117,6 +133,7 @@ namespace {
typedef SkTArray<SkPoint, true> PtArray;
#define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true>
typedef SkTArray<int, true> IntArray;
+typedef SkTArray<float, true> FloatArray;
// Takes 178th time of logf on Z600 / VC2010
int get_float_exp(float x) {
@@ -142,6 +159,32 @@ int get_float_exp(float x) {
return (((*iptr) & 0x7f800000) >> 23) - 127;
}
+
+// returns 0 if quad/conic is degen or close to it
+// in this case approx the path with lines
+// otherwise returns 1
+int is_degen_quad_conic(const SkPoint p[3]) {
bsalomon 2013/07/10 15:14:36 quad_or_conic?
+
+ static const SkScalar gDegenerateToLineTol = SK_Scalar1;
+ static const SkScalar gDegenerateToLineTolSqd =
+ SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol);
+
+ if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd ||
+ p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) {
+ return 1;
+ }
+
+ SkScalar dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]);
+ if (dsqd < gDegenerateToLineTolSqd) {
+ return 1;
+ }
+
+ if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) {
+ return 1;
+ }
+ return 0;
+}
+
// we subdivide the quads to avoid huge overfill
// if it returns -1 then should be drawn as lines
int num_quad_subdivs(const SkPoint p[3]) {
@@ -207,7 +250,9 @@ int generate_lines_and_quads(const SkPath& path,
const GrIRect& devClipBounds,
PtArray* lines,
PtArray* quads,
- IntArray* quadSubdivCnts) {
+ PtArray* conics,
+ IntArray* quadSubdivCnts,
+ FloatArray* conicWeights) {
SkPath::Iter iter(path, false);
int totalQuadCount = 0;
@@ -221,10 +266,48 @@ int generate_lines_and_quads(const SkPath& path,
GrPoint devPts[4];
SkPath::Verb verb = iter.next(pathPts);
switch (verb) {
- case SkPath::kConic_Verb:
- SkASSERT(0);
+ case SkPath::kConic_Verb: {
+ SkScalar t = SkGetTQuadAtMaxCurvature(pathPts);
bsalomon 2013/07/10 15:14:36 maybe this whole bit up to the for should be added
+ int conicCnt = 1;
+ SkConic dst[2];
+ if (t == 0)
+ {
bsalomon 2013/07/10 15:14:36 move {s up to prev line
+ dst[0].set(pathPts, iter.conicWeight());
+ }
+ else
+ {
+ SkConic conic;
+ conic.set(pathPts, iter.conicWeight());
+ conic.chopAt(t, dst);
+ conicCnt = 2;
+ }
+ for (int i = 0; i < conicCnt; ++i) {
+ SkPoint* chopPnts = dst[i].fPts;
+ m.mapPoints(devPts, chopPnts, 3);
+ bounds.setBounds(devPts, 3);
+ bounds.outset(SK_Scalar1, SK_Scalar1);
+ bounds.roundOut(&ibounds);
+ if (SkIRect::Intersects(devClipBounds, ibounds)) {
+ if (is_degen_quad_conic(devPts)) {
+ SkPoint* pts = lines->push_back_n(4);
+ pts[0] = devPts[0];
+ pts[1] = devPts[1];
+ pts[2] = devPts[1];
+ pts[3] = devPts[2];
+ } else {
+ // when in perspective keep conics in src space ???
bsalomon 2013/07/10 15:14:36 should test this... but yes. The later chopping th
+ SkPoint* cPts = persp ? chopPnts : devPts;
+ SkPoint* pts = conics->push_back_n(3);
+ pts[0] = cPts[0];
+ pts[1] = cPts[1];
+ pts[2] = cPts[2];
+ conicWeights->push_back() = dst[i].fW;
+ }
+ }
+ }
+ }
break;
- case SkPath::kMove_Verb:
+ case SkPath::kMove_Verb:
break;
case SkPath::kLine_Verb:
m.mapPoints(devPts, pathPts, 2);
@@ -348,13 +431,22 @@ struct Vertex {
SkScalar fB;
SkScalar fC;
} fLine;
+ struct {
+ SkScalar fA;
+ SkScalar fB;
+ SkScalar fC;
+ SkScalar fD;
+ SkScalar fE;
+ SkScalar fF;
+ } fConic;
GrVec fQuadCoord;
struct {
- SkScalar fBogus[4];
+ SkScalar fBogus[6];
};
};
};
-GR_STATIC_ASSERT(sizeof(Vertex) == 3 * sizeof(GrPoint));
+
+GR_STATIC_ASSERT(sizeof(Vertex) == 4 * sizeof(GrPoint));
void intersect_lines(const SkPoint& ptA, const SkVector& normA,
const SkPoint& ptB, const SkVector& normB,
@@ -364,7 +456,7 @@ void intersect_lines(const SkPoint& ptA, const SkVector& normA,
SkScalar lineBW = -normB.dot(ptB);
SkScalar wInv = SkScalarMul(normA.fX, normB.fY) -
- SkScalarMul(normA.fY, normB.fX);
+ SkScalarMul(normA.fY, normB.fX);
wInv = SkScalarInvert(wInv);
result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY);
@@ -454,6 +546,57 @@ void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice,
DevToUV.apply<kVertsPerQuad, sizeof(Vertex), sizeof(GrPoint)>(verts);
}
+
+// Input Parametric:
+// P(t) = (P0*(1-t)^2 + 2*w*P1*t*(1-t) + P2*t^2) / (1-t)^2 + 2*w*t*(1-t) + t^2)
+// Output Implicit:
+// Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0
+// A = 4w^2*(y0-y1)(y1-y2)-(y0-y2)^2
+// B = 4w^2*((x0-x1)(y2-y1)+(x1-x2)(y1-y0)) + 2(x0-x2)(y0-y2)
+// C = 4w^2(x0-x1)(x1-x2) - (x0-x2)^2
+// D = 4w^2((x0y1-x1y0)(y1-y2)+(x1y2-x2y1)(y0-y1)) + 2(y2-y0)(x0y2-x2y0)
+// E = 4w^2((y0x1-y1x0)(x1-x2)+(y1x2-y2x1)(x0-x1)) + 2(x2-x0)(y0x2-y2x0)
+// F = 4w^2(x1y2-x2y1)(x0y1-x1y0) - (x2y0-x0y2)^2
+
+void set_conic_coeffs(const SkPoint p[3], Vertex verts[kVertsPerConic], const float weight) {
+ const float ww4 = 4 * weight * weight;
+ const float x0Mx1 = p[0].fX - p[1].fX;
+ const float x1Mx2 = p[1].fX - p[2].fX;
+ const float x0Mx2 = p[0].fX - p[2].fX;
+ const float y0My1 = p[0].fY - p[1].fY;
+ const float y1My2 = p[1].fY - p[2].fY;
+ const float y0My2 = p[0].fY - p[2].fY;
+ const float x0y1Mx1y0 = p[0].fX*p[1].fY - p[1].fX*p[0].fY;
+ const float x1y2Mx2y1 = p[1].fX*p[2].fY - p[2].fX*p[1].fY;
+ const float x0y2Mx2y0 = p[0].fX*p[2].fY - p[2].fX*p[0].fY;
+ const float a = ww4 * y0My1 * y1My2 - y0My2 * y0My2;
+ const float b = -ww4 * (x0Mx1 * y1My2 + x1Mx2 * y0My1) + 2 * x0Mx2 * y0My2;
+ const float c = ww4 * x0Mx1 * x1Mx2 - x0Mx2 * x0Mx2;
+ const float d = ww4 * (x0y1Mx1y0 * y1My2 + x1y2Mx2y1 * y0My1) - 2 * y0My2 * x0y2Mx2y0;
+ const float e = -ww4 * (x0y1Mx1y0 * x1Mx2 + x1y2Mx2y1 * x0Mx1) + 2 * x0Mx2 * x0y2Mx2y0;
+ const float f = ww4 * x1y2Mx2y1 * x0y1Mx1y0 - x0y2Mx2y0 * x0y2Mx2y0;
+
+ for (int i = 0; i < kVertsPerConic; ++i) {
+ verts[i].fConic.fA = a/f;
+ verts[i].fConic.fB = b/f;
+ verts[i].fConic.fC = c/f;
+ verts[i].fConic.fD = d/f;
+ verts[i].fConic.fE = e/f;
+ verts[i].fConic.fF = f/f;
+ }
+}
+
+void add_conics(const SkPoint p[3],
+ float weight,
+ const SkMatrix* toDevice,
+ const SkMatrix* toSrc,
+ Vertex** vert,
+ SkRect* devBounds) {
+ bloat_quad(p, toDevice, toSrc, *vert, devBounds);
+ set_conic_coeffs(p, *vert, weight);
+ *vert += kVertsPerConic;
+}
+
void add_quads(const SkPoint p[3],
int subdiv,
const SkMatrix* toDevice,
@@ -515,6 +658,121 @@ void add_line(const SkPoint p[2],
}
+/**
+ * The output of this effect is a hairline edge for conics.
+ * Conics specified by implicit equation Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0.
+ * A, B, C, D are the first vec4 of vertex attributes and
+ * E and F are the vec2 attached to 2nd vertex attrribute.
+ * Coverage is max(0, 1-distance).
+ */
+class HairConicEdgeEffect : public GrEffect {
+public:
+
+ static GrEffectRef* Create() {
+ GR_CREATE_STATIC_EFFECT(gHairConicEdgeEffect, HairConicEdgeEffect, ());
+ gHairConicEdgeEffect->ref();
+ return gHairConicEdgeEffect;
+ }
+
+ virtual ~HairConicEdgeEffect() {}
+
+ static const char* Name() { return "HairConicEdge"; }
+
+ virtual void getConstantColorComponents(GrColor* color,
+ uint32_t* validFlags) const SK_OVERRIDE {
+ *validFlags = 0;
+ }
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
+ return GrTBackendEffectFactory<HairConicEdgeEffect>::getInstance();
+ }
+
+ 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 {
+ const char *vsCoeffABCDName, *fsCoeffABCDName;
+ const char *vsCoeffEFName, *fsCoeffEFName;
+
+ SkAssertResult(builder->enableFeature(
+ GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
+ builder->addVarying(kVec4f_GrSLType, "ConicCoeffsABCD",
+ &vsCoeffABCDName, &fsCoeffABCDName);
+ const SkString* attr0Name =
+ builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+ builder->vsCodeAppendf("\t%s = %s;\n", vsCoeffABCDName, attr0Name->c_str());
+
+ builder->addVarying(kVec2f_GrSLType, "ConicCoeffsEF",
+ &vsCoeffEFName, &fsCoeffEFName);
+ const SkString* attr1Name =
+ builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]);
+ builder->vsCodeAppendf("\t%s = %s;\n", vsCoeffEFName, attr1Name->c_str());
+
+ // Based on Gustavson 2006: "Beyond the Pixel: towards infinite resolution textures"
+ builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
+
+ builder->fsCodeAppendf("\t\tvec3 uv1 = vec3(%s.xy, 1);\n", builder->fragmentPosition());
+ builder->fsCodeAppend("\t\tvec3 u2uvv2 = uv1.xxy * uv1.xyy;\n");
+ builder->fsCodeAppendf("\t\tvec3 ABC = %s.xyz;\n", fsCoeffABCDName);
+ builder->fsCodeAppendf("\t\tvec3 DEF = vec3(%s.w, %s.xy);\n",
+ fsCoeffABCDName, fsCoeffEFName);
+
+ builder->fsCodeAppend("\t\tfloat dfdx = dot(uv1,vec3(2.0*ABC.x,ABC.y,DEF.x));\n");
+ builder->fsCodeAppend("\t\tfloat dfdy = dot(uv1,vec3(ABC.y, 2.0*ABC.z,DEF.y));\n");
+ builder->fsCodeAppend("\t\tfloat gF = dfdx*dfdx + dfdy*dfdy;\n");
+ builder->fsCodeAppend("\t\tedgeAlpha = dot(ABC,u2uvv2) + dot(DEF,uv1);\n");
+ builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / gF);\n");
+ builder->fsCodeAppend("\t\tedgeAlpha = max((1.0 - edgeAlpha), 0.0);\n");
+ // Add line below for smooth cubic ramp
+ // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\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&) {
+ return 0x0;
+ }
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
+
+ private:
+ typedef GrGLEffect INHERITED;
+ };
+
+private:
+ HairConicEdgeEffect() {
+ this->addVertexAttrib(kVec4f_GrSLType);
+ this->addVertexAttrib(kVec2f_GrSLType);
+ this->setWillReadFragmentPosition();
+ }
+
+ virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
+ return true;
+ }
+
+ GR_DECLARE_EFFECT_TEST;
+
+ typedef GrEffect INHERITED;
+};
+
+GR_DEFINE_EFFECT_TEST(HairConicEdgeEffect);
+
+GrEffectRef* HairConicEdgeEffect::TestCreate(SkMWCRandom* random,
+ GrContext*,
+ const GrDrawTargetCaps& caps,
+ GrTexture*[]) {
+ return HairConicEdgeEffect::Create();
+}
///////////////////////////////////////////////////////////////////////////////
/**
@@ -563,7 +821,7 @@ public:
builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
SkAssertResult(builder->enableFeature(
- GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
+ GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName);
builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
@@ -614,7 +872,8 @@ GrEffectRef* HairQuadEdgeEffect::TestCreate(SkMWCRandom* random,
const GrDrawTargetCaps& caps,
GrTexture*[]) {
// Doesn't work without derivative instructions.
- return caps.shaderDerivativeSupport() ? HairQuadEdgeEffect::Create() : NULL;}
+ return caps.shaderDerivativeSupport() ? HairQuadEdgeEffect::Create() : NULL;
+}
///////////////////////////////////////////////////////////////////////////////
@@ -717,6 +976,13 @@ extern const GrVertexAttrib gHairlineAttribs[] = {
{kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
};
+// Conic
+// position + ABCD + EF
+extern const GrVertexAttrib gConicVertexAttribs[] = {
+ { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
+ { kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding },
+ { kVec2f_GrVertexAttribType, 3*sizeof(GrPoint), kEffect_GrVertexAttribBinding }
+};
};
bool GrAAHairLinePathRenderer::createGeom(
@@ -724,6 +990,7 @@ bool GrAAHairLinePathRenderer::createGeom(
GrDrawTarget* target,
int* lineCnt,
int* quadCnt,
+ int* conicCnt,
GrDrawTarget::AutoReleaseGeometry* arg,
SkRect* devBounds) {
GrDrawState* drawState = target->drawState();
@@ -743,14 +1010,18 @@ bool GrAAHairLinePathRenderer::createGeom(
PREALLOC_PTARRAY(128) lines;
PREALLOC_PTARRAY(128) quads;
+ PREALLOC_PTARRAY(128) conics;
IntArray qSubdivs;
+ FloatArray cWeights;
*quadCnt = generate_lines_and_quads(path, viewM, devClipBounds,
- &lines, &quads, &qSubdivs);
+ &lines, &quads, &conics, &qSubdivs, &cWeights);
*lineCnt = lines.count() / 2;
- int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt;
+ *conicCnt = conics.count() / 3;
+ int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt +
+ kVertsPerConic * *conicCnt;
- target->drawState()->setVertexAttribs<gHairlineAttribs>(SK_ARRAY_COUNT(gHairlineAttribs));
+ target->drawState()->setVertexAttribs<gConicVertexAttribs>(SK_ARRAY_COUNT(gConicVertexAttribs));
GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize());
if (!arg->set(target, vertCnt, 0)) {
@@ -780,6 +1051,10 @@ bool GrAAHairLinePathRenderer::createGeom(
add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds);
}
+ // Start Conics
+ for (int i = 0; i < *conicCnt; ++i) {
+ add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts, devBounds);
+ }
return true;
}
@@ -807,6 +1082,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
int lineCnt;
int quadCnt;
+ int conicCnt;
GrDrawTarget::AutoReleaseGeometry arg;
SkRect devBounds;
@@ -814,6 +1090,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
target,
&lineCnt,
&quadCnt,
+ &conicCnt,
&arg,
&devBounds)) {
return false;
@@ -843,6 +1120,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create();
GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create();
+ GrEffectRef* hairConicEffect = HairConicEdgeEffect::Create();
// Check devBounds
#if GR_DEBUG
@@ -850,7 +1128,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000);
SkRect actualBounds;
Vertex* verts = reinterpret_cast<Vertex*>(arg.vertices());
- int vCount = kVertsPerLineSeg * lineCnt + kVertsPerQuad * quadCnt;
+ int vCount = kVertsPerLineSeg * lineCnt + kVertsPerQuad * quadCnt + kVertsPerConic * conicCnt;
bool first = true;
for (int i = 0; i < vCount; ++i) {
SkPoint pos = verts[i].fPos;
@@ -889,20 +1167,43 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
}
}
- target->setIndexSourceToBuffer(fQuadsIndexBuffer);
- int quads = 0;
- drawState->addCoverageEffect(hairQuadEffect, kEdgeAttrIndex)->unref();
- while (quads < quadCnt) {
- int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer);
- target->drawIndexed(kTriangles_GrPrimitiveType,
- 4 * lineCnt + kVertsPerQuad*quads, // startV
- 0, // startI
- kVertsPerQuad*n, // vCount
- kIdxsPerQuad*n, // iCount
- &devBounds);
- quads += n;
+ {
+ GrDrawState::AutoRestoreEffects are(drawState);
+ target->setIndexSourceToBuffer(fQuadsIndexBuffer);
+ int quads = 0;
+ drawState->addCoverageEffect(hairQuadEffect, kEdgeAttrIndex)->unref();
+ while (quads < quadCnt) {
+ int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer);
+ target->drawIndexed(kTriangles_GrPrimitiveType,
+ kVertsPerLineSeg * lineCnt + kVertsPerQuad*quads, // startV
+ 0, // startI
+ kVertsPerQuad*n, // vCount
+ kIdxsPerQuad*n, // iCount
+ &devBounds);
+ quads += n;
+ }
+ }
+
+ {
+ GrDrawState::AutoRestoreEffects are(drawState);
+ target->setIndexSourceToBuffer(fConicsIndexBuffer);
+ int conics = 0;
+ drawState->addCoverageEffect(hairConicEffect, 1, 2)->unref();
+ // drawState->addCoverageEffect(hairConicEffect, kEdgeAttrIndex)->unref();
+ while (conics < conicCnt) {
+ int n = GrMin(conicCnt - conics, kNumConicsInIdxBuffer);
+ target->drawIndexed(kTriangles_GrPrimitiveType,
+ kVertsPerLineSeg*lineCnt + kVertsPerQuad*quadCnt +
+ kVertsPerConic*conics, // startV
+ 0, // startI
+ kVertsPerConic*n, // vCount
+ kIdxsPerConic*n, // iCount
+ &devBounds);
+ conics += n;
+ }
}
target->resetIndexSource();
return true;
}
+
« src/core/SkGeometry.cpp ('K') | « src/gpu/GrAAHairLinePathRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698