| Index: src/gpu/GrAARectRenderer.cpp
 | 
| diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp
 | 
| index d1c377aa532757ec1b392064026cca09787a067a..778205f3bbe5f07b38909bc636c040dfd1dbd14f 100644
 | 
| --- a/src/gpu/GrAARectRenderer.cpp
 | 
| +++ b/src/gpu/GrAARectRenderer.cpp
 | 
| @@ -13,11 +13,10 @@
 | 
|  #include "GrContext.h"
 | 
|  #include "GrDefaultGeoProcFactory.h"
 | 
|  #include "GrGeometryProcessor.h"
 | 
| +#include "GrGpu.h"
 | 
|  #include "GrInvariantOutput.h"
 | 
| -#include "GrResourceKey.h"
 | 
| -#include "GrResourceProvider.h"
 | 
| +#include "GrVertexBuffer.h"
 | 
|  #include "GrTestUtils.h"
 | 
| -#include "GrVertexBuffer.h"
 | 
|  #include "SkColorPriv.h"
 | 
|  #include "gl/GrGLProcessor.h"
 | 
|  #include "gl/GrGLGeometryProcessor.h"
 | 
| @@ -30,6 +29,18 @@
 | 
|      pts->setRectFan(r.fLeft + dx, r.fTop + dy,
 | 
|                      r.fRight - dx, r.fBottom - dy, stride);
 | 
|  }
 | 
| +
 | 
| +static const uint16_t gFillAARectIdx[] = {
 | 
| +    0, 1, 5, 5, 4, 0,
 | 
| +    1, 2, 6, 6, 5, 1,
 | 
| +    2, 3, 7, 7, 6, 2,
 | 
| +    3, 0, 4, 4, 7, 3,
 | 
| +    4, 5, 6, 6, 7, 4,
 | 
| +};
 | 
| +
 | 
| +static const int kIndicesPerAAFillRect = SK_ARRAY_COUNT(gFillAARectIdx);
 | 
| +static const int kVertsPerAAFillRect = 8;
 | 
| +static const int kNumAAFillRectsInIndexBuffer = 256;
 | 
|  
 | 
|  static const GrGeometryProcessor* create_fill_rect_gp(bool tweakAlphaForCoverage,
 | 
|                                                        const SkMatrix& localMatrix) {
 | 
| @@ -46,8 +57,6 @@
 | 
|      return gp;
 | 
|  }
 | 
|  
 | 
| -GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
 | 
| -
 | 
