void GrAAHairLinePathRenderer::drawPath(GrDrawState::StageMask stageMask) { if (!this->createGeom(stageMask)) { return; } GrDrawState* drawState = fTarget->drawState(); GrDrawTarget::AutoStateRestore asr; if (!drawState->getViewMatrix().hasPerspective()) { asr.set(fTarget); GrMatrix ivm; if (drawState->getViewInverse(&ivm)) { drawState->preConcatSamplerMatrices(stageMask, ivm); } drawState->setViewMatrix(GrMatrix::I()); } // TODO: See whether rendering lines as degenerate quads improves perf // when we have a mix fTarget->setIndexSourceToBuffer(fLinesIndexBuffer); int lines = 0; int nBufLines = fLinesIndexBuffer->maxQuads(); while (lines < fLineSegmentCnt) { int n = GrMin(fLineSegmentCnt-lines, nBufLines); drawState->setVertexEdgeType(GrDrawState::kHairLine_EdgeType); fTarget->drawIndexed(kTriangles_PrimitiveType, kVertsPerLineSeg*lines, // startV 0, // startI kVertsPerLineSeg*n, // vCount kIdxsPerLineSeg*n); // iCount lines += n; } fTarget->setIndexSourceToBuffer(fQuadsIndexBuffer); int quads = 0; while (quads < fQuadCnt) { int n = GrMin(fQuadCnt-quads, kNumQuadsInIdxBuffer); drawState->setVertexEdgeType(GrDrawState::kHairQuad_EdgeType); fTarget->drawIndexed(kTriangles_PrimitiveType, 4*fLineSegmentCnt + kVertsPerQuad*quads, // startV 0, // startI kVertsPerQuad*n, // vCount kIdxsPerQuad*n); // iCount quads += n; } }
bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, GrPathFill fill, GrDrawTarget* target, bool antiAlias) { const SkPath* path = &origPath; if (path->isEmpty()) { return true; } GrDrawState* drawState = target->drawState(); GrDrawState::AutoDeviceCoordDraw adcd(drawState); if (!adcd.succeeded()) { return false; } const GrMatrix* vm = &adcd.getOriginalMatrix(); GrVertexLayout layout = 0; layout |= GrDrawTarget::kEdge_VertexLayoutBit; // We use the fact that SkPath::transform path does subdivision based on // perspective. Otherwise, we apply the view matrix when copying to the // segment representation. SkPath tmpPath; if (vm->hasPerspective()) { origPath.transform(*vm, &tmpPath); path = &tmpPath; vm = &GrMatrix::I(); } QuadVertex *verts; uint16_t* idxs; int vCount; int iCount; enum { kPreallocSegmentCnt = 512 / sizeof(Segment), }; SkSTArray<kPreallocSegmentCnt, Segment, true> segments; SkPoint fanPt; if (!get_segments(*path, *vm, &segments, &fanPt, &vCount, &iCount)) { return false; } GrDrawTarget::AutoReleaseGeometry arg(target, layout, vCount, iCount); if (!arg.succeeded()) { return false; } verts = reinterpret_cast<QuadVertex*>(arg.vertices()); idxs = reinterpret_cast<uint16_t*>(arg.indices()); create_vertices(segments, fanPt, verts, idxs); GrDrawState::VertexEdgeType oldEdgeType = drawState->getVertexEdgeType(); drawState->setVertexEdgeType(GrDrawState::kQuad_EdgeType); target->drawIndexed(kTriangles_GrPrimitiveType, 0, // start vertex 0, // start index vCount, iCount); drawState->setVertexEdgeType(oldEdgeType); return true; }
bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, const SkStrokeRec&, GrDrawTarget* target, bool antiAlias) { int lineCnt; int quadCnt; GrDrawTarget::AutoReleaseGeometry arg; if (!this->createGeom(path, target, &lineCnt, &quadCnt, &arg)) { return false; } GrDrawState::AutoDeviceCoordDraw adcd; GrDrawState* drawState = target->drawState(); // createGeom transforms the geometry to device space when the matrix does not have // perspective. if (!drawState->getViewMatrix().hasPerspective()) { adcd.set(drawState); if (!adcd.succeeded()) { return false; } } // TODO: See whether rendering lines as degenerate quads improves perf // when we have a mix GrDrawState::VertexEdgeType oldEdgeType = drawState->getVertexEdgeType(); target->setIndexSourceToBuffer(fLinesIndexBuffer); int lines = 0; int nBufLines = fLinesIndexBuffer->maxQuads(); drawState->setVertexEdgeType(GrDrawState::kHairLine_EdgeType); while (lines < lineCnt) { int n = GrMin(lineCnt - lines, nBufLines); target->drawIndexed(kTriangles_GrPrimitiveType, kVertsPerLineSeg*lines, // startV 0, // startI kVertsPerLineSeg*n, // vCount kIdxsPerLineSeg*n); // iCount lines += n; } target->setIndexSourceToBuffer(fQuadsIndexBuffer); int quads = 0; drawState->setVertexEdgeType(GrDrawState::kHairQuad_EdgeType); while (quads < quadCnt) { int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer); target->drawIndexed(kTriangles_GrPrimitiveType, 4 * lineCnt + kVertsPerQuad*quads, // startV 0, // startI kVertsPerQuad*n, // vCount kIdxsPerQuad*n); // iCount quads += n; } drawState->setVertexEdgeType(oldEdgeType); return true; }
bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, GrPathFill fill, const GrVec* translate, GrDrawTarget* target, GrDrawState::StageMask stageMask, bool antiAlias) { const SkPath* path = &origPath; if (path->isEmpty()) { return true; } GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit); GrDrawState* drawState = target->drawState(); GrMatrix vm = drawState->getViewMatrix(); if (NULL != translate) { vm.postTranslate(translate->fX, translate->fY); } GrMatrix ivm; if (vm.invert(&ivm)) { drawState->preConcatSamplerMatrices(stageMask, ivm); } drawState->viewMatrix()->reset(); GrVertexLayout layout = 0; for (int s = 0; s < GrDrawState::kNumStages; ++s) { if ((1 << s) & stageMask) { layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s); } } layout |= GrDrawTarget::kEdge_VertexLayoutBit; // We use the fact that SkPath::transform path does subdivision based on // perspective. Otherwise, we apply the view matrix when copying to the // segment representation. SkPath tmpPath; if (vm.hasPerspective()) { origPath.transform(vm, &tmpPath); path = &tmpPath; vm.reset(); } QuadVertex *verts; uint16_t* idxs; int vCount; int iCount; enum { kPreallocSegmentCnt = 512 / sizeof(Segment), }; SkSTArray<kPreallocSegmentCnt, Segment, true> segments; SkPoint fanPt; if (!get_segments(*path, vm, &segments, &fanPt, &vCount, &iCount)) { return false; } GrDrawTarget::AutoReleaseGeometry arg(target, layout, vCount, iCount); if (!arg.succeeded()) { return false; } verts = reinterpret_cast<QuadVertex*>(arg.vertices()); idxs = reinterpret_cast<uint16_t*>(arg.indices()); create_vertices(segments, fanPt, verts, idxs); drawState->setVertexEdgeType(GrDrawState::kQuad_EdgeType); target->drawIndexed(kTriangles_PrimitiveType, 0, // start vertex 0, // start index vCount, iCount); return true; }
bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, GrPathFill fill, const GrVec* translate, GrDrawTarget* target, GrDrawState::StageMask stageMask, bool antiAlias) { int lineCnt; int quadCnt; GrDrawTarget::AutoReleaseGeometry arg; if (!this->createGeom(path, translate, target, stageMask, &lineCnt, &quadCnt, &arg)) { return false; } GrDrawTarget::AutoStateRestore asr; GrDrawState* drawState = target->drawState(); if (!drawState->getViewMatrix().hasPerspective()) { // we are going to whack the view matrix to identity to remove // perspective. asr.set(target, GrDrawTarget::kPreserve_ASRInit); drawState = target->drawState(); GrMatrix ivm; if (drawState->getViewInverse(&ivm)) { drawState->preConcatSamplerMatrices(stageMask, ivm); } drawState->viewMatrix()->reset(); } // TODO: See whether rendering lines as degenerate quads improves perf // when we have a mix target->setIndexSourceToBuffer(fLinesIndexBuffer); int lines = 0; int nBufLines = fLinesIndexBuffer->maxQuads(); while (lines < lineCnt) { int n = GrMin(lineCnt - lines, nBufLines); drawState->setVertexEdgeType(GrDrawState::kHairLine_EdgeType); target->drawIndexed(kTriangles_GrPrimitiveType, kVertsPerLineSeg*lines, // startV 0, // startI kVertsPerLineSeg*n, // vCount kIdxsPerLineSeg*n); // iCount lines += n; } target->setIndexSourceToBuffer(fQuadsIndexBuffer); int quads = 0; while (quads < quadCnt) { int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer); drawState->setVertexEdgeType(GrDrawState::kHairQuad_EdgeType); target->drawIndexed(kTriangles_GrPrimitiveType, 4 * lineCnt + kVertsPerQuad*quads, // startV 0, // startI kVertsPerQuad*n, // vCount kIdxsPerQuad*n); // iCount quads += n; } return true; }