void draw(Target* target, const GrGeometryProcessor* gp) const { GrResourceProvider* rp = target->resourceProvider(); SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMatrix, fShape.bounds()); SkPath path; fShape.asPath(&path); bool inverseFill = path.isInverseFillType(); // construct a cache key from the path's genID and the view matrix static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); GrUniqueKey key; static constexpr int kClipBoundsCnt = sizeof(fClipBounds) / sizeof(uint32_t); int shapeKeyDataCnt = fShape.unstyledKeySize(); SkASSERT(shapeKeyDataCnt >= 0); GrUniqueKey::Builder builder(&key, kDomain, shapeKeyDataCnt + kClipBoundsCnt); fShape.writeUnstyledKey(&builder[0]); // For inverse fills, the tessellation is dependent on clip bounds. if (inverseFill) { memcpy(&builder[shapeKeyDataCnt], &fClipBounds, sizeof(fClipBounds)); } else { memset(&builder[shapeKeyDataCnt], 0, sizeof(fClipBounds)); } builder.finish(); SkAutoTUnref<GrBuffer> cachedVertexBuffer(rp->findAndRefTByUniqueKey<GrBuffer>(key)); int actualCount; if (cache_match(cachedVertexBuffer.get(), tol, &actualCount)) { this->drawVertices(target, gp, cachedVertexBuffer.get(), 0, actualCount); return; } bool isLinear; bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags(); StaticVertexAllocator allocator(rp, canMapVB); int count = GrTessellator::PathToTriangles(path, tol, fClipBounds, &allocator, &isLinear); if (count == 0) { return; } this->drawVertices(target, gp, allocator.vertexBuffer(), 0, count); TessInfo info; info.fTolerance = isLinear ? 0 : tol; info.fCount = count; SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info))); key.setCustomData(data.get()); rp->assignUniqueKeyToResource(key, allocator.vertexBuffer()); }
void draw(Target* target, const GrGeometryProcessor* gp) const { GrResourceProvider* rp = target->resourceProvider(); SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMatrix, fPath.getBounds()); SkScalar styleScale = SK_Scalar1; if (fStyle.applies()) { styleScale = GrStyle::MatrixToScaleFactor(fViewMatrix); } // construct a cache key from the path's genID and the view matrix static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); GrUniqueKey key; int clipBoundsCnt = fPath.isInverseFillType() ? sizeof(fClipBounds) / sizeof(uint32_t) : 0; int styleDataCnt = GrStyle::KeySize(fStyle, GrStyle::Apply::kPathEffectAndStrokeRec); if (styleDataCnt >= 0) { GrUniqueKey::Builder builder(&key, kDomain, 2 + clipBoundsCnt + styleDataCnt); builder[0] = fPath.getGenerationID(); builder[1] = fPath.getFillType(); // For inverse fills, the tessellation is dependent on clip bounds. if (fPath.isInverseFillType()) { memcpy(&builder[2], &fClipBounds, sizeof(fClipBounds)); } if (styleDataCnt) { GrStyle::WriteKey(&builder[2 + clipBoundsCnt], fStyle, GrStyle::Apply::kPathEffectAndStrokeRec, styleScale); } builder.finish(); SkAutoTUnref<GrBuffer> cachedVertexBuffer(rp->findAndRefTByUniqueKey<GrBuffer>(key)); int actualCount; if (cache_match(cachedVertexBuffer.get(), tol, &actualCount)) { this->drawVertices(target, gp, cachedVertexBuffer.get(), 0, actualCount); return; } } SkPath path; if (fStyle.applies()) { SkStrokeRec::InitStyle fill; SkAssertResult(fStyle.applyToPath(&path, &fill, fPath, styleScale)); SkASSERT(SkStrokeRec::kFill_InitStyle == fill); } else { path = fPath; } bool isLinear; bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags(); StaticVertexAllocator allocator(rp, canMapVB); int count = GrTessellator::PathToTriangles(path, tol, fClipBounds, &allocator, &isLinear); if (count == 0) { return; } this->drawVertices(target, gp, allocator.vertexBuffer(), 0, count); if (!fPath.isVolatile() && styleDataCnt >= 0) { TessInfo info; info.fTolerance = isLinear ? 0 : tol; info.fCount = count; SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info))); key.setCustomData(data.get()); rp->assignUniqueKeyToResource(key, allocator.vertexBuffer()); SkPathPriv::AddGenIDChangeListener(fPath, new PathInvalidator(key)); } }