|  class AAFillRectBatch : public GrBatch {
 | 
|  public:
 | 
|      struct Geometry {
 | 
| @@ -57,8 +66,8 @@
 | 
|          SkRect fDevRect;
 | 
|      };
 | 
|  
 | 
| -    static GrBatch* Create(const Geometry& geometry) {
 | 
| -        return SkNEW_ARGS(AAFillRectBatch, (geometry));
 | 
| +    static GrBatch* Create(const Geometry& geometry, const GrIndexBuffer* indexBuffer) {
 | 
| +        return SkNEW_ARGS(AAFillRectBatch, (geometry, indexBuffer));
 | 
|      }
 | 
|  
 | 
|      const char* name() const override { return "AAFillRectBatch"; }
 | 
| @@ -112,23 +121,24 @@
 | 
|          init.fUsesLocalCoords = this->usesLocalCoords();
 | 
|          gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
 | 
|  
 | 
| -        SkAutoTUnref<const GrIndexBuffer> indexBuffer(this->getIndexBuffer(
 | 
| -            batchTarget->resourceProvider()));
 | 
| -
 | 
|          size_t vertexStride = gp->getVertexStride();
 | 
| +
 | 
|          SkASSERT(canTweakAlphaForCoverage ?
 | 
|                   vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
 | 
|                   vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
 | 
| +
 | 
|          int instanceCount = fGeoData.count();
 | 
|          int vertexCount = kVertsPerAAFillRect * instanceCount;
 | 
| +
 | 
|          const GrVertexBuffer* vertexBuffer;
 | 
|          int firstVertex;
 | 
| +
 | 
|          void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
 | 
|                                                                vertexCount,
 | 
|                                                                &vertexBuffer,
 | 
|                                                                &firstVertex);
 | 
|  
 | 
| -        if (!vertices || !indexBuffer) {
 | 
| +        if (!vertices) {
 | 
|              SkDebugf("Could not allocate vertices\n");
 | 
|              return;
 | 
|          }
 | 
| @@ -153,7 +163,7 @@
 | 
|          drawInfo.setIndicesPerInstance(kIndicesPerAAFillRect);
 | 
|          drawInfo.adjustStartVertex(firstVertex);
 | 
|          drawInfo.setVertexBuffer(vertexBuffer);
 | 
| -        drawInfo.setIndexBuffer(indexBuffer);
 | 
| +        drawInfo.setIndexBuffer(fIndexBuffer);
 | 
|  
 | 
|          int maxInstancesPerDraw = kNumAAFillRectsInIndexBuffer;
 | 
|  
 | 
| @@ -172,31 +182,12 @@
 | 
|      SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
 | 
|  
 | 
|  private:
 | 
| -    AAFillRectBatch(const Geometry& geometry) {
 | 
| +    AAFillRectBatch(const Geometry& geometry, const GrIndexBuffer* indexBuffer)
 | 
| +        : fIndexBuffer(indexBuffer) {
 | 
|          this->initClassID<AAFillRectBatch>();
 | 
|          fGeoData.push_back(geometry);
 | 
|  
 | 
|          this->setBounds(geometry.fDevRect);
 | 
| -    }
 | 
| -
 | 
| -    static const int kNumAAFillRectsInIndexBuffer = 256;
 | 
| -    static const int kVertsPerAAFillRect = 8;
 | 
| -    static const int kIndicesPerAAFillRect = 30;
 | 
| -
 | 
| -    const GrIndexBuffer* getIndexBuffer(GrResourceProvider* resourceProvider) {
 | 
| -        GR_DEFINE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
 | 
| -
 | 
| -        static const uint16_t gFillAARectIdx[] = {
 | 
| -            0, 1, 5, 5, 4, 0,
 | 
| -            1, 2, 6, 6, 5, 1,
 | 
| -            2, 3, 7, 7, 6, 2,
 | 
| -            3, 0, 4, 4, 7, 3,
 | 
| -            4, 5, 6, 6, 7, 4,
 | 
| -        };
 | 
| -        GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFillAARectIdx) == kIndicesPerAAFillRect);
 | 
| -        return resourceProvider->refOrCreateInstancedIndexBuffer(gFillAARectIdx,
 | 
| -            kIndicesPerAAFillRect, kNumAAFillRectsInIndexBuffer, kVertsPerAAFillRect,
 | 
| -            gAAFillRectIndexBufferKey);
 | 
|      }
 | 
|  
 | 
|      GrColor color() const { return fBatch.fColor; }
 | 
| @@ -333,6 +324,7 @@
 | 
|      };
 | 
|  
 | 
|      BatchTracker fBatch;
 | 
| +    const GrIndexBuffer* fIndexBuffer;
 | 
|      SkSTArray<1, Geometry, true> fGeoData;
 | 
|  };
 | 
|  
 | 
| @@ -344,20 +336,149 @@
 | 
|  };
 | 
|  }
 | 
|  
 | 
| +void GrAARectRenderer::reset() {
 | 
| +    SkSafeSetNull(fAAFillRectIndexBuffer);
 | 
| +    SkSafeSetNull(fAAMiterStrokeRectIndexBuffer);
 | 
| +    SkSafeSetNull(fAABevelStrokeRectIndexBuffer);
 | 
| +}
 | 
| +
 | 
| +static const uint16_t gMiterStrokeAARectIdx[] = {
 | 
| +    0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
 | 
| +    1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
 | 
| +    2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
 | 
| +    3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
 | 
| +
 | 
| +    0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
 | 
| +    1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
 | 
| +    2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
 | 
| +    3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
 | 
| +
 | 
| +    0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
 | 
| +    1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
 | 
| +    2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
 | 
| +    3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
 | 
| +};
 | 
