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

Unified Diff: src/gpu/GrAAHairLinePathRenderer.cpp

Issue 22486003: Fix hairline pathrenderer for Nexus-10. Switches to passing in an offset and using that to compute … (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Clean up asserts Created 7 years, 4 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
« no previous file with comments | « 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 c1f951ab7f91832d95ece209f71b377794c68e48..4a73b53eba53a4338444c2021cabeff6960fe4dc 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -29,15 +29,20 @@ 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;
-bool push_quad_index_data(GrIndexBuffer* qIdxBuffer) {
+static const int kNumLineSegsInIdxBuffer = 256;
+static const size_t kLineSegIdxSBufize = kIdxsPerLineSeg *
+ sizeof(uint16_t) *
+ kNumLineSegsInIdxBuffer;
+
+static bool push_quad_index_data(GrIndexBuffer* qIdxBuffer) {
uint16_t* data = (uint16_t*) qIdxBuffer->lock();
bool tempData = NULL == data;
if (tempData) {
@@ -78,22 +83,66 @@ bool push_quad_index_data(GrIndexBuffer* qIdxBuffer) {
return true;
}
}
+
+static bool push_line_index_data(GrIndexBuffer* lIdxBuffer) {
+ uint16_t* data = (uint16_t*) lIdxBuffer->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 (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 = lIdxBuffer->updateData(data, kLineSegIdxSBufize);
+ delete[] data;
+ return ret;
+ } else {
+ lIdxBuffer->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);
- if (NULL == qIdxBuf ||
- !push_quad_index_data(qIdxBuf)) {
+ if (NULL == qIdxBuf || !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(
@@ -113,10 +162,7 @@ GrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() {
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) {
@@ -266,11 +312,11 @@ int num_quad_subdivs(const SkPoint p[3]) {
int generate_lines_and_quads(const SkPath& path,
const SkMatrix& m,
const SkIRect& devClipBounds,
- PtArray* lines,
- PtArray* quads,
- PtArray* conics,
- IntArray* quadSubdivCnts,
- FloatArray* conicWeights) {
+ GrAAHairLinePathRenderer::PtArray* lines,
+ GrAAHairLinePathRenderer::PtArray* quads,
+ GrAAHairLinePathRenderer::PtArray* conics,
+ GrAAHairLinePathRenderer::IntArray* quadSubdivCnts,
+ GrAAHairLinePathRenderer::FloatArray* conicWeights) {
SkPath::Iter iter(path, false);
int totalQuadCount = 0;
@@ -432,15 +478,15 @@ int generate_lines_and_quads(const SkPath& path,
}
}
-struct Vertex {
+struct LineVertex {
+ GrPoint fPos;
+ GrColor fCoverage;
+};
+
+struct BezierVertex {
GrPoint fPos;
union {
struct {
- SkScalar fA;
- SkScalar fB;
- SkScalar fC;
- } fLine;
- struct {
SkScalar fK;
SkScalar fL;
SkScalar fM;
@@ -452,7 +498,7 @@ struct Vertex {
};
};
-GR_STATIC_ASSERT(sizeof(Vertex) == 3 * sizeof(GrPoint));
+GR_STATIC_ASSERT(sizeof(BezierVertex) == 3 * sizeof(GrPoint));
void intersect_lines(const SkPoint& ptA, const SkVector& normA,
const SkPoint& ptB, const SkVector& normB,
@@ -472,14 +518,14 @@ void intersect_lines(const SkPoint& ptA, const SkVector& normA,
result->fY = SkScalarMul(result->fY, wInv);
}
-void set_uv_quad(const SkPoint qpts[3], Vertex verts[kVertsPerQuad]) {
+void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kVertsPerQuad]) {
// this should be in the src space, not dev coords, when we have perspective
GrPathUtils::QuadUVMatrix DevToUV(qpts);
- DevToUV.apply<kVertsPerQuad, sizeof(Vertex), sizeof(GrPoint)>(verts);
+ DevToUV.apply<kVertsPerQuad, sizeof(BezierVertex), sizeof(GrPoint)>(verts);
}
void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice,
- const SkMatrix* toSrc, Vertex verts[kVertsPerQuad],
+ const SkMatrix* toSrc, BezierVertex verts[kVertsPerQuad],
SkRect* devBounds) {
GrAssert(!toDevice == !toSrc);
// original quad is specified by tri a,b,c
@@ -504,11 +550,11 @@ void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice,
//
// edges a0->b0 and b0->c0 are parallel to original edges a->b and b->c,
// respectively.
- Vertex& a0 = verts[0];
- Vertex& a1 = verts[1];
- Vertex& b0 = verts[2];
- Vertex& c0 = verts[3];
- Vertex& c1 = verts[4];
+ BezierVertex& a0 = verts[0];
+ BezierVertex& a1 = verts[1];
+ BezierVertex& b0 = verts[2];
+ BezierVertex& c0 = verts[3];
+ BezierVertex& c1 = verts[4];
SkVector ab = b;
ab -= a;
@@ -550,7 +596,7 @@ void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice,
devBounds->growToInclude(b0.fPos.fX, b0.fPos.fY);
if (toSrc) {
- toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad);
+ toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(BezierVertex), kVertsPerQuad);
}
}
@@ -603,7 +649,7 @@ void calc_conic_klm(const SkPoint p[3], const SkScalar weight,
// f(x, y, w) = f(P) = K^2 - LM
// K = dot(k, P), L = dot(l, P), M = dot(m, P)
// k, l, m are calculated in function calc_conic_klm
-void set_conic_coeffs(const SkPoint p[3], Vertex verts[kVertsPerQuad], const float weight) {
+void set_conic_coeffs(const SkPoint p[3], BezierVertex verts[kVertsPerQuad], const float weight) {
SkScalar k[3];
SkScalar l[3];
SkScalar m[3];
@@ -622,7 +668,7 @@ void add_conics(const SkPoint p[3],
float weight,
const SkMatrix* toDevice,
const SkMatrix* toSrc,
- Vertex** vert,
+ BezierVertex** vert,
SkRect* devBounds) {
bloat_quad(p, toDevice, toSrc, *vert, devBounds);
set_conic_coeffs(p, *vert, weight);
@@ -633,7 +679,7 @@ void add_quads(const SkPoint p[3],
int subdiv,
const SkMatrix* toDevice,
const SkMatrix* toSrc,
- Vertex** vert,
+ BezierVertex** vert,
SkRect* devBounds) {
GrAssert(subdiv >= 0);
if (subdiv) {
@@ -651,7 +697,8 @@ void add_quads(const SkPoint p[3],
void add_line(const SkPoint p[2],
int rtHeight,
const SkMatrix* toSrc,
- Vertex** vert) {
+ GrColor coverage,
+ LineVertex** vert) {
const SkPoint& a = p[0];
const SkPoint& b = p[1];
@@ -661,29 +708,28 @@ 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 = coverage;
}
- (*vert)[i].fLine.fA = orthVec.fX;
- (*vert)[i].fLine.fB = orthVec.fY;
- (*vert)[i].fLine.fC = lineC;
}
if (NULL != toSrc) {
toSrc->mapPointsWithStride(&(*vert)->fPos,
- sizeof(Vertex),
+ sizeof(LineVertex),
kVertsPerLineSeg);
}
} else {
// just make it degenerate and likely offscreen
- (*vert)[0].fPos.set(SK_ScalarMax, SK_ScalarMax);
- (*vert)[1].fPos.set(SK_ScalarMax, SK_ScalarMax);
- (*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax);
- (*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax);
+ for (int i = 0; i < kVertsPerLineSeg; ++i) {
+ (*vert)[i].fPos.set(SK_ScalarMax, SK_ScalarMax);
+ }
}
*vert += kVertsPerLineSeg;
@@ -934,174 +980,117 @@ 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.
- */
-class HairLineEdgeEffect : public GrEffect {
-public:
-
- static GrEffectRef* Create() {
- GR_CREATE_STATIC_EFFECT(gHairLineEdge, HairLineEdgeEffect, ());
- gHairLineEdge->ref();
- return gHairLineEdge;
- }
-
- virtual ~HairLineEdgeEffect() {}
-
- static const char* Name() { return "HairLineEdge"; }
-
- virtual void getConstantColorComponents(GrColor* color,
- uint32_t* validFlags) const SK_OVERRIDE {
- *validFlags = 0;
- }
-
- virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
- return GrTBackendEffectFactory<HairLineEdgeEffect>::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 *vsName, *fsName;
- const SkString* attrName =
- builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
- builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
-
- 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");
-
- SkString modulate;
- GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
- builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
-
- builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->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:
- HairLineEdgeEffect() {
- this->addVertexAttrib(kVec4f_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(HairLineEdgeEffect);
-
-GrEffectRef* HairLineEdgeEffect::TestCreate(SkMWCRandom* random,
- GrContext*,
- const GrDrawTargetCaps& caps,
- GrTexture*[]) {
- return HairLineEdgeEffect::Create();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
namespace {
// position + edge
-extern const GrVertexAttrib gHairlineAttribs[] = {
+extern const GrVertexAttrib gHairlineBezierAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
};
+
+// position + coverage
+extern const GrVertexAttrib gHairlineLineAttribs[] = {
+ {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
+ {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBinding},
+};
+
};
-bool GrAAHairLinePathRenderer::createGeom(
+bool GrAAHairLinePathRenderer::createLineGeom(
const SkPath& path,
GrDrawTarget* target,
- int* lineCnt,
- int* quadCnt,
- int* conicCnt,
+ const PtArray& lines,
+ int lineCnt,
GrDrawTarget::AutoReleaseGeometry* arg,
SkRect* devBounds) {
GrDrawState* drawState = target->drawState();
int rtHeight = drawState->getRenderTarget()->height();
- SkIRect devClipBounds;
- target->getClip()->getConservativeBounds(drawState->getRenderTarget(), &devClipBounds);
-
- SkMatrix viewM = drawState->getViewMatrix();
+ const SkMatrix& viewM = drawState->getViewMatrix();
- // All the vertices that we compute are within 1 of path control points with the exception of
- // one of the bounding vertices for each quad. The add_quads() function will update the bounds
- // for each quad added.
*devBounds = path.getBounds();
viewM.mapRect(devBounds);
devBounds->outset(SK_Scalar1, SK_Scalar1);
- 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, &conics, &qSubdivs, &cWeights);
-
- *lineCnt = lines.count() / 2;
- *conicCnt = conics.count() / 3;
- int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt +
- kVertsPerQuad * *conicCnt;
+ int vertCnt = kVertsPerLineSeg * lineCnt;
- target->drawState()->setVertexAttribs<gHairlineAttribs>(SK_ARRAY_COUNT(gHairlineAttribs));
- GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize());
+ target->drawState()->setVertexAttribs<gHairlineLineAttribs>(SK_ARRAY_COUNT(gHairlineLineAttribs));
+ GrAssert(sizeof(LineVertex) == target->getDrawState().getVertexSize());
if (!arg->set(target, vertCnt, 0)) {
return false;
}
- Vertex* verts = reinterpret_cast<Vertex*>(arg->vertices());
+ LineVertex* verts = reinterpret_cast<LineVertex*>(arg->vertices());
- const SkMatrix* toDevice = NULL;
const SkMatrix* toSrc = NULL;
SkMatrix ivm;
if (viewM.hasPerspective()) {
if (viewM.invert(&ivm)) {
- toDevice = &viewM;
toSrc = &ivm;
}
}
- for (int i = 0; i < *lineCnt; ++i) {
- add_line(&lines[2*i], rtHeight, toSrc, &verts);
+ for (int i = 0; i < lineCnt; ++i) {
+ add_line(&lines[2*i], rtHeight, toSrc, drawState->getCoverage(), &verts);
}
+ return true;
+}
+
+bool GrAAHairLinePathRenderer::createBezierGeom(
+ const SkPath& path,
+ GrDrawTarget* target,
+ const PtArray& quads,
+ int quadCnt,
+ const PtArray& conics,
+ int conicCnt,
+ const IntArray& qSubdivs,
+ const FloatArray& cWeights,
+ GrDrawTarget::AutoReleaseGeometry* arg,
+ SkRect* devBounds) {
+ GrDrawState* drawState = target->drawState();
+
+ const SkMatrix& viewM = drawState->getViewMatrix();
+
+ // All the vertices that we compute are within 1 of path control points with the exception of
+ // one of the bounding vertices for each quad. The add_quads() function will update the bounds
+ // for each quad added.
+ *devBounds = path.getBounds();
+ viewM.mapRect(devBounds);
+ devBounds->outset(SK_Scalar1, SK_Scalar1);
+
+ int vertCnt = kVertsPerQuad * quadCnt + kVertsPerQuad * conicCnt;
+
+ target->drawState()->setVertexAttribs<gHairlineBezierAttribs>(SK_ARRAY_COUNT(gHairlineBezierAttribs));
+ GrAssert(sizeof(BezierVertex) == target->getDrawState().getVertexSize());
+
+ if (!arg->set(target, vertCnt, 0)) {
+ return false;
+ }
+
+ BezierVertex* verts = reinterpret_cast<BezierVertex*>(arg->vertices());
+
+ const SkMatrix* toDevice = NULL;
+ const SkMatrix* toSrc = NULL;
+ SkMatrix ivm;
+
+ if (viewM.hasPerspective()) {
+ if (viewM.invert(&ivm)) {
+ toDevice = &viewM;
+ toSrc = &ivm;
+ }
+ }
+
int unsubdivQuadCnt = quads.count() / 3;
for (int i = 0; i < unsubdivQuadCnt; ++i) {
GrAssert(qSubdivs[i] >= 0);
add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds);
}
-
+
// Start Conics
- for (int i = 0; i < *conicCnt; ++i) {
+ for (int i = 0; i < conicCnt; ++i) {
add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts, devBounds);
}
return true;
@@ -1122,54 +1111,14 @@ bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path,
return false;
}
-bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
- const SkStrokeRec&,
- GrDrawTarget* target,
- bool antiAlias) {
-
- int lineCnt;
- int quadCnt;
- int conicCnt;
- GrDrawTarget::AutoReleaseGeometry arg;
- SkRect devBounds;
-
- if (!this->createGeom(path,
- target,
- &lineCnt,
- &quadCnt,
- &conicCnt,
- &arg,
- &devBounds)) {
- return false;
- }
-
- GrDrawTarget::AutoStateRestore asr;
-
- // createGeom transforms the geometry to device space when the matrix does not have
- // perspective.
- if (target->getDrawState().getViewMatrix().hasPerspective()) {
- asr.set(target, GrDrawTarget::kPreserve_ASRInit);
- } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) {
- return false;
- }
- GrDrawState* drawState = target->drawState();
-
- // TODO: See whether rendering lines as degenerate quads improves perf
- // when we have a mix
-
- static const int kEdgeAttrIndex = 1;
-
- GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create();
- GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create();
- GrEffectRef* hairConicEffect = HairConicEdgeEffect::Create();
-
- // Check devBounds
-#if GR_DEBUG
+template <class VertexType>
+bool check_bounds(GrDrawState* drawState, const SkRect& devBounds, void* vertices, int vCount)
+{
SkRect tolDevBounds = devBounds;
tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000);
SkRect actualBounds;
- Vertex* verts = reinterpret_cast<Vertex*>(arg.vertices());
- int vCount = kVertsPerLineSeg * lineCnt + kVertsPerQuad * quadCnt + kVertsPerQuad * conicCnt;
+
+ VertexType* verts = reinterpret_cast<VertexType*>(vertices);
bool first = true;
for (int i = 0; i < vCount; ++i) {
SkPoint pos = verts[i].fPos;
@@ -1186,61 +1135,153 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
}
}
if (!first) {
- GrAssert(tolDevBounds.contains(actualBounds));
+ return tolDevBounds.contains(actualBounds);
}
-#endif
+
+ return true;
+}
+bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
+ const SkStrokeRec&,
+ GrDrawTarget* target,
+ bool antiAlias) {
+
+ GrDrawState* drawState = target->drawState();
+
+ SkIRect devClipBounds;
+ target->getClip()->getConservativeBounds(drawState->getRenderTarget(), &devClipBounds);
+
+ int lineCnt;
+ int quadCnt;
+ int conicCnt;
+ PREALLOC_PTARRAY(128) lines;
+ PREALLOC_PTARRAY(128) quads;
+ PREALLOC_PTARRAY(128) conics;
+ IntArray qSubdivs;
+ FloatArray cWeights;
+ quadCnt = generate_lines_and_quads(path, drawState->getViewMatrix(), devClipBounds,
+ &lines, &quads, &conics, &qSubdivs, &cWeights);
+ lineCnt = lines.count() / 2;
+ conicCnt = conics.count() / 3;
+
+ // do lines first
{
- 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);
- target->drawIndexed(kTriangles_GrPrimitiveType,
- kVertsPerLineSeg*lines, // startV
- 0, // startI
- kVertsPerLineSeg*n, // vCount
- kIdxsPerLineSeg*n,
- &devBounds); // iCount
- lines += n;
+ GrDrawTarget::AutoReleaseGeometry arg;
+ SkRect devBounds;
+
+ if (!this->createLineGeom(path,
+ target,
+ lines,
+ lineCnt,
+ &arg,
+ &devBounds)) {
+ return false;
}
- }
- {
- 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;
+ GrDrawTarget::AutoStateRestore asr;
+
+ // createGeom transforms the geometry to device space when the matrix does not have
+ // perspective.
+ if (target->getDrawState().getViewMatrix().hasPerspective()) {
+ asr.set(target, GrDrawTarget::kPreserve_ASRInit);
+ } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) {
+ return false;
+ }
+ GrDrawState* drawState = target->drawState();
+
+ // Check devBounds
+ SkASSERT(check_bounds<LineVertex>(drawState, devBounds, arg.vertices(),
+ kVertsPerLineSeg * lineCnt));
+
+ {
+ GrDrawState::AutoRestoreEffects are(drawState);
+ target->setIndexSourceToBuffer(fLinesIndexBuffer);
+ int lines = 0;
+ while (lines < lineCnt) {
+ int n = GrMin(lineCnt - lines, kNumLineSegsInIdxBuffer);
+ target->drawIndexed(kTriangles_GrPrimitiveType,
+ kVertsPerLineSeg*lines, // startV
+ 0, // startI
+ kVertsPerLineSeg*n, // vCount
+ kIdxsPerLineSeg*n,
+ &devBounds); // iCount
+ lines += n;
+ }
}
}
-
+
+ // then quadratics/conics
{
- GrDrawState::AutoRestoreEffects are(drawState);
- int conics = 0;
- drawState->addCoverageEffect(hairConicEffect, 1, 2)->unref();
- while (conics < conicCnt) {
- int n = GrMin(conicCnt - conics, kNumQuadsInIdxBuffer);
- target->drawIndexed(kTriangles_GrPrimitiveType,
- kVertsPerLineSeg*lineCnt +
- kVertsPerQuad*(quadCnt + conics), // startV
- 0, // startI
- kVertsPerQuad*n, // vCount
- kIdxsPerQuad*n, // iCount
- &devBounds);
- conics += n;
+ GrDrawTarget::AutoReleaseGeometry arg;
+ SkRect devBounds;
+
+ if (!this->createBezierGeom(path,
+ target,
+ quads,
+ quadCnt,
+ conics,
+ conicCnt,
+ qSubdivs,
+ cWeights,
+ &arg,
+ &devBounds)) {
+ return false;
+ }
+
+ GrDrawTarget::AutoStateRestore asr;
+
+ // createGeom transforms the geometry to device space when the matrix does not have
+ // perspective.
+ if (target->getDrawState().getViewMatrix().hasPerspective()) {
+ asr.set(target, GrDrawTarget::kPreserve_ASRInit);
+ } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) {
+ return false;
+ }
+ GrDrawState* drawState = target->drawState();
+
+ static const int kEdgeAttrIndex = 1;
+
+ GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create();
+ GrEffectRef* hairConicEffect = HairConicEdgeEffect::Create();
+
+ // Check devBounds
+ SkASSERT(check_bounds<BezierVertex>(drawState, devBounds, arg.vertices(),
+ kVertsPerQuad * quadCnt + kVertsPerQuad * conicCnt));
+
+ {
+ 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,
+ kVertsPerQuad*quads, // startV
+ 0, // startI
+ kVertsPerQuad*n, // vCount
+ kIdxsPerQuad*n, // iCount
+ &devBounds);
+ quads += n;
+ }
+ }
+
+ {
+ GrDrawState::AutoRestoreEffects are(drawState);
+ int conics = 0;
+ drawState->addCoverageEffect(hairConicEffect, 1, 2)->unref();
+ while (conics < conicCnt) {
+ int n = GrMin(conicCnt - conics, kNumQuadsInIdxBuffer);
+ target->drawIndexed(kTriangles_GrPrimitiveType,
+ kVertsPerQuad*(quadCnt + conics), // startV
+ 0, // startI
+ kVertsPerQuad*n, // vCount
+ kIdxsPerQuad*n, // iCount
+ &devBounds);
+ conics += n;
+ }
}
}
+
target->resetIndexSource();
return true;
« no previous file with comments | « src/gpu/GrAAHairLinePathRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698