Move instanced index buffer creation to flush time
authorbsalomon <bsalomon@google.com>
Mon, 4 May 2015 17:36:42 +0000 (10:36 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 4 May 2015 17:36:43 +0000 (10:36 -0700)
Committed: https://skia.googlesource.com/skia/+/ab622c7b8cc8c39f0a594e4392b9e31b7e1ddb26

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

26 files changed:
gm/beziereffects.cpp
gm/convexpolyeffect.cpp
gyp/gpu.gypi
include/core/SkOnce.h
include/gpu/GrContext.h
include/gpu/GrResourceKey.h
include/gpu/GrTextureProvider.h
src/gpu/GrAADistanceFieldPathRenderer.cpp
src/gpu/GrAAHairLinePathRenderer.cpp
src/gpu/GrAAHairLinePathRenderer.h
src/gpu/GrAARectRenderer.cpp
src/gpu/GrAARectRenderer.h
src/gpu/GrAddPathRenderers_default.cpp
src/gpu/GrAtlasTextContext.cpp
src/gpu/GrBatchTarget.h
src/gpu/GrContext.cpp
src/gpu/GrDashLinePathRenderer.cpp
src/gpu/GrGpu.cpp
src/gpu/GrGpu.h
src/gpu/GrInOrderDrawBuffer.cpp
src/gpu/GrOvalRenderer.cpp
src/gpu/GrOvalRenderer.h
src/gpu/GrResourceProvider.cpp [new file with mode: 0644]
src/gpu/GrResourceProvider.h
src/gpu/effects/GrDashingEffect.cpp
src/gpu/effects/GrDashingEffect.h

index 182d71aaf6749c52a7bd8b50cc8bdeb4137bdb36..656842289867710a072b6ae1456d409d0cbd9a93 100644 (file)
@@ -16,6 +16,7 @@
 #include "GrBufferAllocPool.h"
 #include "GrContext.h"
 #include "GrPathUtils.h"
+#include "GrResourceProvider.h"
 #include "GrTest.h"
 #include "GrTestBatch.h"
 #include "SkColorPriv.h"
@@ -66,17 +67,18 @@ private:
     }
 
     void onGenerateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
-        size_t vertexStride = this->geometryProcessor()->getVertexStride();
+        SkAutoTUnref<const GrIndexBuffer> indexBuffer(
+            batchTarget->resourceProvider()->refQuadIndexBuffer());
 
+        size_t vertexStride = this->geometryProcessor()->getVertexStride();
         const GrVertexBuffer* vertexBuffer;
         int firstVertex;
-
         void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
                                                               kVertsPerCubic,
                                                               &vertexBuffer,
                                                               &firstVertex);
 
-        if (!vertices || !batchTarget->quadIndexBuffer()) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate buffers\n");
             return;
         }
@@ -100,7 +102,7 @@ private:
         drawInfo.setVertexCount(kVertsPerCubic);
         drawInfo.setStartIndex(0);
         drawInfo.setIndexCount(kIndicesPerCubic);
-        drawInfo.setIndexBuffer(batchTarget->quadIndexBuffer());
+        drawInfo.setIndexBuffer(indexBuffer);
         batchTarget->draw(drawInfo);
     }
 
@@ -473,8 +475,10 @@ private:
     }
 
     void onGenerateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
-        size_t vertexStride = this->geometryProcessor()->getVertexStride();
+        SkAutoTUnref<const GrIndexBuffer> indexBuffer(
+            batchTarget->resourceProvider()->refQuadIndexBuffer());
 
+        size_t vertexStride = this->geometryProcessor()->getVertexStride();
         const GrVertexBuffer* vertexBuffer;
         int firstVertex;
 
@@ -483,7 +487,7 @@ private:
                                                               &vertexBuffer,
                                                               &firstVertex);
 
-        if (!vertices || !batchTarget->quadIndexBuffer()) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate buffers\n");
             return;
         }
@@ -505,7 +509,7 @@ private:
         drawInfo.setVertexCount(kVertsPerCubic);
         drawInfo.setStartIndex(0);
         drawInfo.setIndexCount(kIndicesPerCubic);
-        drawInfo.setIndexBuffer(batchTarget->quadIndexBuffer());
+        drawInfo.setIndexBuffer(indexBuffer);
         batchTarget->draw(drawInfo);
     }
 
index 07d5fc2112f15a6bcf0f6d945f00ee0e865d3a9e..60b73c571d97a067d5b566d2ed0b88570dd65212 100644 (file)
@@ -17,6 +17,7 @@
 #include "GrContext.h"
 #include "GrDefaultGeoProcFactory.h"
 #include "GrPathUtils.h"
+#include "GrResourceProvider.h"
 #include "GrTest.h"
 #include "GrTestBatch.h"
 #include "SkColorPriv.h"
@@ -52,8 +53,10 @@ private:
     }
 
     void onGenerateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
-        size_t vertexStride = this->geometryProcessor()->getVertexStride();
+        SkAutoTUnref<const GrIndexBuffer> indexBuffer(
+            batchTarget->resourceProvider()->refQuadIndexBuffer());
 
+        size_t vertexStride = this->geometryProcessor()->getVertexStride();
         const GrVertexBuffer* vertexBuffer;
         int firstVertex;
 
@@ -62,7 +65,7 @@ private:
                                                               &vertexBuffer,
                                                               &firstVertex);
 
-        if (!vertices || !batchTarget->quadIndexBuffer()) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate buffers\n");
             return;
         }
@@ -82,7 +85,7 @@ private:
         drawInfo.setVertexCount(kVertsPerCubic);
         drawInfo.setStartIndex(0);
         drawInfo.setIndexCount(kIndicesPerCubic);
-        drawInfo.setIndexBuffer(batchTarget->quadIndexBuffer());
+        drawInfo.setIndexBuffer(indexBuffer);
         batchTarget->draw(drawInfo);
     }
 
index 4d2549e2fd46b6833ab8ca1d84b8bd219adeb5ae..3944a0355e636748b54264bd950a6c7dad87ea44 100644 (file)
       '<(skia_src_path)/gpu/GrReducedClip.h',
       '<(skia_src_path)/gpu/GrResourceCache.cpp',
       '<(skia_src_path)/gpu/GrResourceCache.h',
+      '<(skia_src_path)/gpu/GrResourceProvider.cpp',
+      '<(skia_src_path)/gpu/GrResourceProvider.h',
       '<(skia_src_path)/gpu/GrStencil.cpp',
       '<(skia_src_path)/gpu/GrStencil.h',
       '<(skia_src_path)/gpu/GrStencilAndCoverPathRenderer.cpp',
index a4188d08f061827395d4cb282a29a414bb361509..c7a87f77a054d314fc8f7f72babad56faaf219db 100644 (file)
@@ -30,7 +30,7 @@
 #include "SkAtomics.h"
 #include "SkSpinlock.h"
 
-// This must be used in a global scope, not in fuction scope or as a class member.
+// This must be used in a global scope, not in function scope or as a class member.
 #define SK_DECLARE_STATIC_ONCE(name) namespace {} static SkOnceFlag name
 
 class SkOnceFlag;
index dc824d51d5891a7116e290122ebc6a9a9b235514..8bdc9f5b2d99fcf87964345723901559d51bd422 100644 (file)
@@ -539,7 +539,6 @@ public:
     GrLayerCache* getLayerCache() { return fLayerCache.get(); }
     GrTextBlobCache* getTextBlobCache() { return fTextBlobCache; }
     GrDrawTarget* getTextTarget();
-    const GrIndexBuffer* getQuadIndexBuffer() const;
     GrAARectRenderer* getAARectRenderer() { return fAARectRenderer; }
     GrResourceProvider* resourceProvider() { return fResourceProvider; }
     const GrResourceProvider* resourceProvider() const { return fResourceProvider; }
index aecdc70c0bdcc1b113a1454c018d39fef194aa57..50a71459290574dd107262274aa96dbdcd1db392 100644 (file)
@@ -10,6 +10,7 @@
 #define GrResourceKey_DEFINED
 
 #include "GrTypes.h"
+#include "SkOnce.h"
 #include "SkTemplates.h"
 
 uint32_t GrResourceKeyHash(const uint32_t* data, size_t size);
@@ -266,6 +267,24 @@ public:
     };
 };
 
+/**
+ * It is common to need a frequently reused GrUniqueKey where the only requirement is that the key
+ * is unique. These macros create such a key in a thread safe manner so the key can be truly global
+ * and only constructed once.
+ */
+
+/** Place outside of function/class definitions. */
+#define GR_DECLARE_STATIC_UNIQUE_KEY(name) SK_DECLARE_STATIC_ONCE(name##_once)
+
+/** Place inside function where the key is used. */
+#define GR_DEFINE_STATIC_UNIQUE_KEY(name)                           \
+    static GrUniqueKey name;                                        \
+    SkOnce(&name##_once, gr_init_static_unique_key_once, &name)
+
+static inline void gr_init_static_unique_key_once(GrUniqueKey* key) {
+    GrUniqueKey::Builder builder(key, GrUniqueKey::GenerateDomain(), 0);
+}
+
 // The cache listens for these messages to purge junk resources proactively.
 class GrUniqueKeyInvalidatedMessage {
 public:
index 3e29dabd47526404647ed0de339f0569567e2259..3f8c760f9b8c3b29343b8dba324143d1d04942da 100644 (file)
@@ -154,6 +154,12 @@ protected:
         fGpu = NULL;
     }
 
+    GrResourceCache* cache() { return fCache; }
+    const GrResourceCache* cache() const { return fCache; }
+
+    GrGpu* gpu() { return fGpu; }
+    const GrGpu* gpu() const { return fGpu; }
+
 private:
     bool isAbandoned() const {
         SkASSERT(SkToBool(fGpu) == SkToBool(fCache));
index 669ec09d97ae02ab629204199a5f22fc38500390..ca8c52fa348289ad62ad95f0d530c46857f55db0 100755 (executable)
@@ -15,6 +15,7 @@
 #include "GrPipelineBuilder.h"
 #include "GrSurfacePriv.h"
 #include "GrSWMaskHelper.h"
+#include "GrResourceProvider.h"
 #include "GrTexturePriv.h"
 #include "GrVertexBuffer.h"
 #include "effects/GrDistanceFieldGeoProc.h"
@@ -194,13 +195,17 @@ public:
 
         this->initDraw(batchTarget, dfProcessor, pipeline);
 
+        static const int kVertsPerQuad = 4;
+        static const int kIndicesPerQuad = 6;
+
+        SkAutoTUnref<const GrIndexBuffer> indexBuffer(
+            batchTarget->resourceProvider()->refQuadIndexBuffer());
+
         // allocate vertices
         size_t vertexStride = dfProcessor->getVertexStride();
         SkASSERT(vertexStride == 2 * sizeof(SkPoint));
-
-        int vertexCount = GrBatchTarget::kVertsPerRect * instanceCount;
-
         const GrVertexBuffer* vertexBuffer;
+        int vertexCount = kVertsPerQuad * instanceCount;
         int firstVertex;
 
         void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
@@ -208,24 +213,23 @@ public:
                                                               &vertexBuffer,
                                                               &firstVertex);
 
-        if (!vertices) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
         }
 
         // We may have to flush while uploading path data to the atlas, so we set up the draw here