| +
 | 
| +static const int kIndicesPerMiterStrokeRect = SK_ARRAY_COUNT(gMiterStrokeAARectIdx);
 | 
| +static const int kVertsPerMiterStrokeRect = 16;
 | 
| +static const int kNumMiterStrokeRectsInIndexBuffer = 256;
 | 
| +
 | 
| +/**
 | 
| + * As in miter-stroke, index = a + b, and a is the current index, b is the shift
 | 
| + * from the first index. The index layout:
 | 
| + * outer AA line: 0~3, 4~7
 | 
| + * outer edge:    8~11, 12~15
 | 
| + * inner edge:    16~19
 | 
| + * inner AA line: 20~23
 | 
| + * Following comes a bevel-stroke rect and its indices:
 | 
| + *
 | 
| + *           4                                 7
 | 
| + *            *********************************
 | 
| + *          *   ______________________________  *
 | 
| + *         *  / 12                          15 \  *
 | 
| + *        *  /                                  \  *
 | 
| + *     0 *  |8     16_____________________19  11 |  * 3
 | 
| + *       *  |       |                    |       |  *
 | 
| + *       *  |       |  ****************  |       |  *
 | 
| + *       *  |       |  * 20        23 *  |       |  *
 | 
| + *       *  |       |  *              *  |       |  *
 | 
| + *       *  |       |  * 21        22 *  |       |  *
 | 
| + *       *  |       |  ****************  |       |  *
 | 
| + *       *  |       |____________________|       |  *
 | 
| + *     1 *  |9    17                      18   10|  * 2
 | 
| + *        *  \                                  /  *
 | 
| + *         *  \13 __________________________14/  *
 | 
| + *          *                                   *
 | 
| + *           **********************************
 | 
| + *          5                                  6
 | 
| + */
 | 
| +static const uint16_t gBevelStrokeAARectIdx[] = {
 | 
| +    // Draw outer AA, from outer AA line to outer edge, shift is 0.
 | 
| +    0 + 0, 1 + 0, 9 + 0, 9 + 0, 8 + 0, 0 + 0,
 | 
| +    1 + 0, 5 + 0, 13 + 0, 13 + 0, 9 + 0, 1 + 0,
 | 
| +    5 + 0, 6 + 0, 14 + 0, 14 + 0, 13 + 0, 5 + 0,
 | 
| +    6 + 0, 2 + 0, 10 + 0, 10 + 0, 14 + 0, 6 + 0,
 | 
| +    2 + 0, 3 + 0, 11 + 0, 11 + 0, 10 + 0, 2 + 0,
 | 
| +    3 + 0, 7 + 0, 15 + 0, 15 + 0, 11 + 0, 3 + 0,
 | 
| +    7 + 0, 4 + 0, 12 + 0, 12 + 0, 15 + 0, 7 + 0,
 | 
| +    4 + 0, 0 + 0, 8 + 0, 8 + 0, 12 + 0, 4 + 0,
 | 
| +
 | 
| +    // Draw the stroke, from outer edge to inner edge, shift is 8.
 | 
| +    0 + 8, 1 + 8, 9 + 8, 9 + 8, 8 + 8, 0 + 8,
 | 
| +    1 + 8, 5 + 8, 9 + 8,
 | 
| +    5 + 8, 6 + 8, 10 + 8, 10 + 8, 9 + 8, 5 + 8,
 | 
| +    6 + 8, 2 + 8, 10 + 8,
 | 
| +    2 + 8, 3 + 8, 11 + 8, 11 + 8, 10 + 8, 2 + 8,
 | 
| +    3 + 8, 7 + 8, 11 + 8,
 | 
| +    7 + 8, 4 + 8, 8 + 8, 8 + 8, 11 + 8, 7 + 8,
 | 
| +    4 + 8, 0 + 8, 8 + 8,
 | 
| +
 | 
| +    // Draw the inner AA, from inner edge to inner AA line, shift is 16.
 | 
| +    0 + 16, 1 + 16, 5 + 16, 5 + 16, 4 + 16, 0 + 16,
 | 
| +    1 + 16, 2 + 16, 6 + 16, 6 + 16, 5 + 16, 1 + 16,
 | 
| +    2 + 16, 3 + 16, 7 + 16, 7 + 16, 6 + 16, 2 + 16,
 | 
| +    3 + 16, 0 + 16, 4 + 16, 4 + 16, 7 + 16, 3 + 16,
 | 
| +};
 | 
