Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(290)

Side by Side Diff: src/core/SkPicture.cpp

Issue 481173003: Revert "Move the code over using the same template type approach previously used for willPlayBackBi… (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/core/SkPicture.h ('k') | src/core/SkRecordAnalysis.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2007 The Android Open Source Project 3 * Copyright 2007 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "SkPictureFlat.h" 10 #include "SkPictureFlat.h"
11 #include "SkPictureData.h" 11 #include "SkPictureData.h"
12 #include "SkPicturePlayback.h" 12 #include "SkPicturePlayback.h"
13 #include "SkPictureRecord.h" 13 #include "SkPictureRecord.h"
14 #include "SkPictureRecorder.h" 14 #include "SkPictureRecorder.h"
15 #include "SkPictureStateTree.h" 15 #include "SkPictureStateTree.h"
16 16
17 #include "SkBitmapDevice.h" 17 #include "SkBitmapDevice.h"
18 #include "SkCanvas.h" 18 #include "SkCanvas.h"
19 #include "SkChunkAlloc.h" 19 #include "SkChunkAlloc.h"
20 #include "SkDrawPictureCallback.h" 20 #include "SkDrawPictureCallback.h"
21 #include "SkPaintPriv.h" 21 #include "SkPaintPriv.h"
22 #include "SkPathEffect.h"
23 #include "SkPicture.h" 22 #include "SkPicture.h"
23 #include "SkRecordAnalysis.h"
24 #include "SkRegion.h" 24 #include "SkRegion.h"
25 #include "SkShader.h"
26 #include "SkStream.h" 25 #include "SkStream.h"
27 #include "SkTDArray.h" 26 #include "SkTDArray.h"
28 #include "SkTLogic.h"
29 #include "SkTSearch.h" 27 #include "SkTSearch.h"
30 #include "SkTime.h" 28 #include "SkTime.h"
31 29
32 #include "SkReader32.h" 30 #include "SkReader32.h"
33 #include "SkWriter32.h" 31 #include "SkWriter32.h"
34 #include "SkRTree.h" 32 #include "SkRTree.h"
35 #include "SkBBoxHierarchyRecord.h" 33 #include "SkBBoxHierarchyRecord.h"
36 34
37 #if SK_SUPPORT_GPU 35 #if SK_SUPPORT_GPU
38 #include "GrContext.h" 36 #include "GrContext.h"
39 #endif 37 #endif
40 38
41 #include "SkRecord.h" 39 #include "SkRecord.h"
42 #include "SkRecordDraw.h" 40 #include "SkRecordDraw.h"
43 #include "SkRecorder.h" 41 #include "SkRecorder.h"
44 42
45 template <typename T> int SafeCount(const T* obj) { 43 template <typename T> int SafeCount(const T* obj) {
46 return obj ? obj->count() : 0; 44 return obj ? obj->count() : 0;
47 } 45 }
48 46
49 /////////////////////////////////////////////////////////////////////////////// 47 ///////////////////////////////////////////////////////////////////////////////
50 48
51 namespace {
52
53 // Some commands have a paint, some have an optional paint. Either way, get bac k a pointer.
54 static const SkPaint* AsPtr(const SkPaint& p) { return &p; }
55 static const SkPaint* AsPtr(const SkRecords::Optional<SkPaint>& p) { return p; }
56
57 /** SkRecords visitor to determine whether an instance may require an
58 "external" bitmap to rasterize. May return false positives.
59 Does not return true for bitmap text.
60
61 Expected use is to determine whether images need to be decoded before
62 rasterizing a particular SkRecord.
63 */
64 struct BitmapTester {
65 // Helpers. These create HasMember_bitmap and HasMember_paint.
66 SK_CREATE_MEMBER_DETECTOR(bitmap);
67 SK_CREATE_MEMBER_DETECTOR(paint);
68
69
70 // Main entry for visitor:
71 // If the command has a bitmap directly, return true.
72 // If the command has a paint and the paint has a bitmap, return true.
73 // Otherwise, return false.
74 template <typename T>
75 bool operator()(const T& r) { return CheckBitmap(r); }
76
77
78 // If the command has a bitmap, of course we're going to play back bitmaps.
79 template <typename T>
80 static SK_WHEN(HasMember_bitmap<T>, bool) CheckBitmap(const T&) { return tru e; }
81
82 // If not, look for one in its paint (if it has a paint).
83 template <typename T>
84 static SK_WHEN(!HasMember_bitmap<T>, bool) CheckBitmap(const T& r) { return CheckPaint(r); }
85
86 // If we have a paint, dig down into the effects looking for a bitmap.
87 template <typename T>
88 static SK_WHEN(HasMember_paint<T>, bool) CheckPaint(const T& r) {
89 const SkPaint* paint = AsPtr(r.paint);
90 if (paint) {
91 const SkShader* shader = paint->getShader();
92 if (shader &&
93 shader->asABitmap(NULL, NULL, NULL) == SkShader::kDefault_Bitmap Type) {
94 return true;
95 }
96 }
97 return false;
98 }
99
100 // If we don't have a paint, that non-paint has no bitmap.
101 template <typename T>
102 static SK_WHEN(!HasMember_paint<T>, bool) CheckPaint(const T&) { return fals e; }
103 };
104
105 bool WillPlaybackBitmaps(const SkRecord& record) {
106 BitmapTester tester;
107 for (unsigned i = 0; i < record.count(); i++) {
108 if (record.visit<bool>(i, tester)) {
109 return true;
110 }
111 }
112 return false;
113 }
114
115 /** SkRecords visitor to determine heuristically whether or not a SkPicture
116 will be performant when rasterized on the GPU.
117 */
118 struct PathCounter {
119 SK_CREATE_MEMBER_DETECTOR(paint);
120
121 PathCounter()
122 : numPaintWithPathEffectUses (0)
123 , numFastPathDashEffects (0)
124 , numAAConcavePaths (0)
125 , numAAHairlineConcavePaths (0) {
126 }
127
128 void checkPaint(const SkPaint* paint) {
129 if (paint && paint->getPathEffect()) {
130 numPaintWithPathEffectUses++;
131 }
132 }
133
134 void operator()(const SkRecords::DrawPoints& op) {
135 this->checkPaint(&op.paint);
136 const SkPathEffect* effect = op.paint.getPathEffect();
137 if (effect) {
138 SkPathEffect::DashInfo info;
139 SkPathEffect::DashType dashType = effect->asADash(&info);
140 if (2 == op.count && SkPaint::kRound_Cap != op.paint.getStrokeCap() &&
141 SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) {
142 numFastPathDashEffects++;
143 }
144 }
145 }
146
147 void operator()(const SkRecords::DrawPath& op) {
148 this->checkPaint(&op.paint);
149 if (op.paint.isAntiAlias() && !op.path.isConvex()) {
150 numAAConcavePaths++;
151
152 if (SkPaint::kStroke_Style == op.paint.getStyle() &&
153 0 == op.paint.getStrokeWidth()) {
154 numAAHairlineConcavePaths++;
155 }
156 }
157 }
158
159 template <typename T>
160 SK_WHEN(HasMember_paint<T>, void) operator()(const T& op) {
161 this->checkPaint(AsPtr(op.paint));
162 }
163
164 template <typename T>
165 SK_WHEN(!HasMember_paint<T>, void) operator()(const T& op) { /* do nothing * / }
166
167
168 int numPaintWithPathEffectUses;
169 int numFastPathDashEffects;
170 int numAAConcavePaths;
171 int numAAHairlineConcavePaths;
172 };
173
174 bool SuitableForGpuRasterization(const SkRecord& record,
175 const char** reason = NULL,
176 int sampleCount = 0) {
177 PathCounter counter;
178 for (unsigned i = 0; i < record.count(); i++) {
179 record.visit<void>(i, counter);
180 }
181
182 // TODO: the heuristic used here needs to be refined
183 static const int kNumPaintWithPathEffectsUsesTol = 1;
184 static const int kNumAAConcavePathsTol = 5;
185
186 int numNonDashedPathEffects = counter.numPaintWithPathEffectUses -
187 counter.numFastPathDashEffects;
188 bool suitableForDash = (0 == counter.numPaintWithPathEffectUses) ||
189 (numNonDashedPathEffects < kNumPaintWithPathEffectsUs esTol
190 && 0 == sampleCount);
191
192 bool ret = suitableForDash &&
193 (counter.numAAConcavePaths - counter.numAAHairlineConcavePaths)
194 < kNumAAConcavePathsTol;
195
196 if (!ret && NULL != reason) {
197 if (!suitableForDash) {
198 if (0 != sampleCount) {
199 *reason = "Can't use multisample on dash effect.";
200 } else {
201 *reason = "Too many non dashed path effects.";
202 }
203 } else if ((counter.numAAConcavePaths - counter.numAAHairlineConcavePath s)
204 >= kNumAAConcavePathsTol)
205 *reason = "Too many anti-aliased concave paths.";
206 else
207 *reason = "Unknown reason for GPU unsuitability.";
208 }
209 return ret;
210 }
211
212 } // namespace
213
214 SkPicture::Analysis::Analysis(const SkRecord& record)
215 : fWillPlaybackBitmaps (WillPlaybackBitmaps(record))
216 , fSuitableForGpuRasterization (SuitableForGpuRasterization(record)) { }
217
218 ///////////////////////////////////////////////////////////////////////////////
219
220 #ifdef SK_SUPPORT_LEGACY_DEFAULT_PICTURE_CTOR 49 #ifdef SK_SUPPORT_LEGACY_DEFAULT_PICTURE_CTOR
221 // fRecord OK 50 // fRecord OK
222 SkPicture::SkPicture() 51 SkPicture::SkPicture()
223 : fWidth(0) 52 : fWidth(0)
224 , fHeight(0) { 53 , fHeight(0)
54 , fRecordWillPlayBackBitmaps(false) {
225 this->needsNewGenID(); 55 this->needsNewGenID();
226 } 56 }
227 #endif 57 #endif
228 58
229 // fRecord OK 59 // fRecord OK
230 SkPicture::SkPicture(int width, int height, 60 SkPicture::SkPicture(int width, int height,
231 const SkPictureRecord& record, 61 const SkPictureRecord& record,
232 bool deepCopyOps) 62 bool deepCopyOps)
233 : fWidth(width) 63 : fWidth(width)
234 , fHeight(height) { 64 , fHeight(height)
65 , fRecordWillPlayBackBitmaps(false) {
235 this->needsNewGenID(); 66 this->needsNewGenID();
236 67
237 SkPictInfo info; 68 SkPictInfo info;
238 this->createHeader(&info); 69 this->createHeader(&info);
239 fData.reset(SkNEW_ARGS(SkPictureData, (record, info, deepCopyOps))); 70 fData.reset(SkNEW_ARGS(SkPictureData, (record, info, deepCopyOps)));
240 } 71 }
241 72
242 // Create an SkPictureData-backed SkPicture from an SkRecord. 73 // Create an SkPictureData-backed SkPicture from an SkRecord.
243 // This for compatibility with serialization code only. This is not cheap. 74 // This for compatibility with serialization code only. This is not cheap.
244 static SkPicture* backport(const SkRecord& src, int width, int height) { 75 static SkPicture* backport(const SkRecord& src, int width, int height) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 } 130 }
300 SkASSERT(SafeCount(fData->fBitmapHeap.get()) == heapSize); 131 SkASSERT(SafeCount(fData->fBitmapHeap.get()) == heapSize);
301 132
302 // needed to create typeface playback 133 // needed to create typeface playback
303 copyInfo.controller.setupPlaybacks(); 134 copyInfo.controller.setupPlaybacks();
304 135
305 newData.reset(SkNEW_ARGS(SkPictureData, (*fData, &copyInfo))); 136 newData.reset(SkNEW_ARGS(SkPictureData, (*fData, &copyInfo)));
306 } 137 }
307 138
308 SkPicture* clone = SkNEW_ARGS(SkPicture, (newData.detach(), fWidth, fHeight) ); 139 SkPicture* clone = SkNEW_ARGS(SkPicture, (newData.detach(), fWidth, fHeight) );
140 clone->fRecordWillPlayBackBitmaps = fRecordWillPlayBackBitmaps;
309 clone->fUniqueID = this->uniqueID(); // need to call method to ensure != 0 141 clone->fUniqueID = this->uniqueID(); // need to call method to ensure != 0
310 142
311 return clone; 143 return clone;
312 #endif 144 #endif
313 } 145 }
314 #endif//SK_SUPPORT_LEGACY_PICTURE_CLONE 146 #endif//SK_SUPPORT_LEGACY_PICTURE_CLONE
315 147
316 // fRecord OK 148 // fRecord OK
317 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) cons t { 149 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) cons t {
318 fAccelData.reset(SkRef(data)); 150 fAccelData.reset(SkRef(data));
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 if (pInfo != NULL) { 263 if (pInfo != NULL) {
432 *pInfo = info; 264 *pInfo = info;
433 } 265 }
434 return true; 266 return true;
435 } 267 }
436 268
437 // fRecord OK 269 // fRecord OK
438 SkPicture::SkPicture(SkPictureData* data, int width, int height) 270 SkPicture::SkPicture(SkPictureData* data, int width, int height)
439 : fData(data) 271 : fData(data)
440 , fWidth(width) 272 , fWidth(width)
441 , fHeight(height) { 273 , fHeight(height)
274 , fRecordWillPlayBackBitmaps(false) {
442 this->needsNewGenID(); 275 this->needsNewGenID();
443 } 276 }
444 277
445 // fRecord OK 278 // fRecord OK
446 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) { 279 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) {
447 SkPictInfo info; 280 SkPictInfo info;
448 281
449 if (!InternalOnly_StreamIsSKP(stream, &info)) { 282 if (!InternalOnly_StreamIsSKP(stream, &info)) {
450 return NULL; 283 return NULL;
451 } 284 }
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 379
547 if (NULL != data) { 380 if (NULL != data) {
548 buffer.writeBool(true); 381 buffer.writeBool(true);
549 data->flatten(buffer); 382 data->flatten(buffer);
550 } else { 383 } else {
551 buffer.writeBool(false); 384 buffer.writeBool(false);
552 } 385 }
553 } 386 }
554 387
555 #if SK_SUPPORT_GPU 388 #if SK_SUPPORT_GPU
556 // fRecord OK 389 // fRecord TODO
557 bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **rea son) const { 390 bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **rea son) const {
558 if (fRecord.get()) {
559 return fAnalysis.fSuitableForGpuRasterization;
560 }
561 if (NULL == fData.get()) { 391 if (NULL == fData.get()) {
562 if (NULL != reason) { 392 if (NULL != reason) {
563 *reason = "Missing internal data."; 393 *reason = "Missing internal data.";
564 } 394 }
565 return false; 395 return false;
566 } 396 }
567 397
568 return fData->suitableForGpuRasterization(context, reason); 398 return fData->suitableForGpuRasterization(context, reason);
569 } 399 }
570 #endif 400 #endif
571 401
572 // fRecord TODO 402 // fRecord TODO
573 bool SkPicture::hasText() const { 403 bool SkPicture::hasText() const {
574 return fData.get() && fData->hasText(); 404 return fData.get() && fData->hasText();
575 } 405 }
576 406
577 // fRecord OK 407 // fRecord OK
578 bool SkPicture::willPlayBackBitmaps() const { 408 bool SkPicture::willPlayBackBitmaps() const {
579 if (fRecord.get()) { 409 if (fRecord.get()) {
580 return fAnalysis.fWillPlaybackBitmaps; 410 return fRecordWillPlayBackBitmaps;
581 } 411 }
582 if (!fData.get()) { 412 if (!fData.get()) {
583 return false; 413 return false;
584 } 414 }
585 return fData->containsBitmaps(); 415 return fData->containsBitmaps();
586 } 416 }
587 417
588 // fRecord OK 418 // fRecord OK
589 static int32_t next_picture_generation_id() { 419 static int32_t next_picture_generation_id() {
590 static int32_t gPictureGenerationID = 0; 420 static int32_t gPictureGenerationID = 0;
(...skipping 13 matching lines...) Expand all
604 } 434 }
605 return fUniqueID; 435 return fUniqueID;
606 } 436 }
607 437
608 // fRecord OK 438 // fRecord OK
609 SkPicture::SkPicture(int width, int height, SkRecord* record, SkBBoxHierarchy* b bh) 439 SkPicture::SkPicture(int width, int height, SkRecord* record, SkBBoxHierarchy* b bh)
610 : fWidth(width) 440 : fWidth(width)
611 , fHeight(height) 441 , fHeight(height)
612 , fRecord(record) 442 , fRecord(record)
613 , fBBH(SkSafeRef(bbh)) 443 , fBBH(SkSafeRef(bbh))
614 , fAnalysis(*record) { 444 , fRecordWillPlayBackBitmaps(SkRecordWillPlaybackBitmaps(*record)) {
615 // TODO: delay as much of this work until just before first playback? 445 // TODO: delay as much of this work until just before first playback?
616 if (fBBH.get()) { 446 if (fBBH.get()) {
617 SkRecordFillBounds(*record, fBBH.get()); 447 SkRecordFillBounds(*record, fBBH.get());
618 } 448 }
619 this->needsNewGenID(); 449 this->needsNewGenID();
620 } 450 }
621 451
622 // Note that we are assuming that this entry point will only be called from 452 // Note that we are assuming that this entry point will only be called from
623 // one thread. Currently the only client of this method is 453 // one thread. Currently the only client of this method is
624 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single 454 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single
(...skipping 16 matching lines...) Expand all
641 int SkPicture::approximateOpCount() const { 471 int SkPicture::approximateOpCount() const {
642 SkASSERT(fRecord.get() || fData.get()); 472 SkASSERT(fRecord.get() || fData.get());
643 if (fRecord.get()) { 473 if (fRecord.get()) {
644 return fRecord->count(); 474 return fRecord->count();
645 } 475 }
646 if (fData.get()) { 476 if (fData.get()) {
647 return fData->opCount(); 477 return fData->opCount();
648 } 478 }
649 return 0; 479 return 0;
650 } 480 }
OLDNEW
« no previous file with comments | « include/core/SkPicture.h ('k') | src/core/SkRecordAnalysis.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698