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