OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
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 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 SkDebugf("Collapse [%d out of %d] %g%spn", gCollapseCount, gCollapseCalls, | 495 SkDebugf("Collapse [%d out of %d] %g%spn", gCollapseCount, gCollapseCalls, |
496 (double)gCollapseCount / gCollapseCalls, "%"); | 496 (double)gCollapseCount / gCollapseCalls, "%"); |
497 #endif | 497 #endif |
498 | 498 |
499 writer->rewindToOffset(saveOffset); | 499 writer->rewindToOffset(saveOffset); |
500 return true; | 500 return true; |
501 } | 501 } |
502 | 502 |
503 typedef bool (*PictureRecordOptProc)(SkWriter32* writer, int32_t offset, | 503 typedef bool (*PictureRecordOptProc)(SkWriter32* writer, int32_t offset, |
504 SkPaintDictionary* paintDict); | 504 SkPaintDictionary* paintDict); |
| 505 enum PictureRecordOptType { |
| 506 kRewind_OptType, // Optimization rewinds the command stream |
| 507 kCollapseSaveLayer_OptType, // Optimization eliminates a save/restore pair |
| 508 }; |
505 | 509 |
| 510 struct PictureRecordOpt { |
| 511 PictureRecordOptProc fProc; |
| 512 PictureRecordOptType fType; |
| 513 }; |
506 /* | 514 /* |
507 * A list of the optimizations that are tried upon seeing a restore | 515 * A list of the optimizations that are tried upon seeing a restore |
508 * TODO: add a real API for such optimizations | 516 * TODO: add a real API for such optimizations |
509 * Add the ability to fire optimizations on any op (not just RESTORE) | 517 * Add the ability to fire optimizations on any op (not just RESTORE) |
510 */ | 518 */ |
511 static const PictureRecordOptProc gPictureRecordOpts[] = { | 519 static const PictureRecordOpt gPictureRecordOpts[] = { |
512 collapse_save_clip_restore, | 520 { collapse_save_clip_restore, kRewind_OptType }, |
513 #ifndef SK_IGNORE_PICTURE_RECORD_SAVE_LAYER_OPT | 521 { remove_save_layer1, kCollapseSaveLayer_OptType }, |
514 remove_save_layer1, | 522 { remove_save_layer2, kCollapseSaveLayer_OptType } |
515 remove_save_layer2, | |
516 #endif | |
517 }; | 523 }; |
518 | 524 |
| 525 // This is called after an optimization has been applied to the command stream |
| 526 // in order to adjust the contents and state of the bounding box hierarchy and |
| 527 // state tree to reflect the optimization. |
| 528 static void apply_optimization_to_bbh(PictureRecordOptType opt, SkPictureStateTr
ee* stateTree, |
| 529 SkBBoxHierarchy* boundingHierarchy) { |
| 530 switch (opt) { |
| 531 case kCollapseSaveLayer_OptType: |
| 532 stateTree->saveCollapsed(); |
| 533 break; |
| 534 case kRewind_OptType: |
| 535 if (NULL != boundingHierarchy) { |
| 536 boundingHierarchy->rewindInserts(); |
| 537 } |
| 538 // Note: No need to touch the state tree for this to work correctly. |
| 539 // Unused branches do not burden the playback, and pruning the tree |
| 540 // would be O(N^2), so it is best to leave it alone. |
| 541 break; |
| 542 default: |
| 543 SkASSERT(0); |
| 544 } |
| 545 } |
| 546 |
519 void SkPictureRecord::restore() { | 547 void SkPictureRecord::restore() { |
520 // FIXME: SkDeferredCanvas needs to be refactored to respect | 548 // FIXME: SkDeferredCanvas needs to be refactored to respect |
521 // save/restore balancing so that the following test can be | 549 // save/restore balancing so that the following test can be |
522 // turned on permanently. | 550 // turned on permanently. |
523 #if 0 | 551 #if 0 |
524 SkASSERT(fRestoreOffsetStack.count() > 1); | 552 SkASSERT(fRestoreOffsetStack.count() > 1); |
525 #endif | 553 #endif |
526 | 554 |
527 // check for underflow | 555 // check for underflow |
528 if (fRestoreOffsetStack.count() == 0) { | 556 if (fRestoreOffsetStack.count() == 0) { |
529 return; | 557 return; |
530 } | 558 } |
531 | 559 |
532 if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) { | 560 if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) { |
533 fFirstSavedLayerIndex = kNoSavedLayerIndex; | 561 fFirstSavedLayerIndex = kNoSavedLayerIndex; |
534 } | 562 } |
535 | 563 |
536 uint32_t initialOffset, size; | 564 uint32_t initialOffset, size; |
537 size_t opt; | 565 size_t opt; |
538 for (opt = 0; opt < SK_ARRAY_COUNT(gPictureRecordOpts); ++opt) { | 566 for (opt = 0; opt < SK_ARRAY_COUNT(gPictureRecordOpts); ++opt) { |
539 if ((*gPictureRecordOpts[opt])(&fWriter, fRestoreOffsetStack.top(), &fPa
ints)) { | 567 if ((*gPictureRecordOpts[opt].fProc)(&fWriter, fRestoreOffsetStack.top()
, &fPaints)) { |
540 // Some optimization fired so don't add the RESTORE | 568 // Some optimization fired so don't add the RESTORE |
541 size = 0; | 569 size = 0; |
542 initialOffset = fWriter.size(); | 570 initialOffset = fWriter.size(); |
| 571 apply_optimization_to_bbh(gPictureRecordOpts[opt].fType, |
| 572 fStateTree, fBoundingHierarchy); |
543 break; | 573 break; |
544 } | 574 } |
545 } | 575 } |
546 | 576 |
547 if (SK_ARRAY_COUNT(gPictureRecordOpts) == opt) { | 577 if (SK_ARRAY_COUNT(gPictureRecordOpts) == opt) { |
548 // No optimization fired so add the RESTORE | 578 // No optimization fired so add the RESTORE |
549 fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.size
()); | 579 fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.size
()); |
550 size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code | 580 size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code |
551 initialOffset = this->addDraw(RESTORE, &size); | 581 initialOffset = this->addDraw(RESTORE, &size); |
552 } | 582 } |
(...skipping 862 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1415 void SkPictureRecord::validateRegions() const { | 1445 void SkPictureRecord::validateRegions() const { |
1416 int count = fRegions.count(); | 1446 int count = fRegions.count(); |
1417 SkASSERT((unsigned) count < 0x1000); | 1447 SkASSERT((unsigned) count < 0x1000); |
1418 for (int index = 0; index < count; index++) { | 1448 for (int index = 0; index < count; index++) { |
1419 const SkFlatData* region = fRegions[index]; | 1449 const SkFlatData* region = fRegions[index]; |
1420 SkASSERT(region); | 1450 SkASSERT(region); |
1421 // region->validate(); | 1451 // region->validate(); |
1422 } | 1452 } |
1423 } | 1453 } |
1424 #endif | 1454 #endif |
OLD | NEW |