2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "SkDrawable.h"
10 #include "SkLayerInfo.h"
11 #include "SkPictureRecorder.h"
13 #include "SkRecordDraw.h"
14 #include "SkRecorder.h"
15 #include "SkRecordOpts.h"
18 SkPictureRecorder::SkPictureRecorder() {}
20 SkPictureRecorder::~SkPictureRecorder() {}
22 SkCanvas* SkPictureRecorder::beginRecording(const SkRect& cullRect,
23 SkBBHFactory* bbhFactory /* = NULL */,
24 uint32_t recordFlags /* = 0 */) {
29 fBBH.reset((*bbhFactory)(cullRect));
33 fRecord.reset(SkNEW(SkRecord));
34 fRecorder.reset(SkNEW_ARGS(SkRecorder, (fRecord.get(), cullRect)));
35 return this->getRecordingCanvas();
38 SkCanvas* SkPictureRecorder::getRecordingCanvas() {
39 return fRecorder.get();
42 SkPicture* SkPictureRecorder::endRecordingAsPicture() {
43 // TODO: delay as much of this work until just before first playback?
44 SkRecordOptimize(fRecord);
46 SkAutoTUnref<SkLayerInfo> saveLayerData;
48 if (fBBH && (fFlags & kComputeSaveLayerInfo_RecordFlag)) {
49 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
51 saveLayerData.reset(SkNEW_ARGS(SkLayerInfo, (key)));
54 SkDrawableList* drawableList = fRecorder->getDrawableList();
55 SkPicture::SnapshotArray* pictList = drawableList ? drawableList->newDrawableSnapshot() : NULL;
59 SkRecordComputeLayers(fCullRect, *fRecord, pictList, fBBH.get(), saveLayerData);
61 SkRecordFillBounds(fCullRect, *fRecord, fBBH.get());
63 SkRect bbhBound = fBBH->getRootBound();
64 SkASSERT((bbhBound.isEmpty() || fCullRect.contains(bbhBound))
65 || (bbhBound.isEmpty() && fCullRect.isEmpty()));
69 SkPicture* pict = SkNEW_ARGS(SkPicture, (fCullRect, fRecord, pictList, fBBH));
72 pict->EXPERIMENTAL_addAccelData(saveLayerData);
75 // release our refs now, so only the picture will be the owner.
76 fRecorder.reset(NULL);
83 void SkPictureRecorder::partialReplay(SkCanvas* canvas) const {
88 int drawableCount = 0;
89 SkDrawable* const* drawables = NULL;
90 SkDrawableList* drawableList = fRecorder->getDrawableList();
92 drawableCount = drawableList->count();
93 drawables = drawableList->begin();
95 SkRecordDraw(*fRecord, canvas, NULL, drawables, drawableCount, NULL/*bbh*/, NULL/*callback*/);
98 ///////////////////////////////////////////////////////////////////////////////////////////////////
100 class SkRecordedDrawable : public SkDrawable {
101 SkAutoTUnref<SkRecord> fRecord;
102 SkAutoTUnref<SkBBoxHierarchy> fBBH;
103 SkAutoTDelete<SkDrawableList> fDrawableList;
104 const SkRect fBounds;
105 const bool fDoSaveLayerInfo;
108 SkRecordedDrawable(SkRecord* record, SkBBoxHierarchy* bbh, SkDrawableList* drawableList,
109 const SkRect& bounds, bool doSaveLayerInfo)
110 : fRecord(SkRef(record))
111 , fBBH(SkSafeRef(bbh))
112 , fDrawableList(drawableList) // we take ownership
114 , fDoSaveLayerInfo(doSaveLayerInfo)
118 SkRect onGetBounds() override { return fBounds; }
120 void onDraw(SkCanvas* canvas) override {
121 SkDrawable* const* drawables = NULL;
122 int drawableCount = 0;
124 drawables = fDrawableList->begin();
125 drawableCount = fDrawableList->count();
127 SkRecordDraw(*fRecord, canvas, NULL, drawables, drawableCount, fBBH, NULL/*callback*/);
130 SkPicture* onNewPictureSnapshot() override {
131 SkPicture::SnapshotArray* pictList = NULL;
133 // TODO: should we plumb-down the BBHFactory and recordFlags from our host
135 pictList = fDrawableList->newDrawableSnapshot();
138 SkAutoTUnref<SkLayerInfo> saveLayerData;
140 if (fBBH && fDoSaveLayerInfo) {
141 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
143 saveLayerData.reset(SkNEW_ARGS(SkLayerInfo, (key)));
145 SkBBoxHierarchy* bbh = NULL; // we've already computed fBBH (received in constructor)
146 // TODO: update saveLayer info computation to reuse the already computed
148 SkRecordComputeLayers(fBounds, *fRecord, pictList, bbh, saveLayerData);
151 SkPicture* pict = SkNEW_ARGS(SkPicture, (fBounds, fRecord, pictList, fBBH));
154 pict->EXPERIMENTAL_addAccelData(saveLayerData);
160 SkDrawable* SkPictureRecorder::endRecordingAsDrawable() {
161 // TODO: delay as much of this work until just before first playback?
162 SkRecordOptimize(fRecord);
165 SkRecordFillBounds(fCullRect, *fRecord, fBBH.get());
168 SkDrawable* drawable = SkNEW_ARGS(SkRecordedDrawable,
169 (fRecord, fBBH, fRecorder->detachDrawableList(),
171 SkToBool(fFlags & kComputeSaveLayerInfo_RecordFlag)));
173 // release our refs now, so only the drawable will be the owner.
174 fRecorder.reset(NULL);