| +
 | 
| +static const int kIndicesPerBevelStrokeRect = SK_ARRAY_COUNT(gBevelStrokeAARectIdx);
 | 
| +static const int kVertsPerBevelStrokeRect = 24;
 | 
| +static const int kNumBevelStrokeRectsInIndexBuffer = 256;
 | 
| +
 | 
| +static int aa_stroke_rect_index_count(bool miterStroke) {
 | 
| +    return miterStroke ? SK_ARRAY_COUNT(gMiterStrokeAARectIdx) :
 | 
| +                         SK_ARRAY_COUNT(gBevelStrokeAARectIdx);
 | 
| +}
 | 
| +
 | 
| +static GrIndexBuffer* setup_aa_stroke_rect_indexbuffer(GrIndexBuffer** aaMiterStrokeRectIndexBuffer,
 | 
| +                                                       GrIndexBuffer** aaBevelStrokeRectIndexBuffer,
 | 
| +                                                       GrGpu* gpu,
 | 
| +                                                       bool miterStroke) {
 | 
| +    if (miterStroke) {
 | 
| +        if (!*aaMiterStrokeRectIndexBuffer) {
 | 
| +            *aaMiterStrokeRectIndexBuffer =
 | 
| +                    gpu->createInstancedIndexBuffer(gMiterStrokeAARectIdx,
 | 
| +                                                    kIndicesPerMiterStrokeRect,
 | 
| +                                                    kNumMiterStrokeRectsInIndexBuffer,
 | 
| +                                                    kVertsPerMiterStrokeRect);
 | 
| +        }
 | 
| +        return *aaMiterStrokeRectIndexBuffer;
 | 
| +    } else {
 | 
| +        if (!*aaBevelStrokeRectIndexBuffer) {
 | 
| +            *aaBevelStrokeRectIndexBuffer =
 | 
| +                    gpu->createInstancedIndexBuffer(gBevelStrokeAARectIdx,
 | 
| +                                                    kIndicesPerBevelStrokeRect,
 | 
| +                                                    kNumBevelStrokeRectsInIndexBuffer,
 | 
| +                                                    kVertsPerBevelStrokeRect);
 | 
| +        }
 | 
| +        return *aaBevelStrokeRectIndexBuffer;
 | 
| +    }
 | 
| +}
 | 
| +
 | 
|  void GrAARectRenderer::geometryFillAARect(GrDrawTarget* target,
 | 
|                                            GrPipelineBuilder* pipelineBuilder,
 | 
|                                            GrColor color,
 | 
|                                            const SkMatrix& viewMatrix,
 | 
|                                            const SkRect& rect,
 | 
|                                            const SkRect& devRect) {
 | 
| +    if (!fAAFillRectIndexBuffer) {
 | 
| +        fAAFillRectIndexBuffer = fGpu->createInstancedIndexBuffer(gFillAARectIdx,
 | 
| +                                                                  kIndicesPerAAFillRect,
 | 
| +                                                                  kNumAAFillRectsInIndexBuffer,
 | 
| +                                                                  kVertsPerAAFillRect);
 | 
| +    }
 | 
| +
 | 
| +    if (!fAAFillRectIndexBuffer) {
 | 
| +        SkDebugf("Unable to create index buffer\n");
 | 
| +        return;
 | 
| +    }
 | 
| +
 | 
|      AAFillRectBatch::Geometry geometry;
 | 
|      geometry.fRect = rect;
 | 
|      geometry.fViewMatrix = viewMatrix;
 | 
|      geometry.fDevRect = devRect;
 | 
|      geometry.fColor = color;
 | 
|  
 | 
| -
 | 
| -    SkAutoTUnref<GrBatch> batch(AAFillRectBatch::Create(geometry));
 | 
| +    SkAutoTUnref<GrBatch> batch(AAFillRectBatch::Create(geometry, fAAFillRectIndexBuffer));
 | 
|      target->drawBatch(pipelineBuilder, batch);
 | 
|  }
 | 
