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

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: Report error message 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
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 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 &fGpuRasterizati onReason)) { }
218
219 ///////////////////////////////////////////////////////////////////////////////
220
49 #ifdef SK_SUPPORT_LEGACY_DEFAULT_PICTURE_CTOR 221 #ifdef SK_SUPPORT_LEGACY_DEFAULT_PICTURE_CTOR
50 // fRecord OK 222 // fRecord OK
51 SkPicture::SkPicture() 223 SkPicture::SkPicture()
52 : fWidth(0) 224 : fWidth(0)
53 , fHeight(0) 225 , fHeight(0) {
54 , fRecordWillPlayBackBitmaps(false) {
55 this->needsNewGenID(); 226 this->needsNewGenID();
56 } 227 }
57 #endif 228 #endif
58 229
59 // fRecord OK 230 // fRecord OK
60 SkPicture::SkPicture(int width, int height, 231 SkPicture::SkPicture(int width, int height,
61 const SkPictureRecord& record, 232 const SkPictureRecord& record,
62 bool deepCopyOps) 233 bool deepCopyOps)
63 : fWidth(width) 234 : fWidth(width)
64 , fHeight(height) 235 , fHeight(height) {
65 , fRecordWillPlayBackBitmaps(false) {
66 this->needsNewGenID(); 236 this->needsNewGenID();
67 237
68 SkPictInfo info; 238 SkPictInfo info;
69 this->createHeader(&info); 239 this->createHeader(&info);
70 fData.reset(SkNEW_ARGS(SkPictureData, (record, info, deepCopyOps))); 240 fData.reset(SkNEW_ARGS(SkPictureData, (record, info, deepCopyOps)));
71 } 241 }
72 242
73 // Create an SkPictureData-backed SkPicture from an SkRecord. 243 // Create an SkPictureData-backed SkPicture from an SkRecord.
74 // This for compatibility with serialization code only. This is not cheap. 244 // This for compatibility with serialization code only. This is not cheap.
75 static SkPicture* backport(const SkRecord& src, int width, int height) { 245 static SkPicture* backport(const SkRecord& src, int width, int height) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 } 300 }
131 SkASSERT(SafeCount(fData->fBitmapHeap.get()) == heapSize); 301 SkASSERT(SafeCount(fData->fBitmapHeap.get()) == heapSize);
132 302
133 // needed to create typeface playback 303 // needed to create typeface playback
134 copyInfo.controller.setupPlaybacks(); 304 copyInfo.controller.setupPlaybacks();
135 305
136 newData.reset(SkNEW_ARGS(SkPictureData, (*fData, &copyInfo))); 306 newData.reset(SkNEW_ARGS(SkPictureData, (*fData, &copyInfo)));
137 } 307 }
138 308
139 SkPicture* clone = SkNEW_ARGS(SkPicture, (newData.detach(), fWidth, fHeight) ); 309 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 310 clone->fUniqueID = this->uniqueID(); // need to call method to ensure != 0
142 311
143 return clone; 312 return clone;
144 #endif 313 #endif
145 } 314 }
146 #endif//SK_SUPPORT_LEGACY_PICTURE_CLONE 315 #endif//SK_SUPPORT_LEGACY_PICTURE_CLONE
147 316
148 // fRecord OK 317 // fRecord OK
149 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) cons t { 318 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) cons t {
150 fAccelData.reset(SkRef(data)); 319 fAccelData.reset(SkRef(data));
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 if (pInfo != NULL) { 432 if (pInfo != NULL) {
264 *pInfo = info; 433 *pInfo = info;
265 } 434 }
266 return true; 435 return true;
267 } 436 }
268 437
269 // fRecord OK 438 // fRecord OK
270 SkPicture::SkPicture(SkPictureData* data, int width, int height) 439 SkPicture::SkPicture(SkPictureData* data, int width, int height)
271 : fData(data) 440 : fData(data)
272 , fWidth(width) 441 , fWidth(width)
273 , fHeight(height) 442 , fHeight(height) {
274 , fRecordWillPlayBackBitmaps(false) {
275 this->needsNewGenID(); 443 this->needsNewGenID();
276 } 444 }
277 445
278 // fRecord OK 446 // fRecord OK
279 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) { 447 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) {
280 SkPictInfo info; 448 SkPictInfo info;
281 449
282 if (!InternalOnly_StreamIsSKP(stream, &info)) { 450 if (!InternalOnly_StreamIsSKP(stream, &info)) {
283 return NULL; 451 return NULL;
284 } 452 }
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 547
380 if (NULL != data) { 548 if (NULL != data) {
381 buffer.writeBool(true); 549 buffer.writeBool(true);
382 data->flatten(buffer); 550 data->flatten(buffer);
383 } else { 551 } else {
384 buffer.writeBool(false); 552 buffer.writeBool(false);
385 } 553 }
386 } 554 }
387 555
388 #if SK_SUPPORT_GPU 556 #if SK_SUPPORT_GPU
389 // fRecord TODO 557 // fRecord OK
390 bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **rea son) const { 558 bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **rea son) const {
559 if (fRecord.get()) {
560 if (reason && fAnalysis.fGpuRasterizationReason) {
561 *reason = fAnalysis.fGpuRasterizationReason;
562 }
563 return fAnalysis.fSuitableForGpuRasterization;
564 }
391 if (NULL == fData.get()) { 565 if (NULL == fData.get()) {
392 if (NULL != reason) { 566 if (NULL != reason) {
393 *reason = "Missing internal data."; 567 *reason = "Missing internal data.";
394 } 568 }
395 return false; 569 return false;
396 } 570 }
397 571
398 return fData->suitableForGpuRasterization(context, reason); 572 return fData->suitableForGpuRasterization(context, reason);
399 } 573 }
400 #endif 574 #endif
401 575
402 // fRecord TODO 576 // fRecord TODO
403 bool SkPicture::hasText() const { 577 bool SkPicture::hasText() const {
404 return fData.get() && fData->hasText(); 578 return fData.get() && fData->hasText();
405 } 579 }
406 580
407 // fRecord OK 581 // fRecord OK
408 bool SkPicture::willPlayBackBitmaps() const { 582 bool SkPicture::willPlayBackBitmaps() const {
409 if (fRecord.get()) { 583 if (fRecord.get()) {
410 return fRecordWillPlayBackBitmaps; 584 return fAnalysis.fWillPlaybackBitmaps;
411 } 585 }
412 if (!fData.get()) { 586 if (!fData.get()) {
413 return false; 587 return false;
414 } 588 }
415 return fData->containsBitmaps(); 589 return fData->containsBitmaps();
416 } 590 }
417 591
418 // fRecord OK 592 // fRecord OK
419 static int32_t next_picture_generation_id() { 593 static int32_t next_picture_generation_id() {
420 static int32_t gPictureGenerationID = 0; 594 static int32_t gPictureGenerationID = 0;
(...skipping 13 matching lines...) Expand all
434 } 608 }
435 return fUniqueID; 609 return fUniqueID;
436 } 610 }
437 611
438 // fRecord OK 612 // fRecord OK
439 SkPicture::SkPicture(int width, int height, SkRecord* record, SkBBoxHierarchy* b bh) 613 SkPicture::SkPicture(int width, int height, SkRecord* record, SkBBoxHierarchy* b bh)
440 : fWidth(width) 614 : fWidth(width)
441 , fHeight(height) 615 , fHeight(height)
442 , fRecord(record) 616 , fRecord(record)
443 , fBBH(SkSafeRef(bbh)) 617 , fBBH(SkSafeRef(bbh))
444 , fRecordWillPlayBackBitmaps(SkRecordWillPlaybackBitmaps(*record)) { 618 , fAnalysis(*record) {
445 // TODO: delay as much of this work until just before first playback? 619 // TODO: delay as much of this work until just before first playback?
446 if (fBBH.get()) { 620 if (fBBH.get()) {
447 SkRecordFillBounds(*record, fBBH.get()); 621 SkRecordFillBounds(*record, fBBH.get());
448 } 622 }
449 this->needsNewGenID(); 623 this->needsNewGenID();
450 } 624 }
451 625
452 // Note that we are assuming that this entry point will only be called from 626 // 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 627 // one thread. Currently the only client of this method is
454 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single 628 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single
(...skipping 16 matching lines...) Expand all
471 int SkPicture::approximateOpCount() const { 645 int SkPicture::approximateOpCount() const {
472 SkASSERT(fRecord.get() || fData.get()); 646 SkASSERT(fRecord.get() || fData.get());
473 if (fRecord.get()) { 647 if (fRecord.get()) {
474 return fRecord->count(); 648 return fRecord->count();
475 } 649 }
476 if (fData.get()) { 650 if (fData.get()) {
477 return fData->opCount(); 651 return fData->opCount();
478 } 652 }
479 return 0; 653 return 0;
480 } 654 }
OLDNEW
« no previous file with comments | « include/core/SkPicture.h ('k') | src/core/SkRecordAnalysis.h » ('j') | tests/PictureTest.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698