-        const GrIndexBuffer* quadIndexBuffer = batchTarget->quadIndexBuffer();
-        int maxInstancesPerDraw = quadIndexBuffer->maxQuads();
+        int maxInstancesPerDraw = indexBuffer->maxQuads();
 
         GrDrawTarget::DrawInfo drawInfo;
         drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
         drawInfo.setStartVertex(0);
         drawInfo.setStartIndex(0);
-        drawInfo.setVerticesPerInstance(GrBatchTarget::kVertsPerRect);
-        drawInfo.setIndicesPerInstance(GrBatchTarget::kIndicesPerRect);
+        drawInfo.setVerticesPerInstance(kVertsPerQuad);
+        drawInfo.setIndicesPerInstance(kIndicesPerQuad);
         drawInfo.adjustStartVertex(firstVertex);
         drawInfo.setVertexBuffer(vertexBuffer);
-        drawInfo.setIndexBuffer(quadIndexBuffer);
+        drawInfo.setIndexBuffer(indexBuffer);
 
         int instancesToFlush = 0;
         for (int i = 0; i < instanceCount; i++) {
@@ -280,7 +284,7 @@ public:
 
             // Now set vertices
             intptr_t offset = reinterpret_cast<intptr_t>(vertices);
-            offset += i * GrBatchTarget::kVertsPerRect * vertexStride;
+            offset += i * kVertsPerQuad * vertexStride;
             SkPoint* positions = reinterpret_cast<SkPoint*>(offset);
             this->drawPath(batchTarget,
                            atlas,
index ad6550072d796609526880b4829f986509f658f5..f046af871f5ef1dab82218130e02defc63480e67 100644 (file)
 #include "GrContext.h"
 #include "GrDefaultGeoProcFactory.h"
 #include "GrDrawTargetCaps.h"
-#include "GrGpu.h"
 #include "GrIndexBuffer.h"
 #include "GrPathUtils.h"
 #include "GrPipelineBuilder.h"
 #include "GrProcessor.h"
+#include "GrResourceProvider.h"
 #include "GrVertexBuffer.h"
 #include "SkGeometry.h"
 #include "SkStroke.h"
@@ -26,6 +26,8 @@
 
 #include "effects/GrBezierEffect.h"
 
+#define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true>
+
 // quadratics are rendered as 5-sided polys in order to bound the
 // AA stroke around the center-curve. See comments in push_quad_index_buffer and
 // bloat_quad. Quadratics and conics share an index buffer
@@ -61,6 +63,14 @@ static const uint16_t kQuadIdxBufPattern[] = {
 static const int kIdxsPerQuad = SK_ARRAY_COUNT(kQuadIdxBufPattern);
 static const int kQuadNumVertices = 5;
 static const int kQuadsNumInIdxBuffer = 256;
+GR_DECLARE_STATIC_UNIQUE_KEY(gQuadsIndexBufferKey);
+
+static const GrIndexBuffer* ref_quads_index_buffer(GrResourceProvider* resourceProvider) {
+    GR_DEFINE_STATIC_UNIQUE_KEY(gQuadsIndexBufferKey);
+    return resourceProvider->refOrCreateInstancedIndexBuffer(
+        kQuadIdxBufPattern, kIdxsPerQuad, kQuadsNumInIdxBuffer, kQuadNumVertices,
+        gQuadsIndexBufferKey);
+}
 
 
 // Each line segment is rendered as two quads and two triangles.
@@ -87,43 +97,17 @@ static const int kIdxsPerLineSeg = SK_ARRAY_COUNT(kLineSegIdxBufPattern);
 static const int kLineSegNumVertices = 6;
 static const int kLineSegsNumInIdxBuffer = 256;
 
-GrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) {
-    GrGpu* gpu = context->getGpu();
-    GrIndexBuffer* qIdxBuf = gpu->createInstancedIndexBuffer(kQuadIdxBufPattern,
-                                                             kIdxsPerQuad,
-                                                             kQuadsNumInIdxBuffer,
-                                                             kQuadNumVertices);
-    SkAutoTUnref<GrIndexBuffer> qIdxBuffer(qIdxBuf);
-    GrIndexBuffer* lIdxBuf = gpu->createInstancedIndexBuffer(kLineSegIdxBufPattern,
-                                                             kIdxsPerLineSeg,
-                                                             kLineSegsNumInIdxBuffer,
-                                                             kLineSegNumVertices);
-    SkAutoTUnref<GrIndexBuffer> lIdxBuffer(lIdxBuf);
-    return SkNEW_ARGS(GrAAHairLinePathRenderer,
-                      (context, lIdxBuf, qIdxBuf));
-}
+GR_DECLARE_STATIC_UNIQUE_KEY(gLinesIndexBufferKey);
 
-GrAAHairLinePathRenderer::GrAAHairLinePathRenderer(
-                                        const GrContext* context,
-                                        const GrIndexBuffer* linesIndexBuffer,
-                                        const GrIndexBuffer* quadsIndexBuffer) {
-    fLinesIndexBuffer = linesIndexBuffer;
-    linesIndexBuffer->ref();
-    fQuadsIndexBuffer = quadsIndexBuffer;
-    quadsIndexBuffer->ref();
+static const GrIndexBuffer* ref_lines_index_buffer(GrResourceProvider* resourceProvider) {
+    GR_DEFINE_STATIC_UNIQUE_KEY(gLinesIndexBufferKey);
+    return resourceProvider->refOrCreateInstancedIndexBuffer(
+        kLineSegIdxBufPattern, kIdxsPerLineSeg,  kLineSegsNumInIdxBuffer, kLineSegNumVertices,
+        gLinesIndexBufferKey);
 }
 
-GrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() {
-    fLinesIndexBuffer->unref();
-    fQuadsIndexBuffer->unref();
-}
-
-namespace {
-
-#define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true>
-
 // Takes 178th time of logf on Z600 / VC2010
-int get_float_exp(float x) {
+static int get_float_exp(float x) {
     GR_STATIC_ASSERT(sizeof(int) == sizeof(float));
 #ifdef SK_DEBUG
     static bool tested;
@@ -151,7 +135,7 @@ int get_float_exp(float x) {
 // found along the curve segment it will return 1 and
 // dst[0] is the original conic. If it returns 2 the dst[0]
 // and dst[1] are the two new conics.
-int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
+static int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
     SkScalar t = SkFindQuadMaxCurvature(src);
     if (t == 0) {
         if (dst) {
@@ -171,7 +155,7 @@ int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
 // Calls split_conic on the entire conic and then once more on each subsection.
 // Most cases will result in either 1 conic (chop point is not within t range)
 // or 3 points (split once and then one subsection is split again).
-int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
+static int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
     SkConic dstTemp[2];
     int conicCnt = split_conic(src, dstTemp, weight);
     if (2 == conicCnt) {
@@ -186,7 +170,7 @@ int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
 // returns 0 if quad/conic is degen or close to it
 // in this case approx the path with lines
 // otherwise returns 1
-int is_degen_quad_or_conic(const SkPoint p[3], SkScalar* dsqd) {
+static int is_degen_quad_or_conic(const SkPoint p[3], SkScalar* dsqd) {
     static const SkScalar gDegenerateToLineTol = SK_Scalar1;
     static const SkScalar gDegenerateToLineTolSqd =
         SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol);
@@ -207,14 +191,14 @@ int is_degen_quad_or_conic(const SkPoint p[3], SkScalar* dsqd) {
     return 0;
 }
 
-int is_degen_quad_or_conic(const SkPoint p[3]) {
+static int is_degen_quad_or_conic(const SkPoint p[3]) {
     SkScalar dsqd;
     return is_degen_quad_or_conic(p, &dsqd);
 }
 
 // we subdivide the quads to avoid huge overfill
 // if it returns -1 then should be drawn as lines
-int num_quad_subdivs(const SkPoint p[3]) {
+static int num_quad_subdivs(const SkPoint p[3]) {
     SkScalar dsqd;
     if (is_degen_quad_or_conic(p, &dsqd)) {
         return -1;
@@ -250,14 +234,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) {
+static 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) {
     SkPath::Iter iter(path, false);
 
     int totalQuadCount = 0;
@@ -441,9 +425,9 @@ struct BezierVertex {
 
 GR_STATIC_ASSERT(sizeof(BezierVertex) == 3 * sizeof(SkPoint));
 
-void intersect_lines(const SkPoint& ptA, const SkVector& normA,
-                     const SkPoint& ptB, const SkVector& normB,
-                     SkPoint* result) {
+static void intersect_lines(const SkPoint& ptA, const SkVector& normA,
+                            const SkPoint& ptB, const SkVector& normB,
+                            SkPoint* result) {
 
     SkScalar lineAW = -normA.dot(ptA);
     SkScalar lineBW = -normB.dot(ptB);
@@ -459,14 +443,14 @@ void intersect_lines(const SkPoint& ptA, const SkVector& normA,
     result->fY = SkScalarMul(result->fY, wInv);
 }
 
-void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kQuadNumVertices]) {
+static void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kQuadNumVertices]) {
     // this should be in the src space, not dev coords, when we have perspective
     GrPathUtils::QuadUVMatrix DevToUV(qpts);
     DevToUV.apply<kQuadNumVertices, sizeof(BezierVertex), sizeof(SkPoint)>(verts);
 }
 
-void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice,
-                const SkMatrix* toSrc, BezierVertex verts[kQuadNumVertices]) {
+static void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice,
+                       const SkMatrix* toSrc, BezierVertex verts[kQuadNumVertices]) {
     SkASSERT(!toDevice == !toSrc);
     // original quad is specified by tri a,b,c
     SkPoint a = qpts[0];
@@ -544,8 +528,8 @@ void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice,
 // f(x, y, w) = f(P) = K^2 - LM
 // K = dot(k, P), L = dot(l, P), M = dot(m, P)
 // k, l, m are calculated in function GrPathUtils::getConicKLM
-void set_conic_coeffs(const SkPoint p[3], BezierVertex verts[kQuadNumVertices],
-                      const SkScalar weight) {
+static void set_conic_coeffs(const SkPoint p[3], BezierVertex verts[kQuadNumVertices],
+                             const SkScalar weight) {
     SkScalar klm[9];
 
     GrPathUtils::getConicKLM(p, weight, klm);
@@ -558,21 +542,21 @@ void set_conic_coeffs(const SkPoint p[3], BezierVertex verts[kQuadNumVertices],
     }
 }
 
-void add_conics(const SkPoint p[3],
-                const SkScalar weight,
-                const SkMatrix* toDevice,
-                const SkMatrix* toSrc,
-                BezierVertex** vert) {
+static void add_conics(const SkPoint p[3],
+                       const SkScalar weight,
+                       const SkMatrix* toDevice,
+                       const SkMatrix* toSrc,
+                       BezierVertex** vert) {
     bloat_quad(p, toDevice, toSrc, *vert);
     set_conic_coeffs(p, *vert, weight);
     *vert += kQuadNumVertices;
 }
 
-void add_quads(const SkPoint p[3],
-               int subdiv,
-               const SkMatrix* toDevice,
-               const SkMatrix* toSrc,
-               BezierVertex** vert) {
+static void add_quads(const SkPoint p[3],
+                      int subdiv,
+                      const SkMatrix* toDevice,
+                      const SkMatrix* toSrc,
+                      BezierVertex** vert) {
     SkASSERT(subdiv >= 0);
     if (subdiv) {
         SkPoint newP[5];
@@ -586,10 +570,10 @@ void add_quads(const SkPoint p[3],
     }
 }
 
-void add_line(const SkPoint p[2],
-              const SkMatrix* toSrc,
-              uint8_t coverage,
-              LineVertex** vert) {
+static void add_line(const SkPoint p[2],
+                     const SkMatrix* toSrc,
+                     uint8_t coverage,
+                     LineVertex** vert) {
     const SkPoint& a = p[0];
     const SkPoint& b = p[1];
 
@@ -631,8 +615,6 @@ void add_line(const SkPoint p[2],
     *vert += kLineSegNumVertices;
 }
 
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target,
@@ -703,11 +685,8 @@ public:
         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));
+    static GrBatch* Create(const Geometry& geometry) {
+        return SkNEW_ARGS(AAHairlineBatch, (geometry));
     }
 
     const char* name() const override { return "AAHairlineBatch"; }
@@ -745,11 +724,7 @@ private:
     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);
+    AAHairlineBatch(const Geometry& geometry) {
         this->initClassID<AAHairlineBatch>();
         fGeoData.push_back(geometry);
 
@@ -808,8 +783,6 @@ private:
 
     BatchTracker fBatch;
     SkSTArray<1, Geometry, true> fGeoData;
-    const GrIndexBuffer* fLinesIndexBuffer;
-    const GrIndexBuffer* fQuadsIndexBuffer;
 };
 
 void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) {
@@ -880,6 +853,8 @@ void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel
 
     // do lines first
     if (lineCount) {
+        SkAutoTUnref<const GrIndexBuffer> linesIndexBuffer(
+            ref_lines_index_buffer(batchTarget->resourceProvider()));
         batchTarget->initDraw(lineGP, pipeline);
 
         // TODO remove this when batch is everywhere
@@ -900,7 +875,7 @@ void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel
                                                               &vertexBuffer,
                                                               &firstVertex);
 
-        if (!vertices) {
+        if (!vertices || !linesIndexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
         }
@@ -915,7 +890,7 @@ void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel
         {
             GrDrawTarget::DrawInfo info;
             info.setVertexBuffer(vertexBuffer);
-            info.setIndexBuffer(fLinesIndexBuffer);
+            info.setIndexBuffer(linesIndexBuffer);
             info.setPrimitiveType(kTriangles_GrPrimitiveType);
             info.setStartIndex(0);
 
@@ -937,6 +912,9 @@ void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel
         const GrVertexBuffer* vertexBuffer;
         int firstVertex;
 
+        SkAutoTUnref<const GrIndexBuffer> quadsIndexBuffer(
+            ref_quads_index_buffer(batchTarget->resourceProvider()));
+
         size_t vertexStride = sizeof(BezierVertex);
         int vertexCount = kQuadNumVertices * quadCount + kQuadNumVertices * conicCount;
         void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
@@ -944,7 +922,7 @@ void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel
                                                               &vertexBuffer,
                                                               &firstVertex);
 
-        if (!vertices) {
+        if (!vertices || !quadsIndexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
         }
@@ -977,7 +955,7 @@ void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel
             {
                GrDrawTarget::DrawInfo info;
                info.setVertexBuffer(vertexBuffer);
-               info.setIndexBuffer(fQuadsIndexBuffer);
+               info.setIndexBuffer(quadsIndexBuffer);
                info.setPrimitiveType(kTriangles_GrPrimitiveType);
                info.setStartIndex(0);
 
@@ -1009,7 +987,7 @@ void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel
             {
                 GrDrawTarget::DrawInfo info;
                 info.setVertexBuffer(vertexBuffer);
-                info.setIndexBuffer(fQuadsIndexBuffer);
+                info.setIndexBuffer(quadsIndexBuffer);
                 info.setPrimitiveType(kTriangles_GrPrimitiveType);
                 info.setStartIndex(0);
 
@@ -1033,9 +1011,7 @@ static GrBatch* create_hairline_batch(GrColor color,
                                       const SkMatrix& viewMatrix,
                                       const SkPath& path,
                                       const GrStrokeInfo& stroke,
-                                      const SkIRect& devClipBounds,
-                                      const GrIndexBuffer* linesIndexBuffer,
-                                      const GrIndexBuffer* quadsIndexBuffer) {
+                                      const SkIRect& devClipBounds) {
     SkScalar hairlineCoverage;
     uint8_t newCoverage = 0xff;
     if (GrPathRenderer::IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) {
@@ -1049,7 +1025,7 @@ static GrBatch* create_hairline_batch(GrColor color,
     geometry.fPath = path;
     geometry.fDevClipBounds = devClipBounds;
 
-    return AAHairlineBatch::Create(geometry, linesIndexBuffer, quadsIndexBuffer);
+    return AAHairlineBatch::Create(geometry);
 }
 
 bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target,
@@ -1059,18 +1035,12 @@ bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target,
                                           const SkPath& path,
                                           const GrStrokeInfo& stroke,
                                           bool) {
-    if (!fLinesIndexBuffer || !fQuadsIndexBuffer) {
-        SkDebugf("unable to allocate indices\n");
-        return false;
-    }
-
     SkIRect devClipBounds;
     pipelineBuilder->clip().getConservativeBounds(pipelineBuilder->getRenderTarget(),
                                                   &devClipBounds);
 
     SkAutoTUnref<GrBatch> batch(create_hairline_batch(color, viewMatrix, path, stroke,
-                                                      devClipBounds, fLinesIndexBuffer,
-                                                      fQuadsIndexBuffer));
+                                                      devClipBounds));
     target->drawBatch(pipelineBuilder, batch);
 
     return true;
@@ -1081,28 +1051,13 @@ bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target,
 #ifdef GR_TEST_UTILS
 
 BATCH_TEST_DEFINE(AAHairlineBatch) {
-    // TODO put these in the cache
-    static GrIndexBuffer* gQuadIndexBuffer;
-    static GrIndexBuffer* gLineIndexBuffer;
-    if (!gQuadIndexBuffer) {
-        gQuadIndexBuffer = context->getGpu()->createInstancedIndexBuffer(kQuadIdxBufPattern,
-                                                                         kIdxsPerQuad,
-                                                                         kQuadsNumInIdxBuffer,
-                                                                         kQuadNumVertices);
-        gLineIndexBuffer = context->getGpu()->createInstancedIndexBuffer(kLineSegIdxBufPattern,
-                                                                         kIdxsPerLineSeg,
-                                                                         kLineSegsNumInIdxBuffer,
-                                                                         kLineSegNumVertices);
-    }
-
     GrColor color = GrRandomColor(random);
     SkMatrix viewMatrix = GrTest::TestMatrix(random);
     GrStrokeInfo stroke(SkStrokeRec::kHairline_InitStyle);
     SkPath path = GrTest::TestPath(random);
     SkIRect devClipBounds;
     devClipBounds.setEmpty();
-    return create_hairline_batch(color, viewMatrix, path, stroke, devClipBounds, gLineIndexBuffer,
-                                 gQuadIndexBuffer);
+    return create_hairline_batch(color, viewMatrix, path, stroke, devClipBounds);
 }
 
 #endif
index 9f8d8aae9e27e09a094bcc5d5e25a7706dde6201..b523493badb966ee3d02b08d924112d2a7a0d85e 100644 (file)
 
 class GrAAHairLinePathRenderer : public GrPathRenderer {
 public:
-    virtual ~GrAAHairLinePathRenderer();
+    static GrPathRenderer* Create()  { return SkNEW(GrAAHairLinePathRenderer); }
 
-    static GrPathRenderer* Create(GrContext* context);
-
-    virtual bool canDrawPath(const GrDrawTarget*,
-                             const GrPipelineBuilder*,
-                             const SkMatrix& viewMatrix,
-                             const SkPath&,
-                             const GrStrokeInfo&,
-                             bool antiAlias) const override;
+    bool canDrawPath(const GrDrawTarget*,
+                     const GrPipelineBuilder*,
+                     const SkMatrix& viewMatrix,
+                     const SkPath&,
+                     const GrStrokeInfo&,
+                     bool antiAlias) const override;
 
     typedef SkTArray<SkPoint, true> PtArray;
     typedef SkTArray<int, true> IntArray;
     typedef SkTArray<float, true> FloatArray;
 
 protected:
-    virtual bool onDrawPath(GrDrawTarget*,
-                            GrPipelineBuilder*,
-                            GrColor,
-                            const SkMatrix& viewMatrix,
-                            const SkPath&,
-                            const GrStrokeInfo&,
-                            bool antiAlias) override;
+    bool onDrawPath(GrDrawTarget*,
+                    GrPipelineBuilder*,
+                    GrColor,
+                    const SkMatrix& viewMatrix,
+                    const SkPath&,
+                    const GrStrokeInfo&,
+                    bool antiAlias) override;
 
 private:
-    GrAAHairLinePathRenderer(const GrContext* context,
-                             const GrIndexBuffer* fLinesIndexBuffer,
-                             const GrIndexBuffer* fQuadsIndexBuffer);
-
-    const GrIndexBuffer*        fLinesIndexBuffer;
-    const GrIndexBuffer*        fQuadsIndexBuffer;
+    GrAAHairLinePathRenderer() {}
 
     typedef GrPathRenderer INHERITED;
 };
index 778205f3bbe5f07b38909bc636c040dfd1dbd14f..d1c377aa532757ec1b392064026cca09787a067a 100644 (file)
 #include "GrContext.h"
 #include "GrDefaultGeoProcFactory.h"
 #include "GrGeometryProcessor.h"
-#include "GrGpu.h"
 #include "GrInvariantOutput.h"
-#include "GrVertexBuffer.h"
+#include "GrResourceKey.h"
+#include "GrResourceProvider.h"
 #include "GrTestUtils.h"
+#include "GrVertexBuffer.h"
 #include "SkColorPriv.h"
 #include "gl/GrGLProcessor.h"
 #include "gl/GrGLGeometryProcessor.h"
@@ -30,18 +31,6 @@ static void set_inset_fan(SkPoint* pts, size_t stride,
                     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) {
     uint32_t flags = GrDefaultGeoProcFactory::kColor_GPType;
@@ -57,6 +46,8 @@ static const GrGeometryProcessor* create_fill_rect_gp(bool tweakAlphaForCoverage
     return gp;
 }
 
+GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
+
 class AAFillRectBatch : public GrBatch {
 public:
     struct Geometry {
@@ -66,8 +57,8 @@ public:
         SkRect fDevRect;
     };
 
-    static GrBatch* Create(const Geometry& geometry, const GrIndexBuffer* indexBuffer) {
-        return SkNEW_ARGS(AAFillRectBatch, (geometry, indexBuffer));
+    static GrBatch* Create(const Geometry& geometry) {
+        return SkNEW_ARGS(AAFillRectBatch, (geometry));
     }
 
     const char* name() const override { return "AAFillRectBatch"; }
@@ -121,24 +112,23 @@ public:
         init.fUsesLocalCoords = this->usesLocalCoords();
         gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
 
-        size_t vertexStride = gp->getVertexStride();
+        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) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
         }
@@ -163,7 +153,7 @@ public:
         drawInfo.setIndicesPerInstance(kIndicesPerAAFillRect);
         drawInfo.adjustStartVertex(firstVertex);
         drawInfo.setVertexBuffer(vertexBuffer);
-        drawInfo.setIndexBuffer(fIndexBuffer);
+        drawInfo.setIndexBuffer(indexBuffer);
 
         int maxInstancesPerDraw = kNumAAFillRectsInIndexBuffer;
 
@@ -182,14 +172,33 @@ public:
     SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
 
 private:
-    AAFillRectBatch(const Geometry& geometry, const GrIndexBuffer* indexBuffer)
-        : fIndexBuffer(indexBuffer) {
+    AAFillRectBatch(const Geometry& geometry) {
         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; }
     bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
     bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCoverage; }
@@ -324,7 +333,6 @@ private:
     };
 
     BatchTracker fBatch;
-    const GrIndexBuffer* fIndexBuffer;
     SkSTArray<1, Geometry, true> fGeoData;
 };
 
@@ -336,149 +344,20 @@ enum CoverageAttribType {
 };
 }
 
-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, fAAFillRectIndexBuffer));
+
+    SkAutoTUnref<GrBatch> batch(AAFillRectBatch::Create(geometry));
     target->drawBatch(pipelineBuilder, batch);
 }
 
@@ -544,6 +423,9 @@ void GrAARectRenderer::strokeAARect(GrDrawTarget* target,
                                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
@@ -555,9 +437,8 @@ public:
         bool fMiterStroke;
     };
 
-    static GrBatch* Create(const Geometry& geometry, const SkMatrix& viewMatrix,
-                           const GrIndexBuffer* indexBuffer) {
-        return SkNEW_ARGS(AAStrokeRectBatch, (geometry, viewMatrix, indexBuffer));
+    static GrBatch* Create(const Geometry& geometry, const SkMatrix& viewMatrix) {
+        return SkNEW_ARGS(AAStrokeRectBatch, (geometry, viewMatrix));
     }
 
     const char* name() const override { return "AAStrokeRect"; }
@@ -604,6 +485,9 @@ public:
 
         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
         // everywhere we can remove this nastiness
@@ -619,7 +503,6 @@ public:
         SkASSERT(canTweakAlphaForCoverage ?
                  vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
                  vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
-
         int innerVertexNum = 4;
         int outerVertexNum = this->miterStroke() ? 4 : 8;
         int totalVertexNum = (outerVertexNum + innerVertexNum) * 2;
@@ -635,7 +518,7 @@ public:
                                                               &vertexBuffer,
                                                               &firstVertex);
 
-        if (!vertices) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
         }
@@ -654,18 +537,19 @@ public:
                                                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(aa_stroke_rect_index_count(this->miterStroke()));
+        drawInfo.setIndicesPerInstance(indicesPerInstance);
         drawInfo.adjustStartVertex(firstVertex);
         drawInfo.setVertexBuffer(vertexBuffer);
-        drawInfo.setIndexBuffer(fIndexBuffer);
+        drawInfo.setIndexBuffer(indexBuffer);
 
-        int maxInstancesPerDraw = kNumBevelStrokeRectsInIndexBuffer;
+        int maxInstancesPerDraw = this->miterStroke() ? kNumMiterRectsInIndexBuffer :
+                                                        kNumBevelRectsInIndexBuffer;
 
         while (instanceCount) {
             drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
@@ -682,9 +566,7 @@ public:
     SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
 
 private:
-    AAStrokeRectBatch(const Geometry& geometry, const SkMatrix& viewMatrix,
-                      const GrIndexBuffer* indexBuffer)
-        : fIndexBuffer(indexBuffer) {
+    AAStrokeRectBatch(const Geometry& geometry, const SkMatrix& viewMatrix)  {
         this->initClassID<AAStrokeRectBatch>();
         fBatch.fViewMatrix = viewMatrix;
         fGeoData.push_back(geometry);
@@ -695,6 +577,106 @@ private:
         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; }
     bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
     bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCoverage; }
@@ -855,7 +837,6 @@ private:
     };
 
     BatchTracker fBatch;
-    const GrIndexBuffer* fIndexBuffer;
     SkSTArray<1, Geometry, true> fGeoData;
 };
 
@@ -867,15 +848,6 @@ void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target,
                                             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;
@@ -883,7 +855,7 @@ void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target,
     geometry.fDevInside = devInside;
     geometry.fMiterStroke = miterStroke;
 
-    SkAutoTUnref<GrBatch> batch(AAStrokeRectBatch::Create(geometry, viewMatrix, indexBuffer));
+    SkAutoTUnref<GrBatch> batch(AAStrokeRectBatch::Create(geometry, viewMatrix));
     target->drawBatch(pipelineBuilder, batch);
 }
 
@@ -919,30 +891,12 @@ BATCH_TEST_DEFINE(AAFillRectBatch) {
     geo.fViewMatrix = GrTest::TestMatrix(random);
     geo.fRect = GrTest::TestRect(random);
     geo.fDevRect = GrTest::TestRect(random);
-
-    static GrIndexBuffer* aaFillRectIndexBuffer = NULL;
-    if (!aaFillRectIndexBuffer) {
-        aaFillRectIndexBuffer =
-                context->getGpu()->createInstancedIndexBuffer(gFillAARectIdx,
-                                                              kIndicesPerAAFillRect,
-                                                              kNumAAFillRectsInIndexBuffer,
-                                                              kVertsPerAAFillRect);
-    }
-
-    return AAFillRectBatch::Create(geo, aaFillRectIndexBuffer);
+    return AAFillRectBatch::Create(geo);
 }
 
 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);
     SkScalar minDim = SkMinScalar(outside.width(), outside.height());
@@ -959,7 +913,7 @@ BATCH_TEST_DEFINE(AAStrokeRectBatch) {
     geo.fDevInside = inside;
     geo.fMiterStroke = miterStroke;
 
-    return AAStrokeRectBatch::Create(geo, GrTest::TestMatrix(random), indexBuffer);
+    return AAStrokeRectBatch::Create(geo, GrTest::TestMatrix(random));
 }
 
 #endif
index 3193f4bc3a4d83d4d9a522be22bfa36e2b56939e..023eadc34fdaa104502ce7d55ecfd8910c8e5f00 100644 (file)
@@ -16,7 +16,6 @@
 
 class GrClip;
 class GrDrawTarget;
-class GrGpu;
 class GrIndexBuffer;
 class GrPipelineBuilder;
 
@@ -27,19 +26,6 @@ class GrAARectRenderer : public SkRefCnt {
 public:
     SK_DECLARE_INST_COUNT(GrAARectRenderer)
 
-    GrAARectRenderer(GrGpu* gpu)
-    : fGpu(gpu)
-    , fAAFillRectIndexBuffer(NULL)
-    , fAAMiterStrokeRectIndexBuffer(NULL)
-    , fAABevelStrokeRectIndexBuffer(NULL) {
-    }
-
-    void reset();
-
-    ~GrAARectRenderer() {
-        this->reset();
-    }
-
     // TODO: potentialy fuse the fill & stroke methods and differentiate
     // between them by passing in stroke (==NULL means fill).
 
@@ -84,11 +70,6 @@ private:
                               const SkRect& devInside,
                               bool miterStroke);
 
-    GrGpu*                      fGpu;
-    GrIndexBuffer*              fAAFillRectIndexBuffer;
-    GrIndexBuffer*              fAAMiterStrokeRectIndexBuffer;
-    GrIndexBuffer*              fAABevelStrokeRectIndexBuffer;
-
     typedef SkRefCnt INHERITED;
 };
 
index 06e98a98cfb3cc81bf0065d310cf6f6aa10f3931..0f675acb4c8c874321fd427b4df8aa79eb46dca9 100644 (file)
@@ -39,7 +39,7 @@ void GrPathRenderer::AddPathRenderers(GrContext* ctx, GrPathRendererChain* chain
     if (GrPathRenderer* pr = GrStencilAndCoverPathRenderer::Create(ctx)) {
         chain->addPathRenderer(pr)->unref();
     }
-    if (GrPathRenderer* pr = GrAAHairLinePathRenderer::Create(ctx)) {
+    if (GrPathRenderer* pr = GrAAHairLinePathRenderer::Create()) {
         chain->addPathRenderer(pr)->unref();
     }
     chain->addPathRenderer(SkNEW(GrAAConvexPathRenderer))->unref();
index 14930fa4a3008860715dc9b5477ab3aa18c316c2..33e4f7ed86237dba488e395e25978f81e3e8e6ca 100644 (file)
@@ -13,6 +13,7 @@
 #include "GrDrawTarget.h"
 #include "GrFontScaler.h"
 #include "GrIndexBuffer.h"
+#include "GrResourceProvider.h"
 #include "GrStrokeInfo.h"
 #include "GrTextBlobCache.h"
 #include "GrTexturePriv.h"
@@ -1514,14 +1515,16 @@ public:
 
         int glyphCount = this->numGlyphs();
         int instanceCount = fInstanceCount;
+        SkAutoTUnref<const GrIndexBuffer> indexBuffer(
+            batchTarget->resourceProvider()->refQuadIndexBuffer());
+
         const GrVertexBuffer* vertexBuffer;
         int firstVertex;
-
         void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
                                                               glyphCount * kVerticesPerGlyph,
                                                               &vertexBuffer,
                                                               &firstVertex);
-        if (!vertices) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
         }
@@ -1529,8 +1532,7 @@ public:
         unsigned char* currVertex = reinterpret_cast<unsigned char*>(vertices);
 
         // setup drawinfo
-        const GrIndexBuffer* quadIndexBuffer = batchTarget->quadIndexBuffer();
-        int maxInstancesPerDraw = quadIndexBuffer->maxQuads();
+        int maxInstancesPerDraw = indexBuffer->maxQuads();
 
         GrDrawTarget::DrawInfo drawInfo;
         drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
@@ -1540,7 +1542,7 @@ public:
         drawInfo.setIndicesPerInstance(kIndicesPerGlyph);
         drawInfo.adjustStartVertex(firstVertex);
         drawInfo.setVertexBuffer(vertexBuffer);
-        drawInfo.setIndexBuffer(quadIndexBuffer);
+        drawInfo.setIndexBuffer(indexBuffer);
 
         // We cache some values to avoid going to the glyphcache for the same fontScaler twice
         // in a row
index 9bd6b9409c41c2355e4246e42527e80b5fe1c053..97cd2ed727b9252a24655e7a654f9866e8d2a131 100644 (file)
@@ -121,9 +121,7 @@ public:
     GrVertexBufferAllocPool* vertexPool() { return fVertexPool; }
     GrIndexBufferAllocPool* indexPool() { return fIndexPool; }
 
-    const static int kVertsPerRect = 4;
-    const static int kIndicesPerRect = 6;
-    const GrIndexBuffer* quadIndexBuffer() const { return fGpu->getQuadIndexBuffer(); }
+    GrResourceProvider* resourceProvider() const { return fGpu->getContext()->resourceProvider(); }
 
     // A helper for draws which overallocate and then return data to the pool
     void putBackIndices(size_t indices) { fIndexPool->putBack(indices * sizeof(uint16_t)); }
index 47095135259eb4e8654fabaaad877baf49125363..819774a076a88b657f270dd7bc171a4a4908aaa6 100755 (executable)
@@ -125,8 +125,8 @@ void GrContext::initCommon() {
 
     fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (this)));
 
-    fAARectRenderer = SkNEW_ARGS(GrAARectRenderer, (fGpu));
-    fOvalRenderer = SkNEW_ARGS(GrOvalRenderer, (fGpu));
+    fAARectRenderer = SkNEW(GrAARectRenderer);
+    fOvalRenderer = SkNEW(GrOvalRenderer);
 
     fDidTestPMConversions = false;
 
@@ -186,9 +186,6 @@ void GrContext::abandonContext() {
     delete fDrawBufferIBAllocPool;
     fDrawBufferIBAllocPool = NULL;
 
-    fAARectRenderer->reset();
-    fOvalRenderer->reset();
-
     fBatchFontCache->freeAll();
     fLayerCache->freeAll();
     fTextBlobCache->freeAll();
@@ -205,9 +202,6 @@ void GrContext::freeGpuResources() {
         fDrawBuffer->purgeResources();
     }
 
-    fAARectRenderer->reset();
-    fOvalRenderer->reset();
-
     fBatchFontCache->freeAll();
     fLayerCache->freeAll();
     // a path renderer may be holding onto resources
@@ -1840,10 +1834,6 @@ GrDrawTarget* GrContext::getTextTarget() {
     return this->prepareToDraw();
 }
 
-const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
-    return fGpu->getQuadIndexBuffer();
-}
-
 namespace {
 void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
     GrConfigConversionEffect::PMConversion pmToUPM;
index bd49a72156f27a90c9a1f32488a74f42805a06e2..67dc6c770394b93dda55c7d0c146ab218284bd10 100644 (file)
@@ -39,6 +39,6 @@ bool GrDashLinePathRenderer::onDrawPath(GrDrawTarget* target,
                                         bool useAA) {
     SkPoint pts[2];
     SkAssertResult(path.isLine(pts));
-    return GrDashingEffect::DrawDashLine(fGpu, target, pipelineBuilder, color,
+    return GrDashingEffect::DrawDashLine(target, pipelineBuilder, color,
                                          viewMatrix, pts, useAA, stroke);
 }
index fdb098a637f7f62d2eda9fa75a86b6c8cab26b0e..cdf5226ed1f4c8418f7748efbe022e3c1dcb4090 100644 (file)
 GrGpu::GrGpu(GrContext* context)
     : fResetTimestamp(kExpiredTimestamp+1)
     , fResetBits(kAll_GrBackendState)
-    , fQuadIndexBuffer(NULL)
     , fGpuTraceMarkerCount(0)
     , fContext(context) {
 }
 
-GrGpu::~GrGpu() {
-    SkSafeSetNull(fQuadIndexBuffer);
-}
+GrGpu::~GrGpu() {}
 
 void GrGpu::contextAbandoned() {}
 
@@ -184,39 +181,6 @@ GrIndexBuffer* GrGpu::createIndexBuffer(size_t size, bool dynamic) {
     return this->onCreateIndexBuffer(size, dynamic);
 }
 
-GrIndexBuffer* GrGpu::createInstancedIndexBuffer(const uint16_t* pattern,
-                                                 int patternSize,
-                                                 int reps,
-                                                 int vertCount,
-                                                 bool isDynamic) {
-    size_t bufferSize = patternSize * reps * sizeof(uint16_t);
-    GrGpu* me = const_cast<GrGpu*>(this);
-    GrIndexBuffer* buffer = me->createIndexBuffer(bufferSize, isDynamic);
-    if (buffer) {
-        uint16_t* data = (uint16_t*) buffer->map();
-        bool useTempData = (NULL == data);
-        if (useTempData) {
-            data = SkNEW_ARRAY(uint16_t, reps * patternSize);
-        }
-        for (int i = 0; i < reps; ++i) {
-            int baseIdx = i * patternSize;
-            uint16_t baseVert = (uint16_t)(i * vertCount);
-            for (int j = 0; j < patternSize; ++j) {
-                data[baseIdx+j] = baseVert + pattern[j];
-            }
-        }
-        if (useTempData) {
-            if (!buffer->updateData(data, bufferSize)) {
-                SkFAIL("Can't get indices into buffer!");
-            }
-            SkDELETE_ARRAY(data);
-        } else {
-            buffer->unmap();
-        }
-    }
-    return buffer;
-}
-
 void GrGpu::clear(const SkIRect* rect,
                   GrColor color,
                   bool canIgnoreRect,
@@ -305,29 +269,6 @@ void GrGpu::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
 
 ////////////////////////////////////////////////////////////////////////////////
 
-static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1;
-
-GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535);
-
-static const uint16_t gQuadIndexPattern[] = {
-  0, 1, 2, 0, 2, 3
-};
-
-const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const {
-    if (NULL == fQuadIndexBuffer || fQuadIndexBuffer->wasDestroyed()) {
-        SkSafeUnref(fQuadIndexBuffer);
-        GrGpu* me = const_cast<GrGpu*>(this);
-        fQuadIndexBuffer = me->createInstancedIndexBuffer(gQuadIndexPattern,
-                                                          6,
-                                                          MAX_QUADS,
-                                                          4);
-    }
-
-    return fQuadIndexBuffer;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
 void GrGpu::draw(const DrawArgs& args, const GrDrawTarget::DrawInfo& info) {
     this->handleDirtyContext();
     this->onDraw(args, info);
index b2dbec65fb1566b5a74083c8e32865cc0400f1ae..3903af6344bd015f37c9227dc8a5d7a787d5c8ce 100644 (file)
@@ -118,34 +118,6 @@ public:
      */
     GrIndexBuffer* createIndexBuffer(size_t size, bool dynamic);
 
-    /**
-     * Creates an index buffer for instance drawing with a specific pattern.
-     *
-     * @param pattern     the pattern to repeat
-     * @param patternSize size in bytes of the pattern
-     * @param reps        number of times to repeat the pattern
-     * @param vertCount   number of vertices the pattern references
-     * @param dynamic     hints whether the data will be frequently changed
-     *                    by either GrIndexBuffer::map() or
-     *                    GrIndexBuffer::updateData().
-     *
-     * @return The index buffer if successful, otherwise NULL.
-     */
-    GrIndexBuffer* createInstancedIndexBuffer(const uint16_t* pattern,
-                                              int patternSize,
-                                              int reps,
-                                              int vertCount,
-                                              bool isDynamic = false);
-
-    /**
-     * Returns an index buffer that can be used to render quads.
-     * Six indices per quad: 0, 1, 2, 0, 2, 3, etc.
-     * The max number of quads can be queried using GrIndexBuffer::maxQuads().
-     * Draw with kTriangles_GrPrimitiveType
-     * @ return the quad index buffer
-     */
-    const GrIndexBuffer* getQuadIndexBuffer() const;
-
     /**
      * Resolves MSAA.
      */
@@ -520,8 +492,6 @@ private:
 
     ResetTimestamp                                                      fResetTimestamp;
     uint32_t                                                            fResetBits;
-    // these are mutable so they can be created on-demand
-    mutable GrIndexBuffer*                                              fQuadIndexBuffer;
     // To keep track that we always have at least as many debug marker adds as removes
     int                                                                 fGpuTraceMarkerCount;
     GrTraceMarkerSet                                                    fActiveTraceMarkers;
index e298be6c8bffb575798ae14250512495626e0fe5..8190ec0e8a880bc4a6aa696f0c4a5b2f5545080c 100644 (file)
@@ -8,6 +8,7 @@
 #include "GrInOrderDrawBuffer.h"
 
 #include "GrDefaultGeoProcFactory.h"
+#include "GrResourceProvider.h"
 #include "GrTemplates.h"
 
 GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrContext* context,
@@ -137,17 +138,18 @@ public:
                  vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
 
         int instanceCount = fGeoData.count();
-        int vertexCount = kVertsPerRect * instanceCount;
+        SkAutoTUnref<const GrIndexBuffer> indexBuffer(
+            batchTarget->resourceProvider()->refQuadIndexBuffer());
 
+        int vertexCount = kVertsPerRect * instanceCount;
         const GrVertexBuffer* vertexBuffer;
         int firstVertex;
-
         void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
                                                               vertexCount,
                                                               &vertexBuffer,
                                                               &firstVertex);
 
-        if (!vertices || !batchTarget->quadIndexBuffer()) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate buffers\n");
             return;
         }
@@ -181,8 +183,6 @@ public:
             }
         }
 
-        const GrIndexBuffer* quadIndexBuffer = batchTarget->quadIndexBuffer();
-
         GrDrawTarget::DrawInfo drawInfo;
         drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
         drawInfo.setStartVertex(0);
@@ -191,9 +191,9 @@ public:
         drawInfo.setIndicesPerInstance(kIndicesPerRect);
         drawInfo.adjustStartVertex(firstVertex);
         drawInfo.setVertexBuffer(vertexBuffer);
-        drawInfo.setIndexBuffer(quadIndexBuffer);
+        drawInfo.setIndexBuffer(indexBuffer);
 
-        int maxInstancesPerDraw = quadIndexBuffer->maxQuads();
+        int maxInstancesPerDraw = indexBuffer->maxQuads();
         while (instanceCount) {
             drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
             drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
index 8723d70a58ba30944b1d036ecdb557f0c797db5a..38efefa8570071157bbcb72a763ff3c7f5e9fa01 100644 (file)
 #include "GrBufferAllocPool.h"
 #include "GrDrawTarget.h"
 #include "GrGeometryProcessor.h"
-#include "GrGpu.h"
 #include "GrInvariantOutput.h"
 #include "GrPipelineBuilder.h"
 #include "GrProcessor.h"
+#include "GrResourceProvider.h"
 #include "GrVertexBuffer.h"
 #include "SkRRect.h"
 #include "SkStrokeRec.h"
@@ -646,11 +646,6 @@ GrGeometryProcessor* DIEllipseEdgeEffect::TestCreate(SkRandom* random,
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrOvalRenderer::reset() {
-    SkSafeSetNull(fRRectIndexBuffer);
-    SkSafeSetNull(fStrokeRRectIndexBuffer);
-}
-
 bool GrOvalRenderer::drawOval(GrDrawTarget* target,
                               GrPipelineBuilder* pipelineBuilder,
                               GrColor color,
@@ -659,8 +654,7 @@ bool GrOvalRenderer::drawOval(GrDrawTarget* target,
                               const SkRect& oval,
                               const SkStrokeRec& stroke)
 {
-    bool useCoverageAA = useAA &&
-        !pipelineBuilder->getRenderTarget()->isMultisampled();
+    bool useCoverageAA = useAA && !pipelineBuilder->getRenderTarget()->isMultisampled();
 
     if (!useCoverageAA) {
         return false;
@@ -697,9 +691,7 @@ public:
         SkRect fDevBounds;
     };
 
-    static GrBatch* Create(const Geometry& geometry) {
-        return SkNEW_ARGS(CircleBatch, (geometry));
-    }
+    static GrBatch* Create(const Geometry& geometry) { return SkNEW_ARGS(CircleBatch, (geometry)); }
 
     const char* name() const override { return "CircleBatch"; }
 
@@ -756,6 +748,8 @@ public:
         size_t vertexStride = gp->getVertexStride();
         SkASSERT(vertexStride == sizeof(CircleVertex));
 
+        SkAutoTUnref<const GrIndexBuffer> indexBuffer(
+            batchTarget->resourceProvider()->refQuadIndexBuffer());
         const GrVertexBuffer* vertexBuffer;
         int firstVertex;
 
@@ -764,7 +758,7 @@ public:
                                                               &vertexBuffer,
                                                               &firstVertex);
 
-        if (!vertices || !batchTarget->quadIndexBuffer()) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate buffers\n");
             return;
         }
@@ -804,8 +798,6 @@ public:
             verts += kVertsPerCircle;
         }
 
-        const GrIndexBuffer* quadIndexBuffer = batchTarget->quadIndexBuffer();
-
         GrDrawTarget::DrawInfo drawInfo;
         drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
         drawInfo.setStartVertex(0);
@@ -814,9 +806,9 @@ public:
         drawInfo.setIndicesPerInstance(kIndicesPerCircle);
         drawInfo.adjustStartVertex(firstVertex);
         drawInfo.setVertexBuffer(vertexBuffer);
-        drawInfo.setIndexBuffer(quadIndexBuffer);
+        drawInfo.setIndexBuffer(indexBuffer);
 
-        int maxInstancesPerDraw = quadIndexBuffer->maxQuads();
+        int maxInstancesPerDraw = indexBuffer->maxQuads();
 
         while (instanceCount) {
             drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
@@ -1022,6 +1014,8 @@ public:
         SkASSERT(vertexStride == sizeof(EllipseVertex));
 
         const GrVertexBuffer* vertexBuffer;
+        SkAutoTUnref<const GrIndexBuffer> indexBuffer(
+            batchTarget->resourceProvider()->refQuadIndexBuffer());
         int firstVertex;
 
         void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
@@ -1029,7 +1023,7 @@ public:
                                                               &vertexBuffer,
                                                               &firstVertex);
 
-        if (!vertices || !batchTarget->quadIndexBuffer()) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate buffers\n");
             return;
         }
@@ -1074,8 +1068,6 @@ public:
             verts += kVertsPerEllipse;
         }
 
-        const GrIndexBuffer* quadIndexBuffer = batchTarget->quadIndexBuffer();
-
         GrDrawTarget::DrawInfo drawInfo;
         drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
         drawInfo.setStartVertex(0);
@@ -1084,9 +1076,9 @@ public:
         drawInfo.setIndicesPerInstance(kIndicesPerEllipse);
         drawInfo.adjustStartVertex(firstVertex);
         drawInfo.setVertexBuffer(vertexBuffer);
-        drawInfo.setIndexBuffer(quadIndexBuffer);
+        drawInfo.setIndexBuffer(indexBuffer);
 
-        int maxInstancesPerDraw = quadIndexBuffer->maxQuads();
+        int maxInstancesPerDraw = indexBuffer->maxQuads();
 
         while (instanceCount) {
             drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
@@ -1325,20 +1317,21 @@ public:
         init.fUsesLocalCoords = this->usesLocalCoords();
         gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
 
+        SkAutoTUnref<const GrIndexBuffer> indexBuffer(
+            batchTarget->resourceProvider()->refQuadIndexBuffer());
+
         int instanceCount = fGeoData.count();
         int vertexCount = kVertsPerEllipse * instanceCount;
         size_t vertexStride = gp->getVertexStride();
         SkASSERT(vertexStride == sizeof(DIEllipseVertex));
-
         const GrVertexBuffer* vertexBuffer;
         int firstVertex;
-
         void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
                                                               vertexCount,
                                                               &vertexBuffer,
                                                               &firstVertex);
 
-        if (!vertices || !batchTarget->quadIndexBuffer()) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate buffers\n");
             return;
         }
@@ -1379,8 +1372,6 @@ public:
             verts += kVertsPerEllipse;
         }
 
-        const GrIndexBuffer* quadIndexBuffer = batchTarget->quadIndexBuffer();
-
         GrDrawTarget::DrawInfo drawInfo;
         drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
         drawInfo.setStartVertex(0);
@@ -1389,9 +1380,9 @@ public:
         drawInfo.setIndicesPerInstance(kIndicesPerEllipse);
         drawInfo.adjustStartVertex(firstVertex);
         drawInfo.setVertexBuffer(vertexBuffer);
-        drawInfo.setIndexBuffer(quadIndexBuffer);
+        drawInfo.setIndexBuffer(indexBuffer);
 
-        int maxInstancesPerDraw = quadIndexBuffer->maxQuads();
+        int maxInstancesPerDraw = indexBuffer->maxQuads();
 
         while (instanceCount) {
             drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
@@ -1579,6 +1570,24 @@ static const int kIndicesPerRRect = SK_ARRAY_COUNT(gRRectIndices);
 static const int kVertsPerRRect = 16;
 static const int kNumRRectsInIndexBuffer = 256;
 
+GR_DECLARE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey);
+GR_DECLARE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey);
+static const GrIndexBuffer* ref_rrect_index_buffer(bool strokeOnly,
+                                                   GrResourceProvider* resourceProvider) {
+    GR_DEFINE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey);
+    GR_DEFINE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey);
+    if (strokeOnly) {
+        return resourceProvider->refOrCreateInstancedIndexBuffer(
+            gRRectIndices, kIndicesPerStrokeRRect, kNumRRectsInIndexBuffer, kVertsPerRRect,
+            gStrokeRRectOnlyIndexBufferKey);
+    } else {
+        return resourceProvider->refOrCreateInstancedIndexBuffer(
+            gRRectIndices, kIndicesPerRRect, kNumRRectsInIndexBuffer, kVertsPerRRect,
+            gRRectOnlyIndexBufferKey);
+
+    }
+}
+
 bool GrOvalRenderer::drawDRRect(GrDrawTarget* target,
                                 GrPipelineBuilder* pipelineBuilder,
                                 GrColor color,
@@ -1657,8 +1666,8 @@ public:
         SkRect fDevBounds;
     };
 
-    static GrBatch* Create(const Geometry& geometry, const GrIndexBuffer* indexBuffer) {
-        return SkNEW_ARGS(RRectCircleRendererBatch, (geometry, indexBuffer));
+    static GrBatch* Create(const Geometry& geometry) {
+        return SkNEW_ARGS(RRectCircleRendererBatch, (geometry));
     }
 
     const char* name() const override { return "RRectCircleBatch"; }
@@ -1718,6 +1727,8 @@ public:
         SkASSERT(vertexStride == sizeof(CircleVertex));
 
         const GrVertexBuffer* vertexBuffer;
+        SkAutoTUnref<const GrIndexBuffer> indexBuffer(
+            ref_rrect_index_buffer(this->stroke(), batchTarget->resourceProvider()));
         int firstVertex;
 
         void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
@@ -1725,7 +1736,7 @@ public:
                                                               &vertexBuffer,
                                                               &firstVertex);
 
-        if (!vertices) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
         }
@@ -1780,7 +1791,6 @@ public:
         int indexCnt = this->stroke() ? SK_ARRAY_COUNT(gRRectIndices) - 6 :
                                         SK_ARRAY_COUNT(gRRectIndices);
 
-
         GrDrawTarget::DrawInfo drawInfo;
         drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
         drawInfo.setStartVertex(0);
@@ -1789,7 +1799,7 @@ public:
         drawInfo.setIndicesPerInstance(indexCnt);
         drawInfo.adjustStartVertex(firstVertex);
         drawInfo.setVertexBuffer(vertexBuffer);
-        drawInfo.setIndexBuffer(fIndexBuffer);
+        drawInfo.setIndexBuffer(indexBuffer);
 
         int maxInstancesPerDraw = kNumRRectsInIndexBuffer;
 
@@ -1808,8 +1818,7 @@ public:
     SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
 
 private:
-    RRectCircleRendererBatch(const Geometry& geometry, const GrIndexBuffer* indexBuffer)
-        : fIndexBuffer(indexBuffer) {
+    RRectCircleRendererBatch(const Geometry& geometry) {
         this->initClassID<RRectCircleRendererBatch>();
         fGeoData.push_back(geometry);
 
@@ -1853,7 +1862,6 @@ private:
 
     BatchTracker fBatch;
     SkSTArray<1, Geometry, true> fGeoData;
-    const GrIndexBuffer* fIndexBuffer;
 };
 
 class RRectEllipseRendererBatch : public GrBatch {
@@ -1869,8 +1877,8 @@ public:
         SkRect fDevBounds;
     };
 
-    static GrBatch* Create(const Geometry& geometry, const GrIndexBuffer* indexBuffer) {
-        return SkNEW_ARGS(RRectEllipseRendererBatch, (geometry, indexBuffer));
+    static GrBatch* Create(const Geometry& geometry) {
+        return SkNEW_ARGS(RRectEllipseRendererBatch, (geometry));
     }
 
     const char* name() const override { return "RRectEllipseRendererBatch"; }
@@ -1930,6 +1938,8 @@ public:
         SkASSERT(vertexStride == sizeof(EllipseVertex));
 
         const GrVertexBuffer* vertexBuffer;
+        SkAutoTUnref<const GrIndexBuffer> indexBuffer(
+            ref_rrect_index_buffer(this->stroke(), batchTarget->resourceProvider()));
         int firstVertex;
 
         void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
@@ -1937,7 +1947,7 @@ public:
                                                               &vertexBuffer,
                                                               &firstVertex);
 
-        if (!vertices) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
         }
@@ -2011,7 +2021,7 @@ public:
         drawInfo.setIndicesPerInstance(indexCnt);
         drawInfo.adjustStartVertex(firstVertex);
         drawInfo.setVertexBuffer(vertexBuffer);
-        drawInfo.setIndexBuffer(fIndexBuffer);
+        drawInfo.setIndexBuffer(indexBuffer);
 
         int maxInstancesPerDraw = kNumRRectsInIndexBuffer;
 
@@ -2030,8 +2040,7 @@ public:
     SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
 
 private:
-    RRectEllipseRendererBatch(const Geometry& geometry, const GrIndexBuffer* indexBuffer)
-        : fIndexBuffer(indexBuffer) {
+    RRectEllipseRendererBatch(const Geometry& geometry) {
         this->initClassID<RRectEllipseRendererBatch>();
         fGeoData.push_back(geometry);
 
@@ -2075,40 +2084,13 @@ private:
 
     BatchTracker fBatch;
     SkSTArray<1, Geometry, true> fGeoData;
-    const GrIndexBuffer* fIndexBuffer;
 };
 
-static GrIndexBuffer* create_rrect_indexbuffer(GrIndexBuffer** strokeRRectIndexBuffer,
-                                               GrIndexBuffer** rrectIndexBuffer,
-                                               bool isStrokeOnly,
-                                               GrGpu* gpu) {
-    if (isStrokeOnly) {
-        if (NULL == *strokeRRectIndexBuffer) {
-            *strokeRRectIndexBuffer = gpu->createInstancedIndexBuffer(gRRectIndices,
-                                                                      kIndicesPerStrokeRRect,
-                                                                      kNumRRectsInIndexBuffer,
-                                                                      kVertsPerRRect);
-        }
-        return *strokeRRectIndexBuffer;
-    } else {
-        if (NULL == *rrectIndexBuffer) {
-            *rrectIndexBuffer = gpu->createInstancedIndexBuffer(gRRectIndices,
-                                                                kIndicesPerRRect,
-                                                                kNumRRectsInIndexBuffer,
-                                                                kVertsPerRRect);
-        }
-        return *rrectIndexBuffer;
-    }
-}
-
 static GrBatch* create_rrect_batch(GrColor color,
                                    const SkMatrix& viewMatrix,
                                    const SkRRect& rrect,
                                    const SkStrokeRec& stroke,
-                                   SkRect* bounds,
-                                   GrIndexBuffer** strokeRRectIndexBuffer,
-                                   GrIndexBuffer** rrectIndexBuffer,
-                                   GrGpu* gpu) {
+                                   SkRect* bounds) {
     SkASSERT(viewMatrix.rectStaysRect());
     SkASSERT(rrect.isSimple());
     SkASSERT(!rrect.isOval());
@@ -2159,15 +2141,6 @@ static GrBatch* create_rrect_batch(GrColor color,
         return NULL;
     }
 
-    GrIndexBuffer* indexBuffer = create_rrect_indexbuffer(strokeRRectIndexBuffer,
-                                                          rrectIndexBuffer,
-                                                          isStrokeOnly,
-                                                          gpu);
-    if (NULL == indexBuffer) {
-        SkDebugf("Failed to create index buffer!\n");
-        return NULL;
-    }
-
     // if the corners are circles, use the circle renderer
     if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius) {
         SkScalar innerRadius = 0.0f;
@@ -2208,8 +2181,7 @@ static GrBatch* create_rrect_batch(GrColor color,
         geometry.fStroke = isStrokeOnly;
         geometry.fDevBounds = *bounds;
 
-        return RRectCircleRendererBatch::Create(geometry, indexBuffer);
-
+        return RRectCircleRendererBatch::Create(geometry);
     // otherwise we use the ellipse renderer
     } else {
         SkScalar innerXRadius = 0.0f;
@@ -2259,7 +2231,7 @@ static GrBatch* create_rrect_batch(GrColor color,
         geometry.fStroke = isStrokeOnly;
         geometry.fDevBounds = *bounds;
 
-        return RRectEllipseRendererBatch::Create(geometry, indexBuffer);
+        return RRectEllipseRendererBatch::Create(geometry);
     }
 }
 
@@ -2287,9 +2259,7 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target,
     }
 
     SkRect bounds;
-    SkAutoTUnref<GrBatch> batch(create_rrect_batch(color, viewMatrix, rrect, stroke, &bounds,
-                                                   &fStrokeRRectIndexBuffer, &fRRectIndexBuffer,
-                                                   fGpu));
+    SkAutoTUnref<GrBatch> batch(create_rrect_batch(color, viewMatrix, rrect, stroke, &bounds));
     if (!batch) {
         return false;
     }
@@ -2347,11 +2317,8 @@ BATCH_TEST_DEFINE(RRectBatch) {
     GrColor color = GrRandomColor(random);
     const SkRRect& rrect = GrTest::TestRRectSimple(random);
 
-    static GrIndexBuffer* gStrokeRRectIndexBuffer;
-    static GrIndexBuffer* gRRectIndexBuffer;
     SkRect bounds;
-    return create_rrect_batch(color, viewMatrix, rrect, random_strokerec(random), &bounds,
-                              &gStrokeRRectIndexBuffer, &gRRectIndexBuffer, context->getGpu());
+    return create_rrect_batch(color, viewMatrix, rrect, random_strokerec(random), &bounds);
 }
 
 #endif
index f31aa69bb2d0d34e93064923517503d5469e2a2c..57ce2a5dfe056174d9cc6e0386e09443bc02e313 100644 (file)
@@ -24,16 +24,6 @@ class GrOvalRenderer : public SkRefCnt {
 public:
     SK_DECLARE_INST_COUNT(GrOvalRenderer)
 
-    GrOvalRenderer(GrGpu* gpu)
-        : fGpu(gpu)
-        , fRRectIndexBuffer(NULL)
-        , fStrokeRRectIndexBuffer(NULL) {}
-    ~GrOvalRenderer() {
-        this->reset();
-    }
-
-    void reset();
-
     bool drawOval(GrDrawTarget*,
                   GrPipelineBuilder*,
                   GrColor,
@@ -79,10 +69,6 @@ private:
                     const SkRect& circle,
                     const SkStrokeRec& stroke);
 
-    GrGpu*         fGpu;
-    GrIndexBuffer* fRRectIndexBuffer;
-    GrIndexBuffer* fStrokeRRectIndexBuffer;
-
     typedef SkRefCnt INHERITED;
 };
 
diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp
new file mode 100644 (file)
index 0000000..8fc3272
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrResourceProvider.h"
+
+#include "GrGpu.h"
+#include "GrResourceCache.h"
+#include "GrResourceKey.h"
+#include "GrVertexBuffer.h"
+
+GR_DECLARE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey);
+
+GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache) : INHERITED(gpu, cache) {
+    GR_DEFINE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey);
+    fQuadIndexBufferKey = gQuadIndexBufferKey;
+}
+
+const GrIndexBuffer* GrResourceProvider::createInstancedIndexBuffer(const uint16_t* pattern,
+                                                                    int patternSize,
+                                                                    int reps,
+                                                                    int vertCount,
+                                                                    const GrUniqueKey& key) {
+    size_t bufferSize = patternSize * reps * sizeof(uint16_t);
+
+    GrIndexBuffer* buffer = this->gpu()->createIndexBuffer(bufferSize, /* dynamic = */ false);
+    if (!buffer) {
+        return NULL;
+    }
+    uint16_t* data = (uint16_t*) buffer->map();
+    bool useTempData = (NULL == data);
+    if (useTempData) {
+        data = SkNEW_ARRAY(uint16_t, reps * patternSize);
+    }
+    for (int i = 0; i < reps; ++i) {
+        int baseIdx = i * patternSize;
+        uint16_t baseVert = (uint16_t)(i * vertCount);
+        for (int j = 0; j < patternSize; ++j) {
+            data[baseIdx+j] = baseVert + pattern[j];
+        }
+    }
+    if (useTempData) {
+        if (!buffer->updateData(data, bufferSize)) {
+            buffer->unref();
+            return NULL;
+        }
+        SkDELETE_ARRAY(data);
+    } else {
+        buffer->unmap();
+    }
+    this->assignUniqueKeyToResource(key, buffer);
+    return buffer;
+}
+
+const GrIndexBuffer* GrResourceProvider::createQuadIndexBuffer() {
+    static const int kMaxQuads = 1 << 12; // max possible: (1 << 14) - 1;
+    GR_STATIC_ASSERT(4 * kMaxQuads <= 65535);
+    static const uint16_t kPattern[] = { 0, 1, 2, 0, 2, 3 };
+
+    return this->createInstancedIndexBuffer(kPattern, 6, kMaxQuads, 4, fQuadIndexBufferKey);
+}
+
index f560afa0fd509ff4e47a6d2910941474c8bda955..0d80cdd2a086f45941aba8c838ef9d7cc49de8fe 100644 (file)
@@ -10,6 +10,9 @@
 
 #include "GrTextureProvider.h"
 
+class GrIndexBuffer;
+class GrVertexBuffer;
+
 /**
  * An extension of the texture provider for arbitrary resource types. This class is intended for
  * use within the Gr code base, not by clients or extensions (e.g. third party GrProcessor
 class GrResourceProvider : public GrTextureProvider {
 public:
 
-    GrResourceProvider(GrGpu* gpu, GrResourceCache* cache) : INHERITED(gpu, cache) {}
+    GrResourceProvider(GrGpu* gpu, GrResourceCache* cache);
+
+    template <typename T> T* findAndRefTByUniqueKey(const GrUniqueKey& key) {
+        return static_cast<T*>(this->findAndRefResourceByUniqueKey(key));
+    }
+
+    /**
+     * Either finds and refs, or creates an index buffer for instanced drawing with a specific
+     * pattern if the index buffer is not found. If the return is non-null, the caller owns
+     * a ref on the returned GrIndexBuffer.
+     *
+     * @param pattern     the pattern of indices to repeat
+     * @param patternSize size in bytes of the pattern
+     * @param reps        number of times to repeat the pattern
+     * @param vertCount   number of vertices the pattern references
+     * @param key         Key to be assigned to the index buffer.
+     *
+     * @return The index buffer if successful, otherwise NULL.
+     */
+    const GrIndexBuffer* refOrCreateInstancedIndexBuffer(const uint16_t* pattern,
+                                                         int patternSize,
+                                                         int reps,
+                                                         int vertCount,
+                                                         const GrUniqueKey& key) {
+        if (GrIndexBuffer* buffer = this->findAndRefTByUniqueKey<GrIndexBuffer>(key)) {
+            return buffer;
+        }
+        return this->createInstancedIndexBuffer(pattern, patternSize, reps, vertCount, key);
+    }
+
+    /**
+     * Returns an index buffer that can be used to render quads.
+     * Six indices per quad: 0, 1, 2, 0, 2, 3, etc.
+     * The max number of quads can be queried using GrIndexBuffer::maxQuads().
+     * Draw with kTriangles_GrPrimitiveType
+     * @ return the quad index buffer
+     */
+    const GrIndexBuffer* refQuadIndexBuffer() {
+        if (GrIndexBuffer* buffer =
+            this->findAndRefTByUniqueKey<GrIndexBuffer>(fQuadIndexBufferKey)) {
+            return buffer;
+        }
+        return this->createQuadIndexBuffer();
+    }
+
 
     using GrTextureProvider::assignUniqueKeyToResource;
     using GrTextureProvider::findAndRefResourceByUniqueKey;
     using GrTextureProvider::abandon;
 
+private:
+    const GrIndexBuffer* createInstancedIndexBuffer(const uint16_t* pattern,
+                                                    int patternSize,
+                                                    int reps,
+                                                    int vertCount,
+                                                    const GrUniqueKey& key);
+
+    const GrIndexBuffer* createQuadIndexBuffer();
+
+    GrUniqueKey fQuadIndexBufferKey;
+
     typedef GrTextureProvider INHERITED;
 };
 
index 3f0df6737796a42a0ccbba098e23855843908d50..fa8b3a2dcf941bfc6c29b2fa27e39f6bcb1c49f8 100644 (file)
@@ -19,6 +19,7 @@
 #include "GrDrawTargetCaps.h"
 #include "GrInvariantOutput.h"
 #include "GrProcessor.h"
+#include "GrResourceProvider.h"
 #include "GrStrokeInfo.h"
 #include "GrVertexBuffer.h"
 #include "SkGr.h"
@@ -535,16 +536,17 @@ public:
             draw.fHasEndRect = hasEndRect;
         }
 
+        SkAutoTUnref<const GrIndexBuffer> indexBuffer(
+            batchTarget->resourceProvider()->refQuadIndexBuffer());
+
         const GrVertexBuffer* vertexBuffer;
         int firstVertex;
-
         size_t vertexStride = gp->getVertexStride();
         void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
                                                               totalRectCount * kVertsPerDash,
                                                               &vertexBuffer,
                                                               &firstVertex);
