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:
parent
57c8d833cd
commit
25fd36c7ef
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user