Revert of Hairline batch (patchset #17 id:360001 of https://codereview.chromium.org...
authorjoshualitt <joshualitt@google.com>
Tue, 3 Feb 2015 16:40:22 +0000 (08:40 -0800)
committerCommit bot <commit-bot@chromium.org>
Tue, 3 Feb 2015 16:40:22 +0000 (08:40 -0800)
Reason for revert:
still a performance regression

Original issue's description:
> Hairline batch
>
> BUG=skia:
>
> Committed: https://skia.googlesource.com/skia/+/6eff8701f027016fbb3147412ec2292dcec2b7f5
>
> Committed: https://skia.googlesource.com/skia/+/658d55cd6121c67488aaf5d0832c9712737f26a5

TBR=bsalomon@google.com,joshualitt@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=skia:

Review URL: https://codereview.chromium.org/882883003

src/gpu/GrAAHairLinePathRenderer.cpp
src/gpu/GrAAHairLinePathRenderer.h
src/gpu/GrAARectRenderer.cpp
src/gpu/GrBatch.h
src/gpu/GrBatchTarget.cpp
src/gpu/GrBatchTarget.h
src/gpu/GrInOrderDrawBuffer.cpp

index 6ecaa2e..ce24cf8 100644 (file)
@@ -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<LineVertex*>(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<BezierVertex*>(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,469 +800,179 @@ 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<SkPoint, true> PtArray;
-    typedef SkTArray<int, true> IntArray;
-    typedef SkTArray<float, true> FloatArray;
-
-    AAHairlineBatch(const Geometry& geometry, const GrIndexBuffer* linesIndexBuffer,
-                    const GrIndexBuffer* quadsIndexBuffer)
-        : fLinesIndexBuffer(linesIndexBuffer)
-        , fQuadsIndexBuffer(quadsIndexBuffer) {
-        SkASSERT(linesIndexBuffer && quadsIndexBuffer);
-        this->initClassID<AAHairlineBatch>();
-        fGeoData.push_back(geometry);
+bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target,
+                                          GrPipelineBuilder* pipelineBuilder,
+                                          GrColor color,
+                                          const SkMatrix& viewMatrix,
+                                          const SkPath& path,
+                                          const SkStrokeRec& stroke,
+                                          bool antiAlias) {
+    SkScalar hairlineCoverage;
+    uint8_t newCoverage = 0xff;
+    if (IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) {
+        newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff);
     }
 
-    bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE {
-        AAHairlineBatch* that = t->cast<AAHairlineBatch>();
-
-        // 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;
-        }
+    SkIRect devClipBounds;
+    target->getClip()->getConservativeBounds(pipelineBuilder->getRenderTarget(), &devClipBounds);
 
-        SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
-        if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
+    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;
+
+    // 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;
         }
-
-        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) {
+    // do lines first
+    if (lineCnt) {
+        GrDrawTarget::AutoReleaseGeometry arg;
+        SkRect devBounds;
+
+        GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder);
         uint32_t gpFlags = GrDefaultGeoProcFactory::kPosition_GPType |
                            GrDefaultGeoProcFactory::kCoverage_GPType;
         SkAutoTUnref<const GrGeometryProcessor> gp(GrDefaultGeoProcFactory::Create(gpFlags,
-                                                                                   args.fColor,
-                                                                                   viewMatrix,
+                                                                                   color,
+                                                                                   vm,
                                                                                    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<LineVertex*>(vertices);
-        for (int i = 0; i < lineCnt; ++i) {
-            add_line(&lines[2*i], toSrc, args.fCoverage, &verts);
+                                                                                   newCoverage));
+
+        if (!this->createLineGeom(target,
+                                  pipelineBuilder,
+                                  viewMatrix,
+                                  newCoverage,
+                                  gp->getVertexStride(),
+                                  &arg,
+                                  &devBounds,
+                                  path,
+                                  lines,
+                                  lineCnt)) {
+            return false;
         }
 
         // Check devBounds
         SkASSERT(check_bounds<LineVertex>(viewMatrix.hasPerspective() ? viewMatrix : SkMatrix::I(),
-                                          args.fDevBounds,
-                                          vertices,
+                                          devBounds,
+                                          arg.vertices(),
                                           kLineSegNumVertices * lineCnt));
 
         {
-            GrDrawTarget::DrawInfo info;
-            info.setVertexBuffer(vertexBuffer);
-            info.setIndexBuffer(fLinesIndexBuffer);
-            info.setPrimitiveType(kTriangles_GrPrimitiveType);
-            info.setStartIndex(0);
-
+            target->setIndexSourceToBuffer(fLinesIndexBuffer);
             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);
-
+                target->drawIndexed(pipelineBuilder,
+                                    gp,
+                                    kTriangles_GrPrimitiveType,
+                                    kLineSegNumVertices*lines,     // startV
+                                    0,                             // startI
+                                    kLineSegNumVertices*n,         // vCount
+                                    kIdxsPerLineSeg*n,             // iCount
+                                    &devBounds);
                 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,
+    // then quadratics/conics
+    if (quadCnt || conicCnt) {
+        GrDrawTarget::AutoReleaseGeometry arg;
+        SkRect devBounds;
+
+        if (!this->createBezierGeom(target,
+                                    pipelineBuilder,
+                                    viewMatrix,
+                                    &arg,
+                                    &devBounds,
+                                    path,
                                     quads,
-                                    quadCount,
+                                    quadCnt,
                                     conics,
-                                    conicCount,
+                                    conicCnt,
                                     qSubdivs,
                                     cWeights,
-                                    vertexStride)) {
-            SkDebugf("Couldn't create bezier geometry\n");
-            return;
+                                    sizeof(BezierVertex))) {
+            return false;
         }
 
         // Check devBounds
-        SkASSERT(check_bounds<BezierVertex>(vm,
-                                            args.fDevBounds,
-                                            vertices,
-                                            kQuadNumVertices * quadCount +
-                                            kQuadNumVertices * conicCount));
-
-        if (quadCount > 0) {
+        SkASSERT(check_bounds<BezierVertex>(viewMatrix.hasPerspective() ? viewMatrix :
+                                                                          SkMatrix::I(),
+                                            devBounds,
+                                            arg.vertices(),
+                                            kQuadNumVertices * quadCnt +
+                                            kQuadNumVertices * conicCnt));
+
+        if (quadCnt > 0) {
             SkAutoTUnref<GrGeometryProcessor> hairQuadProcessor(
-                    GrQuadEffect::Create(args.fColor,
+                    GrQuadEffect::Create(color,
                                          vm,
                                          kHairlineAA_GrProcessorEdgeType,
-                                         batchTarget->caps(),
+                                         *target->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);
+                                         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 (conicCount > 0) {
+        if (conicCnt > 0) {
             SkAutoTUnref<GrGeometryProcessor> 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<BezierVertex*>(vertices);
-
-        const SkMatrix* toDevice = NULL;
-        const SkMatrix* toSrc = NULL;
-        SkMatrix ivm;
-
-        if (viewMatrix.hasPerspective()) {
-            if (viewMatrix.invert(&ivm)) {
-                toDevice = &viewMatrix;
-                toSrc = &ivm;
+                    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;
             }
         }
-
-        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) {
-    SkScalar hairlineCoverage;
-    uint8_t newCoverage = 0xff;
-    if (IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) {
-        newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff);
-    }
-
-    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);
-
-    AAHairlineBatch::Geometry geometry;
-    geometry.fColor = color;
-    geometry.fCoverage = newCoverage;
-    geometry.fViewMatrix = viewMatrix;
-    geometry.fPath = path;
-    SkDEBUGCODE(geometry.fDevBounds = devRect;)
-    geometry.fDevClipBounds = devClipBounds;
-
-    GrBatch* batch = AAHairlineBatch::Create(geometry, fLinesIndexBuffer, fQuadsIndexBuffer);
-    target->drawBatch(pipelineBuilder, batch, &devRect);
+    target->resetIndexSource();
 
     return true;
 }
index ea1d8ed..91c00d7 100644 (file)
@@ -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;
 
index 420c9e7..48692eb 100644 (file)
@@ -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
index 2f1afee..ceb2c5c 100644 (file)
@@ -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;
 };
 
index 1b68923..6a31353 100644 (file)
@@ -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]);
     }
 }
index 37f5c9b..b739077 100644 (file)
@@ -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; }
 
