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

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: Remove obsolete code 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 SK_CREATE_TYPE_DETECTOR(DrawPoints);
121 SK_CREATE_TYPE_DETECTOR(DrawPath);
122
123 PathCounter()
124 : numPaintWithPathEffectUses (0)
125 , numFastPathDashEffects (0)
126 , numAAConcavePaths (0)
127 , numAAHairlineConcavePaths (0) {
128 }
129
130 void checkPaint(const SkPaint* paint) {
131 if (paint && paint->getPathEffect()) {
132 numPaintWithPathEffectUses++;
133 }
134 }
135
136 void operator()(const SkRecords::DrawPoints& op) {
137 this->checkPaint(&op.paint);
138 const SkPathEffect* effect = op.paint.getPathEffect();
139 if (effect) {
mtklein 2014/08/18 21:50:54 I like to scope these when possible: if (const Sk
140 SkPathEffect::DashInfo info;
141 SkPathEffect::DashType dashType = effect->asADash(&info);
142 if (2 == op.count && SkPaint::kRound_Cap != op.paint.getStrokeCap() &&
143 SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) {
144 numFastPathDashEffects++;
145 }
146 }
147 }
148
149 void operator()(const SkRecords::DrawPath& op) {
150 this->checkPaint(&op.paint);
151 if (op.paint.isAntiAlias() && !op.path.isConvex()) {
152 numAAConcavePaths++;
153
154 if (SkPaint::kStroke_Style == op.paint.getStyle() &&
155 0 == op.paint.getStrokeWidth()) {
156 numAAHairlineConcavePaths++;
157 }
158 }
159 }
160
161 template <typename T>
162 SK_WHEN(HasMember_paint<T>, void) operator()(const T& op) {
163 this->checkPaint(AsPtr(op.paint));
164 }
165
166 template <typename T>
167 SK_WHEN(!HasMember_paint<T>, void) operator()(const T& op) { /* do nothing * / }
168
169
170 int numPaintWithPathEffectUses;
171 int numFastPathDashEffects;
172 int numAAConcavePaths;
173 int numAAHairlineConcavePaths;
174 };
175
176 bool SuitableForGpuRasterization(const SkRecord& record,
177 const char** reason = NULL,
178 int sampleCount = 0) {
179 PathCounter counter;
180 for (unsigned i = 0; i < record.count(); i++) {
181 record.visit<void>(i, counter);
182 }
183
184 // TODO: the heuristic used here needs to be refined
185 static const int kNumPaintWithPathEffectsUsesTol = 1;
186 static const int kNumAAConcavePathsTol = 5;
187
188 int numNonDashedPathEffects = counter.numPaintWithPathEffectUses -
189 counter.numFastPathDashEffects;
190 bool suitableForDash = (0 == counter.numPaintWithPathEffectUses) ||
191 (numNonDashedPathEffects < kNumPaintWithPathEffectsUs esTol
192 && 0 == sampleCount);
193
194 bool ret = suitableForDash &&
195 (counter.numAAConcavePaths - counter.numAAHairlineConcavePaths)
196 < kNumAAConcavePathsTol;
197
198 if (!ret && NULL != reason) {
199 if (!suitableForDash) {
200 if (0 != sampleCount) {
201 *reason = "Can't use multisample on dash effect.";
202 } else {
203 *reason = "Too many non dashed path effects.";
204 }
205 } else if ((counter.numAAConcavePaths - counter.numAAHairlineConcavePath s)
206 >= kNumAAConcavePathsTol)
207 *reason = "Too many anti-aliased concave paths.";
208 else
209 *reason = "Unknown reason for GPU unsuitability.";
210 }
211 return ret;
212 }
213
214 } // namespace
215
216 SkPicture::Analysis::Analysis(const SkRecord& record)
217 : fWillPlaybackBitmaps (WillPlaybackBitmaps(record))
218 , fSuitableForGpuRasterization (SuitableForGpuRasterization(record)) { }
219
220 ///////////////////////////////////////////////////////////////////////////////
221
49 #ifdef SK_SUPPORT_LEGACY_DEFAULT_PICTURE_CTOR 222 #ifdef SK_SUPPORT_LEGACY_DEFAULT_PICTURE_CTOR
50 // fRecord OK 223 // fRecord OK
51 SkPicture::SkPicture() 224 SkPicture::SkPicture()
52 : fWidth(0) 225 : fWidth(0)
53 , fHeight(0) 226 , fHeight(0) {
54 , fRecordWillPlayBackBitmaps(false) {
55 this->needsNewGenID(); 227 this->needsNewGenID();
56 } 228 }
57 #endif 229 #endif
58 230
59 // fRecord OK 231 // fRecord OK
60 SkPicture::SkPicture(int width, int height, 232 SkPicture::SkPicture(int width, int height,
61 const SkPictureRecord& record, 233 const SkPictureRecord& record,
62 bool deepCopyOps) 234 bool deepCopyOps)
63 : fWidth(width) 235 : fWidth(width)
64 , fHeight(height) 236 , fHeight(height) {
65 , fRecordWillPlayBackBitmaps(false) {
66 this->needsNewGenID(); 237 this->needsNewGenID();
67 238
68 SkPictInfo info; 239 SkPictInfo info;
69 this->createHeader(&info); 240 this->createHeader(&info);
70 fData.reset(SkNEW_ARGS(SkPictureData, (record, info, deepCopyOps))); 241 fData.reset(SkNEW_ARGS(SkPictureData, (record, info, deepCopyOps)));
71 } 242 }
72 243
73 // Create an SkPictureData-backed SkPicture from an SkRecord. 244 // Create an SkPictureData-backed SkPicture from an SkRecord.
74 // This for compatibility with serialization code only. This is not cheap. 245 // This for compatibility with serialization code only. This is not cheap.
75 static SkPicture* backport(const SkRecord& src, int width, int height) { 246 static SkPicture* backport(const SkRecord& src, int width, int height) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 } 301 }
131 SkASSERT(SafeCount(fData->fBitmapHeap.get()) == heapSize); 302 SkASSERT(SafeCount(fData->fBitmapHeap.get()) == heapSize);
132 303
133 // needed to create typeface playback 304 // needed to create typeface playback
134 copyInfo.controller.setupPlaybacks(); 305 copyInfo.controller.setupPlaybacks();
135 306
136 newData.reset(SkNEW_ARGS(SkPictureData, (*fData, &copyInfo))); 307 newData.reset(SkNEW_ARGS(SkPictureData, (*fData, &copyInfo)));
137 } 308 }
138 309
139 SkPicture* clone = SkNEW_ARGS(SkPicture, (newData.detach(), fWidth, fHeight) ); 310 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 311 clone->fUniqueID = this->uniqueID(); // need to call method to ensure != 0
142 312
143 return clone; 313 return clone;
144 #endif 314 #endif
145 } 315 }
146 #endif//SK_SUPPORT_LEGACY_PICTURE_CLONE 316 #endif//SK_SUPPORT_LEGACY_PICTURE_CLONE
147 317
148 // fRecord OK 318 // fRecord OK
149 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) cons t { 319 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) cons t {
150 fAccelData.reset(SkRef(data)); 320 fAccelData.reset(SkRef(data));
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 if (pInfo != NULL) { 427 if (pInfo != NULL) {
258 *pInfo = info; 428 *pInfo = info;
259 } 429 }
260 return true; 430 return true;
261 } 431 }
262 432
263 // fRecord OK 433 // fRecord OK
264 SkPicture::SkPicture(SkPictureData* data, int width, int height) 434 SkPicture::SkPicture(SkPictureData* data, int width, int height)
265 : fData(data) 435 : fData(data)
266 , fWidth(width) 436 , fWidth(width)
267 , fHeight(height) 437 , fHeight(height) {
268 , fRecordWillPlayBackBitmaps(false) {
269 this->needsNewGenID(); 438 this->needsNewGenID();
270 } 439 }
271 440
272 // fRecord OK 441 // fRecord OK
273 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) { 442 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) {
274 SkPictInfo info; 443 SkPictInfo info;
275 444
276 if (!InternalOnly_StreamIsSKP(stream, &info)) { 445 if (!InternalOnly_StreamIsSKP(stream, &info)) {
277 return NULL; 446 return NULL;
278 } 447 }
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 542
374 if (NULL != data) { 543 if (NULL != data) {
375 buffer.writeBool(true); 544 buffer.writeBool(true);
376 data->flatten(buffer); 545 data->flatten(buffer);
377 } else { 546 } else {
378 buffer.writeBool(false); 547 buffer.writeBool(false);
379 } 548 }
380 } 549 }
381 550
382 #if SK_SUPPORT_GPU 551 #if SK_SUPPORT_GPU
383 // fRecord TODO 552 // fRecord OK
384 bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **rea son) const { 553 bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **rea son) const {
554 if (fRecord.get()) {
555 return fAnalysis.fSuitableForGpuRasterization;
556 }
385 if (NULL == fData.get()) { 557 if (NULL == fData.get()) {
386 if (NULL != reason) { 558 if (NULL != reason) {
387 *reason = "Missing internal data."; 559 *reason = "Missing internal data.";
388 } 560 }
389 return false; 561 return false;
390 } 562 }
391 563
392 return fData->suitableForGpuRasterization(context, reason); 564 return fData->suitableForGpuRasterization(context, reason);
393 } 565 }
394 #endif 566 #endif
395 567
396 // fRecord OK 568 // fRecord OK
397 bool SkPicture::willPlayBackBitmaps() const { 569 bool SkPicture::willPlayBackBitmaps() const {
398 if (fRecord.get()) { 570 if (fRecord.get()) {
399 return fRecordWillPlayBackBitmaps; 571 return fAnalysis.fWillPlaybackBitmaps;
400 } 572 }
401 if (!fData.get()) { 573 if (!fData.get()) {
402 return false; 574 return false;
403 } 575 }
404 return fData->containsBitmaps(); 576 return fData->containsBitmaps();
405 } 577 }
406 578
407 // fRecord OK 579 // fRecord OK
408 static int32_t next_picture_generation_id() { 580 static int32_t next_picture_generation_id() {
409 static int32_t gPictureGenerationID = 0; 581 static int32_t gPictureGenerationID = 0;
(...skipping 13 matching lines...) Expand all
423 } 595 }
424 return fUniqueID; 596 return fUniqueID;
425 } 597 }
426 598
427 // fRecord OK 599 // fRecord OK
428 SkPicture::SkPicture(int width, int height, SkRecord* record, SkBBoxHierarchy* b bh) 600 SkPicture::SkPicture(int width, int height, SkRecord* record, SkBBoxHierarchy* b bh)
429 : fWidth(width) 601 : fWidth(width)
430 , fHeight(height) 602 , fHeight(height)
431 , fRecord(record) 603 , fRecord(record)
432 , fBBH(SkSafeRef(bbh)) 604 , fBBH(SkSafeRef(bbh))
433 , fRecordWillPlayBackBitmaps(SkRecordWillPlaybackBitmaps(*record)) { 605 , fAnalysis(*record) {
434 // TODO: delay as much of this work until just before first playback? 606 // TODO: delay as much of this work until just before first playback?
435 if (fBBH.get()) { 607 if (fBBH.get()) {
436 SkRecordFillBounds(*record, fBBH.get()); 608 SkRecordFillBounds(*record, fBBH.get());
437 } 609 }
438 this->needsNewGenID(); 610 this->needsNewGenID();
439 } 611 }
440 612
441 // Note that we are assuming that this entry point will only be called from 613 // Note that we are assuming that this entry point will only be called from
442 // one thread. Currently the only client of this method is 614 // one thread. Currently the only client of this method is
443 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single 615 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single
444 // thread. 616 // thread.
445 void SkPicture::addDeletionListener(DeletionListener* listener) const { 617 void SkPicture::addDeletionListener(DeletionListener* listener) const {
446 SkASSERT(NULL != listener); 618 SkASSERT(NULL != listener);
447 619
448 *fDeletionListeners.append() = SkRef(listener); 620 *fDeletionListeners.append() = SkRef(listener);
449 } 621 }
450 622
451 void SkPicture::callDeletionListeners() { 623 void SkPicture::callDeletionListeners() {
452 for (int i = 0; i < fDeletionListeners.count(); ++i) { 624 for (int i = 0; i < fDeletionListeners.count(); ++i) {
453 fDeletionListeners[i]->onDeletion(this->uniqueID()); 625 fDeletionListeners[i]->onDeletion(this->uniqueID());
454 } 626 }
455 627
456 fDeletionListeners.unrefAll(); 628 fDeletionListeners.unrefAll();
457 } 629 }
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