|  
 | 
| @@ -423,9 +544,6 @@
 | 
|                                 devOutsideAssist, devInside, miterStroke);
 | 
|  }
 | 
|  
 | 
| -GR_DECLARE_STATIC_UNIQUE_KEY(gMiterIndexBufferKey);
 | 
| -GR_DECLARE_STATIC_UNIQUE_KEY(gBevelIndexBufferKey);
 | 
| -
 | 
|  class AAStrokeRectBatch : public GrBatch {
 | 
|  public:
 | 
|      // TODO support AA rotated stroke rects by copying around view matrices
 | 
| @@ -437,8 +555,9 @@
 | 
|          bool fMiterStroke;
 | 
|      };
 | 
|  
 | 
| -    static GrBatch* Create(const Geometry& geometry, const SkMatrix& viewMatrix) {
 | 
| -        return SkNEW_ARGS(AAStrokeRectBatch, (geometry, viewMatrix));
 | 
| +    static GrBatch* Create(const Geometry& geometry, const SkMatrix& viewMatrix,
 | 
| +                           const GrIndexBuffer* indexBuffer) {
 | 
| +        return SkNEW_ARGS(AAStrokeRectBatch, (geometry, viewMatrix, indexBuffer));
 | 
|      }
 | 
|  
 | 
|      const char* name() const override { return "AAStrokeRect"; }
 | 
| @@ -484,9 +603,6 @@
 | 
|                                                                         localMatrix));
 | 
|  
 | 
|          batchTarget->initDraw(gp, pipeline);
 | 
| -
 | 
| -        const SkAutoTUnref<const GrIndexBuffer> indexBuffer(
 | 
| -            GetIndexBuffer(batchTarget->resourceProvider(), this->miterStroke()));
 | 
|  
 | 
|          // TODO this is hacky, but the only way we have to initialize the GP is to use the
 | 
|          // GrPipelineInfo struct so we can generate the correct shader.  Once we have GrBatch
 | 
| @@ -503,6 +619,7 @@
 | 
|          SkASSERT(canTweakAlphaForCoverage ?
 | 
|                   vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
 | 
|                   vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
 | 
| +
 | 
|          int innerVertexNum = 4;
 | 
|          int outerVertexNum = this->miterStroke() ? 4 : 8;
 | 
|          int totalVertexNum = (outerVertexNum + innerVertexNum) * 2;
 | 
| @@ -518,7 +635,7 @@
 | 
|                                                                &vertexBuffer,
 | 
|                                                                &firstVertex);
 | 
|  
 | 
| -        if (!vertices || !indexBuffer) {
 | 
| +        if (!vertices) {
 | 
|              SkDebugf("Could not allocate vertices\n");
 | 
|              return;
 | 
|          }
 | 
| @@ -537,19 +654,18 @@
 | 
|                                                 args.fMiterStroke,
 | 
|                                                 canTweakAlphaForCoverage);
 | 
|          }
 | 
| -        int indicesPerInstance = this->miterStroke() ? kMiterIndexCnt : kBevelIndexCnt;
 | 
| +
 | 
|          GrDrawTarget::DrawInfo drawInfo;
 | 
|          drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
 | 
|          drawInfo.setStartVertex(0);
 | 
|          drawInfo.setStartIndex(0);
 | 
|          drawInfo.setVerticesPerInstance(totalVertexNum);
 | 
| -        drawInfo.setIndicesPerInstance(indicesPerInstance);
 | 
| +        drawInfo.setIndicesPerInstance(aa_stroke_rect_index_count(this->miterStroke()));
 | 
|          drawInfo.adjustStartVertex(firstVertex);
 | 
|          drawInfo.setVertexBuffer(vertexBuffer);
 | 
