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 12 bool 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 47 void 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 58 void 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 73 void SkPictureContentInfo::onAddPaintPtr(const SkPaint* paint) { 74 if (paint && paint->getPathEffect()) { 75 ++fNumPaintWithPathEffectUses; 76 } 77 } 78 79 void SkPictureContentInfo::onSaveLayer() { 80 *fSaveStack.append() = kSaveLayer_Flag; 81 } 82 83 void SkPictureContentInfo::onSave() { 84 *fSaveStack.append() = kSave_Flag; 85 } 86 87 void 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 109 void 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 122 void 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 135 void 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 149 void 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 163 void 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