OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkPictureRecord.h" | 8 #include "SkPictureRecord.h" |
9 #include "SkTSearch.h" | 9 #include "SkTSearch.h" |
10 #include "SkPixelRef.h" | 10 #include "SkPixelRef.h" |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 void SkPictureRecord::willSave() { | 148 void SkPictureRecord::willSave() { |
149 // record the offset to us, making it non-positive to distinguish a save | 149 // record the offset to us, making it non-positive to distinguish a save |
150 // from a clip entry. | 150 // from a clip entry. |
151 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten()); | 151 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten()); |
152 this->recordSave(); | 152 this->recordSave(); |
153 | 153 |
154 this->INHERITED::willSave(); | 154 this->INHERITED::willSave(); |
155 } | 155 } |
156 | 156 |
157 void SkPictureRecord::recordSave() { | 157 void SkPictureRecord::recordSave() { |
| 158 fContentInfo.onSave(); |
| 159 |
158 // op only | 160 // op only |
159 size_t size = kSaveSize; | 161 size_t size = kSaveSize; |
160 size_t initialOffset = this->addDraw(SAVE, &size); | 162 size_t initialOffset = this->addDraw(SAVE, &size); |
161 | 163 |
162 this->validate(initialOffset, size); | 164 this->validate(initialOffset, size); |
163 } | 165 } |
164 | 166 |
165 SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds, | 167 SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds, |
166 const SkPaint* paint,
SaveFlags flags) { | 168 const SkPaint* paint,
SaveFlags flags) { |
167 // record the offset to us, making it non-positive to distinguish a save | 169 // record the offset to us, making it non-positive to distinguish a save |
168 // from a clip entry. | 170 // from a clip entry. |
169 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten()); | 171 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten()); |
170 this->recordSaveLayer(bounds, paint, flags); | 172 this->recordSaveLayer(bounds, paint, flags); |
171 if (kNoSavedLayerIndex == fFirstSavedLayerIndex) { | 173 if (kNoSavedLayerIndex == fFirstSavedLayerIndex) { |
172 fFirstSavedLayerIndex = fRestoreOffsetStack.count(); | 174 fFirstSavedLayerIndex = fRestoreOffsetStack.count(); |
173 } | 175 } |
174 | 176 |
175 this->INHERITED::willSaveLayer(bounds, paint, flags); | 177 this->INHERITED::willSaveLayer(bounds, paint, flags); |
176 /* No need for a (potentially very big) layer which we don't actually need | 178 /* No need for a (potentially very big) layer which we don't actually need |
177 at this time (and may not be able to afford since during record our | 179 at this time (and may not be able to afford since during record our |
178 clip starts out the size of the picture, which is often much larger | 180 clip starts out the size of the picture, which is often much larger |
179 than the size of the actual device we'll use during playback). | 181 than the size of the actual device we'll use during playback). |
180 */ | 182 */ |
181 return kNoLayer_SaveLayerStrategy; | 183 return kNoLayer_SaveLayerStrategy; |
182 } | 184 } |
183 | 185 |
184 void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint
, | 186 void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint
, |
185 SaveFlags flags) { | 187 SaveFlags flags) { |
| 188 fContentInfo.onSaveLayer(); |
| 189 |
186 // op + bool for 'bounds' | 190 // op + bool for 'bounds' |
187 size_t size = 2 * kUInt32Size; | 191 size_t size = 2 * kUInt32Size; |
188 if (NULL != bounds) { | 192 if (NULL != bounds) { |
189 size += sizeof(*bounds); // + rect | 193 size += sizeof(*bounds); // + rect |
190 } | 194 } |
191 // + paint index + flags | 195 // + paint index + flags |
192 size += 2 * kUInt32Size; | 196 size += 2 * kUInt32Size; |
193 | 197 |
194 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size)
; | 198 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size)
; |
195 | 199 |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 } | 523 } |
520 | 524 |
521 typedef bool (*PictureRecordOptProc)(SkWriter32* writer, int32_t offset, | 525 typedef bool (*PictureRecordOptProc)(SkWriter32* writer, int32_t offset, |
522 SkPaintDictionary* paintDict); | 526 SkPaintDictionary* paintDict); |
523 enum PictureRecordOptType { | 527 enum PictureRecordOptType { |
524 kRewind_OptType, // Optimization rewinds the command stream | 528 kRewind_OptType, // Optimization rewinds the command stream |
525 kCollapseSaveLayer_OptType, // Optimization eliminates a save/restore pair | 529 kCollapseSaveLayer_OptType, // Optimization eliminates a save/restore pair |
526 }; | 530 }; |
527 | 531 |
528 enum PictureRecordOptFlags { | 532 enum PictureRecordOptFlags { |
529 kSkipIfBBoxHierarchy_Flag = 0x1, // Optimization should be skipped if the | 533 kSkipIfBBoxHierarchy_Flag = 0x1, // Optimization should be skipped if the |
530 // SkPicture has a bounding box hierarchy. | 534 // SkPicture has a bounding box hierarchy
. |
| 535 kRescindLastSave_Flag = 0x2, |
| 536 kRescindLastSaveLayer_Flag = 0x4, |
531 }; | 537 }; |
532 | 538 |
533 struct PictureRecordOpt { | 539 struct PictureRecordOpt { |
534 PictureRecordOptProc fProc; | 540 PictureRecordOptProc fProc; |
535 PictureRecordOptType fType; | 541 PictureRecordOptType fType; |
536 unsigned fFlags; | 542 unsigned fFlags; |
537 }; | 543 }; |
538 /* | 544 /* |
539 * A list of the optimizations that are tried upon seeing a restore | 545 * A list of the optimizations that are tried upon seeing a restore |
540 * TODO: add a real API for such optimizations | 546 * TODO: add a real API for such optimizations |
541 * Add the ability to fire optimizations on any op (not just RESTORE) | 547 * Add the ability to fire optimizations on any op (not just RESTORE) |
542 */ | 548 */ |
543 static const PictureRecordOpt gPictureRecordOpts[] = { | 549 static const PictureRecordOpt gPictureRecordOpts[] = { |
544 // 'collapse_save_clip_restore' is skipped if there is a BBoxHierarchy | 550 // 'collapse_save_clip_restore' is skipped if there is a BBoxHierarchy |
545 // because it is redundant with the state traversal optimization in | 551 // because it is redundant with the state traversal optimization in |
546 // SkPictureStateTree, and applying the optimization introduces significant | 552 // SkPictureStateTree, and applying the optimization introduces significant |
547 // record time overhead because it requires rewinding contents that were | 553 // record time overhead because it requires rewinding contents that were |
548 // recorded into the BBoxHierarchy. | 554 // recorded into the BBoxHierarchy. |
549 { collapse_save_clip_restore, kRewind_OptType, kSkipIfBBoxHierarchy_Flag }, | 555 { collapse_save_clip_restore, kRewind_OptType, |
550 { remove_save_layer1, kCollapseSaveLayer_OptType, 0 }, | 556 kSkipIfBBoxHierarchy_Flag|kResci
ndLastSave_Flag }, |
551 { remove_save_layer2, kCollapseSaveLayer_OptType, 0 } | 557 { remove_save_layer1, kCollapseSaveLayer_OptType, kRescindLastSaveLa
yer_Flag }, |
| 558 { remove_save_layer2, kCollapseSaveLayer_OptType, kRescindLastSaveLa
yer_Flag } |
552 }; | 559 }; |
553 | 560 |
554 // This is called after an optimization has been applied to the command stream | 561 // This is called after an optimization has been applied to the command stream |
555 // in order to adjust the contents and state of the bounding box hierarchy and | 562 // in order to adjust the contents and state of the bounding box hierarchy and |
556 // state tree to reflect the optimization. | 563 // state tree to reflect the optimization. |
557 static void apply_optimization_to_bbh(PictureRecordOptType opt, SkPictureStateTr
ee* stateTree, | 564 static void apply_optimization_to_bbh(PictureRecordOptType opt, SkPictureStateTr
ee* stateTree, |
558 SkBBoxHierarchy* boundingHierarchy) { | 565 SkBBoxHierarchy* boundingHierarchy) { |
559 switch (opt) { | 566 switch (opt) { |
560 case kCollapseSaveLayer_OptType: | 567 case kCollapseSaveLayer_OptType: |
561 if (NULL != stateTree) { | 568 if (NULL != stateTree) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 if (fOptsEnabled) { | 603 if (fOptsEnabled) { |
597 for (opt = 0; opt < SK_ARRAY_COUNT(gPictureRecordOpts); ++opt) { | 604 for (opt = 0; opt < SK_ARRAY_COUNT(gPictureRecordOpts); ++opt) { |
598 if (0 != (gPictureRecordOpts[opt].fFlags & kSkipIfBBoxHierarchy_Flag
) | 605 if (0 != (gPictureRecordOpts[opt].fFlags & kSkipIfBBoxHierarchy_Flag
) |
599 && NULL != fBoundingHierarchy) { | 606 && NULL != fBoundingHierarchy) { |
600 continue; | 607 continue; |
601 } | 608 } |
602 if ((*gPictureRecordOpts[opt].fProc)(&fWriter, fRestoreOffsetStack.t
op(), &fPaints)) { | 609 if ((*gPictureRecordOpts[opt].fProc)(&fWriter, fRestoreOffsetStack.t
op(), &fPaints)) { |
603 // Some optimization fired so don't add the RESTORE | 610 // Some optimization fired so don't add the RESTORE |
604 apply_optimization_to_bbh(gPictureRecordOpts[opt].fType, | 611 apply_optimization_to_bbh(gPictureRecordOpts[opt].fType, |
605 fStateTree, fBoundingHierarchy); | 612 fStateTree, fBoundingHierarchy); |
| 613 if (gPictureRecordOpts[opt].fFlags & kRescindLastSave_Flag) { |
| 614 fContentInfo.rescindLastSave(); |
| 615 } else if (gPictureRecordOpts[opt].fFlags & kRescindLastSaveLaye
r_Flag) { |
| 616 fContentInfo.rescindLastSaveLayer(); |
| 617 } |
606 break; | 618 break; |
607 } | 619 } |
608 } | 620 } |
609 } | 621 } |
610 | 622 |
611 if (!fOptsEnabled || SK_ARRAY_COUNT(gPictureRecordOpts) == opt) { | 623 if (!fOptsEnabled || SK_ARRAY_COUNT(gPictureRecordOpts) == opt) { |
612 // No optimization fired so add the RESTORE | 624 // No optimization fired so add the RESTORE |
613 this->recordRestore(); | 625 this->recordRestore(); |
614 } | 626 } |
615 | 627 |
616 fRestoreOffsetStack.pop(); | 628 fRestoreOffsetStack.pop(); |
617 | 629 |
618 this->INHERITED::willRestore(); | 630 this->INHERITED::willRestore(); |
619 } | 631 } |
620 | 632 |
621 void SkPictureRecord::recordRestore(bool fillInSkips) { | 633 void SkPictureRecord::recordRestore(bool fillInSkips) { |
| 634 fContentInfo.onRestore(); |
| 635 |
622 if (fillInSkips) { | 636 if (fillInSkips) { |
623 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWrite
r.bytesWritten()); | 637 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWrite
r.bytesWritten()); |
624 } | 638 } |
625 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code | 639 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code |
626 size_t initialOffset = this->addDraw(RESTORE, &size); | 640 size_t initialOffset = this->addDraw(RESTORE, &size); |
627 this->validate(initialOffset, size); | 641 this->validate(initialOffset, size); |
628 } | 642 } |
629 | 643 |
630 void SkPictureRecord::recordTranslate(const SkMatrix& m) { | 644 void SkPictureRecord::recordTranslate(const SkMatrix& m) { |
631 SkASSERT(SkMatrix::kTranslate_Mask == m.getType()); | 645 SkASSERT(SkMatrix::kTranslate_Mask == m.getType()); |
(...skipping 1019 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1651 void SkPictureRecord::validateRegions() const { | 1665 void SkPictureRecord::validateRegions() const { |
1652 int count = fRegions.count(); | 1666 int count = fRegions.count(); |
1653 SkASSERT((unsigned) count < 0x1000); | 1667 SkASSERT((unsigned) count < 0x1000); |
1654 for (int index = 0; index < count; index++) { | 1668 for (int index = 0; index < count; index++) { |
1655 const SkFlatData* region = fRegions[index]; | 1669 const SkFlatData* region = fRegions[index]; |
1656 SkASSERT(region); | 1670 SkASSERT(region); |
1657 // region->validate(); | 1671 // region->validate(); |
1658 } | 1672 } |
1659 } | 1673 } |
1660 #endif | 1674 #endif |
OLD | NEW |