void GrGLPathRendering::drawPath(const GrPath* path, SkPath::FillType fill) { GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); SkASSERT(NULL != fGpu->drawState()->getRenderTarget()); SkASSERT(NULL != fGpu->drawState()->getRenderTarget()->getStencilBuffer()); this->flushPathStencilSettings(fill); SkASSERT(!fHWPathStencilSettings.isTwoSided()); const SkStrokeRec& stroke = path->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(StencilFillPath(id, fillMode, writeMask)); } this->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX); } else { this->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX); } } else { if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { GL_CALL(StencilFillPath(id, fillMode, writeMask)); } if (stroke.needToApply()) { GL_CALL(StencilStrokePath(id, 0xffff, writeMask)); } 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); } }
void GrGLPathRendering::onStencilPath(const StencilPathArgs& args, const GrPath* path) { GrGLGpu* gpu = this->gpu(); SkASSERT(gpu->caps()->shaderCaps()->pathRenderingSupport()); gpu->flushColorWrite(false); gpu->flushDrawFace(GrPipelineBuilder::kBoth_DrawFace); GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(args.fRenderTarget); SkISize size = SkISize::Make(rt->width(), rt->height()); this->setProjectionMatrix(*args.fViewMatrix, size, rt->origin()); gpu->flushScissor(*args.fScissor, rt->getViewport(), rt->origin()); gpu->flushHWAAState(rt, args.fUseHWAA); gpu->flushRenderTarget(rt, NULL); const GrGLPath* glPath = static_cast<const GrGLPath*>(path); this->flushPathStencilSettings(*args.fStencil); SkASSERT(!fHWPathStencilSettings.isTwoSided()); GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode( fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); if (glPath->shouldFill()) { GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask)); } if (glPath->shouldStroke()) { GL_CALL(StencilStrokePath(glPath->pathID(), 0xffff, writeMask)); } }
void GrGLPathRendering::onDrawPath(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, const GrPipeline::FixedDynamicState& fixedDynamicState, const GrStencilSettings& stencilPassSettings, const GrPath* path) { if (!this->gpu()->flushGLState(primProc, pipeline, &fixedDynamicState, nullptr, 1, false)) { return; } const GrGLPath* glPath = static_cast<const GrGLPath*>(path); this->flushPathStencilSettings(stencilPassSettings); SkASSERT(!fHWPathStencilSettings.isTwoSided()); GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.front().fPassOp); GrGLint writeMask = fHWPathStencilSettings.front().fWriteMask; if (glPath->shouldStroke()) { if (glPath->shouldFill()) { GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask)); } GL_CALL(StencilThenCoverStrokePath(glPath->pathID(), 0xffff, writeMask, GR_GL_BOUNDING_BOX)); } else { GL_CALL(StencilThenCoverFillPath(glPath->pathID(), fillMode, writeMask, GR_GL_BOUNDING_BOX)); } }
inline void GrGLPathRendering::stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode) { if (caps().stencilThenCoverSupport) { GL_CALL(StencilThenCoverFillPath(path, fillMode, mask, coverMode)); return; } GL_CALL(StencilFillPath(path, fillMode, mask)); GL_CALL(CoverFillPath(path, coverMode)); }
void GrGLPathRendering::stencilPath(const GrPath* path, SkPath::FillType fill) { GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); SkASSERT(NULL != fGpu->drawState()->getRenderTarget()); SkASSERT(NULL != fGpu->drawState()->getRenderTarget()->getStencilBuffer()); this->flushPathStencilSettings(fill); SkASSERT(!fHWPathStencilSettings.isTwoSided()); GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); GL_CALL(StencilFillPath(id, fillMode, writeMask)); }
void GrGLPathRendering::stencilPath(const GrPath* path, const GrStencilSettings& stencilSettings) { GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); this->flushPathStencilSettings(stencilSettings); SkASSERT(!fHWPathStencilSettings.isTwoSided()); const SkStrokeRec& stroke = path->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.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { GL_CALL(StencilFillPath(id, fillMode, writeMask)); } if (stroke.needToApply()) { GL_CALL(StencilStrokePath(id, 0xffff, writeMask)); } }
void GrGLPathRendering::onDrawPath(const DrawPathArgs& args, const GrPath* path) { if (!this->gpu()->flushGLState(args)) { return; } const GrGLPath* glPath = static_cast<const GrGLPath*>(path); this->flushPathStencilSettings(*args.fStencil); SkASSERT(!fHWPathStencilSettings.isTwoSided()); GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode( fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); if (glPath->shouldStroke()) { if (glPath->shouldFill()) { GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask)); } GL_CALL(StencilThenCoverStrokePath(glPath->pathID(), 0xffff, writeMask, GR_GL_BOUNDING_BOX)); } else { GL_CALL(StencilThenCoverFillPath(glPath->pathID(), fillMode, writeMask, GR_GL_BOUNDING_BOX)); } }