| -        drawInfo.setIndexBuffer(indexBuffer);
 | 
| -
 | 
| -        int maxInstancesPerDraw = this->miterStroke() ? kNumMiterRectsInIndexBuffer :
 | 
| -                                                        kNumBevelRectsInIndexBuffer;
 | 
| +        drawInfo.setIndexBuffer(fIndexBuffer);
 | 
| +
 | 
| +        int maxInstancesPerDraw = kNumBevelStrokeRectsInIndexBuffer;
 | 
|  
 | 
|          while (instanceCount) {
 | 
|              drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
 | 
| @@ -566,7 +682,9 @@
 | 
|      SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
 | 
|  
 | 
|  private:
 | 
| -    AAStrokeRectBatch(const Geometry& geometry, const SkMatrix& viewMatrix)  {
 | 
| +    AAStrokeRectBatch(const Geometry& geometry, const SkMatrix& viewMatrix,
 | 
| +                      const GrIndexBuffer* indexBuffer)
 | 
| +        : fIndexBuffer(indexBuffer) {
 | 
|          this->initClassID<AAStrokeRectBatch>();
 | 
|          fBatch.fViewMatrix = viewMatrix;
 | 
|          fGeoData.push_back(geometry);
 | 
| @@ -575,106 +693,6 @@
 | 
|          // the join for proper bounds
 | 
|          fBounds = geometry.fDevOutside;
 | 
|          fBounds.join(geometry.fDevOutsideAssist);
 | 
| -    }
 | 
| -
 | 
| -
 | 
| -    static const int kMiterIndexCnt = 3 * 24;
 | 
| -    static const int kMiterVertexCnt = 16;
 | 
| -    static const int kNumMiterRectsInIndexBuffer = 256;
 | 
| -
 | 
| -    static const int kBevelIndexCnt = 48 + 36 + 24;
 | 
| -    static const int kBevelVertexCnt = 24;
 | 
| -    static const int kNumBevelRectsInIndexBuffer = 256;
 | 
| -
 | 
| -    static const GrIndexBuffer* GetIndexBuffer(GrResourceProvider* resourceProvider,
 | 
| -                                               bool miterStroke) {
 | 
| -
 | 
| -        if (miterStroke) {
 | 
| -            static const uint16_t gMiterIndices[] = {
 | 
| -                0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
 | 
| -                1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
 | 
| -                2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
 | 
| -                3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
 | 
| -
 | 
| -                0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
 | 
| -                1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
 | 
| -                2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
 | 
| -                3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
 | 
| -
 | 
| -                0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
 | 
| -                1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
 | 
| -                2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
 | 
| -                3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
 | 
| -            };
 | 
| -            GR_STATIC_ASSERT(SK_ARRAY_COUNT(gMiterIndices) == kMiterIndexCnt);
 | 
| -            GR_DEFINE_STATIC_UNIQUE_KEY(gMiterIndexBufferKey);
 | 
| -            return resourceProvider->refOrCreateInstancedIndexBuffer(gMiterIndices,
 | 
| -                kMiterIndexCnt, kNumMiterRectsInIndexBuffer, kMiterVertexCnt,
 | 
| -                gMiterIndexBufferKey);
 | 
| -        } else {
 | 
| -            /**
 | 
| -             * As in miter-stroke, index = a + b, and a is the current index, b is the shift
 | 
| -             * from the first index. The index layout:
 | 
| -             * outer AA line: 0~3, 4~7
 | 
| -             * outer edge:    8~11, 12~15
 | 
| -             * inner edge:    16~19
 | 
| -             * inner AA line: 20~23
 | 
| -             * Following comes a bevel-stroke rect and its indices:
 | 
| -             *
 | 
| -             *           4                                 7
 | 
| -             *            *********************************
 | 
| -             *          *   ______________________________  *
 | 
| -             *         *  / 12                          15 \  *
 | 
| -             *        *  /                                  \  *
 | 
| -             *     0 *  |8     16_____________________19  11 |  * 3
 | 
| -             *       *  |       |                    |       |  *
 | 
| -             *       *  |       |  ****************  |       |  *
 | 
| -             *       *  |       |  * 20        23 *  |       |  *
 | 
| -             *       *  |       |  *              *  |       |  *
 | 
| -             *       *  |       |  * 21        22 *  |       |  *
 | 
| -             *       *  |       |  ****************  |       |  *
 | 
| -             *       *  |       |____________________|       |  *
 | 
| -             *     1 *  |9    17                      18   10|  * 2
 | 
| -             *        *  \                                  /  *
 | 
| -             *         *  \13 __________________________14/  *
 | 
| -             *          *                                   *
 | 
| -             *           **********************************
 | 
| -             *          5                                  6
 | 
| -             */
 | 
| -            static const uint16_t gBevelIndices[] = {
 | 
| -                // Draw outer AA, from outer AA line to outer edge, shift is 0.
 | 
| -                0 + 0, 1 + 0,  9 + 0,  9 + 0,  8 + 0, 0 + 0,
 | 
| -                1 + 0, 5 + 0, 13 + 0, 13 + 0,  9 + 0, 1 + 0,
 | 
| -                5 + 0, 6 + 0, 14 + 0, 14 + 0, 13 + 0, 5 + 0,
 | 
| -                6 + 0, 2 + 0, 10 + 0, 10 + 0, 14 + 0, 6 + 0,
 | 
| -                2 + 0, 3 + 0, 11 + 0, 11 + 0, 10 + 0, 2 + 0,
 | 
| -                3 + 0, 7 + 0, 15 + 0, 15 + 0, 11 + 0, 3 + 0,
 | 
| -                7 + 0, 4 + 0, 12 + 0, 12 + 0, 15 + 0, 7 + 0,
 | 
| -                4 + 0, 0 + 0,  8 + 0,  8 + 0, 12 + 0, 4 + 0,
 | 
| -
 | 
| -                // Draw the stroke, from outer edge to inner edge, shift is 8.
 | 
| -                0 + 8, 1 + 8, 9 + 8, 9 + 8, 8 + 8, 0 + 8,
 | 
| -                1 + 8, 5 + 8, 9 + 8,
 | 
| -                5 + 8, 6 + 8, 10 + 8, 10 + 8, 9 + 8, 5 + 8,
 | 
| -                6 + 8, 2 + 8, 10 + 8,
 | 
| -                2 + 8, 3 + 8, 11 + 8, 11 + 8, 10 + 8, 2 + 8,
 | 
| -                3 + 8, 7 + 8, 11 + 8,
 | 
| -                7 + 8, 4 + 8, 8 + 8, 8 + 8, 11 + 8, 7 + 8,
 | 
| -                4 + 8, 0 + 8, 8 + 8,
 | 
| -
 | 
| -                // Draw the inner AA, from inner edge to inner AA line, shift is 16.
 | 
| -                0 + 16, 1 + 16, 5 + 16, 5 + 16, 4 + 16, 0 + 16,
 | 
| -                1 + 16, 2 + 16, 6 + 16, 6 + 16, 5 + 16, 1 + 16,
 | 
| -                2 + 16, 3 + 16, 7 + 16, 7 + 16, 6 + 16, 2 + 16,
 | 
| -                3 + 16, 0 + 16, 4 + 16, 4 + 16, 7 + 16, 3 + 16,
 | 
| -            };
 | 
| -            GR_STATIC_ASSERT(SK_ARRAY_COUNT(gBevelIndices) == kBevelIndexCnt);
 | 
| -
 | 
| -            GR_DEFINE_STATIC_UNIQUE_KEY(gBevelIndexBufferKey);
 | 
| -            return resourceProvider->refOrCreateInstancedIndexBuffer(gBevelIndices,
 | 
| -                kBevelIndexCnt, kNumBevelRectsInIndexBuffer, kBevelVertexCnt,
 | 
| -                gBevelIndexBufferKey);
 | 
| -        }
 | 
|      }
 | 
|  
 | 
|      GrColor color() const { return fBatch.fColor; }
 | 
| @@ -837,6 +855,7 @@
 | 
|      };
 | 
|  
 | 
|      BatchTracker fBatch;
 | 
| +    const GrIndexBuffer* fIndexBuffer;
 | 
|      SkSTArray<1, Geometry, true> fGeoData;
 | 
|  };
 | 
