| 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 |