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