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