зеркало из https://github.com/mozilla/moz-skia.git
simplify GrPathRenderer interface
Review URL: http://codereview.appspot.com/5706053/ git-svn-id: http://skia.googlecode.com/svn/trunk@3312 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
6a81b8a282
Коммит
c2099d2707
|
@ -700,6 +700,7 @@ private:
|
|||
|
||||
GrPathRenderer* getPathRenderer(const GrPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target,
|
||||
bool antiAlias);
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,15 +18,6 @@
|
|||
GrAAConvexPathRenderer::GrAAConvexPathRenderer() {
|
||||
}
|
||||
|
||||
bool GrAAConvexPathRenderer::canDrawPath(const GrDrawTarget::Caps& targetCaps,
|
||||
const SkPath& path,
|
||||
GrPathFill fill,
|
||||
bool antiAlias) const {
|
||||
return targetCaps.fShaderDerivativeSupport && antiAlias &&
|
||||
kHairLine_PathFill != fill && !GrIsFillInverted(fill) &&
|
||||
path.isConvex();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct Segment {
|
||||
|
@ -415,17 +406,38 @@ void create_vertices(const SegmentArray& segments,
|
|||
|
||||
}
|
||||
|
||||
void GrAAConvexPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
|
||||
GrAssert(fPath->isConvex());
|
||||
if (fPath->isEmpty()) {
|
||||
return;
|
||||
bool GrAAConvexPathRenderer::canDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target,
|
||||
bool antiAlias) const {
|
||||
if (!target->getCaps().fShaderDerivativeSupport || !antiAlias ||
|
||||
kHairLine_PathFill == fill || GrIsFillInverted(fill) ||
|
||||
!path.isConvex()) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
GrDrawState* drawState = fTarget->drawState();
|
||||
}
|
||||
|
||||
bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
bool antiAlias) {
|
||||
|
||||
|
||||
if (origPath.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
GrDrawState* drawState = target->drawState();
|
||||
|
||||
GrDrawTarget::AutoStateRestore asr;
|
||||
GrMatrix vm = drawState->getViewMatrix();
|
||||
vm.postTranslate(fTranslate.fX, fTranslate.fY);
|
||||
asr.set(fTarget);
|
||||
if (NULL != translate) {
|
||||
vm.postTranslate(translate->fX, translate->fY);
|
||||
}
|
||||
asr.set(target);
|
||||
GrMatrix ivm;
|
||||
if (vm.invert(&ivm)) {
|
||||
drawState->preConcatSamplerMatrices(stageMask, ivm);
|
||||
|
@ -433,7 +445,7 @@ void GrAAConvexPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
|
|||
drawState->setViewMatrix(GrMatrix::I());
|
||||
|
||||
SkPath path;
|
||||
fPath->transform(vm, &path);
|
||||
origPath.transform(vm, &path);
|
||||
|
||||
GrVertexLayout layout = 0;
|
||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||
|
@ -451,26 +463,27 @@ void GrAAConvexPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
|
|||
SegmentArray segments;
|
||||
SkPoint fanPt;
|
||||
if (!get_segments(path, &segments, &fanPt, &vCount, &iCount)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fTarget->reserveVertexSpace(layout,
|
||||
vCount,
|
||||
reinterpret_cast<void**>(&verts))) {
|
||||
return;
|
||||
if (!target->reserveVertexSpace(layout,
|
||||
vCount,
|
||||
reinterpret_cast<void**>(&verts))) {
|
||||
return false;
|
||||
}
|
||||
if (!fTarget->reserveIndexSpace(iCount, reinterpret_cast<void**>(&idxs))) {
|
||||
fTarget->resetVertexSource();
|
||||
return;
|
||||
if (!target->reserveIndexSpace(iCount, reinterpret_cast<void**>(&idxs))) {
|
||||
target->resetVertexSource();
|
||||
return false;
|
||||
}
|
||||
|
||||
create_vertices(segments, fanPt, verts, idxs);
|
||||
|
||||
drawState->setVertexEdgeType(GrDrawState::kQuad_EdgeType);
|
||||
fTarget->drawIndexed(kTriangles_PrimitiveType,
|
||||
0, // start vertex
|
||||
0, // start index
|
||||
vCount,
|
||||
iCount);
|
||||
target->drawIndexed(kTriangles_PrimitiveType,
|
||||
0, // start vertex
|
||||
0, // start index
|
||||
vCount,
|
||||
iCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,16 @@
|
|||
class GrAAConvexPathRenderer : public GrPathRenderer {
|
||||
public:
|
||||
GrAAConvexPathRenderer();
|
||||
bool canDrawPath(const GrDrawTarget::Caps& targetCaps,
|
||||
const SkPath& path,
|
||||
GrPathFill fill,
|
||||
bool antiAlias) const;
|
||||
void drawPath(GrDrawState::StageMask stageMask);
|
||||
|
||||
virtual bool canDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target,
|
||||
bool antiAlias) const SK_OVERRIDE;
|
||||
protected:
|
||||
virtual bool onDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
bool antiAlias) SK_OVERRIDE;
|
||||
};
|
||||
|
|
|
@ -99,7 +99,6 @@ GrAAHairLinePathRenderer::GrAAHairLinePathRenderer(
|
|||
linesIndexBuffer->ref();
|
||||
fQuadsIndexBuffer = quadsIndexBuffer;
|
||||
quadsIndexBuffer->ref();
|
||||
this->resetGeom();
|
||||
}
|
||||
|
||||
GrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() {
|
||||
|
@ -107,33 +106,6 @@ GrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() {
|
|||
fQuadsIndexBuffer->unref();
|
||||
}
|
||||
|
||||
bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget::Caps& targetCaps,
|
||||
const SkPath& path,
|
||||
GrPathFill fill,
|
||||
bool antiAlias) const {
|
||||
static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask |
|
||||
SkPath::kQuad_SegmentMask;
|
||||
return (kHairLine_PathFill == fill &&
|
||||
antiAlias &&
|
||||
(targetCaps.fShaderDerivativeSupport ||
|
||||
!(gReqDerivMask & path.getSegmentMasks())));
|
||||
}
|
||||
|
||||
void GrAAHairLinePathRenderer::pathWillClear() {
|
||||
this->resetGeom();
|
||||
}
|
||||
|
||||
void GrAAHairLinePathRenderer::resetGeom() {
|
||||
fPreviousStages = ~0;
|
||||
fPreviousRTHeight = ~0;
|
||||
fPreviousViewMatrix = GrMatrix::InvalidMatrix();
|
||||
fLineSegmentCnt = 0;
|
||||
fQuadCnt = 0;
|
||||
if ((fQuadCnt || fLineSegmentCnt) && NULL != fTarget) {
|
||||
fTarget->resetVertexSource();
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
typedef SkTArray<SkPoint, true> PtArray;
|
||||
|
@ -528,28 +500,23 @@ void add_line(const SkPoint p[2],
|
|||
|
||||
}
|
||||
|
||||
bool GrAAHairLinePathRenderer::createGeom(GrDrawState::StageMask stageMask) {
|
||||
const GrDrawState& drawState = fTarget->getDrawState();
|
||||
bool GrAAHairLinePathRenderer::createGeom(const SkPath& path,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
int* lineCnt,
|
||||
int* quadCnt) {
|
||||
const GrDrawState& drawState = target->getDrawState();
|
||||
int rtHeight = drawState.getRenderTarget()->height();
|
||||
|
||||
GrIRect clip;
|
||||
if (fTarget->getClip().hasConservativeBounds()) {
|
||||
GrRect clipRect = fTarget->getClip().getConservativeBounds();
|
||||
if (target->getClip().hasConservativeBounds()) {
|
||||
GrRect clipRect = target->getClip().getConservativeBounds();
|
||||
clipRect.roundOut(&clip);
|
||||
} else {
|
||||
clip.setLargest();
|
||||
}
|
||||
|
||||
// If none of the inputs that affect generation of path geometry have
|
||||
// have changed since last previous path draw then we can reuse the
|
||||
// previous geoemtry.
|
||||
if (stageMask == fPreviousStages &&
|
||||
fPreviousViewMatrix == drawState.getViewMatrix() &&
|
||||
fPreviousTranslate == fTranslate &&
|
||||
rtHeight == fPreviousRTHeight &&
|
||||
fClipRect == clip) {
|
||||
return true;
|
||||
}
|
||||
|
||||
GrVertexLayout layout = GrDrawTarget::kEdge_VertexLayoutBit;
|
||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||
|
@ -563,16 +530,20 @@ bool GrAAHairLinePathRenderer::createGeom(GrDrawState::StageMask stageMask) {
|
|||
PREALLOC_PTARRAY(128) lines;
|
||||
PREALLOC_PTARRAY(128) quads;
|
||||
IntArray qSubdivs;
|
||||
fQuadCnt = generate_lines_and_quads(*fPath, viewM, fTranslate, clip,
|
||||
static const GrVec gZeroVec = {0, 0};
|
||||
if (NULL == translate) {
|
||||
translate = &gZeroVec;
|
||||
}
|
||||
*quadCnt = generate_lines_and_quads(path, viewM, *translate, clip,
|
||||
&lines, &quads, &qSubdivs);
|
||||
|
||||
fLineSegmentCnt = lines.count() / 2;
|
||||
int vertCnt = kVertsPerLineSeg * fLineSegmentCnt + kVertsPerQuad * fQuadCnt;
|
||||
*lineCnt = lines.count() / 2;
|
||||
int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt;
|
||||
|
||||
GrAssert(sizeof(Vertex) == GrDrawTarget::VertexSize(layout));
|
||||
|
||||
Vertex* verts;
|
||||
if (!fTarget->reserveVertexSpace(layout, vertCnt, (void**)&verts)) {
|
||||
if (!target->reserveVertexSpace(layout, vertCnt, (void**)&verts)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -587,7 +558,7 @@ bool GrAAHairLinePathRenderer::createGeom(GrDrawState::StageMask stageMask) {
|
|||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < fLineSegmentCnt; ++i) {
|
||||
for (int i = 0; i < *lineCnt; ++i) {
|
||||
add_line(&lines[2*i], rtHeight, toSrc, &verts);
|
||||
}
|
||||
|
||||
|
@ -597,25 +568,50 @@ bool GrAAHairLinePathRenderer::createGeom(GrDrawState::StageMask stageMask) {
|
|||
add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts);
|
||||
}
|
||||
|
||||
fPreviousStages = stageMask;
|
||||
fPreviousViewMatrix = drawState.getViewMatrix();
|
||||
fPreviousRTHeight = rtHeight;
|
||||
fClipRect = clip;
|
||||
fPreviousTranslate = fTranslate;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrAAHairLinePathRenderer::drawPath(GrDrawState::StageMask stageMask) {
|
||||
|
||||
if (!this->createGeom(stageMask)) {
|
||||
return;
|
||||
bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target,
|
||||
bool antiAlias) const {
|
||||
if (fill != kHairLine_PathFill || !antiAlias) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GrDrawState* drawState = fTarget->drawState();
|
||||
static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask |
|
||||
SkPath::kQuad_SegmentMask;
|
||||
if (!target->getCaps().fShaderDerivativeSupport &&
|
||||
(gReqDerivMask & path.getSegmentMasks())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
bool antiAlias) {
|
||||
|
||||
int lineCnt;
|
||||
int quadCnt;
|
||||
|
||||
if (!this->createGeom(path,
|
||||
translate,
|
||||
target,
|
||||
stageMask,
|
||||
&lineCnt,
|
||||
&quadCnt)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GrDrawState* drawState = target->drawState();
|
||||
|
||||
GrDrawTarget::AutoStateRestore asr;
|
||||
if (!drawState->getViewMatrix().hasPerspective()) {
|
||||
asr.set(fTarget);
|
||||
asr.set(target);
|
||||
GrMatrix ivm;
|
||||
if (drawState->getViewInverse(&ivm)) {
|
||||
drawState->preConcatSamplerMatrices(stageMask, ivm);
|
||||
|
@ -625,32 +621,32 @@ void GrAAHairLinePathRenderer::drawPath(GrDrawState::StageMask stageMask) {
|
|||
|
||||
// TODO: See whether rendering lines as degenerate quads improves perf
|
||||
// when we have a mix
|
||||
fTarget->setIndexSourceToBuffer(fLinesIndexBuffer);
|
||||
target->setIndexSourceToBuffer(fLinesIndexBuffer);
|
||||
int lines = 0;
|
||||
int nBufLines = fLinesIndexBuffer->maxQuads();
|
||||
while (lines < fLineSegmentCnt) {
|
||||
int n = GrMin(fLineSegmentCnt-lines, nBufLines);
|
||||
while (lines < lineCnt) {
|
||||
int n = GrMin(lineCnt - lines, nBufLines);
|
||||
drawState->setVertexEdgeType(GrDrawState::kHairLine_EdgeType);
|
||||
fTarget->drawIndexed(kTriangles_PrimitiveType,
|
||||
kVertsPerLineSeg*lines, // startV
|
||||
0, // startI
|
||||
kVertsPerLineSeg*n, // vCount
|
||||
kIdxsPerLineSeg*n); // iCount
|
||||
target->drawIndexed(kTriangles_PrimitiveType,
|
||||
kVertsPerLineSeg*lines, // startV
|
||||
0, // startI
|
||||
kVertsPerLineSeg*n, // vCount
|
||||
kIdxsPerLineSeg*n); // iCount
|
||||
lines += n;
|
||||
}
|
||||
|
||||
fTarget->setIndexSourceToBuffer(fQuadsIndexBuffer);
|
||||
target->setIndexSourceToBuffer(fQuadsIndexBuffer);
|
||||
int quads = 0;
|
||||
while (quads < fQuadCnt) {
|
||||
int n = GrMin(fQuadCnt-quads, kNumQuadsInIdxBuffer);
|
||||
while (quads < quadCnt) {
|
||||
int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer);
|
||||
drawState->setVertexEdgeType(GrDrawState::kHairQuad_EdgeType);
|
||||
fTarget->drawIndexed(kTriangles_PrimitiveType,
|
||||
4*fLineSegmentCnt + kVertsPerQuad*quads, // startV
|
||||
0, // startI
|
||||
kVertsPerQuad*n, // vCount
|
||||
kIdxsPerQuad*n); // iCount
|
||||
target->drawIndexed(kTriangles_PrimitiveType,
|
||||
4 * lineCnt + kVertsPerQuad*quads, // startV
|
||||
0, // startI
|
||||
kVertsPerQuad*n, // vCount
|
||||
kIdxsPerQuad*n); // iCount
|
||||
quads += n;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,41 +16,35 @@ public:
|
|||
virtual ~GrAAHairLinePathRenderer();
|
||||
|
||||
static GrPathRenderer* Create(GrContext* context);
|
||||
// GrPathRenderer overrides
|
||||
virtual bool canDrawPath(const GrDrawTarget::Caps& targetCaps,
|
||||
const SkPath& path,
|
||||
GrPathFill fill,
|
||||
bool antiAlias) const SK_OVERRIDE;
|
||||
virtual void drawPath(GrDrawState::StageMask stages) SK_OVERRIDE;
|
||||
|
||||
virtual bool canDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target,
|
||||
bool antiAlias) const SK_OVERRIDE;
|
||||
protected:
|
||||
|
||||
// GrPathRenderer overrides
|
||||
virtual void pathWillClear() SK_OVERRIDE;
|
||||
|
||||
virtual bool onDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
bool antiAlias) SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
void resetGeom();
|
||||
|
||||
GrAAHairLinePathRenderer(const GrContext* context,
|
||||
const GrIndexBuffer* fLinesIndexBuffer,
|
||||
const GrIndexBuffer* fQuadsIndexBuffer);
|
||||
|
||||
bool createGeom(GrDrawState::StageMask stages);
|
||||
bool createGeom(const SkPath& path,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
int* lineCnt,
|
||||
int* quadCnt);
|
||||
|
||||
const GrIndexBuffer* fLinesIndexBuffer;
|
||||
const GrIndexBuffer* fQuadsIndexBuffer;
|
||||
|
||||
// have to recreate geometry if stages in use changes :(
|
||||
GrDrawState::StageMask fPreviousStages;
|
||||
int fPreviousRTHeight;
|
||||
SkVector fPreviousTranslate;
|
||||
GrIRect fClipRect;
|
||||
|
||||
// this path renderer draws everything in device coordinates
|
||||
GrMatrix fPreviousViewMatrix;
|
||||
int fLineSegmentCnt;
|
||||
int fQuadCnt;
|
||||
|
||||
typedef GrPathRenderer INHERITED;
|
||||
};
|
||||
|
||||
|
|
|
@ -1381,7 +1381,7 @@ void GrContext::drawPath(const GrPaint& paint, const GrPath& path,
|
|||
|
||||
GrPathRenderer* pr = NULL;
|
||||
if (prAA) {
|
||||
pr = this->getPathRenderer(path, fill, true);
|
||||
pr = this->getPathRenderer(path, fill, target, true);
|
||||
if (NULL == pr) {
|
||||
GrAutoScratchTexture ast;
|
||||
GrIRect pathBounds, clipBounds;
|
||||
|
@ -1422,7 +1422,7 @@ void GrContext::drawPath(const GrPaint& paint, const GrPath& path,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
pr = this->getPathRenderer(path, fill, false);
|
||||
pr = this->getPathRenderer(path, fill, target, false);
|
||||
}
|
||||
|
||||
if (NULL == pr) {
|
||||
|
@ -1432,9 +1432,7 @@ void GrContext::drawPath(const GrPaint& paint, const GrPath& path,
|
|||
return;
|
||||
}
|
||||
|
||||
GrPathRenderer::AutoClearPath arp(pr, target, &path, fill, prAA, translate);
|
||||
|
||||
pr->drawPath(stageMask);
|
||||
pr->drawPath(path, fill, translate, target, stageMask, prAA);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1884,13 +1882,13 @@ GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
|
|||
|
||||
GrPathRenderer* GrContext::getPathRenderer(const GrPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target,
|
||||
bool antiAlias) {
|
||||
if (NULL == fPathRendererChain) {
|
||||
fPathRendererChain =
|
||||
new GrPathRendererChain(this, GrPathRendererChain::kNone_UsageFlag);
|
||||
}
|
||||
return fPathRendererChain->getPathRenderer(fGpu->getCaps(), path,
|
||||
fill, antiAlias);
|
||||
return fPathRendererChain->getPathRenderer(path, fill, target, antiAlias);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -18,21 +18,7 @@
|
|||
GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport,
|
||||
bool stencilWrapOpsSupport)
|
||||
: fSeparateStencil(separateStencilSupport)
|
||||
, fStencilWrapOps(stencilWrapOpsSupport)
|
||||
, fSubpathCount(0)
|
||||
, fSubpathVertCount(0)
|
||||
, fPreviousSrcTol(-GR_Scalar1)
|
||||
, fPreviousStages(-1) {
|
||||
fTarget = NULL;
|
||||
}
|
||||
|
||||
bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget::Caps& targetCaps,
|
||||
const SkPath& path,
|
||||
GrPathFill fill,
|
||||
bool antiAlias) const {
|
||||
// this class can draw any path with any fill but doesn't do any
|
||||
// anti-aliasing.
|
||||
return !antiAlias;
|
||||
, fStencilWrapOps(stencilWrapOpsSupport) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -175,22 +161,12 @@ static inline bool single_pass_path(const GrPath& path, GrPathFill fill) {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool GrDefaultPathRenderer::requiresStencilPass(const GrDrawTarget* target,
|
||||
const GrPath& path,
|
||||
GrPathFill fill) const {
|
||||
bool GrDefaultPathRenderer::requiresStencilPass(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target) const {
|
||||
return !single_pass_path(path, fill);
|
||||
}
|
||||
|
||||
void GrDefaultPathRenderer::pathWillClear() {
|
||||
fSubpathVertCount.reset(0);
|
||||
fTarget->resetVertexSource();
|
||||
if (fUseIndexedDraw) {
|
||||
fTarget->resetIndexSource();
|
||||
}
|
||||
fPreviousSrcTol = -GR_Scalar1;
|
||||
fPreviousStages = -1;
|
||||
}
|
||||
|
||||
static inline void append_countour_edge_indices(GrPathFill fillType,
|
||||
uint16_t fanCenterIdx,
|
||||
uint16_t edgeV0Idx,
|
||||
|
@ -205,13 +181,21 @@ static inline void append_countour_edge_indices(GrPathFill fillType,
|
|||
*((*indices)++) = edgeV0Idx + 1;
|
||||
}
|
||||
|
||||
bool GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
|
||||
GrDrawState::StageMask stageMask) {
|
||||
bool GrDefaultPathRenderer::createGeom(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrScalar srcSpaceTol,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
GrPrimitiveType* primType,
|
||||
int* vertexCnt,
|
||||
int* indexCnt) {
|
||||
{
|
||||
SK_TRACE_EVENT0("GrDefaultPathRenderer::createGeom");
|
||||
|
||||
GrScalar srcSpaceTolSqd = GrMul(srcSpaceTol, srcSpaceTol);
|
||||
int maxPts = GrPathUtils::worstCasePointCount(*fPath, &fSubpathCount,
|
||||
int contourCnt;
|
||||
int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt,
|
||||
srcSpaceTol);
|
||||
|
||||
if (maxPts <= 0) {
|
||||
|
@ -229,27 +213,27 @@ bool GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
|
|||
}
|
||||
}
|
||||
|
||||
fUseIndexedDraw = fSubpathCount > 1;
|
||||
bool indexed = contourCnt > 1;
|
||||
|
||||
int maxIdxs = 0;
|
||||
if (kHairLine_PathFill == fFill) {
|
||||
if (fUseIndexedDraw) {
|
||||
if (kHairLine_PathFill == fill) {
|
||||
if (indexed) {
|
||||
maxIdxs = 2 * maxPts;
|
||||
fPrimitiveType = kLines_PrimitiveType;
|
||||
*primType = kLines_PrimitiveType;
|
||||
} else {
|
||||
fPrimitiveType = kLineStrip_PrimitiveType;
|
||||
*primType = kLineStrip_PrimitiveType;
|
||||
}
|
||||
} else {
|
||||
if (fUseIndexedDraw) {
|
||||
if (indexed) {
|
||||
maxIdxs = 3 * maxPts;
|
||||
fPrimitiveType = kTriangles_PrimitiveType;
|
||||
*primType = kTriangles_PrimitiveType;
|
||||
} else {
|
||||
fPrimitiveType = kTriangleFan_PrimitiveType;
|
||||
*primType = kTriangleFan_PrimitiveType;
|
||||
}
|
||||
}
|
||||
|
||||
GrPoint* base;
|
||||
if (!fTarget->reserveVertexSpace(layout, maxPts, (void**)&base)) {
|
||||
if (!target->reserveVertexSpace(layout, maxPts, (void**)&base)) {
|
||||
return false;
|
||||
}
|
||||
GrAssert(NULL != base);
|
||||
|
@ -258,23 +242,21 @@ bool GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
|
|||
uint16_t* idxBase = NULL;
|
||||
uint16_t* idx = NULL;
|
||||
uint16_t subpathIdxStart = 0;
|
||||
if (fUseIndexedDraw) {
|
||||
if (!fTarget->reserveIndexSpace(maxIdxs, (void**)&idxBase)) {
|
||||
fTarget->resetVertexSource();
|
||||
if (indexed) {
|
||||
if (!target->reserveIndexSpace(maxIdxs, (void**)&idxBase)) {
|
||||
target->resetVertexSource();
|
||||
return false;
|
||||
}
|
||||
GrAssert(NULL != idxBase);
|
||||
idx = idxBase;
|
||||
}
|
||||
|
||||
fSubpathVertCount.reset(fSubpathCount);
|
||||
|
||||
GrPoint pts[4];
|
||||
|
||||
bool first = true;
|
||||
int subpath = 0;
|
||||
|
||||
SkPath::Iter iter(*fPath, false);
|
||||
SkPath::Iter iter(path, false);
|
||||
|
||||
for (;;) {
|
||||
GrPathCmd cmd = (GrPathCmd)iter.next(pts);
|
||||
|
@ -282,7 +264,6 @@ bool GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
|
|||
case kMove_PathCmd:
|
||||
if (!first) {
|
||||
uint16_t currIdx = (uint16_t) (vert - base);
|
||||
fSubpathVertCount[subpath] = currIdx - subpathIdxStart;
|
||||
subpathIdxStart = currIdx;
|
||||
++subpath;
|
||||
}
|
||||
|
@ -290,9 +271,9 @@ bool GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
|
|||
vert++;
|
||||
break;
|
||||
case kLine_PathCmd:
|
||||
if (fUseIndexedDraw) {
|
||||
if (indexed) {
|
||||
uint16_t prevIdx = (uint16_t)(vert - base) - 1;
|
||||
append_countour_edge_indices(fFill, subpathIdxStart,
|
||||
append_countour_edge_indices(fill, subpathIdxStart,
|
||||
prevIdx, &idx);
|
||||
}
|
||||
*(vert++) = pts[1];
|
||||
|
@ -305,9 +286,9 @@ bool GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
|
|||
pts[0], pts[1], pts[2],
|
||||
srcSpaceTolSqd, &vert,
|
||||
GrPathUtils::quadraticPointCount(pts, srcSpaceTol));
|
||||
if (fUseIndexedDraw) {
|
||||
if (indexed) {
|
||||
for (uint16_t i = 0; i < numPts; ++i) {
|
||||
append_countour_edge_indices(fFill, subpathIdxStart,
|
||||
append_countour_edge_indices(fill, subpathIdxStart,
|
||||
firstQPtIdx + i, &idx);
|
||||
}
|
||||
}
|
||||
|
@ -320,9 +301,9 @@ bool GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
|
|||
pts[0], pts[1], pts[2], pts[3],
|
||||
srcSpaceTolSqd, &vert,
|
||||
GrPathUtils::cubicPointCount(pts, srcSpaceTol));
|
||||
if (fUseIndexedDraw) {
|
||||
if (indexed) {
|
||||
for (uint16_t i = 0; i < numPts; ++i) {
|
||||
append_countour_edge_indices(fFill, subpathIdxStart,
|
||||
append_countour_edge_indices(fill, subpathIdxStart,
|
||||
firstCPtIdx + i, &idx);
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +313,6 @@ bool GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
|
|||
break;
|
||||
case kEnd_PathCmd:
|
||||
uint16_t currIdx = (uint16_t) (vert - base);
|
||||
fSubpathVertCount[subpath] = currIdx - subpathIdxStart;
|
||||
goto FINISHED;
|
||||
}
|
||||
first = false;
|
||||
|
@ -341,49 +321,49 @@ FINISHED:
|
|||
GrAssert((vert - base) <= maxPts);
|
||||
GrAssert((idx - idxBase) <= maxIdxs);
|
||||
|
||||
fVertexCnt = vert - base;
|
||||
fIndexCnt = idx - idxBase;
|
||||
*vertexCnt = vert - base;
|
||||
*indexCnt = idx - idxBase;
|
||||
|
||||
if (fTranslate.fX || fTranslate.fY) {
|
||||
if (NULL != translate &&
|
||||
(translate->fX || translate->fY)) {
|
||||
int count = vert - base;
|
||||
for (int i = 0; i < count; i++) {
|
||||
base[i].offset(fTranslate.fX, fTranslate.fY);
|
||||
base[i].offset(translate->fX, translate->fY);
|
||||
}
|
||||
}
|
||||
}
|
||||
// set these at the end so if we failed on first drawPath inside a
|
||||
// setPath/clearPath block we won't assume geom was created on a subsequent
|
||||
// drawPath in the same block.
|
||||
fPreviousSrcTol = srcSpaceTol;
|
||||
fPreviousStages = stageMask;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
|
||||
bool stencilOnly) {
|
||||
bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
bool stencilOnly) {
|
||||
|
||||
GrMatrix viewM = fTarget->getDrawState().getViewMatrix();
|
||||
GrMatrix viewM = target->getDrawState().getViewMatrix();
|
||||
GrScalar tol = GR_Scalar1;
|
||||
tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, fPath->getBounds());
|
||||
GrDrawState* drawState = fTarget->drawState();
|
||||
tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, path.getBounds());
|
||||
GrDrawState* drawState = target->drawState();
|
||||
|
||||
// FIXME: It's really dumb that we recreate the verts for a new vertex
|
||||
// layout. We only do that because the GrDrawTarget API doesn't allow
|
||||
// us to change the vertex layout after reserveVertexSpace(). We won't
|
||||
// actually change the vertex data when the layout changes since all the
|
||||
// stages reference the positions (rather than having separate tex coords)
|
||||
// and we don't ever have per-vert colors. In practice our call sites
|
||||
// won't change the stages in use inside a setPath / removePath pair. But
|
||||
// it is a silly limitation of the GrDrawTarget design that should be fixed.
|
||||
if (tol != fPreviousSrcTol ||
|
||||
stageMask != fPreviousStages) {
|
||||
if (!this->createGeom(tol, stageMask)) {
|
||||
return;
|
||||
}
|
||||
int vertexCnt;
|
||||
int indexCnt;
|
||||
GrPrimitiveType primType;
|
||||
if (!this->createGeom(path,
|
||||
fill,
|
||||
translate,
|
||||
tol,
|
||||
target,
|
||||
stageMask,
|
||||
&primType,
|
||||
&vertexCnt,
|
||||
&indexCnt)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GrAssert(NULL != fTarget);
|
||||
GrDrawTarget::AutoStateRestore asr(fTarget);
|
||||
GrAssert(NULL != target);
|
||||
GrDrawTarget::AutoStateRestore asr(target);
|
||||
bool colorWritesWereDisabled = drawState->isColorWriteDisabled();
|
||||
// face culling doesn't make sense here
|
||||
GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
|
||||
|
@ -394,7 +374,7 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
|
|||
bool reverse = false;
|
||||
bool lastPassIsBounds;
|
||||
|
||||
if (kHairLine_PathFill == fFill) {
|
||||
if (kHairLine_PathFill == fill) {
|
||||
passCount = 1;
|
||||
if (stencilOnly) {
|
||||
passes[0] = &gDirectToStencil;
|
||||
|
@ -404,7 +384,7 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
|
|||
lastPassIsBounds = false;
|
||||
drawFace[0] = GrDrawState::kBoth_DrawFace;
|
||||
} else {
|
||||
if (single_pass_path(*fPath, fFill)) {
|
||||
if (single_pass_path(path, fill)) {
|
||||
passCount = 1;
|
||||
if (stencilOnly) {
|
||||
passes[0] = &gDirectToStencil;
|
||||
|
@ -414,7 +394,7 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
|
|||
drawFace[0] = GrDrawState::kBoth_DrawFace;
|
||||
lastPassIsBounds = false;
|
||||
} else {
|
||||
switch (fFill) {
|
||||
switch (fill) {
|
||||
case kInverseEvenOdd_PathFill:
|
||||
reverse = true;
|
||||
// fallthrough
|
||||
|
@ -475,7 +455,7 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
|
|||
break;
|
||||
default:
|
||||
GrAssert(!"Unknown path fFill!");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -507,44 +487,63 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
|
|||
if (stageMask) {
|
||||
if (!drawState->getViewInverse(&vmi)) {
|
||||
GrPrintf("Could not invert matrix.");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
drawState->preConcatSamplerMatrices(stageMask, vmi);
|
||||
}
|
||||
drawState->setViewMatrix(GrMatrix::I());
|
||||
}
|
||||
} else {
|
||||
bounds = fPath->getBounds();
|
||||
bounds.offset(fTranslate);
|
||||
bounds = path.getBounds();
|
||||
if (NULL != translate) {
|
||||
bounds.offset(*translate);
|
||||
}
|
||||
}
|
||||
GrDrawTarget::AutoGeometryPush agp(fTarget);
|
||||
fTarget->drawSimpleRect(bounds, NULL, stageMask);
|
||||
GrDrawTarget::AutoGeometryPush agp(target);
|
||||
target->drawSimpleRect(bounds, NULL, stageMask);
|
||||
} else {
|
||||
if (passCount > 1) {
|
||||
drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
|
||||
}
|
||||
if (fUseIndexedDraw) {
|
||||
fTarget->drawIndexed(fPrimitiveType, 0, 0,
|
||||
fVertexCnt, fIndexCnt);
|
||||
if (indexCnt) {
|
||||
target->drawIndexed(primType, 0, 0,
|
||||
vertexCnt, indexCnt);
|
||||
} else {
|
||||
int baseVertex = 0;
|
||||
for (int sp = 0; sp < fSubpathCount; ++sp) {
|
||||
fTarget->drawNonIndexed(fPrimitiveType, baseVertex,
|
||||
fSubpathVertCount[sp]);
|
||||
baseVertex += fSubpathVertCount[sp];
|
||||
}
|
||||
target->drawNonIndexed(primType, 0, vertexCnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrDefaultPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
|
||||
this->onDrawPath(stageMask, false);
|
||||
bool GrDefaultPathRenderer::canDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target,
|
||||
bool antiAlias) const {
|
||||
// this class can draw any path with any fill but doesn't do any
|
||||
// anti-aliasing.
|
||||
return !antiAlias;
|
||||
}
|
||||
|
||||
void GrDefaultPathRenderer::drawPathToStencil() {
|
||||
GrAssert(kInverseEvenOdd_PathFill != fFill);
|
||||
GrAssert(kInverseWinding_PathFill != fFill);
|
||||
this->onDrawPath(0, true);
|
||||
bool GrDefaultPathRenderer::onDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
bool antiAlias) {
|
||||
return this->internalDrawPath(path,
|
||||
fill,
|
||||
translate,
|
||||
target,
|
||||
stageMask,
|
||||
false);
|
||||
}
|
||||
|
||||
void GrDefaultPathRenderer::drawPathToStencil(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
GrDrawTarget* target) {
|
||||
GrAssert(kInverseEvenOdd_PathFill != fill);
|
||||
GrAssert(kInverseWinding_PathFill != fill);
|
||||
this->internalDrawPath(path, fill, NULL, target, 0, true);
|
||||
}
|
||||
|
|
|
@ -20,40 +20,49 @@ public:
|
|||
GrDefaultPathRenderer(bool separateStencilSupport,
|
||||
bool stencilWrapOpsSupport);
|
||||
|
||||
virtual bool canDrawPath(const GrDrawTarget::Caps& targetCaps,
|
||||
const SkPath& path,
|
||||
GrPathFill fill,
|
||||
bool antiAlias) const SK_OVERRIDE;
|
||||
|
||||
virtual bool requiresStencilPass(const GrDrawTarget* target,
|
||||
const SkPath& path,
|
||||
GrPathFill fill) const SK_OVERRIDE;
|
||||
virtual bool requiresStencilPass(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target) const SK_OVERRIDE;
|
||||
|
||||
virtual void drawPath(GrDrawState::StageMask stageMask) SK_OVERRIDE;
|
||||
virtual void drawPathToStencil() SK_OVERRIDE;
|
||||
virtual bool canDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target,
|
||||
bool antiAlias) const SK_OVERRIDE;
|
||||
|
||||
protected:
|
||||
virtual void pathWillClear();
|
||||
virtual void drawPathToStencil(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
GrDrawTarget* target) SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
|
||||
void onDrawPath(GrDrawState::StageMask stages, bool stencilOnly);
|
||||
virtual bool onDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
bool antiAlias) SK_OVERRIDE;
|
||||
|
||||
bool createGeom(GrScalar srcSpaceTol,
|
||||
GrDrawState::StageMask stages);
|
||||
bool internalDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
bool stencilOnly);
|
||||
|
||||
bool createGeom(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrScalar srcSpaceTol,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stages,
|
||||
GrPrimitiveType* primType,
|
||||
int* vertexCnt,
|
||||
int* indexCnt);
|
||||
|
||||
bool fSeparateStencil;
|
||||
bool fStencilWrapOps;
|
||||
|
||||
int fSubpathCount;
|
||||
SkAutoSTMalloc<8, uint16_t> fSubpathVertCount;
|
||||
int fIndexCnt;
|
||||
int fVertexCnt;
|
||||
GrScalar fPreviousSrcTol;
|
||||
GrDrawState::StageMask fPreviousStages;
|
||||
GrPrimitiveType fPrimitiveType;
|
||||
bool fUseIndexedDraw;
|
||||
|
||||
typedef GrPathRenderer INHERITED;
|
||||
};
|
||||
|
||||
|
|
|
@ -632,7 +632,6 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
|
|||
|
||||
GrPathRenderer* pr = NULL;
|
||||
const GrPath* clipPath = NULL;
|
||||
GrPathRenderer::AutoClearPath arp;
|
||||
if (kRect_ClipType == clip.getElementType(c)) {
|
||||
canRenderDirectToStencil = true;
|
||||
fill = kEvenOdd_PathFill;
|
||||
|
@ -655,8 +654,7 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
|
|||
return false;
|
||||
}
|
||||
canRenderDirectToStencil =
|
||||
!pr->requiresStencilPass(this, *clipPath, fill);
|
||||
arp.set(pr, this, clipPath, fill, false, NULL);
|
||||
!pr->requiresStencilPass(*clipPath, fill, this);
|
||||
}
|
||||
|
||||
GrSetOp op = (c == start) ? startOp : clip.getOp(c);
|
||||
|
@ -690,9 +688,9 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
|
|||
} else {
|
||||
if (canRenderDirectToStencil) {
|
||||
*drawState->stencil() = gDrawToStencil;
|
||||
pr->drawPath(0);
|
||||
pr->drawPath(*clipPath, fill, NULL, this, 0, false);
|
||||
} else {
|
||||
pr->drawPathToStencil();
|
||||
pr->drawPathToStencil(*clipPath, fill, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -708,7 +706,7 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
|
|||
this->drawSimpleRect(clip.getRect(c), NULL, 0);
|
||||
} else {
|
||||
SET_RANDOM_COLOR
|
||||
pr->drawPath(0);
|
||||
pr->drawPath(*clipPath, fill, NULL, this, 0, false);
|
||||
}
|
||||
} else {
|
||||
SET_RANDOM_COLOR
|
||||
|
@ -739,8 +737,7 @@ GrPathRenderer* GrGpu::getClipPathRenderer(const GrPath& path,
|
|||
new GrPathRendererChain(this->getContext(),
|
||||
GrPathRendererChain::kNonAAOnly_UsageFlag);
|
||||
}
|
||||
return fPathRendererChain->getPathRenderer(this->getCaps(),
|
||||
path, fill, false);
|
||||
return fPathRendererChain->getPathRenderer(path, fill, this, false);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,36 +8,6 @@
|
|||
|
||||
#include "GrPathRenderer.h"
|
||||
|
||||
GrPathRenderer::GrPathRenderer()
|
||||
: fPath(NULL)
|
||||
, fTarget(NULL) {
|
||||
GrPathRenderer::GrPathRenderer() {
|
||||
}
|
||||
|
||||
void GrPathRenderer::setPath(GrDrawTarget* target,
|
||||
const SkPath* path,
|
||||
GrPathFill fill,
|
||||
bool antiAlias,
|
||||
const GrPoint* translate) {
|
||||
GrAssert(NULL == fPath);
|
||||
GrAssert(NULL == fTarget);
|
||||
GrAssert(NULL != target);
|
||||
|
||||
fTarget = target;
|
||||
fPath = path;
|
||||
fFill = fill;
|
||||
fAntiAlias = antiAlias;
|
||||
if (NULL != translate) {
|
||||
fTranslate = *translate;
|
||||
} else {
|
||||
fTranslate.fX = fTranslate.fY = 0;
|
||||
}
|
||||
this->pathWasSet();
|
||||
}
|
||||
|
||||
void GrPathRenderer::clearPath() {
|
||||
this->pathWillClear();
|
||||
fTarget->resetVertexSource();
|
||||
fTarget->resetIndexSource();
|
||||
fTarget = NULL;
|
||||
fPath = NULL;
|
||||
}
|
||||
|
|
|
@ -49,25 +49,7 @@ public:
|
|||
GrPathRendererChain* prChain);
|
||||
|
||||
|
||||
GrPathRenderer(void);
|
||||
/**
|
||||
* Returns true if this path renderer is able to render the path.
|
||||
* Returning false allows the caller to fallback to another path renderer.
|
||||
* When searching for a path renderer capable of rendering a path this
|
||||
* function is called.
|
||||
*
|
||||
* @param targetCaps The caps of the draw target that will be used to draw
|
||||
* the path.
|
||||
* @param path The path to draw
|
||||
* @param fill The fill rule to use
|
||||
* @param antiAlias True if anti-aliasing is required.
|
||||
*
|
||||
* @return true if the path can be drawn by this object, false otherwise.
|
||||
*/
|
||||
virtual bool canDrawPath(const GrDrawTarget::Caps& targetCaps,
|
||||
const SkPath& path,
|
||||
GrPathFill fill,
|
||||
bool antiAlias) const = 0;
|
||||
GrPathRenderer();
|
||||
|
||||
/**
|
||||
* For complex clips Gr uses the stencil buffer. The path renderer must be
|
||||
|
@ -90,54 +72,37 @@ public:
|
|||
* returns true the drawPathToStencil will be used when rendering
|
||||
* clips.
|
||||
*/
|
||||
virtual bool requiresStencilPass(const GrDrawTarget* target,
|
||||
const SkPath& path,
|
||||
GrPathFill fill) const { return false; }
|
||||
|
||||
/**
|
||||
* Sets the path to render and target to render into. All calls to drawPath
|
||||
* and drawPathToStencil must occur between setPath and clearPath. The
|
||||
* path cannot be modified externally between setPath and clearPath. The
|
||||
* path may be drawn several times (e.g. tiled supersampler). The target's
|
||||
* state may change between setPath and drawPath* calls. However, if the
|
||||
* path renderer specified vertices/indices during setPath or drawPath*
|
||||
* they will still be set at subsequent drawPath* calls until the next
|
||||
* clearPath. The target's draw state may change between drawPath* calls
|
||||
* so if the subclass does any caching of tesselation, etc. then it must
|
||||
* validate that target parameters that guided the decisions still hold.
|
||||
*
|
||||
* @param target the target to draw into.
|
||||
* @param path the path to draw.
|
||||
* @param fill the fill rule to apply.
|
||||
* @param antiAlias perform antiAliasing when drawing the path.
|
||||
* @param translate optional additional translation to apply to
|
||||
* the path. NULL means (0,0).
|
||||
*/
|
||||
void setPath(GrDrawTarget* target,
|
||||
const SkPath* path,
|
||||
GrPathFill fill,
|
||||
bool antiAlias,
|
||||
const GrPoint* translate);
|
||||
|
||||
/**
|
||||
* Notifies path renderer that path set in setPath is no longer in use.
|
||||
*/
|
||||
void clearPath();
|
||||
virtual bool requiresStencilPass(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool canDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target,
|
||||
bool antiAlias) const = 0;
|
||||
/**
|
||||
* Draws the path into the draw target. If requiresStencilBuffer returned
|
||||
* false then the target may be setup for stencil rendering (since the
|
||||
* path renderer didn't claim that it needs to use the stencil internally).
|
||||
*
|
||||
* Only called between setPath / clearPath.
|
||||
*
|
||||
* @param stages bitfield that indicates which stages are
|
||||
* in use. All enabled stages expect positions
|
||||
* as texture coordinates. The path renderer
|
||||
* use the remaining stages for its path
|
||||
* filling algorithm.
|
||||
*/
|
||||
virtual void drawPath(GrDrawState::StageMask stageMask) = 0;
|
||||
virtual bool drawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
bool antiAlias) {
|
||||
GrAssert(this->canDrawPath(path, fill, target, antiAlias));
|
||||
return this->onDrawPath(path, fill, translate,
|
||||
target, stageMask, antiAlias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the path to the stencil buffer. Assume the writable stencil bits
|
||||
|
@ -150,64 +115,20 @@ public:
|
|||
* The default implementation assumes the path filling algorithm doesn't
|
||||
* require a separate stencil pass and so crashes.
|
||||
*
|
||||
* Only called between setPath / clearPath.
|
||||
*/
|
||||
virtual void drawPathToStencil() {
|
||||
virtual void drawPathToStencil(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
GrDrawTarget* target) {
|
||||
GrCrash("Unexpected call to drawPathToStencil.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper that sets a path and automatically remove it in destructor.
|
||||
*/
|
||||
class AutoClearPath {
|
||||
public:
|
||||
AutoClearPath() {
|
||||
fPathRenderer = NULL;
|
||||
}
|
||||
AutoClearPath(GrPathRenderer* pr,
|
||||
GrDrawTarget* target,
|
||||
const SkPath* path,
|
||||
GrPathFill fill,
|
||||
bool antiAlias,
|
||||
const GrPoint* translate) {
|
||||
GrAssert(NULL != pr);
|
||||
pr->setPath(target, path, fill, antiAlias, translate);
|
||||
fPathRenderer = pr;
|
||||
}
|
||||
void set(GrPathRenderer* pr,
|
||||
GrDrawTarget* target,
|
||||
const SkPath* path,
|
||||
GrPathFill fill,
|
||||
bool antiAlias,
|
||||
const GrPoint* translate) {
|
||||
if (NULL != fPathRenderer) {
|
||||
fPathRenderer->clearPath();
|
||||
}
|
||||
GrAssert(NULL != pr);
|
||||
pr->setPath(target, path, fill, antiAlias, translate);
|
||||
fPathRenderer = pr;
|
||||
}
|
||||
~AutoClearPath() {
|
||||
if (NULL != fPathRenderer) {
|
||||
fPathRenderer->clearPath();
|
||||
}
|
||||
}
|
||||
private:
|
||||
GrPathRenderer* fPathRenderer;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
// subclass can override these to be notified just after a path is set
|
||||
// and just before the path is cleared.
|
||||
virtual void pathWasSet() {}
|
||||
virtual void pathWillClear() {}
|
||||
|
||||
const SkPath* fPath;
|
||||
GrDrawTarget* fTarget;
|
||||
GrPathFill fFill;
|
||||
GrPoint fTranslate;
|
||||
bool fAntiAlias;
|
||||
virtual bool onDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
bool antiAlias) = 0;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -31,16 +31,15 @@ GrPathRenderer* GrPathRendererChain::addPathRenderer(GrPathRenderer* pr) {
|
|||
return pr;
|
||||
}
|
||||
|
||||
GrPathRenderer* GrPathRendererChain::getPathRenderer(
|
||||
const GrDrawTarget::Caps& targetCaps,
|
||||
const GrPath& path,
|
||||
GrPathFill fill,
|
||||
bool antiAlias) {
|
||||
GrPathRenderer* GrPathRendererChain::getPathRenderer(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target,
|
||||
bool antiAlias) {
|
||||
if (!fInit) {
|
||||
this->init();
|
||||
}
|
||||
for (int i = 0; i < fChain.count(); ++i) {
|
||||
if (fChain[i]->canDrawPath(targetCaps, path, fill, antiAlias)) {
|
||||
if (fChain[i]->canDrawPath(path, fill, target, antiAlias)) {
|
||||
return fChain[i];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,9 +40,9 @@ public:
|
|||
// takes a ref and unrefs in destructor
|
||||
GrPathRenderer* addPathRenderer(GrPathRenderer* pr);
|
||||
|
||||
GrPathRenderer* getPathRenderer(const GrDrawTarget::Caps& targetCaps,
|
||||
const SkPath& path,
|
||||
GrPathRenderer* getPathRenderer(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target,
|
||||
bool antiAlias);
|
||||
|
||||
private:
|
||||
|
|
|
@ -347,20 +347,26 @@ static size_t computeEdgesAndIntersect(const GrMatrix& matrix,
|
|||
return edges->count();
|
||||
}
|
||||
|
||||
void GrTesselatedPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
|
||||
GrDrawTarget::AutoStateRestore asr(fTarget);
|
||||
GrDrawState* drawState = fTarget->drawState();
|
||||
bool GrTesselatedPathRenderer::onDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
bool antiAlias) {
|
||||
|
||||
GrDrawTarget::AutoStateRestore asr(target);
|
||||
GrDrawState* drawState = target->drawState();
|
||||
// face culling doesn't make sense here
|
||||
GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
|
||||
|
||||
GrMatrix viewM = drawState->getViewMatrix();
|
||||
|
||||
GrScalar tol = GR_Scalar1;
|
||||
tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, fPath->getBounds());
|
||||
tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, path.getBounds());
|
||||
GrScalar tolSqd = GrMul(tol, tol);
|
||||
|
||||
int subpathCnt;
|
||||
int maxPts = GrPathUtils::worstCasePointCount(*fPath, &subpathCnt, tol);
|
||||
int maxPts = GrPathUtils::worstCasePointCount(path, &subpathCnt, tol);
|
||||
|
||||
GrVertexLayout layout = 0;
|
||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||
|
@ -369,13 +375,13 @@ void GrTesselatedPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
|
|||
}
|
||||
}
|
||||
|
||||
bool inverted = GrIsFillInverted(fFill);
|
||||
bool inverted = GrIsFillInverted(fill);
|
||||
if (inverted) {
|
||||
maxPts += 4;
|
||||
subpathCnt++;
|
||||
}
|
||||
if (maxPts > USHRT_MAX) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
SkAutoSTMalloc<8, GrPoint> baseMem(maxPts);
|
||||
GrPoint* base = baseMem;
|
||||
|
@ -385,7 +391,7 @@ void GrTesselatedPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
|
|||
SkAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt);
|
||||
|
||||
GrPoint pts[4];
|
||||
SkPath::Iter iter(*fPath, false);
|
||||
SkPath::Iter iter(path, false);
|
||||
|
||||
bool first = true;
|
||||
int subpath = 0;
|
||||
|
@ -427,9 +433,9 @@ void GrTesselatedPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
|
|||
first = false;
|
||||
}
|
||||
FINISHED:
|
||||
if (0 != fTranslate.fX || 0 != fTranslate.fY) {
|
||||
if (NULL != translate && 0 != translate->fX && 0 != translate->fY) {
|
||||
for (int i = 0; i < vert - base; i++) {
|
||||
base[i].offset(fTranslate.fX, fTranslate.fY);
|
||||
base[i].offset(translate->fX, translate->fY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,25 +462,25 @@ FINISHED:
|
|||
size_t count = vert - base;
|
||||
|
||||
if (count < 3) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (subpathCnt == 1 && !inverted && fPath->isConvex()) {
|
||||
if (fAntiAlias) {
|
||||
if (subpathCnt == 1 && !inverted && path.isConvex()) {
|
||||
if (antiAlias) {
|
||||
GrEdgeArray edges;
|
||||
GrMatrix inverse, matrix = drawState->getViewMatrix();
|
||||
drawState->getViewInverse(&inverse);
|
||||
|
||||
count = computeEdgesAndIntersect(matrix, inverse, base, count, &edges, 0.0f);
|
||||
size_t maxEdges = fTarget->getMaxEdges();
|
||||
size_t maxEdges = target->getMaxEdges();
|
||||
if (count == 0) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (count <= maxEdges) {
|
||||
// All edges fit; upload all edges and draw all verts as a fan
|
||||
fTarget->setVertexSourceToArray(layout, base, count);
|
||||
target->setVertexSourceToArray(layout, base, count);
|
||||
drawState->setEdgeAAData(&edges[0], count);
|
||||
fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);
|
||||
target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);
|
||||
} else {
|
||||
// Upload "maxEdges" edges and verts at a time, and draw as
|
||||
// separate fans
|
||||
|
@ -482,31 +488,31 @@ FINISHED:
|
|||
edges[i] = edges[0];
|
||||
base[i] = base[0];
|
||||
int size = GR_CT_MIN(count - i, maxEdges);
|
||||
fTarget->setVertexSourceToArray(layout, &base[i], size);
|
||||
target->setVertexSourceToArray(layout, &base[i], size);
|
||||
drawState->setEdgeAAData(&edges[i], size);
|
||||
fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, size);
|
||||
target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, size);
|
||||
}
|
||||
}
|
||||
drawState->setEdgeAAData(NULL, 0);
|
||||
} else {
|
||||
fTarget->setVertexSourceToArray(layout, base, count);
|
||||
fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);
|
||||
target->setVertexSourceToArray(layout, base, count);
|
||||
target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fAntiAlias) {
|
||||
if (antiAlias) {
|
||||
// Run the tesselator once to get the boundaries.
|
||||
GrBoundaryTess btess(count, fill_type_to_glu_winding_rule(fFill));
|
||||
GrBoundaryTess btess(count, fill_type_to_glu_winding_rule(fill));
|
||||
btess.addVertices(base, subpathVertCount, subpathCnt);
|
||||
|
||||
GrMatrix inverse, matrix = drawState->getViewMatrix();
|
||||
if (!drawState->getViewInverse(&inverse)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (btess.vertices().count() > USHRT_MAX) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Inflate the boundary, and run the tesselator again to generate
|
||||
|
@ -532,7 +538,7 @@ FINISHED:
|
|||
Sk_gluTessEndPolygon(ptess.tess());
|
||||
|
||||
if (ptess.vertices().count() > USHRT_MAX) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Draw the resulting polys and upload their edge data.
|
||||
|
@ -570,37 +576,34 @@ FINISHED:
|
|||
tri_edges[t++] = edge5;
|
||||
}
|
||||
drawState->setEdgeAAData(&tri_edges[0], t);
|
||||
fTarget->setVertexSourceToArray(layout, &tri_verts[0], 3);
|
||||
fTarget->drawNonIndexed(kTriangles_PrimitiveType, 0, 3);
|
||||
target->setVertexSourceToArray(layout, &tri_verts[0], 3);
|
||||
target->drawNonIndexed(kTriangles_PrimitiveType, 0, 3);
|
||||
}
|
||||
drawState->setEdgeAAData(NULL, 0);
|
||||
drawState->disableState(GrDrawState::kEdgeAAConcave_StateBit);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
GrPolygonTess ptess(count, fill_type_to_glu_winding_rule(fFill));
|
||||
GrPolygonTess ptess(count, fill_type_to_glu_winding_rule(fill));
|
||||
ptess.addVertices(base, subpathVertCount, subpathCnt);
|
||||
const GrPointArray& vertices = ptess.vertices();
|
||||
const GrIndexArray& indices = ptess.indices();
|
||||
if (indices.count() > 0) {
|
||||
fTarget->setVertexSourceToArray(layout, vertices.begin(), vertices.count());
|
||||
fTarget->setIndexSourceToArray(indices.begin(), indices.count());
|
||||
fTarget->drawIndexed(kTriangles_PrimitiveType,
|
||||
target->setVertexSourceToArray(layout, vertices.begin(), vertices.count());
|
||||
target->setIndexSourceToArray(indices.begin(), indices.count());
|
||||
target->drawIndexed(kTriangles_PrimitiveType,
|
||||
0,
|
||||
0,
|
||||
vertices.count(),
|
||||
indices.count());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrTesselatedPathRenderer::canDrawPath(const GrDrawTarget::Caps& caps,
|
||||
const SkPath& path,
|
||||
bool GrTesselatedPathRenderer::canDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target,
|
||||
bool antiAlias) const {
|
||||
return kHairLine_PathFill != fill;
|
||||
}
|
||||
|
||||
void GrTesselatedPathRenderer::drawPathToStencil() {
|
||||
GrAlwaysAssert(!"multipass stencil should not be needed");
|
||||
}
|
||||
|
||||
|
|
|
@ -16,12 +16,17 @@ class GrTesselatedPathRenderer : public GrPathRenderer {
|
|||
public:
|
||||
GrTesselatedPathRenderer();
|
||||
|
||||
virtual void drawPath(GrDrawState::StageMask stageMask);
|
||||
virtual bool canDrawPath(const GrDrawTarget::Caps& targetCaps,
|
||||
const GrPath& path,
|
||||
virtual bool canDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrDrawTarget* target,
|
||||
bool antiAlias) const SK_OVERRIDE;
|
||||
virtual void drawPathToStencil() SK_OVERRIDE;
|
||||
|
||||
virtual bool onDrawPath(const SkPath& path,
|
||||
GrPathFill fill,
|
||||
const GrVec* translate,
|
||||
GrDrawTarget* target,
|
||||
GrDrawState::StageMask stageMask,
|
||||
bool antiAlias) SK_OVERRIDE;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -102,7 +102,6 @@ bool GrGLVertexBuffer::updateData(const void* src, size_t srcSizeInBytes) {
|
|||
this->bind();
|
||||
GrGLenum usage = dynamic() ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW;
|
||||
|
||||
bool doNullHint = GR_GL_USE_BUFFER_DATA_NULL_HINT;
|
||||
#if GR_GL_USE_BUFFER_DATA_NULL_HINT
|
||||
if (this->sizeInBytes() == srcSizeInBytes) {
|
||||
GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, srcSizeInBytes, src, usage));
|
||||
|
|
Загрузка…
Ссылка в новой задаче