|  
 | 
| @@ -848,6 +867,15 @@
 | 
|                                              const SkRect& devOutsideAssist,
 | 
|                                              const SkRect& devInside,
 | 
|                                              bool miterStroke) {
 | 
| +    GrIndexBuffer* indexBuffer = setup_aa_stroke_rect_indexbuffer(&fAAMiterStrokeRectIndexBuffer,
 | 
| +                                                                  &fAABevelStrokeRectIndexBuffer,
 | 
| +                                                                  fGpu,
 | 
| +                                                                  miterStroke);
 | 
| +    if (!indexBuffer) {
 | 
| +        SkDebugf("Failed to create index buffer!\n");
 | 
| +        return;
 | 
| +    }
 | 
| +
 | 
|      AAStrokeRectBatch::Geometry geometry;
 | 
|      geometry.fColor = color;
 | 
|      geometry.fDevOutside = devOutside;
 | 
| @@ -855,7 +883,7 @@
 | 
|      geometry.fDevInside = devInside;
 | 
|      geometry.fMiterStroke = miterStroke;
 | 
|  
 | 
| -    SkAutoTUnref<GrBatch> batch(AAStrokeRectBatch::Create(geometry, viewMatrix));
 | 
| +    SkAutoTUnref<GrBatch> batch(AAStrokeRectBatch::Create(geometry, viewMatrix, indexBuffer));
 | 
|      target->drawBatch(pipelineBuilder, batch);
 | 
|  }
 | 