-
-        if (!vertices || !batchTarget->quadIndexBuffer()) {
+        if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate buffers\n");
             return;
         }
@@ -607,8 +609,6 @@ public:
             rectIndex++;
         }
 
-        const GrIndexBuffer* dashIndexBuffer = batchTarget->quadIndexBuffer();
-
         GrDrawTarget::DrawInfo drawInfo;
         drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
         drawInfo.setStartVertex(0);
@@ -617,9 +617,9 @@ public:
         drawInfo.setIndicesPerInstance(kIndicesPerDash);
         drawInfo.adjustStartVertex(firstVertex);
         drawInfo.setVertexBuffer(vertexBuffer);
-        drawInfo.setIndexBuffer(dashIndexBuffer);
+        drawInfo.setIndexBuffer(indexBuffer);
 
-        int maxInstancesPerDraw = dashIndexBuffer->maxQuads();
+        int maxInstancesPerDraw = indexBuffer->maxQuads();
         while (totalRectCount) {
             drawInfo.setInstanceCount(SkTMin(totalRectCount, maxInstancesPerDraw));
             drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
@@ -761,7 +761,7 @@ static GrBatch* create_batch(GrColor color, const SkMatrix& viewMatrix, const Sk
     return DashBatch::Create(geometry, cap, aaMode, fullDash);
 }
 
-bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target,
+bool GrDashingEffect::DrawDashLine(GrDrawTarget* target,
                                    GrPipelineBuilder* pipelineBuilder, GrColor color,
                                    const SkMatrix& viewMatrix, const SkPoint pts[2],
                                    bool useAA, const GrStrokeInfo& strokeInfo) {
index 999abb23d8e4e4e668dc55950d7da07496ffb50a..05b1c9020542a2e6e9534f44390cde5f1079e7fc 100644 (file)
 
 class GrClip;
 class GrDrawTarget;
-class GrGpu;
 class GrPaint;
 class GrPipelineBuilder;
 class GrStrokeInfo;
 
 namespace GrDashingEffect {
-    bool DrawDashLine(GrGpu*, GrDrawTarget*, GrPipelineBuilder*, GrColor,
+    bool DrawDashLine(GrDrawTarget*, GrPipelineBuilder*, GrColor,
                       const SkMatrix& viewMatrix, const SkPoint pts[2], bool useAA,
                       const GrStrokeInfo& strokeInfo);
     bool CanDrawDashLine(const SkPoint pts[2], const GrStrokeInfo& strokeInfo,