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 - 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 
onDrawPoints(size_t count,const SkPaint & paint)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 
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         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 
onAddPaintPtr(const SkPaint * paint)73 void SkPictureContentInfo::onAddPaintPtr(const SkPaint* paint) {
74     if (paint && paint->getPathEffect()) {
75         ++fNumPaintWithPathEffectUses;
76     }
77 }
78 
onSaveLayer()79 void SkPictureContentInfo::onSaveLayer() {
80     *fSaveStack.append() = kSaveLayer_Flag;
81 }
82 
onSave()83 void SkPictureContentInfo::onSave() {
84     *fSaveStack.append() = kSave_Flag;
85 }
86 
onRestore()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 
rescindLastSave()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 
rescindLastSaveLayer()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 
set(const SkPictureContentInfo & src)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 
reset()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 
swap(SkPictureContentInfo * other)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