| /* |
| * Copyright 2014 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "SkPaint.h" |
| #include "SkPathEffect.h" |
| #include "SkPictureContentInfo.h" |
| |
| bool SkPictureContentInfo::suitableForGpuRasterization(GrContext* context, const char **reason, |
| int sampleCount) const { |
| // TODO: the heuristic used here needs to be refined |
| static const int kNumPaintWithPathEffectUsesTol = 1; |
| static const int kNumAAConcavePaths = 5; |
| |
| SkASSERT(fNumAAHairlineConcavePaths <= fNumAAConcavePaths); |
| |
| int numNonDashedPathEffects = fNumPaintWithPathEffectUses - |
| fNumFastPathDashEffects; |
| |
| bool suitableForDash = (0 == fNumPaintWithPathEffectUses) || |
| (numNonDashedPathEffects < kNumPaintWithPathEffectUsesTol |
| && 0 == sampleCount); |
| |
| bool ret = suitableForDash && |
| (fNumAAConcavePaths - fNumAAHairlineConcavePaths - fNumAADFEligibleConcavePaths) |
| < kNumAAConcavePaths; |
| if (!ret && reason) { |
| if (!suitableForDash) { |
| if (0 != sampleCount) { |
| *reason = "Can't use multisample on dash effect."; |
| } else { |
| *reason = "Too many non dashed path effects."; |
| } |
| } else if ((fNumAAConcavePaths - fNumAAHairlineConcavePaths - fNumAADFEligibleConcavePaths) |
| >= kNumAAConcavePaths) { |
| *reason = "Too many anti-aliased concave paths."; |
| } else { |
| *reason = "Unknown reason for GPU unsuitability."; |
| } |
| } |
| return ret; |
| } |
| |
| void SkPictureContentInfo::onDrawPoints(size_t count, const SkPaint& paint) { |
| if (paint.getPathEffect() != nullptr) { |
| SkPathEffect::DashInfo info; |
| SkPathEffect::DashType dashType = paint.getPathEffect()->asADash(&info); |
| if (2 == count && SkPaint::kRound_Cap != paint.getStrokeCap() && |
| SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) { |
| ++fNumFastPathDashEffects; |
| } |
| } |
| } |
| |
| void SkPictureContentInfo::onDrawPath(const SkPath& path, const SkPaint& paint) { |
| if (paint.isAntiAlias() && !path.isConvex()) { |
| ++fNumAAConcavePaths; |
| |
| SkPaint::Style paintStyle = paint.getStyle(); |
| const SkRect& pathBounds = path.getBounds(); |
| if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) { |
| ++fNumAAHairlineConcavePaths; |
| } else if (SkPaint::kFill_Style == paintStyle && pathBounds.width() < 64.f && |
| pathBounds.height() < 64.f && !path.isVolatile()) { |
| ++fNumAADFEligibleConcavePaths; |
| } |
| } |
| } |
| |
| void SkPictureContentInfo::onAddPaintPtr(const SkPaint* paint) { |
| if (paint && paint->getPathEffect()) { |
| ++fNumPaintWithPathEffectUses; |
| } |
| } |
| |
| void SkPictureContentInfo::onSaveLayer() { |
| *fSaveStack.append() = kSaveLayer_Flag; |
| } |
| |
| void SkPictureContentInfo::onSave() { |
| *fSaveStack.append() = kSave_Flag; |
| } |
| |
| void SkPictureContentInfo::onRestore() { |
| SkASSERT(fSaveStack.count() > 0); |
| |
| bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag; |
| |
| if (fSaveStack.top() & kSaveLayer_Flag) { |
| ++fNumLayers; |
| if (containedSaveLayer) { |
| ++fNumInteriorLayers; |
| } else { |
| ++fNumLeafLayers; |
| } |
| containedSaveLayer = true; |
| } |
| |
| fSaveStack.pop(); |
| |
| if (containedSaveLayer && fSaveStack.count() > 0) { |
| fSaveStack.top() |= kContainedSaveLayer_Flag; |
| } |
| } |
| |
| void SkPictureContentInfo::rescindLastSave() { |
| SkASSERT(fSaveStack.count() > 0); |
| SkASSERT(fSaveStack.top() & kSave_Flag); |
| |
| bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag; |
| |
| fSaveStack.pop(); |
| |
| if (containedSaveLayer && fSaveStack.count() > 0) { |
| fSaveStack.top() |= kContainedSaveLayer_Flag; |
| } |
| } |
| |
| void SkPictureContentInfo::rescindLastSaveLayer() { |
| SkASSERT(fSaveStack.count() > 0); |
| SkASSERT(fSaveStack.top() & kSaveLayer_Flag); |
| |
| bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag; |
| |
| fSaveStack.pop(); |
| |
| if (containedSaveLayer && fSaveStack.count() > 0) { |
| fSaveStack.top() |= kContainedSaveLayer_Flag; |
| } |
| } |
| |
| void SkPictureContentInfo::set(const SkPictureContentInfo& src) { |
| fNumOperations = src.fNumOperations; |
| fNumTexts = src.fNumTexts; |
| fNumPaintWithPathEffectUses = src.fNumPaintWithPathEffectUses; |
| fNumFastPathDashEffects = src.fNumFastPathDashEffects; |
| fNumAAConcavePaths = src.fNumAAConcavePaths; |
| fNumAAHairlineConcavePaths = src.fNumAAHairlineConcavePaths; |
| fNumAADFEligibleConcavePaths = src.fNumAADFEligibleConcavePaths; |
| fNumLayers = src.fNumLayers; |
| fNumInteriorLayers = src.fNumInteriorLayers; |
| fNumLeafLayers = src.fNumLeafLayers; |
| fSaveStack = src.fSaveStack; |
| } |
| |
| void SkPictureContentInfo::reset() { |
| fNumOperations = 0; |
| fNumTexts = 0; |
| fNumPaintWithPathEffectUses = 0; |
| fNumFastPathDashEffects = 0; |
| fNumAAConcavePaths = 0; |
| fNumAAHairlineConcavePaths = 0; |
| fNumAADFEligibleConcavePaths = 0; |
| fNumLayers = 0; |
| fNumInteriorLayers = 0; |
| fNumLeafLayers = 0; |
| fSaveStack.rewind(); |
| } |
| |
| void SkPictureContentInfo::swap(SkPictureContentInfo* other) { |
| SkTSwap(fNumOperations, other->fNumOperations); |
| SkTSwap(fNumTexts, other->fNumTexts); |
| SkTSwap(fNumPaintWithPathEffectUses, other->fNumPaintWithPathEffectUses); |
| SkTSwap(fNumFastPathDashEffects, other->fNumFastPathDashEffects); |
| SkTSwap(fNumAAConcavePaths, other->fNumAAConcavePaths); |
| SkTSwap(fNumAAHairlineConcavePaths, other->fNumAAHairlineConcavePaths); |
| SkTSwap(fNumAADFEligibleConcavePaths, other->fNumAADFEligibleConcavePaths); |
| SkTSwap(fNumLayers, other->fNumLayers); |
| SkTSwap(fNumInteriorLayers, other->fNumInteriorLayers); |
| SkTSwap(fNumLeafLayers, other->fNumLeafLayers); |
| fSaveStack.swap(other->fSaveStack); |
| } |