OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2015 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 "SkBBoxHierarchy.h" | |
9 #include "SkBigPicture.h" | |
10 #include "SkPathEffect.h" | |
11 #include "SkPictureCommon.h" | |
12 #include "SkRecord.h" | |
13 #include "SkRecordDraw.h" | |
14 | |
15 SkBigPicture::SkBigPicture(const SkRect& cull, | |
16 SkRecord* record, | |
17 SnapshotArray* drawablePicts, | |
18 SkBBoxHierarchy* bbh, | |
19 AccelData* accelData, | |
20 size_t approxBytesUsedBySubPictures) | |
21 : fCullRect(cull) | |
22 , fAnalysis(*record) | |
23 , fApproxBytesUsedBySubPictures(approxBytesUsedBySubPictures) | |
24 , fRecord(record) // Take ownership of caller's ref. | |
25 , fDrawablePicts(drawablePicts) // Take ownership. | |
26 , fBBH(bbh) // Take ownership of caller's ref. | |
27 , fAccelData(accelData) // Take ownership of caller's ref. | |
28 {} | |
29 | |
30 void SkBigPicture::playback(SkCanvas* canvas, AbortCallback* callback) const { | |
31 SkASSERT(canvas); | |
32 | |
33 // If the query contains the whole picture, don't bother with the BBH. | |
34 SkRect clipBounds = { 0, 0, 0, 0 }; | |
35 (void)canvas->getClipBounds(&clipBounds); | |
36 const bool useBBH = !clipBounds.contains(this->cullRect()); | |
37 | |
38 SkRecordDraw(*fRecord, | |
39 canvas, | |
40 this->drawablePicts(), | |
41 nullptr, | |
42 this->drawableCount(), | |
43 useBBH ? fBBH.get() : nullptr, | |
44 callback); | |
45 } | |
46 | |
47 void SkBigPicture::partialPlayback(SkCanvas* canvas, | |
48 unsigned start, | |
49 unsigned stop, | |
50 const SkMatrix& initialCTM) const { | |
51 SkASSERT(canvas); | |
52 SkRecordPartialDraw(*fRecord, | |
53 canvas, | |
54 this->drawablePicts(), | |
55 this->drawableCount(), | |
56 start, | |
57 stop, | |
58 initialCTM); | |
59 } | |
60 | |
61 SkRect SkBigPicture::cullRect() const { return fCullRect; } | |
62 bool SkBigPicture::hasText() const { return fAnalysis.fHasText; } | |
63 bool SkBigPicture::willPlayBackBitmaps() const { return fAnalysis.fWillPlayba
ckBitmaps; } | |
64 int SkBigPicture::numSlowPaths() const { return fAnalysis.fNumSlowPat
hsAndDashEffects; } | |
65 int SkBigPicture::approximateOpCount() const { return fRecord->count(); } | |
66 size_t SkBigPicture::approximateBytesUsed() const { | |
67 size_t bytes = sizeof(*this) + fRecord->bytesUsed() + fApproxBytesUsedBySubP
ictures; | |
68 if (fBBH) { bytes += fBBH->bytesUsed(); } | |
69 return bytes; | |
70 } | |
71 bool SkBigPicture::suitableForGpuRasterization(GrContext*, const char** reason)
const { | |
72 return fAnalysis.suitableForGpuRasterization(reason); | |
73 } | |
74 | |
75 int SkBigPicture::drawableCount() const { | |
76 return fDrawablePicts ? fDrawablePicts->count() : 0; | |
77 } | |
78 SkPicture const* const* SkBigPicture::drawablePicts() const { | |
79 return fDrawablePicts ? fDrawablePicts->begin() : nullptr; | |
80 } | |
81 | |
82 // Some ops have a paint, some have an optional paint. Either way, get back a p
ointer. | |
83 static const SkPaint* as_ptr(const SkPaint& p) { return &p; } | |
84 static const SkPaint* as_ptr(const SkRecords::Optional<SkPaint>& p) { return p;
} | |
85 | |
86 struct SkBigPicture::PathCounter { | |
87 SK_CREATE_MEMBER_DETECTOR(paint); | |
88 | |
89 PathCounter() : fNumSlowPathsAndDashEffects(0) {} | |
90 | |
91 // Recurse into nested pictures. | |
92 void operator()(const SkRecords::DrawPicture& op) { | |
93 fNumSlowPathsAndDashEffects += op.picture->numSlowPaths(); | |
94 } | |
95 | |
96 void checkPaint(const SkPaint* paint) { | |
97 if (paint && paint->getPathEffect()) { | |
98 // Initially assume it's slow. | |
99 fNumSlowPathsAndDashEffects++; | |
100 } | |
101 } | |
102 | |
103 void operator()(const SkRecords::DrawPoints& op) { | |
104 this->checkPaint(&op.paint); | |
105 const SkPathEffect* effect = op.paint.getPathEffect(); | |
106 if (effect) { | |
107 SkPathEffect::DashInfo info; | |
108 SkPathEffect::DashType dashType = effect->asADash(&info); | |
109 if (2 == op.count && SkPaint::kRound_Cap != op.paint.getStrokeCap()
&& | |
110 SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) { | |
111 fNumSlowPathsAndDashEffects--; | |
112 } | |
113 } | |
114 } | |
115 | |
116 void operator()(const SkRecords::DrawPath& op) { | |
117 this->checkPaint(&op.paint); | |
118 if (op.paint.isAntiAlias() && !op.path.isConvex()) { | |
119 SkPaint::Style paintStyle = op.paint.getStyle(); | |
120 const SkRect& pathBounds = op.path.getBounds(); | |
121 if (SkPaint::kStroke_Style == paintStyle && | |
122 0 == op.paint.getStrokeWidth()) { | |
123 // AA hairline concave path is not slow. | |
124 } else if (SkPaint::kFill_Style == paintStyle && pathBounds.width()
< 64.f && | |
125 pathBounds.height() < 64.f && !op.path.isVolatile()) { | |
126 // AADF eligible concave path is not slow. | |
127 } else { | |
128 fNumSlowPathsAndDashEffects++; | |
129 } | |
130 } | |
131 } | |
132 | |
133 template <typename T> | |
134 SK_WHEN(HasMember_paint<T>, void) operator()(const T& op) { | |
135 this->checkPaint(as_ptr(op.paint)); | |
136 } | |
137 | |
138 template <typename T> | |
139 SK_WHEN(!HasMember_paint<T>, void) operator()(const T& op) { /* do nothing *
/ } | |
140 | |
141 int fNumSlowPathsAndDashEffects; | |
142 }; | |
143 | |
144 SkBigPicture::Analysis::Analysis(const SkRecord& record) { | |
145 SkTextHunter text; | |
146 SkBitmapHunter bitmap; | |
147 PathCounter path; | |
148 | |
149 bool hasText = false, hasBitmap = false; | |
150 for (unsigned i = 0; i < record.count(); i++) { | |
151 hasText = hasText || record.visit<bool>(i, text); | |
152 hasBitmap = hasBitmap || record.visit<bool>(i, bitmap); | |
153 record.visit<void>(i, path); | |
154 } | |
155 | |
156 fHasText = hasText; | |
157 fWillPlaybackBitmaps = hasBitmap; | |
158 fNumSlowPathsAndDashEffects = SkTMin<int>(path.fNumSlowPathsAndDashEffects,
255); | |
159 } | |
160 | |
161 bool SkBigPicture::Analysis::suitableForGpuRasterization(const char** reason) co
nst { | |
162 if (fNumSlowPathsAndDashEffects > 5) { | |
163 if (reason) { *reason = "Too many slow paths (either concave or dashed).
"; } | |
164 return false; | |
165 } | |
166 return true; | |
167 } | |
OLD | NEW |