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

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

Issue 364823009: Port suitableForGpuRasterization to SkRecord (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Rebase 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"
22 #include "SkPicture.h" 23 #include "SkPicture.h"
23 #include "SkRecordAnalysis.h"
24 #include "SkRegion.h" 24 #include "SkRegion.h"
25 #include "SkShader.h"
25 #include "SkStream.h" 26 #include "SkStream.h"
26 #include "SkTDArray.h" 27 #include "SkTDArray.h"
28 #include "SkTLogic.h"
27 #include "SkTSearch.h" 29 #include "SkTSearch.h"
28 #include "SkTime.h" 30 #include "SkTime.h"
29 31
30 #include "SkReader32.h" 32 #include "SkReader32.h"
31 #include "SkWriter32.h" 33 #include "SkWriter32.h"
32 #include "SkRTree.h" 34 #include "SkRTree.h"
33 #include "SkBBoxHierarchyRecord.h" 35 #include "SkBBoxHierarchyRecord.h"
34 36
35 #if SK_SUPPORT_GPU 37 #if SK_SUPPORT_GPU
36 #include "GrContext.h" 38 #include "GrContext.h"
37 #endif 39 #endif
38 40
39 #include "SkRecord.h" 41 #include "SkRecord.h"
40 #include "SkRecordDraw.h" 42 #include "SkRecordDraw.h"
41 #include "SkRecorder.h" 43 #include "SkRecorder.h"
42 44
43 template <typename T> int SafeCount(const T* obj) { 45 template <typename T> int SafeCount(const T* obj) {
44 return obj ? obj->count() : 0; 46 return obj ? obj->count() : 0;
45 } 47 }
46 48
47 /////////////////////////////////////////////////////////////////////////////// 49 ///////////////////////////////////////////////////////////////////////////////
48 50
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 } // namespace
175
176 void SkPicture::Analysis::init(const SkRecord& record) {
177
178 fWillPlaybackBitmaps = WillPlaybackBitmaps(record);
179
180 PathCounter counter;
181 for (unsigned i = 0; i < record.count(); i++) {
182 record.visit<void>(i, counter);
183 }
184 fNumPaintWithPathEffectUses = counter.numPaintWithPathEffectUses;
185 fNumFastPathDashEffects = counter.numFastPathDashEffects;
186 fNumAAConcavePaths = counter.numAAConcavePaths;
187 fNumAAHairlineConcavePaths = counter.numAAHairlineConcavePaths;
188 }
189
190 bool SkPicture::Analysis::suitableForGpuRasterization(const char** reason,
191 int sampleCount) const {
192 // TODO: the heuristic used here needs to be refined
193 static const int kNumPaintWithPathEffectsUsesTol = 1;
194 static const int kNumAAConcavePathsTol = 5;
195
196 int numNonDashedPathEffects = fNumPaintWithPathEffectUses -
197 fNumFastPathDashEffects;
198 bool suitableForDash = (0 == fNumPaintWithPathEffectUses) ||
199 (numNonDashedPathEffects < kNumPaintWithPathEffectsUs esTol
200 && 0 == sampleCount);
201
202 bool ret = suitableForDash &&
203 (fNumAAConcavePaths - fNumAAHairlineConcavePaths)
204 < kNumAAConcavePathsTol;
205
206 if (!ret && NULL != reason) {
207 if (!suitableForDash) {
208 if (0 != sampleCount) {
209 *reason = "Can't use multisample on dash effect.";
210 } else {
211 *reason = "Too many non dashed path effects.";
212 }
213 } else if ((fNumAAConcavePaths - fNumAAHairlineConcavePaths)
214 >= kNumAAConcavePathsTol)
215 *reason = "Too many anti-aliased concave paths.";
216 else
217 *reason = "Unknown reason for GPU unsuitability.";
218 }
219 return ret;
220 }
221
222 ///////////////////////////////////////////////////////////////////////////////
223
49 #ifdef SK_SUPPORT_LEGACY_DEFAULT_PICTURE_CTOR 224 #ifdef SK_SUPPORT_LEGACY_DEFAULT_PICTURE_CTOR
50 // fRecord OK 225 // fRecord OK
51 SkPicture::SkPicture() 226 SkPicture::SkPicture()
52 : fWidth(0) 227 : fWidth(0)
53 , fHeight(0) 228 , fHeight(0) {
54 , fRecordWillPlayBackBitmaps(false) {
55 this->needsNewGenID(); 229 this->needsNewGenID();
56 } 230 }
57 #endif 231 #endif
58 232
59 // fRecord OK 233 // fRecord OK
60 SkPicture::SkPicture(int width, int height, 234 SkPicture::SkPicture(int width, int height,
61 const SkPictureRecord& record, 235 const SkPictureRecord& record,
62 bool deepCopyOps) 236 bool deepCopyOps)
63 : fWidth(width) 237 : fWidth(width)
64 , fHeight(height) 238 , fHeight(height)
65 , fRecordWillPlayBackBitmaps(false) { 239 , fAnalysis() {
66 this->needsNewGenID(); 240 this->needsNewGenID();
67 241
68 SkPictInfo info; 242 SkPictInfo info;
69 this->createHeader(&info); 243 this->createHeader(&info);
70 fData.reset(SkNEW_ARGS(SkPictureData, (record, info, deepCopyOps))); 244 fData.reset(SkNEW_ARGS(SkPictureData, (record, info, deepCopyOps)));
71 } 245 }
72 246
73 // Create an SkPictureData-backed SkPicture from an SkRecord. 247 // Create an SkPictureData-backed SkPicture from an SkRecord.
74 // This for compatibility with serialization code only. This is not cheap. 248 // This for compatibility with serialization code only. This is not cheap.
75 static SkPicture* backport(const SkRecord& src, int width, int height) { 249 static SkPicture* backport(const SkRecord& src, int width, int height) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 } 304 }
131 SkASSERT(SafeCount(fData->fBitmapHeap.get()) == heapSize); 305 SkASSERT(SafeCount(fData->fBitmapHeap.get()) == heapSize);
132 306
133 // needed to create typeface playback 307 // needed to create typeface playback
134 copyInfo.controller.setupPlaybacks(); 308 copyInfo.controller.setupPlaybacks();
135 309
136 newData.reset(SkNEW_ARGS(SkPictureData, (*fData, &copyInfo))); 310 newData.reset(SkNEW_ARGS(SkPictureData, (*fData, &copyInfo)));
137 } 311 }
138 312
139 SkPicture* clone = SkNEW_ARGS(SkPicture, (newData.detach(), fWidth, fHeight) ); 313 SkPicture* clone = SkNEW_ARGS(SkPicture, (newData.detach(), fWidth, fHeight) );
140 clone->fRecordWillPlayBackBitmaps = fRecordWillPlayBackBitmaps;
141 clone->fUniqueID = this->uniqueID(); // need to call method to ensure != 0 314 clone->fUniqueID = this->uniqueID(); // need to call method to ensure != 0
142 315
143 return clone; 316 return clone;
144 #endif 317 #endif
145 } 318 }
146 #endif//SK_SUPPORT_LEGACY_PICTURE_CLONE 319 #endif//SK_SUPPORT_LEGACY_PICTURE_CLONE
147 320
148 // fRecord OK 321 // fRecord OK
149 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) cons t { 322 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) cons t {
150 fAccelData.reset(SkRef(data)); 323 fAccelData.reset(SkRef(data));
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 *pInfo = info; 437 *pInfo = info;
265 } 438 }
266 return true; 439 return true;
267 } 440 }
268 441
269 // fRecord OK 442 // fRecord OK
270 SkPicture::SkPicture(SkPictureData* data, int width, int height) 443 SkPicture::SkPicture(SkPictureData* data, int width, int height)
271 : fData(data) 444 : fData(data)
272 , fWidth(width) 445 , fWidth(width)
273 , fHeight(height) 446 , fHeight(height)
274 , fRecordWillPlayBackBitmaps(false) { 447 , fAnalysis() {
275 this->needsNewGenID(); 448 this->needsNewGenID();
276 } 449 }
277 450
278 // fRecord OK 451 // fRecord OK
279 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) { 452 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) {
280 SkPictInfo info; 453 SkPictInfo info;
281 454
282 if (!InternalOnly_StreamIsSKP(stream, &info)) { 455 if (!InternalOnly_StreamIsSKP(stream, &info)) {
283 return NULL; 456 return NULL;
284 } 457 }
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 552
380 if (NULL != data) { 553 if (NULL != data) {
381 buffer.writeBool(true); 554 buffer.writeBool(true);
382 data->flatten(buffer); 555 data->flatten(buffer);
383 } else { 556 } else {
384 buffer.writeBool(false); 557 buffer.writeBool(false);
385 } 558 }
386 } 559 }
387 560
388 #if SK_SUPPORT_GPU 561 #if SK_SUPPORT_GPU
389 // fRecord TODO 562 // fRecord OK
390 bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **rea son) const { 563 bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **rea son) const {
564 if (fRecord.get()) {
565 return fAnalysis.suitableForGpuRasterization(reason, 0);
566 }
391 if (NULL == fData.get()) { 567 if (NULL == fData.get()) {
392 if (NULL != reason) { 568 if (NULL != reason) {
393 *reason = "Missing internal data."; 569 *reason = "Missing internal data.";
394 } 570 }
395 return false; 571 return false;
396 } 572 }
397 573
398 return fData->suitableForGpuRasterization(context, reason); 574 return fData->suitableForGpuRasterization(context, reason);
399 } 575 }
400 #endif 576 #endif
401 577
402 // fRecord TODO 578 // fRecord TODO
403 bool SkPicture::hasText() const { 579 bool SkPicture::hasText() const {
404 return fData.get() && fData->hasText(); 580 return fData.get() && fData->hasText();
405 } 581 }
406 582
407 // fRecord OK 583 // fRecord OK
408 bool SkPicture::willPlayBackBitmaps() const { 584 bool SkPicture::willPlayBackBitmaps() const {
409 if (fRecord.get()) { 585 if (fRecord.get()) {
410 return fRecordWillPlayBackBitmaps; 586 return fAnalysis.fWillPlaybackBitmaps;
411 } 587 }
412 if (!fData.get()) { 588 if (!fData.get()) {
413 return false; 589 return false;
414 } 590 }
415 return fData->containsBitmaps(); 591 return fData->containsBitmaps();
416 } 592 }
417 593
418 // fRecord OK 594 // fRecord OK
419 static int32_t next_picture_generation_id() { 595 static int32_t next_picture_generation_id() {
420 static int32_t gPictureGenerationID = 0; 596 static int32_t gPictureGenerationID = 0;
(...skipping 13 matching lines...) Expand all
434 } 610 }
435 return fUniqueID; 611 return fUniqueID;
436 } 612 }
437 613
438 // fRecord OK 614 // fRecord OK
439 SkPicture::SkPicture(int width, int height, SkRecord* record, SkBBoxHierarchy* b bh) 615 SkPicture::SkPicture(int width, int height, SkRecord* record, SkBBoxHierarchy* b bh)
440 : fWidth(width) 616 : fWidth(width)
441 , fHeight(height) 617 , fHeight(height)
442 , fRecord(record) 618 , fRecord(record)
443 , fBBH(SkSafeRef(bbh)) 619 , fBBH(SkSafeRef(bbh))
444 , fRecordWillPlayBackBitmaps(SkRecordWillPlaybackBitmaps(*record)) { 620 , fAnalysis() {
445 // TODO: delay as much of this work until just before first playback? 621 // TODO: delay as much of this work until just before first playback?
622
623 const_cast<Analysis*>(&fAnalysis)->init(*record);
446 if (fBBH.get()) { 624 if (fBBH.get()) {
447 SkRecordFillBounds(*record, fBBH.get()); 625 SkRecordFillBounds(*record, fBBH.get());
448 } 626 }
449 this->needsNewGenID(); 627 this->needsNewGenID();
450 } 628 }
451 629
452 // Note that we are assuming that this entry point will only be called from 630 // Note that we are assuming that this entry point will only be called from
453 // one thread. Currently the only client of this method is 631 // one thread. Currently the only client of this method is
454 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single 632 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single
455 // thread. 633 // thread.
(...skipping 15 matching lines...) Expand all
471 int SkPicture::approximateOpCount() const { 649 int SkPicture::approximateOpCount() const {
472 SkASSERT(fRecord.get() || fData.get()); 650 SkASSERT(fRecord.get() || fData.get());
473 if (fRecord.get()) { 651 if (fRecord.get()) {
474 return fRecord->count(); 652 return fRecord->count();
475 } 653 }
476 if (fData.get()) { 654 if (fData.get()) {
477 return fData->opCount(); 655 return fData->opCount();
478 } 656 }
479 return 0; 657 return 0;
480 } 658 }
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