|  
 | 
| @@ -891,11 +919,29 @@
 | 
|      geo.fViewMatrix = GrTest::TestMatrix(random);
 | 
|      geo.fRect = GrTest::TestRect(random);
 | 
|      geo.fDevRect = GrTest::TestRect(random);
 | 
| -    return AAFillRectBatch::Create(geo);
 | 
| +
 | 
| +    static GrIndexBuffer* aaFillRectIndexBuffer = NULL;
 | 
| +    if (!aaFillRectIndexBuffer) {
 | 
| +        aaFillRectIndexBuffer =
 | 
| +                context->getGpu()->createInstancedIndexBuffer(gFillAARectIdx,
 | 
| +                                                              kIndicesPerAAFillRect,
 | 
| +                                                              kNumAAFillRectsInIndexBuffer,
 | 
| +                                                              kVertsPerAAFillRect);
 | 
| +    }
 | 
| +
 | 
| +    return AAFillRectBatch::Create(geo, aaFillRectIndexBuffer);
 | 
|  }
 | 
|  
 | 
|  BATCH_TEST_DEFINE(AAStrokeRectBatch) {
 | 
| +    static GrIndexBuffer* aaMiterStrokeRectIndexBuffer = NULL;
 | 
| +    static GrIndexBuffer* aaBevelStrokeRectIndexBuffer = NULL;
 | 
| +
 | 
|      bool miterStroke = random->nextBool();
 | 
| +
 | 
| +    GrIndexBuffer* indexBuffer = setup_aa_stroke_rect_indexbuffer(&aaMiterStrokeRectIndexBuffer,
 | 
| +                                                                  &aaBevelStrokeRectIndexBuffer,
 | 
| +                                                                  context->getGpu(),
 | 
| +                                                                  miterStroke);
 | 
|  
 | 
|      // Create mock stroke rect
 | 
|      SkRect outside = GrTest::TestRect(random);
 | 
| @@ -913,7 +959,7 @@
 | 
|      geo.fDevInside = inside;
 | 
|      geo.fMiterStroke = miterStroke;
 | 
|  
 | 
| -    return AAStrokeRectBatch::Create(geo, GrTest::TestMatrix(random));
 | 
| +    return AAStrokeRectBatch::Create(geo, GrTest::TestMatrix(random), indexBuffer);
 | 
|  }
 | 
|  
 | 
|  #endif
 | 
| 
 |