inline void GrGLPathRendering::stencilThenCoverFillPathInstanced( GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues) { if (caps().stencilThenCoverSupport) { GL_CALL(StencilThenCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase, fillMode, mask, coverMode, transformType, transformValues)); return; } GL_CALL(StencilFillPathInstanced(numPaths, pathNameType, paths, pathBase, fillMode, mask, transformType, transformValues)); GL_CALL(CoverFillPathInstanced(numPaths, pathNameType, paths, pathBase, coverMode, transformType, transformValues)); }
void GrGLPathRendering::onDrawPaths(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, const GrStencilSettings& stencil, const GrPathRange* pathRange, const void* indices, PathIndexType indexType, const float transformValues[], PathTransformType transformType, int count) { SkDEBUGCODE(verify_floats(transformValues, gXformType2ComponentCount[transformType] * count)); if (!this->gpu()->flushGLState(pipeline, primProc)) { return; } this->flushPathStencilSettings(stencil); SkASSERT(!fHWPathStencilSettings.isTwoSided()); const GrGLPathRange* glPathRange = static_cast<const GrGLPathRange*>(pathRange); GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.front().fPassOp); GrGLint writeMask = fHWPathStencilSettings.front().fWriteMask; if (glPathRange->shouldStroke()) { if (glPathRange->shouldFill()) { GL_CALL(StencilFillPathInstanced( count, gIndexType2GLType[indexType], indices, glPathRange->basePathID(), fillMode, writeMask, gXformType2GLType[transformType], transformValues)); } GL_CALL(StencilThenCoverStrokePathInstanced( count, gIndexType2GLType[indexType], indices, glPathRange->basePathID(), 0xffff, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, gXformType2GLType[transformType], transformValues)); } else { GL_CALL(StencilThenCoverFillPathInstanced( count, gIndexType2GLType[indexType], indices, glPathRange->basePathID(), fillMode, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, gXformType2GLType[transformType], transformValues)); } }
void GrGLPathRendering::onDrawPaths(const DrawPathArgs& args, const GrPathRange* pathRange, const void* indices, PathIndexType indexType, const float transformValues[], PathTransformType transformType, int count) { if (!this->gpu()->flushGLState(args)) { return; } this->flushPathStencilSettings(*args.fStencil); SkASSERT(!fHWPathStencilSettings.isTwoSided()); const GrGLPathRange* glPathRange = static_cast<const GrGLPathRange*>(pathRange); GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode( fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); if (glPathRange->shouldStroke()) { if (glPathRange->shouldFill()) { GL_CALL(StencilFillPathInstanced( count, gIndexType2GLType[indexType], indices, glPathRange->basePathID(), fillMode, writeMask, gXformType2GLType[transformType], transformValues)); } GL_CALL(StencilThenCoverStrokePathInstanced( count, gIndexType2GLType[indexType], indices, glPathRange->basePathID(), 0xffff, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, gXformType2GLType[transformType], transformValues)); } else { GL_CALL(StencilThenCoverFillPathInstanced( count, gIndexType2GLType[indexType], indices, glPathRange->basePathID(), fillMode, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, gXformType2GLType[transformType], transformValues)); } }
void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, const void* indices, PathIndexType indexType, const float transformValues[], PathTransformType transformType, int count, const GrStencilSettings& stencilSettings) { SkASSERT(fGpu->caps()->shaderCaps()->pathRenderingSupport()); GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID(); this->flushPathStencilSettings(stencilSettings); SkASSERT(!fHWPathStencilSettings.isTwoSided()); const SkStrokeRec& stroke = pathRange->getStroke(); GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode( fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); if (stroke.needToApply()) { if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { GL_CALL(StencilFillPathInstanced( count, gIndexType2GLType[indexType], indices, baseID, fillMode, writeMask, gXformType2GLType[transformType], transformValues)); } this->stencilThenCoverStrokePathInstanced( count, gIndexType2GLType[indexType], indices, baseID, 0xffff, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, gXformType2GLType[transformType], transformValues); } else { this->stencilThenCoverFillPathInstanced( count, gIndexType2GLType[indexType], indices, baseID, fillMode, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, gXformType2GLType[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); } }