1/* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkPaint.h" 9#include "SkPathEffect.h" 10#include "SkPictureContentInfo.h" 11 12bool SkPictureContentInfo::suitableForGpuRasterization(GrContext* context, const char **reason, 13 int sampleCount) const { 14 // TODO: the heuristic used here needs to be refined 15 static const int kNumPaintWithPathEffectUsesTol = 1; 16 static const int kNumAAConcavePaths = 5; 17 18 SkASSERT(fNumAAHairlineConcavePaths <= fNumAAConcavePaths); 19 20 int numNonDashedPathEffects = fNumPaintWithPathEffectUses - 21 fNumFastPathDashEffects; 22 23 bool suitableForDash = (0 == fNumPaintWithPathEffectUses) || 24 (numNonDashedPathEffects < kNumPaintWithPathEffectUsesTol 25 && 0 == sampleCount); 26 27 bool ret = suitableForDash && 28 (fNumAAConcavePaths - fNumAAHairlineConcavePaths - fNumAADFEligibleConcavePaths) 29 < kNumAAConcavePaths; 30 if (!ret && reason) { 31 if (!suitableForDash) { 32 if (0 != sampleCount) { 33 *reason = "Can't use multisample on dash effect."; 34 } else { 35 *reason = "Too many non dashed path effects."; 36 } 37 } else if ((fNumAAConcavePaths - fNumAAHairlineConcavePaths - fNumAADFEligibleConcavePaths) 38 >= kNumAAConcavePaths) { 39 *reason = "Too many anti-aliased concave paths."; 40 } else { 41 *reason = "Unknown reason for GPU unsuitability."; 42 } 43 } 44 return ret; 45} 46 47void SkPictureContentInfo::onDrawPoints(size_t count, const SkPaint& paint) { 48 if (paint.getPathEffect() != nullptr) { 49 SkPathEffect::DashInfo info; 50 SkPathEffect::DashType dashType = paint.getPathEffect()->asADash(&info); 51 if (2 == count && SkPaint::kRound_Cap != paint.getStrokeCap() && 52 SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) { 53 ++fNumFastPathDashEffects; 54 } 55 } 56} 57 58void SkPictureContentInfo::onDrawPath(const SkPath& path, const SkPaint& paint) { 59 if (paint.isAntiAlias() && !path.isConvex()) { 60 ++fNumAAConcavePaths; 61 62 SkPaint::Style paintStyle = paint.getStyle(); 63 const SkRect& pathBounds = path.getBounds(); 64 if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) { 65 ++fNumAAHairlineConcavePaths; 66 } else if (SkPaint::kFill_Style == paintStyle && pathBounds.width() < 64.f && 67 pathBounds.height() < 64.f && !path.isVolatile()) { 68 ++fNumAADFEligibleConcavePaths; 69 } 70 } 71} 72 73void SkPictureContentInfo::onAddPaintPtr(const SkPaint* paint) { 74 if (paint && paint->getPathEffect()) { 75 ++fNumPaintWithPathEffectUses; 76 } 77} 78 79void SkPictureContentInfo::onSaveLayer() { 80 *fSaveStack.append() = kSaveLayer_Flag; 81} 82 83void SkPictureContentInfo::onSave() { 84 *fSaveStack.append() = kSave_Flag; 85} 86 87void SkPictureContentInfo::onRestore() { 88 SkASSERT(fSaveStack.count() > 0); 89 90 bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag; 91 92 if (fSaveStack.top() & kSaveLayer_Flag) { 93 ++fNumLayers; 94 if (containedSaveLayer) { 95 ++fNumInteriorLayers; 96 } else { 97 ++fNumLeafLayers; 98 } 99 containedSaveLayer = true; 100 } 101 102 fSaveStack.pop(); 103 104 if (containedSaveLayer && fSaveStack.count() > 0) { 105 fSaveStack.top() |= kContainedSaveLayer_Flag; 106 } 107} 108 109void SkPictureContentInfo::rescindLastSave() { 110 SkASSERT(fSaveStack.count() > 0); 111 SkASSERT(fSaveStack.top() & kSave_Flag); 112 113 bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag; 114 115 fSaveStack.pop(); 116 117 if (containedSaveLayer && fSaveStack.count() > 0) { 118 fSaveStack.top() |= kContainedSaveLayer_Flag; 119 } 120} 121 122void SkPictureContentInfo::rescindLastSaveLayer() { 123 SkASSERT(fSaveStack.count() > 0); 124 SkASSERT(fSaveStack.top() & kSaveLayer_Flag); 125 126 bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag; 127 128 fSaveStack.pop(); 129 130 if (containedSaveLayer && fSaveStack.count() > 0) { 131 fSaveStack.top() |= kContainedSaveLayer_Flag; 132 } 133} 134 135void SkPictureContentInfo::set(const SkPictureContentInfo& src) { 136 fNumOperations = src.fNumOperations; 137 fNumTexts = src.fNumTexts; 138 fNumPaintWithPathEffectUses = src.fNumPaintWithPathEffectUses; 139 fNumFastPathDashEffects = src.fNumFastPathDashEffects; 140 fNumAAConcavePaths = src.fNumAAConcavePaths; 141 fNumAAHairlineConcavePaths = src.fNumAAHairlineConcavePaths; 142 fNumAADFEligibleConcavePaths = src.fNumAADFEligibleConcavePaths; 143 fNumLayers = src.fNumLayers; 144 fNumInteriorLayers = src.fNumInteriorLayers; 145 fNumLeafLayers = src.fNumLeafLayers; 146 fSaveStack = src.fSaveStack; 147} 148 149void SkPictureContentInfo::reset() { 150 fNumOperations = 0; 151 fNumTexts = 0; 152 fNumPaintWithPathEffectUses = 0; 153 fNumFastPathDashEffects = 0; 154 fNumAAConcavePaths = 0; 155 fNumAAHairlineConcavePaths = 0; 156 fNumAADFEligibleConcavePaths = 0; 157 fNumLayers = 0; 158 fNumInteriorLayers = 0; 159 fNumLeafLayers = 0; 160 fSaveStack.rewind(); 161} 162 163void SkPictureContentInfo::swap(SkPictureContentInfo* other) { 164 SkTSwap(fNumOperations, other->fNumOperations); 165 SkTSwap(fNumTexts, other->fNumTexts); 166 SkTSwap(fNumPaintWithPathEffectUses, other->fNumPaintWithPathEffectUses); 167 SkTSwap(fNumFastPathDashEffects, other->fNumFastPathDashEffects); 168 SkTSwap(fNumAAConcavePaths, other->fNumAAConcavePaths); 169 SkTSwap(fNumAAHairlineConcavePaths, other->fNumAAHairlineConcavePaths); 170 SkTSwap(fNumAADFEligibleConcavePaths, other->fNumAADFEligibleConcavePaths); 171 SkTSwap(fNumLayers, other->fNumLayers); 172 SkTSwap(fNumInteriorLayers, other->fNumInteriorLayers); 173 SkTSwap(fNumLeafLayers, other->fNumLeafLayers); 174 fSaveStack.swap(other->fSaveStack); 175} 176