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
suitableForGpuRasterization(GrContext * context,const char ** reason,int sampleCount) const12 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)
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)
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
onDrawPoints(size_t count,const SkPaint & paint)47 void SkPictureContentInfo::onDrawPoints(size_t count, const SkPaint& paint) {
48 if (paint.getPathEffect() != NULL) {
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
onDrawPath(const SkPath & path,const SkPaint & paint)58 void SkPictureContentInfo::onDrawPath(const SkPath& path, const SkPaint& paint) {
59 if (paint.isAntiAlias() && !path.isConvex()) {
60 ++fNumAAConcavePaths;
61
62 if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) {
63 ++fNumAAHairlineConcavePaths;
64 }
65 }
66 }
67
onAddPaintPtr(const SkPaint * paint)68 void SkPictureContentInfo::onAddPaintPtr(const SkPaint* paint) {
69 if (paint && paint->getPathEffect()) {
70 ++fNumPaintWithPathEffectUses;
71 }
72 }
73
onSaveLayer()74 void SkPictureContentInfo::onSaveLayer() {
75 *fSaveStack.append() = kSaveLayer_Flag;
76 }
77
onSave()78 void SkPictureContentInfo::onSave() {
79 *fSaveStack.append() = kSave_Flag;
80 }
81
onRestore()82 void SkPictureContentInfo::onRestore() {
83 SkASSERT(fSaveStack.count() > 0);
84
85 bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag;
86
87 if (fSaveStack.top() & kSaveLayer_Flag) {
88 ++fNumLayers;
89 if (containedSaveLayer) {
90 ++fNumInteriorLayers;
91 } else {
92 ++fNumLeafLayers;
93 }
94 containedSaveLayer = true;
95 }
96
97 fSaveStack.pop();
98
99 if (containedSaveLayer && fSaveStack.count() > 0) {
100 fSaveStack.top() |= kContainedSaveLayer_Flag;
101 }
102 }
103
rescindLastSave()104 void SkPictureContentInfo::rescindLastSave() {
105 SkASSERT(fSaveStack.count() > 0);
106 SkASSERT(fSaveStack.top() & kSave_Flag);
107
108 bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag;
109
110 fSaveStack.pop();
111
112 if (containedSaveLayer && fSaveStack.count() > 0) {
113 fSaveStack.top() |= kContainedSaveLayer_Flag;
114 }
115 }
116
rescindLastSaveLayer()117 void SkPictureContentInfo::rescindLastSaveLayer() {
118 SkASSERT(fSaveStack.count() > 0);
119 SkASSERT(fSaveStack.top() & kSaveLayer_Flag);
120
121 bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag;
122
123 fSaveStack.pop();
124
125 if (containedSaveLayer && fSaveStack.count() > 0) {
126 fSaveStack.top() |= kContainedSaveLayer_Flag;
127 }
128 }
129
set(const SkPictureContentInfo & src)130 void SkPictureContentInfo::set(const SkPictureContentInfo& src) {
131 fNumOperations = src.fNumOperations;
132 fNumTexts = src.fNumTexts;
133 fNumPaintWithPathEffectUses = src.fNumPaintWithPathEffectUses;
134 fNumFastPathDashEffects = src.fNumFastPathDashEffects;
135 fNumAAConcavePaths = src.fNumAAConcavePaths;
136 fNumAAHairlineConcavePaths = src.fNumAAHairlineConcavePaths;
137 fNumLayers = src.fNumLayers;
138 fNumInteriorLayers = src.fNumInteriorLayers;
139 fNumLeafLayers = src.fNumLeafLayers;
140 fSaveStack = src.fSaveStack;
141 }
142
reset()143 void SkPictureContentInfo::reset() {
144 fNumOperations = 0;
145 fNumTexts = 0;
146 fNumPaintWithPathEffectUses = 0;
147 fNumFastPathDashEffects = 0;
148 fNumAAConcavePaths = 0;
149 fNumAAHairlineConcavePaths = 0;
150 fNumLayers = 0;
151 fNumInteriorLayers = 0;
152 fNumLeafLayers = 0;
153 fSaveStack.rewind();
154 }
155
swap(SkPictureContentInfo * other)156 void SkPictureContentInfo::swap(SkPictureContentInfo* other) {
157 SkTSwap(fNumOperations, other->fNumOperations);
158 SkTSwap(fNumTexts, other->fNumTexts);
159 SkTSwap(fNumPaintWithPathEffectUses, other->fNumPaintWithPathEffectUses);
160 SkTSwap(fNumFastPathDashEffects, other->fNumFastPathDashEffects);
161 SkTSwap(fNumAAConcavePaths, other->fNumAAConcavePaths);
162 SkTSwap(fNumAAHairlineConcavePaths, other->fNumAAHairlineConcavePaths);
163 SkTSwap(fNumLayers, other->fNumLayers);
164 SkTSwap(fNumInteriorLayers, other->fNumInteriorLayers);
165 SkTSwap(fNumLeafLayers, other->fNumLeafLayers);
166 fSaveStack.swap(other->fSaveStack);
167 }
168