Move instanced index buffer creation to flush time
Review URL: https://codereview.chromium.org/1116943004
This commit is contained in:
parent
f15132fdcf
commit
ab622c7b8c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -167,6 +167,8 @@
|
||||
'<(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',
|
||||
|
@ -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;
|
||||
|
@ -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; }
|
||||
|
@ -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:
|
||||
|
@ -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));
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
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(
|
||||
const GrContext* context,
|
||||
const GrIndexBuffer* linesIndexBuffer,
|
||||
const GrIndexBuffer* quadsIndexBuffer) {
|
||||
fLinesIndexBuffer = linesIndexBuffer;
|
||||
linesIndexBuffer->ref();
|
||||
fQuadsIndexBuffer = quadsIndexBuffer;
|
||||
quadsIndexBuffer->ref();
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -13,37 +13,30 @@
|
||||
|
||||
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;
|
||||
};
|
||||
|
@ -13,10 +13,11 @@
|
||||
#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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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)); }
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -24,14 +24,11 @@
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -13,10 +13,10 @@
|
||||
#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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
64
src/gpu/GrResourceProvider.cpp
Normal file
64
src/gpu/GrResourceProvider.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
@ -18,12 +21,67 @@
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -15,13 +15,12 @@
|
||||
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user