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