SkPictureRecorder.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * Copyright 2014 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "include/core/SkData.h"
  8. #include "include/core/SkDrawable.h"
  9. #include "include/core/SkPictureRecorder.h"
  10. #include "include/core/SkTypes.h"
  11. #include "src/core/SkBigPicture.h"
  12. #include "src/core/SkMiniRecorder.h"
  13. #include "src/core/SkRecord.h"
  14. #include "src/core/SkRecordDraw.h"
  15. #include "src/core/SkRecordOpts.h"
  16. #include "src/core/SkRecordedDrawable.h"
  17. #include "src/core/SkRecorder.h"
  18. SkPictureRecorder::SkPictureRecorder() {
  19. fActivelyRecording = false;
  20. fMiniRecorder.reset(new SkMiniRecorder);
  21. fRecorder.reset(new SkRecorder(nullptr, SkRect::MakeEmpty(), fMiniRecorder.get()));
  22. }
  23. SkPictureRecorder::~SkPictureRecorder() {}
  24. SkCanvas* SkPictureRecorder::beginRecording(const SkRect& userCullRect,
  25. SkBBHFactory* bbhFactory /* = nullptr */,
  26. uint32_t recordFlags /* = 0 */) {
  27. const SkRect cullRect = userCullRect.isEmpty() ? SkRect::MakeEmpty() : userCullRect;
  28. fCullRect = cullRect;
  29. fFlags = recordFlags;
  30. if (bbhFactory) {
  31. fBBH.reset((*bbhFactory)());
  32. SkASSERT(fBBH.get());
  33. }
  34. if (!fRecord) {
  35. fRecord.reset(new SkRecord);
  36. }
  37. SkRecorder::DrawPictureMode dpm = (recordFlags & kPlaybackDrawPicture_RecordFlag)
  38. ? SkRecorder::Playback_DrawPictureMode
  39. : SkRecorder::Record_DrawPictureMode;
  40. fRecorder->reset(fRecord.get(), cullRect, dpm, fMiniRecorder.get());
  41. fActivelyRecording = true;
  42. return this->getRecordingCanvas();
  43. }
  44. SkCanvas* SkPictureRecorder::getRecordingCanvas() {
  45. return fActivelyRecording ? fRecorder.get() : nullptr;
  46. }
  47. sk_sp<SkPicture> SkPictureRecorder::finishRecordingAsPicture(uint32_t finishFlags) {
  48. fActivelyRecording = false;
  49. fRecorder->restoreToCount(1); // If we were missing any restores, add them now.
  50. if (fRecord->count() == 0) {
  51. auto pic = fMiniRecorder->detachAsPicture(fBBH ? nullptr : &fCullRect);
  52. fBBH.reset(nullptr);
  53. return pic;
  54. }
  55. // TODO: delay as much of this work until just before first playback?
  56. SkRecordOptimize(fRecord.get());
  57. SkDrawableList* drawableList = fRecorder->getDrawableList();
  58. SkBigPicture::SnapshotArray* pictList =
  59. drawableList ? drawableList->newDrawableSnapshot() : nullptr;
  60. if (fBBH.get()) {
  61. SkAutoTMalloc<SkRect> bounds(fRecord->count());
  62. SkRecordFillBounds(fCullRect, *fRecord, bounds);
  63. fBBH->insert(bounds, fRecord->count());
  64. // Now that we've calculated content bounds, we can update fCullRect, often trimming it.
  65. // TODO: get updated fCullRect from bounds instead of forcing the BBH to return it?
  66. SkRect bbhBound = fBBH->getRootBound();
  67. SkASSERT((bbhBound.isEmpty() || fCullRect.contains(bbhBound))
  68. || (bbhBound.isEmpty() && fCullRect.isEmpty()));
  69. fCullRect = bbhBound;
  70. }
  71. size_t subPictureBytes = fRecorder->approxBytesUsedBySubPictures();
  72. for (int i = 0; pictList && i < pictList->count(); i++) {
  73. subPictureBytes += pictList->begin()[i]->approximateBytesUsed();
  74. }
  75. return sk_make_sp<SkBigPicture>(fCullRect, fRecord.release(), pictList, fBBH.release(),
  76. subPictureBytes);
  77. }
  78. sk_sp<SkPicture> SkPictureRecorder::finishRecordingAsPictureWithCull(const SkRect& cullRect,
  79. uint32_t finishFlags) {
  80. fCullRect = cullRect;
  81. return this->finishRecordingAsPicture(finishFlags);
  82. }
  83. void SkPictureRecorder::partialReplay(SkCanvas* canvas) const {
  84. if (nullptr == canvas) {
  85. return;
  86. }
  87. int drawableCount = 0;
  88. SkDrawable* const* drawables = nullptr;
  89. SkDrawableList* drawableList = fRecorder->getDrawableList();
  90. if (drawableList) {
  91. drawableCount = drawableList->count();
  92. drawables = drawableList->begin();
  93. }
  94. SkRecordDraw(*fRecord, canvas, nullptr, drawables, drawableCount, nullptr/*bbh*/, nullptr/*callback*/);
  95. }
  96. sk_sp<SkDrawable> SkPictureRecorder::finishRecordingAsDrawable(uint32_t finishFlags) {
  97. fActivelyRecording = false;
  98. fRecorder->flushMiniRecorder();
  99. fRecorder->restoreToCount(1); // If we were missing any restores, add them now.
  100. SkRecordOptimize(fRecord.get());
  101. if (fBBH.get()) {
  102. SkAutoTMalloc<SkRect> bounds(fRecord->count());
  103. SkRecordFillBounds(fCullRect, *fRecord, bounds);
  104. fBBH->insert(bounds, fRecord->count());
  105. }
  106. sk_sp<SkDrawable> drawable =
  107. sk_make_sp<SkRecordedDrawable>(std::move(fRecord), std::move(fBBH),
  108. fRecorder->detachDrawableList(), fCullRect);
  109. return drawable;
  110. }