@@ -71,7 +62,8 @@ private:
     struct BufferedFlush {
         BufferedFlush(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline)
             : fPrimitiveProcessor(primProc)
-            , fPipeline(pipeline) {}
+            , fPipeline(pipeline)
+            , fDraws(kDrawRecorderInitialSizeInBytes) {}
         typedef GrPendingProgramElement<const GrPrimitiveProcessor> ProgramPrimitiveProcessor;
         ProgramPrimitiveProcessor fPrimitiveProcessor;
         const GrPipeline* fPipeline;
@@ -81,6 +73,7 @@ private:
 
     enum {
         kFlushBufferInitialSizeInBytes = 8 * sizeof(BufferedFlush),
+        kDrawRecorderInitialSizeInBytes = 8 * sizeof(DrawInfo),
     };
 
     typedef GrTRecorder<BufferedFlush, TBufferAlign> FlushBuffer;
@@ -88,7 +81,6 @@ private:
     FlushBuffer fFlushBuffer;
     // TODO this is temporary
     FlushBuffer::Iter fIter;
-    int fNumberOfDraws;
 };
 
 #endif
index 8805711..a760dcb 100644 (file)
@@ -473,8 +473,7 @@ void GrInOrderDrawBuffer::onFlush() {
 
         // TODO temporary hack
         if (kDrawBatch_Cmd == strip_trace_bit(iter->fType)) {
-            DrawBatch* db = reinterpret_cast<DrawBatch*>(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;
     }
 }