Chromium Code Reviews| Index: src/gpu/GrAAHairLinePathRenderer.cpp |
| diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp |
| index 96e0677eceb691d8a457b44510d6627398f63423..e9de91b4af066ed6da73ca655eed2b597c0ded97 100644 |
| --- a/src/gpu/GrAAHairLinePathRenderer.cpp |
| +++ b/src/gpu/GrAAHairLinePathRenderer.cpp |
| @@ -13,11 +13,11 @@ |
| #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" |
| @@ -25,6 +25,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 |
| @@ -60,6 +62,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. |
| @@ -86,43 +96,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; |
| @@ -150,7 +134,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) { |
| @@ -170,7 +154,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) { |
| @@ -185,7 +169,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); |
| @@ -206,14 +190,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; |
| @@ -249,14 +233,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; |
| @@ -440,9 +424,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); |
| @@ -458,14 +442,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]; |
| @@ -543,8 +527,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); |
| @@ -557,21 +541,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]; |
| @@ -585,10 +569,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]; |
| @@ -630,8 +614,6 @@ void add_line(const SkPoint p[2], |
| *vert += kLineSegNumVertices; |
| } |
| -} |
| - |
| /////////////////////////////////////////////////////////////////////////////// |
| bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target, |
| @@ -702,11 +684,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"; } |
| @@ -744,11 +723,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); |
| @@ -807,8 +782,6 @@ private: |
| BatchTracker fBatch; |
| SkSTArray<1, Geometry, true> fGeoData; |
| - const GrIndexBuffer* fLinesIndexBuffer; |
| - const GrIndexBuffer* fQuadsIndexBuffer; |
| }; |
| void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) { |
| @@ -879,6 +852,8 @@ void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel |
| // do lines first |
| if (lineCount) { |
| + SkAutoTUnref<const GrIndexBuffer> linesIndexBuffer( |
| + ref_lines_index_buffer(batchTarget->resourceProvider())); |
|
robertphillips
2015/05/04 13:16:00
Check if this fails ? We seem to do it every where
bsalomon
2015/05/04 15:01:09
Done.
|
| batchTarget->initDraw(lineGP, pipeline); |
| // TODO remove this when batch is everywhere |
| @@ -914,7 +889,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); |
| @@ -936,6 +911,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, |
| @@ -943,7 +921,7 @@ void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel |
| &vertexBuffer, |
| &firstVertex); |
| - if (!vertices) { |
| + if (!vertices || !quadsIndexBuffer) { |
| SkDebugf("Could not allocate vertices\n"); |
| return; |
| } |
| @@ -976,7 +954,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); |
| @@ -1008,7 +986,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); |
| @@ -1035,11 +1013,6 @@ bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, |
| const SkPath& path, |
| const GrStrokeInfo& stroke, |
| bool) { |
| - if (!fLinesIndexBuffer || !fQuadsIndexBuffer) { |
| - SkDebugf("unable to allocate indices\n"); |
| - return false; |
| - } |
| - |
| SkScalar hairlineCoverage; |
| uint8_t newCoverage = 0xff; |
| if (IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) { |
| @@ -1057,8 +1030,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, |
| geometry.fPath = path; |
| geometry.fDevClipBounds = devClipBounds; |
| - SkAutoTUnref<GrBatch> batch(AAHairlineBatch::Create(geometry, fLinesIndexBuffer, |
| - fQuadsIndexBuffer)); |
| + SkAutoTUnref<GrBatch> batch(AAHairlineBatch::Create(geometry)); |
| target->drawBatch(pipelineBuilder, batch); |
| return true; |