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