From cb3f50468dcd6e838628b425828b8f4386a48109 Mon Sep 17 00:00:00 2001 From: joshualitt Date: Mon, 2 Feb 2015 18:12:39 -0800 Subject: [PATCH] Revert of Hairline batch (patchset #16 id:300001 of https://codereview.chromium.org/876673002/) Reason for revert: Regression Original issue's description: > Hairline batch > > BUG=skia: > > Committed: https://skia.googlesource.com/skia/+/6eff8701f027016fbb3147412ec2292dcec2b7f5 TBR=bsalomon@google.com,joshualitt@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=skia: Review URL: https://codereview.chromium.org/894273002 --- src/gpu/GrAAHairLinePathRenderer.cpp | 739 ++++++++++----------------- src/gpu/GrAAHairLinePathRenderer.h | 25 + src/gpu/GrAARectRenderer.cpp | 5 +- src/gpu/GrBatch.h | 8 +- src/gpu/GrBatchTarget.cpp | 25 +- src/gpu/GrBatchTarget.h | 14 +- src/gpu/GrInOrderDrawBuffer.cpp | 5 +- 7 files changed, 319 insertions(+), 502 deletions(-) diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp index 6ecaa2eba4..ce24cf8c26 100644 --- a/src/gpu/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/GrAAHairLinePathRenderer.cpp @@ -7,9 +7,6 @@ #include "GrAAHairLinePathRenderer.h" -#include "GrBatch.h" -#include "GrBatchTarget.h" -#include "GrBufferAllocPool.h" #include "GrContext.h" #include "GrDefaultGeoProcFactory.h" #include "GrDrawTargetCaps.h" @@ -256,14 +253,14 @@ int num_quad_subdivs(const SkPoint p[3]) { * subdivide large quads to reduce over-fill. This subdivision has to be * performed before applying the perspective matrix. */ -int gather_lines_and_quads(const SkPath& path, - const SkMatrix& m, - const SkIRect& devClipBounds, - GrAAHairLinePathRenderer::PtArray* lines, - GrAAHairLinePathRenderer::PtArray* quads, - GrAAHairLinePathRenderer::PtArray* conics, - GrAAHairLinePathRenderer::IntArray* quadSubdivCnts, - GrAAHairLinePathRenderer::FloatArray* conicWeights) { +int generate_lines_and_quads(const SkPath& path, + const SkMatrix& m, + const SkIRect& devClipBounds, + GrAAHairLinePathRenderer::PtArray* lines, + GrAAHairLinePathRenderer::PtArray* quads, + GrAAHairLinePathRenderer::PtArray* conics, + GrAAHairLinePathRenderer::IntArray* quadSubdivCnts, + GrAAHairLinePathRenderer::FloatArray* conicWeights) { SkPath::Iter iter(path, false); int totalQuadCount = 0; @@ -472,7 +469,8 @@ void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kQuadNumVertices]) { } void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, - const SkMatrix* toSrc, BezierVertex verts[kQuadNumVertices]) { + const SkMatrix* toSrc, BezierVertex verts[kQuadNumVertices], + SkRect* devBounds) { SkASSERT(!toDevice == !toSrc); // original quad is specified by tri a,b,c SkPoint a = qpts[0]; @@ -537,6 +535,7 @@ void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, c1.fPos -= cbN; intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); + devBounds->growToInclude(&verts[0].fPos, sizeof(BezierVertex), kQuadNumVertices); if (toSrc) { toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(BezierVertex), kQuadNumVertices); @@ -568,8 +567,9 @@ void add_conics(const SkPoint p[3], const SkScalar weight, const SkMatrix* toDevice, const SkMatrix* toSrc, - BezierVertex** vert) { - bloat_quad(p, toDevice, toSrc, *vert); + BezierVertex** vert, + SkRect* devBounds) { + bloat_quad(p, toDevice, toSrc, *vert, devBounds); set_conic_coeffs(p, *vert, weight); *vert += kQuadNumVertices; } @@ -578,15 +578,16 @@ void add_quads(const SkPoint p[3], int subdiv, const SkMatrix* toDevice, const SkMatrix* toSrc, - BezierVertex** vert) { + BezierVertex** vert, + SkRect* devBounds) { SkASSERT(subdiv >= 0); if (subdiv) { SkPoint newP[5]; SkChopQuadAtHalf(p, newP); - add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert); - add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert); + add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert, devBounds); + add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert, devBounds); } else { - bloat_quad(p, toDevice, toSrc, *vert); + bloat_quad(p, toDevice, toSrc, *vert, devBounds); set_uv_quad(p, *vert); *vert += kQuadNumVertices; } @@ -641,6 +642,106 @@ void add_line(const SkPoint p[2], /////////////////////////////////////////////////////////////////////////////// +bool GrAAHairLinePathRenderer::createLineGeom(GrDrawTarget* target, + GrPipelineBuilder* pipelineBuilder, + const SkMatrix& viewMatrix, + uint8_t coverage, + size_t vertexStride, + GrDrawTarget::AutoReleaseGeometry* arg, + SkRect* devBounds, + const SkPath& path, + const PtArray& lines, + int lineCnt) { + int vertCnt = kLineSegNumVertices * lineCnt; + + SkASSERT(vertexStride == sizeof(LineVertex)); + if (!arg->set(target, vertCnt, vertexStride, 0)) { + return false; + } + + LineVertex* verts = reinterpret_cast(arg->vertices()); + + const SkMatrix* toSrc = NULL; + SkMatrix ivm; + + if (viewMatrix.hasPerspective()) { + if (viewMatrix.invert(&ivm)) { + toSrc = &ivm; + } + } + devBounds->set(lines.begin(), lines.count()); + for (int i = 0; i < lineCnt; ++i) { + add_line(&lines[2*i], toSrc, coverage, &verts); + } + // All the verts computed by add_line are within sqrt(1^2 + 0.5^2) of the end points. + static const SkScalar kSqrtOfOneAndAQuarter = 1.118f; + // Add a little extra to account for vector normalization precision. + static const SkScalar kOutset = kSqrtOfOneAndAQuarter + SK_Scalar1 / 20; + devBounds->outset(kOutset, kOutset); + + return true; +} + +bool GrAAHairLinePathRenderer::createBezierGeom(GrDrawTarget* target, + GrPipelineBuilder* pipelineBuilder, + const SkMatrix& viewMatrix, + GrDrawTarget::AutoReleaseGeometry* arg, + SkRect* devBounds, + const SkPath& path, + const PtArray& quads, + int quadCnt, + const PtArray& conics, + int conicCnt, + const IntArray& qSubdivs, + const FloatArray& cWeights, + size_t vertexStride) { + int vertCnt = kQuadNumVertices * quadCnt + kQuadNumVertices * conicCnt; + + if (!arg->set(target, vertCnt, vertexStride, 0)) { + return false; + } + + BezierVertex* verts = reinterpret_cast(arg->vertices()); + + const SkMatrix* toDevice = NULL; + const SkMatrix* toSrc = NULL; + SkMatrix ivm; + + if (viewMatrix.hasPerspective()) { + if (viewMatrix.invert(&ivm)) { + toDevice = &viewMatrix; + toSrc = &ivm; + } + } + + // Seed the dev bounds with some pts known to be inside. Each quad and conic grows the bounding + // box to include its vertices. + SkPoint seedPts[2]; + if (quadCnt) { + seedPts[0] = quads[0]; + seedPts[1] = quads[2]; + } else if (conicCnt) { + seedPts[0] = conics[0]; + seedPts[1] = conics[2]; + } + if (toDevice) { + toDevice->mapPoints(seedPts, 2); + } + devBounds->set(seedPts[0], seedPts[1]); + + int unsubdivQuadCnt = quads.count() / 3; + for (int i = 0; i < unsubdivQuadCnt; ++i) { + SkASSERT(qSubdivs[i] >= 0); + 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; +} + bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target, const GrPipelineBuilder* pipelineBuilder, const SkMatrix& viewMatrix, @@ -699,444 +800,13 @@ bool check_bounds(const SkMatrix& viewMatrix, const SkRect& devBounds, void* ver return true; } -class AAHairlineBatch : public GrBatch { -public: - struct Geometry { - GrColor fColor; - uint8_t fCoverage; - SkMatrix fViewMatrix; - SkPath fPath; - SkDEBUGCODE(SkRect fDevBounds;) - SkIRect fDevClipBounds; - }; - - // TODO Batch itself should not hold on to index buffers. Instead, these should live in the - // cache. - static GrBatch* Create(const Geometry& geometry, const GrIndexBuffer* linesIndexBuffer, - const GrIndexBuffer* quadsIndexBuffer) { - return SkNEW_ARGS(AAHairlineBatch, (geometry, linesIndexBuffer, quadsIndexBuffer)); - } - - const char* name() const SK_OVERRIDE { return "AAHairlineBatch"; } - - void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE { - // When this is called on a batch, there is only one geometry bundle - out->setKnownFourComponents(fGeoData[0].fColor); - } - void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE { - out->setUnknownSingleComponent(); - } - - void initBatchOpt(const GrBatchOpt& batchOpt) { - fBatchOpt = batchOpt; - } - - void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE { - // Handle any color overrides - if (init.fColorIgnored) { - fGeoData[0].fColor = GrColor_ILLEGAL; - } else if (GrColor_ILLEGAL != init.fOverrideColor) { - fGeoData[0].fColor = init.fOverrideColor; - } - - // setup batch properties - fBatch.fColorIgnored = init.fColorIgnored; - fBatch.fColor = fGeoData[0].fColor; - fBatch.fUsesLocalCoords = init.fUsesLocalCoords; - fBatch.fCoverageIgnored = init.fCoverageIgnored; - fBatch.fCoverage = fGeoData[0].fCoverage; - SkDEBUGCODE(fBatch.fDevBounds = fGeoData[0].fDevBounds;) - } - - void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) SK_OVERRIDE { - int instanceCount = fGeoData.count(); - for (int i = 0; i < instanceCount; i++) { - const Geometry& args = fGeoData[i]; - - // createGeom transforms the geometry to device space when the matrix does not have - // perspective. - SkMatrix vm = args.fViewMatrix; - SkMatrix invert = SkMatrix::I(); - if (!args.fViewMatrix.hasPerspective()) { - vm = SkMatrix::I(); - if (!args.fViewMatrix.invert(&invert)) { - return; - } - } - - int lineCount; - int quadCount; - int conicCount; - PREALLOC_PTARRAY(128) lines; - PREALLOC_PTARRAY(128) quads; - PREALLOC_PTARRAY(128) conics; - IntArray qSubdivs; - FloatArray cWeights; - quadCount = gather_lines_and_quads(args.fPath, args.fViewMatrix, args.fDevClipBounds, - &lines, &quads, &conics, &qSubdivs, &cWeights); - - lineCount = lines.count() / 2; - conicCount = conics.count() / 3; - - // do lines first - if (lineCount) { - this->generateLines(batchTarget, pipeline, args, vm, invert, lines, lineCount); - } - - if (quadCount || conicCount) { - this->generateQuadsAndConics(batchTarget, - pipeline, - args, - quads, - quadCount, - conics, - conicCount, - qSubdivs, - cWeights, - vm, - invert); - } - } - } - - SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } - -private: - typedef SkTArray PtArray; - typedef SkTArray IntArray; - typedef SkTArray FloatArray; - - AAHairlineBatch(const Geometry& geometry, const GrIndexBuffer* linesIndexBuffer, - const GrIndexBuffer* quadsIndexBuffer) - : fLinesIndexBuffer(linesIndexBuffer) - , fQuadsIndexBuffer(quadsIndexBuffer) { - SkASSERT(linesIndexBuffer && quadsIndexBuffer); - this->initClassID(); - fGeoData.push_back(geometry); - } - - bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE { - AAHairlineBatch* that = t->cast(); - - // We go to identity if we don't have perspective - if (this->viewMatrix().hasPerspective() && - !this->viewMatrix().cheapEqualTo(that->viewMatrix())) { - return false; - } - - // TODO we can actually batch hairlines if they are the same color in a kind of bulk method - // but we haven't implemented this yet - // TODO investigate going to vertex color and coverage? - if (this->coverage() != that->coverage()) { - return false; - } - - if (this->color() != that->color()) { - return false; - } - - SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); - if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) { - return false; - } - - fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()); - return true; - } - - GrColor color() const { return fBatch.fColor; } - uint8_t coverage() const { return fBatch.fCoverage; } - bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } - const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } - - void generateLines(GrBatchTarget* batchTarget, - const GrPipeline* pipeline, - const Geometry& args, - const SkMatrix& viewMatrix, - const SkMatrix& invert, - const PtArray& lines, - int lineCnt) { - uint32_t gpFlags = GrDefaultGeoProcFactory::kPosition_GPType | - GrDefaultGeoProcFactory::kCoverage_GPType; - SkAutoTUnref gp(GrDefaultGeoProcFactory::Create(gpFlags, - args.fColor, - viewMatrix, - invert, - false, - args.fCoverage)); - - batchTarget->initDraw(gp, pipeline); - - // TODO remove this when batch is everywhere - GrPipelineInfo init; - init.fColorIgnored = fBatch.fColorIgnored; - init.fOverrideColor = GrColor_ILLEGAL; - init.fCoverageIgnored = fBatch.fCoverageIgnored; - init.fUsesLocalCoords = this->usesLocalCoords(); - gp->initBatchTracker(batchTarget->currentBatchTracker(), init); - - const GrVertexBuffer* vertexBuffer; - int firstVertex; - - size_t vertexStride = gp->getVertexStride(); - int vertexCount = kLineSegNumVertices * lineCnt; - void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride, - vertexCount, - &vertexBuffer, - &firstVertex); - - SkASSERT(gp->getVertexStride() == sizeof(LineVertex)); - - // generate lines - const SkMatrix* toSrc = NULL; - if (args.fViewMatrix.hasPerspective()) { - SkMatrix perspectiveInvert; - if (!args.fViewMatrix.invert(&perspectiveInvert)) { - return; - } - toSrc = &perspectiveInvert; - } - - LineVertex* verts = reinterpret_cast(vertices); - for (int i = 0; i < lineCnt; ++i) { - add_line(&lines[2*i], toSrc, args.fCoverage, &verts); - } - - // Check devBounds - SkASSERT(check_bounds(viewMatrix.hasPerspective() ? viewMatrix : SkMatrix::I(), - args.fDevBounds, - vertices, - kLineSegNumVertices * lineCnt)); - - { - GrDrawTarget::DrawInfo info; - info.setVertexBuffer(vertexBuffer); - info.setIndexBuffer(fLinesIndexBuffer); - info.setPrimitiveType(kTriangles_GrPrimitiveType); - info.setStartIndex(0); - - int lines = 0; - while (lines < lineCnt) { - int n = SkTMin(lineCnt - lines, kLineSegsNumInIdxBuffer); - - info.setStartVertex(kLineSegNumVertices*lines + firstVertex); - info.setVertexCount(kLineSegNumVertices*n); - info.setIndexCount(kIdxsPerLineSeg*n); - batchTarget->draw(info); - - lines += n; - } - } - } - - void generateQuadsAndConics(GrBatchTarget* batchTarget, - const GrPipeline* pipeline, - const Geometry& args, - const PREALLOC_PTARRAY(128)& quads, - int quadCount, - const PREALLOC_PTARRAY(128)& conics, - int conicCount, - const IntArray& qSubdivs, - const FloatArray& cWeights, - const SkMatrix& vm, - const SkMatrix& invert) { - const GrVertexBuffer* vertexBuffer; - int firstVertex; - - size_t vertexStride = sizeof(BezierVertex); - int vertexCount = kQuadNumVertices * quadCount + kQuadNumVertices * conicCount; - void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride, - vertexCount, - &vertexBuffer, - &firstVertex); - - if (!this->createBezierGeom(vertices, - args.fViewMatrix, - args.fPath, - quads, - quadCount, - conics, - conicCount, - qSubdivs, - cWeights, - vertexStride)) { - SkDebugf("Couldn't create bezier geometry\n"); - return; - } - - // Check devBounds - SkASSERT(check_bounds(vm, - args.fDevBounds, - vertices, - kQuadNumVertices * quadCount + - kQuadNumVertices * conicCount)); - - if (quadCount > 0) { - SkAutoTUnref hairQuadProcessor( - GrQuadEffect::Create(args.fColor, - vm, - kHairlineAA_GrProcessorEdgeType, - batchTarget->caps(), - invert, - args.fCoverage)); - - batchTarget->initDraw(hairQuadProcessor, pipeline); - - // TODO remove this when batch is everywhere - GrPipelineInfo init; - init.fColorIgnored = fBatch.fColorIgnored; - init.fOverrideColor = GrColor_ILLEGAL; - init.fCoverageIgnored = fBatch.fCoverageIgnored; - init.fUsesLocalCoords = this->usesLocalCoords(); - hairQuadProcessor->initBatchTracker(batchTarget->currentBatchTracker(), init); - - this->drawBeziers(batchTarget, - hairQuadProcessor, - pipeline, - vertexBuffer, - firstVertex, - quadCount); - } - - if (conicCount > 0) { - SkAutoTUnref hairConicProcessor( - GrConicEffect::Create(args.fColor, - vm, - kHairlineAA_GrProcessorEdgeType, - batchTarget->caps(), - invert, - args.fCoverage)); - - batchTarget->initDraw(hairConicProcessor, pipeline); - - // TODO remove this when batch is everywhere - GrPipelineInfo init; - init.fColorIgnored = fBatch.fColorIgnored; - init.fOverrideColor = GrColor_ILLEGAL; - init.fCoverageIgnored = fBatch.fCoverageIgnored; - init.fUsesLocalCoords = this->usesLocalCoords(); - hairConicProcessor->initBatchTracker(batchTarget->currentBatchTracker(), init); - - this->drawConics(batchTarget, - hairConicProcessor, - pipeline, - vertexBuffer, - firstVertex, - conicCount, - quadCount); - } - } - - bool createBezierGeom(void* vertices, - const SkMatrix& viewMatrix, - const SkPath& path, - const PtArray& quads, - int quadCnt, - const PtArray& conics, - int conicCnt, - const IntArray& qSubdivs, - const FloatArray& cWeights, - size_t vertexStride) { - BezierVertex* verts = reinterpret_cast(vertices); - - const SkMatrix* toDevice = NULL; - const SkMatrix* toSrc = NULL; - SkMatrix ivm; - - if (viewMatrix.hasPerspective()) { - if (viewMatrix.invert(&ivm)) { - toDevice = &viewMatrix; - toSrc = &ivm; - } - } - - int unsubdivQuadCnt = quads.count() / 3; - for (int i = 0; i < unsubdivQuadCnt; ++i) { - SkASSERT(qSubdivs[i] >= 0); - add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts); - } - - // Start Conics - for (int i = 0; i < conicCnt; ++i) { - add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts); - } - return true; - } - - void drawBeziers(GrBatchTarget* batchTarget, - const GrGeometryProcessor* hairQuadProcessor, - const GrPipeline* pipeline, - const GrVertexBuffer* vertexBuffer, - int firstVertex, - int quadCount) { - GrDrawTarget::DrawInfo info; - info.setVertexBuffer(vertexBuffer); - info.setIndexBuffer(fQuadsIndexBuffer); - info.setPrimitiveType(kTriangles_GrPrimitiveType); - info.setStartIndex(0); - - int quads = 0; - while (quads < quadCount) { - int n = SkTMin(quadCount - quads, kQuadsNumInIdxBuffer); - - info.setStartVertex(kQuadNumVertices*quads + firstVertex); - info.setVertexCount(kQuadNumVertices*n); - info.setIndexCount(kIdxsPerQuad*n); - batchTarget->draw(info); - - quads += n; - } - } - - void drawConics(GrBatchTarget* batchTarget, - const GrGeometryProcessor* hairConicProcessor, - const GrPipeline* pipeline, - const GrVertexBuffer* vertexBuffer, - int firstVertex, - int conicCount, - int quadCount) { - GrDrawTarget::DrawInfo info; - info.setVertexBuffer(vertexBuffer); - info.setIndexBuffer(fQuadsIndexBuffer); - info.setPrimitiveType(kTriangles_GrPrimitiveType); - info.setStartIndex(0); - - int conics = 0; - while (conics < conicCount) { - int n = SkTMin(conicCount - conics, kQuadsNumInIdxBuffer); - - info.setStartVertex(kQuadNumVertices*(quadCount + conics) + firstVertex); - info.setVertexCount(kQuadNumVertices*n); - info.setIndexCount(kIdxsPerQuad*n); - batchTarget->draw(info); - - conics += n; - } - } - - struct BatchTracker { - GrColor fColor; - uint8_t fCoverage; - SkRect fDevBounds; - bool fUsesLocalCoords; - bool fColorIgnored; - bool fCoverageIgnored; - }; - - GrBatchOpt fBatchOpt; - BatchTracker fBatch; - SkSTArray<1, Geometry, true> fGeoData; - const GrIndexBuffer* fLinesIndexBuffer; - const GrIndexBuffer* fQuadsIndexBuffer; -}; - bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, GrPipelineBuilder* pipelineBuilder, GrColor color, const SkMatrix& viewMatrix, const SkPath& path, const SkStrokeRec& stroke, - bool) { + bool antiAlias) { SkScalar hairlineCoverage; uint8_t newCoverage = 0xff; if (IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) { @@ -1146,22 +816,163 @@ bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, SkIRect devClipBounds; target->getClip()->getConservativeBounds(pipelineBuilder->getRenderTarget(), &devClipBounds); - // This outset was determined experimentally by running skps and gms. It probably could be a - // bit tighter - SkRect devRect = path.getBounds(); - devRect.outset(7, 7); - viewMatrix.mapRect(&devRect); + 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, viewMatrix, devClipBounds, + &lines, &quads, &conics, &qSubdivs, &cWeights); + lineCnt = lines.count() / 2; + conicCnt = conics.count() / 3; - AAHairlineBatch::Geometry geometry; - geometry.fColor = color; - geometry.fCoverage = newCoverage; - geometry.fViewMatrix = viewMatrix; - geometry.fPath = path; - SkDEBUGCODE(geometry.fDevBounds = devRect;) - geometry.fDevClipBounds = devClipBounds; + // createGeom transforms the geometry to device space when the matrix does not have + // perspective. + SkMatrix vm = viewMatrix; + SkMatrix invert = SkMatrix::I(); + if (!viewMatrix.hasPerspective()) { + vm = SkMatrix::I(); + if (!viewMatrix.invert(&invert)) { + return false; + } + } - GrBatch* batch = AAHairlineBatch::Create(geometry, fLinesIndexBuffer, fQuadsIndexBuffer); - target->drawBatch(pipelineBuilder, batch, &devRect); + // do lines first + if (lineCnt) { + GrDrawTarget::AutoReleaseGeometry arg; + SkRect devBounds; + + GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder); + uint32_t gpFlags = GrDefaultGeoProcFactory::kPosition_GPType | + GrDefaultGeoProcFactory::kCoverage_GPType; + SkAutoTUnref gp(GrDefaultGeoProcFactory::Create(gpFlags, + color, + vm, + invert, + false, + newCoverage)); + + if (!this->createLineGeom(target, + pipelineBuilder, + viewMatrix, + newCoverage, + gp->getVertexStride(), + &arg, + &devBounds, + path, + lines, + lineCnt)) { + return false; + } + + // Check devBounds + SkASSERT(check_bounds(viewMatrix.hasPerspective() ? viewMatrix : SkMatrix::I(), + devBounds, + arg.vertices(), + kLineSegNumVertices * lineCnt)); + + { + target->setIndexSourceToBuffer(fLinesIndexBuffer); + int lines = 0; + while (lines < lineCnt) { + int n = SkTMin(lineCnt - lines, kLineSegsNumInIdxBuffer); + target->drawIndexed(pipelineBuilder, + gp, + kTriangles_GrPrimitiveType, + kLineSegNumVertices*lines, // startV + 0, // startI + kLineSegNumVertices*n, // vCount + kIdxsPerLineSeg*n, // iCount + &devBounds); + lines += n; + } + } + } + + // then quadratics/conics + if (quadCnt || conicCnt) { + GrDrawTarget::AutoReleaseGeometry arg; + SkRect devBounds; + + if (!this->createBezierGeom(target, + pipelineBuilder, + viewMatrix, + &arg, + &devBounds, + path, + quads, + quadCnt, + conics, + conicCnt, + qSubdivs, + cWeights, + sizeof(BezierVertex))) { + return false; + } + + // Check devBounds + SkASSERT(check_bounds(viewMatrix.hasPerspective() ? viewMatrix : + SkMatrix::I(), + devBounds, + arg.vertices(), + kQuadNumVertices * quadCnt + + kQuadNumVertices * conicCnt)); + + if (quadCnt > 0) { + SkAutoTUnref hairQuadProcessor( + GrQuadEffect::Create(color, + vm, + kHairlineAA_GrProcessorEdgeType, + *target->caps(), + invert, + newCoverage)); + SkASSERT(hairQuadProcessor); + GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder); + target->setIndexSourceToBuffer(fQuadsIndexBuffer); + + int quads = 0; + while (quads < quadCnt) { + int n = SkTMin(quadCnt - quads, kQuadsNumInIdxBuffer); + target->drawIndexed(pipelineBuilder, + hairQuadProcessor, + kTriangles_GrPrimitiveType, + kQuadNumVertices*quads, // startV + 0, // startI + kQuadNumVertices*n, // vCount + kIdxsPerQuad*n, // iCount + &devBounds); + quads += n; + } + } + + if (conicCnt > 0) { + SkAutoTUnref hairConicProcessor( + GrConicEffect::Create(color, vm, kHairlineAA_GrProcessorEdgeType, + *target->caps(), invert, newCoverage)); + SkASSERT(hairConicProcessor); + GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder); + target->setIndexSourceToBuffer(fQuadsIndexBuffer); + + int conics = 0; + while (conics < conicCnt) { + int n = SkTMin(conicCnt - conics, kQuadsNumInIdxBuffer); + target->drawIndexed(pipelineBuilder, + hairConicProcessor, + kTriangles_GrPrimitiveType, + kQuadNumVertices*(quadCnt + conics), // startV + 0, // startI + kQuadNumVertices*n, // vCount + kIdxsPerQuad*n, // iCount + &devBounds); + conics += n; + } + } + } + + target->resetIndexSource(); return true; } diff --git a/src/gpu/GrAAHairLinePathRenderer.h b/src/gpu/GrAAHairLinePathRenderer.h index ea1d8edd65..91c00d78c3 100644 --- a/src/gpu/GrAAHairLinePathRenderer.h +++ b/src/gpu/GrAAHairLinePathRenderer.h @@ -42,6 +42,31 @@ private: const GrIndexBuffer* fLinesIndexBuffer, const GrIndexBuffer* fQuadsIndexBuffer); + bool createLineGeom(GrDrawTarget* target, + GrPipelineBuilder*, + const SkMatrix& viewMatrix, + uint8_t coverage, + size_t vertexStride, + GrDrawTarget::AutoReleaseGeometry* arg, + SkRect* devBounds, + const SkPath& path, + const PtArray& lines, + int lineCnt); + + bool createBezierGeom(GrDrawTarget* target, + GrPipelineBuilder*, + const SkMatrix& viewMatrix, + GrDrawTarget::AutoReleaseGeometry* arg, + SkRect* devBounds, + const SkPath& path, + const PtArray& quads, + int quadCnt, + const PtArray& conics, + int conicCnt, + const IntArray& qSubdivs, + const FloatArray& cWeights, + size_t vertexStride); + const GrIndexBuffer* fLinesIndexBuffer; const GrIndexBuffer* fQuadsIndexBuffer; diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp index 420c9e7c5a..48692ebf5e 100644 --- a/src/gpu/GrAARectRenderer.cpp +++ b/src/gpu/GrAARectRenderer.cpp @@ -208,7 +208,10 @@ private: return false; } - SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); + if (this->usesLocalCoords() != that->usesLocalCoords()) { + return false; + } + // We apply the viewmatrix to the rect points on the cpu. However, if the pipeline uses // local coords then we won't be able to batch. We could actually upload the viewmatrix // using vertex attributes in these cases, but haven't investigated that diff --git a/src/gpu/GrBatch.h b/src/gpu/GrBatch.h index 2f1afee1e4..ceb2c5cc2a 100644 --- a/src/gpu/GrBatch.h +++ b/src/gpu/GrBatch.h @@ -46,7 +46,7 @@ struct GrBatchOpt { class GrBatch : public SkRefCnt { public: SK_DECLARE_INST_COUNT(GrBatch) - GrBatch() : fNumberOfDraws(0) { SkDEBUGCODE(fUsed = false;) } + GrBatch() { SkDEBUGCODE(fUsed = false;) } virtual ~GrBatch() {} virtual const char* name() const = 0; @@ -75,10 +75,6 @@ public: virtual void generateGeometry(GrBatchTarget*, const GrPipeline*) = 0; - // TODO this goes away when batches are everywhere - void setNumberOfDraws(int numberOfDraws) { fNumberOfDraws = numberOfDraws; } - int numberOfDraws() const { return fNumberOfDraws; } - void* operator new(size_t size); void operator delete(void* target); @@ -130,8 +126,6 @@ private: SkDEBUGCODE(bool fUsed;) - int fNumberOfDraws; - typedef SkRefCnt INHERITED; }; diff --git a/src/gpu/GrBatchTarget.cpp b/src/gpu/GrBatchTarget.cpp index 1b68923472..6a3135310a 100644 --- a/src/gpu/GrBatchTarget.cpp +++ b/src/gpu/GrBatchTarget.cpp @@ -32,20 +32,17 @@ void GrBatchTarget::flush() { fFlushBuffer.reset(); }*/ -void GrBatchTarget::flushNext(int n) { - for (; n > 0; n--) { - SkDEBUGCODE(bool verify =) fIter.next(); - SkASSERT(verify); - GrProgramDesc desc; - BufferedFlush* bf = fIter.get(); - const GrPipeline* pipeline = bf->fPipeline; - const GrPrimitiveProcessor* primProc = bf->fPrimitiveProcessor.get(); - fGpu->buildProgramDesc(&desc, *primProc, *pipeline, pipeline->descInfo(), - bf->fBatchTracker); +void GrBatchTarget::flushNext() { + fIter.next(); + GrProgramDesc desc; + BufferedFlush* bf = fIter.get(); + const GrPipeline* pipeline = bf->fPipeline; + const GrPrimitiveProcessor* primProc = bf->fPrimitiveProcessor.get(); + fGpu->buildProgramDesc(&desc, *primProc, *pipeline, pipeline->descInfo(), + bf->fBatchTracker); - GrGpu::DrawArgs args(primProc, pipeline, &desc, &bf->fBatchTracker); - for (int i = 0; i < bf->fDraws.count(); i++) { - fGpu->draw(args, bf->fDraws[i]); - } + GrGpu::DrawArgs args(primProc, pipeline, &desc, &bf->fBatchTracker); + for (int i = 0; i < bf->fDraws.count(); i++) { + fGpu->draw(args, bf->fDraws[i]); } } diff --git a/src/gpu/GrBatchTarget.h b/src/gpu/GrBatchTarget.h index e2249ee7d4..b73907746f 100644 --- a/src/gpu/GrBatchTarget.h +++ b/src/gpu/GrBatchTarget.h @@ -17,9 +17,6 @@ * that render their batch. */ -class GrIndexBufferAllocPool; -class GrVertexBufferAllocPool; - class GrBatchTarget : public SkNoncopyable { public: GrBatchTarget(GrGpu* gpu, @@ -29,13 +26,11 @@ public: , fVertexPool(vpool) , fIndexPool(ipool) , fFlushBuffer(kFlushBufferInitialSizeInBytes) - , fIter(fFlushBuffer) - , fNumberOfDraws(0) {} + , fIter(fFlushBuffer) {} typedef GrDrawTarget::DrawInfo DrawInfo; void initDraw(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline) { GrNEW_APPEND_TO_RECORDER(fFlushBuffer, BufferedFlush, (primProc, pipeline)); - fNumberOfDraws++; } void draw(const GrDrawTarget::DrawInfo& draw) { @@ -44,10 +39,8 @@ public: // TODO this is temporary until batch is everywhere //void flush(); - void resetNumberOfDraws() { fNumberOfDraws = 0; } - int numberOfDraws() const { return fNumberOfDraws; } void preFlush() { fIter = FlushBuffer::Iter(fFlushBuffer); } - void flushNext(int n); + void flushNext(); void postFlush() { SkASSERT(!fIter.next()); fFlushBuffer.reset(); } // TODO This goes away when everything uses batch @@ -56,8 +49,6 @@ public: return &fFlushBuffer.back().fBatchTracker; } - const GrDrawTargetCaps& caps() const { return *fGpu->caps(); } - GrVertexBufferAllocPool* vertexPool() { return fVertexPool; } GrIndexBufferAllocPool* indexPool() { return fIndexPool; } @@ -90,7 +81,6 @@ private: FlushBuffer fFlushBuffer; // TODO this is temporary FlushBuffer::Iter fIter; - int fNumberOfDraws; }; #endif diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index 8805711bb9..a760dcbf6f 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -473,8 +473,7 @@ void GrInOrderDrawBuffer::onFlush() { // TODO temporary hack if (kDrawBatch_Cmd == strip_trace_bit(iter->fType)) { - DrawBatch* db = reinterpret_cast(iter.get()); - fBatchTarget.flushNext(db->fBatch->numberOfDraws()); + fBatchTarget.flushNext(); continue; } @@ -647,9 +646,7 @@ void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() { void GrInOrderDrawBuffer::closeBatch() { if (fDrawBatch) { - fBatchTarget.resetNumberOfDraws(); fDrawBatch->execute(this, fPrevState); - fDrawBatch->fBatch->setNumberOfDraws(fBatchTarget.numberOfDraws()); fDrawBatch = NULL; } }