Indexed drawing for paths with multiple contours

Review URL: http://codereview.appspot.com/4648071/



git-svn-id: http://skia.googlecode.com/svn/trunk@1800 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-07-06 17:41:08 +00:00
parent 57c8d833cd
commit 25fd36c7ef
3 changed files with 119 additions and 33 deletions

View File

@ -241,7 +241,7 @@ private:
void onDrawPath(GrDrawTarget::StageBitfield stages, bool stencilOnly);
void createGeom(GrScalar srcSpaceTolSqd,
bool createGeom(GrScalar srcSpaceTol,
GrDrawTarget::StageBitfield stages);
bool fSeparateStencil;
@ -249,9 +249,12 @@ private:
int fSubpathCount;
SkAutoSTMalloc<8, uint16_t> fSubpathVertCount;
int fIndexCnt;
int fVertexCnt;
GrScalar fPreviousSrcTol;
GrDrawTarget::StageBitfield fPreviousStages;
GrPrimitiveType fPrimitiveType;
bool fUseIndexedDraw;
typedef GrPathRenderer INHERITED;
};

View File

@ -26,6 +26,8 @@
// probably makes no sense for this to be less than a page
static const size_t VERTEX_POOL_VB_SIZE = 1 << 18;
static const int VERTEX_POOL_VB_COUNT = 4;
static const size_t INDEX_POOL_IB_SIZE = 1 << 16;
static const int INDEX_POOL_IB_COUNT = 4;
////////////////////////////////////////////////////////////////////////////////
@ -670,7 +672,9 @@ void GrGpu::prepareVertexPool() {
void GrGpu::prepareIndexPool() {
if (NULL == fIndexPool) {
GrAssert(0 == fIndexPoolUseCnt);
fIndexPool = new GrIndexBufferAllocPool(this, true, 0, 1);
fIndexPool = new GrIndexBufferAllocPool(this, true,
INDEX_POOL_IB_SIZE,
INDEX_POOL_IB_COUNT);
fIndexPool->releaseGpuRef();
} else if (!fIndexPoolUseCnt) {
// the client doesn't have valid data in the pool

View File

@ -38,6 +38,7 @@ void GrPathRenderer::setPath(GrDrawTarget* target,
void GrPathRenderer::clearPath() {
this->pathWillClear();
fTarget->resetVertexSource();
fTarget->resetIndexSource();
fTarget = NULL;
fPath = NULL;
}
@ -229,18 +230,40 @@ void GrDefaultPathRenderer::pathWillClear() {
fPreviousStages = -1;
}
void GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
static inline void append_countour_edge_indices(GrPathFill fillType,
uint16_t fanCenterIdx,
uint16_t edgeV0Idx,
uint16_t** indices) {
// when drawing lines we're appending line segments along
// the contour. When applying the other fill rules we're
// drawing triangle fans around fanCenterIdx.
if (kHairLine_PathFill != fillType) {
*((*indices)++) = fanCenterIdx;
}
*((*indices)++) = edgeV0Idx;
*((*indices)++) = edgeV0Idx + 1;
}
bool GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
GrDrawTarget::StageBitfield stages) {
{
SK_TRACE_EVENT0("GrDefaultPathRenderer::createGeom");
fPreviousSrcTol = srcSpaceTol;
fPreviousStages = stages;
GrScalar srcSpaceTolSqd = GrMul(srcSpaceTol, srcSpaceTol);
int maxPts = GrPathUtils::worstCasePointCount(*fPath, &fSubpathCount,
srcSpaceTol);
if (maxPts <= 0) {
return false;
}
if (maxPts > ((int)SK_MaxU16 + 1)) {
GrPrintf("Path not rendered, too many verts (%d)\n", maxPts);
return false;
}
fPreviousSrcTol = srcSpaceTol;
fPreviousStages = stages;
GrVertexLayout layout = 0;
for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
if ((1 << s) & stages) {
@ -248,12 +271,36 @@ void GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
}
}
// add 4 to hold the bounding rect
GrPoint* base;
fTarget->reserveVertexSpace(layout, maxPts + 4, (void**)&base);
fUseIndexedDraw = fSubpathCount > 1;
int maxIdxs = 0;
if (kHairLine_PathFill == fFill) {
if (fUseIndexedDraw) {
maxIdxs = 2 * maxPts;
fPrimitiveType = kLines_PrimitiveType;
} else {
fPrimitiveType = kLineStrip_PrimitiveType;
}
} else {
if (fUseIndexedDraw) {
maxIdxs = 3 * maxPts;
fPrimitiveType = kTriangles_PrimitiveType;
} else {
fPrimitiveType = kTriangleFan_PrimitiveType;
}
}
GrPoint* base;
fTarget->reserveVertexSpace(layout, maxPts, (void**)&base);
GrPoint* vert = base;
GrPoint* subpathBase = base;
uint16_t* idxBase = NULL;
uint16_t* idx = NULL;
uint16_t subpathIdxStart = 0;
if (fUseIndexedDraw) {
fTarget->reserveIndexSpace(maxIdxs, (void**)&idxBase);
idx = idxBase;
}
fSubpathVertCount.realloc(fSubpathCount);
@ -269,41 +316,68 @@ void GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
switch (cmd) {
case kMove_PathCmd:
if (!first) {
fSubpathVertCount[subpath] = vert-subpathBase;
subpathBase = vert;
uint16_t currIdx = (uint16_t) (vert - base);
fSubpathVertCount[subpath] = currIdx - subpathIdxStart;
subpathIdxStart = currIdx;
++subpath;
}
*vert = pts[0];
vert++;
break;
case kLine_PathCmd:
*vert = pts[1];
vert++;
if (fUseIndexedDraw) {
uint16_t prevIdx = (uint16_t)(vert - base) - 1;
append_countour_edge_indices(fFill, subpathIdxStart,
prevIdx, &idx);
}
*(vert++) = pts[1];
break;
case kQuadratic_PathCmd: {
GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2],
srcSpaceTolSqd, &vert,
GrPathUtils::quadraticPointCount(pts, srcSpaceTol));
// first pt of quad is the pt we ended on in previous step
uint16_t firstQPtIdx = (uint16_t)(vert - base) - 1;
uint16_t numPts = (uint16_t)
GrPathUtils::generateQuadraticPoints(
pts[0], pts[1], pts[2],
srcSpaceTolSqd, &vert,
GrPathUtils::quadraticPointCount(pts, srcSpaceTol));
if (fUseIndexedDraw) {
for (uint16_t i = 0; i < numPts; ++i) {
append_countour_edge_indices(fFill, subpathIdxStart,
firstQPtIdx + i, &idx);
}
}
break;
}
case kCubic_PathCmd: {
GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3],
srcSpaceTolSqd, &vert,
GrPathUtils::cubicPointCount(pts, srcSpaceTol));
// first pt of cubic is the pt we ended on in previous step
uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1;
uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints(
pts[0], pts[1], pts[2], pts[3],
srcSpaceTolSqd, &vert,
GrPathUtils::cubicPointCount(pts, srcSpaceTol));
if (fUseIndexedDraw) {
for (uint16_t i = 0; i < numPts; ++i) {
append_countour_edge_indices(fFill, subpathIdxStart,
firstCPtIdx + i, &idx);
}
}
break;
}
case kClose_PathCmd:
break;
case kEnd_PathCmd:
fSubpathVertCount[subpath] = vert-subpathBase;
++subpath; // this could be only in debug
uint16_t currIdx = (uint16_t) (vert - base);
fSubpathVertCount[subpath] = currIdx - subpathIdxStart;
goto FINISHED;
}
first = false;
}
FINISHED:
GrAssert(subpath == fSubpathCount);
GrAssert((vert - base) <= maxPts);
GrAssert((idx - idxBase) <= maxIdxs);
fVertexCnt = vert - base;
fIndexCnt = idx - idxBase;
if (fTranslate.fX || fTranslate.fY) {
int count = vert - base;
@ -312,6 +386,7 @@ FINISHED:
}
}
}
return true;
}
void GrDefaultPathRenderer::onDrawPath(GrDrawTarget::StageBitfield stages,
@ -343,7 +418,9 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawTarget::StageBitfield stages,
// it is a silly limitation of the GrDrawTarget design that should be fixed.
if (tol != fPreviousSrcTol ||
stages != fPreviousStages) {
this->createGeom(tol, stages);
if (!this->createGeom(tol, stages)) {
return;
}
}
GrAssert(NULL != fTarget);
@ -352,7 +429,6 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawTarget::StageBitfield stages,
// face culling doesn't make sense here
GrAssert(GrDrawTarget::kBoth_DrawFace == fTarget->getDrawFace());
GrPrimitiveType type;
int passCount = 0;
const GrStencilSettings* passes[3];
GrDrawTarget::DrawFace drawFace[3];
@ -360,7 +436,6 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawTarget::StageBitfield stages,
bool lastPassIsBounds;
if (kHairLine_PathFill == fFill) {
type = kLineStrip_PrimitiveType;
passCount = 1;
if (stencilOnly) {
passes[0] = &gDirectToStencil;
@ -370,7 +445,6 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawTarget::StageBitfield stages,
lastPassIsBounds = false;
drawFace[0] = GrDrawTarget::kBoth_DrawFace;
} else {
type = kTriangleFan_PrimitiveType;
if (single_pass_path(*fTarget, *fPath, fFill)) {
passCount = 1;
if (stencilOnly) {
@ -481,11 +555,16 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawTarget::StageBitfield stages,
if (passCount > 1) {
fTarget->enableState(GrDrawTarget::kNoColorWrites_StateBit);
}
int baseVertex = 0;
for (int sp = 0; sp < fSubpathCount; ++sp) {
fTarget->drawNonIndexed(type, baseVertex,
fSubpathVertCount[sp]);
baseVertex += fSubpathVertCount[sp];
if (fUseIndexedDraw) {
fTarget->drawIndexed(fPrimitiveType, 0, 0,
fVertexCnt, fIndexCnt);
} else {
int baseVertex = 0;
for (int sp = 0; sp < fSubpathCount; ++sp) {
fTarget->drawNonIndexed(fPrimitiveType, baseVertex,
fSubpathVertCount[sp]);
baseVertex += fSubpathVertCount[sp];
}
}
}
}