inline void GrGLPathRendering::stencilThenCoverStrokePathInstanced( GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues) { if (caps().stencilThenCoverSupport) { GL_CALL(StencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase, reference, mask, coverMode, transformType, transformValues)); return; } GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase, reference, mask, transformType, transformValues)); GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase, coverMode, transformType, transformValues)); }
void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, const uint32_t indices[], int count, const float transforms[], PathTransformType transformsType, SkPath::FillType fill) { SkASSERT(fGpu->caps()->pathRenderingSupport()); SkASSERT(NULL != fGpu->drawState()->getRenderTarget()); SkASSERT(NULL != fGpu->drawState()->getRenderTarget()->getStencilBuffer()); GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID(); this->flushPathStencilSettings(fill); SkASSERT(!fHWPathStencilSettings.isTwoSided()); const SkStrokeRec& stroke = pathRange->getStroke(); SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(fill); GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode( fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); if (nonInvertedFill == fill) { if (stroke.needToApply()) { if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { GL_CALL(StencilFillPathInstanced( count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask, gXformType2GLType[transformsType], transforms)); } this->stencilThenCoverStrokePathInstanced( count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, gXformType2GLType[transformsType], transforms); } else { this->stencilThenCoverFillPathInstanced( count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, gXformType2GLType[transformsType], transforms); } } else { if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { GL_CALL(StencilFillPathInstanced( count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask, gXformType2GLType[transformsType], transforms)); } if (stroke.needToApply()) { GL_CALL(StencilStrokePathInstanced( count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask, gXformType2GLType[transformsType], transforms)); } GrDrawState* drawState = fGpu->drawState(); GrDrawState::AutoViewMatrixRestore avmr; SkRect bounds = SkRect::MakeLTRB(0, 0, SkIntToScalar(drawState->getRenderTarget()->width()), SkIntToScalar(drawState->getRenderTarget()->height())); SkMatrix vmi; // mapRect through persp matrix may not be correct if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) { vmi.mapRect(&bounds); // theoretically could set bloat = 0, instead leave it because of matrix inversion // precision. SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf; bounds.outset(bloat, bloat); } else { avmr.setIdentity(drawState); } fGpu->drawSimpleRect(bounds); } }