Index: src/gpu/GrAAHairLinePathRenderer.cpp |
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp |
index ad6550072d796609526880b4829f986509f658f5..f046af871f5ef1dab82218130e02defc63480e67 100644 |
--- a/src/gpu/GrAAHairLinePathRenderer.cpp |
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp |
@@ -14,11 +14,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" |
@@ -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 |