blob: 22b1ee3eac13ac6a8732bec8d9927695c33db986 [file] [log] [blame]
robertphillips@google.com770963f2014-04-18 18:04:41 +00001/*
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
reed6be2aa92014-11-18 11:08:05 -08008#include "SkData.h"
reed3cb38402015-02-06 08:36:15 -08009#include "SkDrawable.h"
robertphillips82365912014-11-12 09:32:34 -080010#include "SkLayerInfo.h"
robertphillips@google.com770963f2014-04-18 18:04:41 +000011#include "SkPictureRecorder.h"
mtklein98b84852015-04-21 15:23:59 -070012#include "SkPictureUtils.h"
mtklein887f3972014-06-17 12:08:15 -070013#include "SkRecord.h"
14#include "SkRecordDraw.h"
robertphillips81f71b62014-11-11 04:54:49 -080015#include "SkRecordOpts.h"
mtklein98b84852015-04-21 15:23:59 -070016#include "SkRecorder.h"
mtklein887f3972014-06-17 12:08:15 -070017#include "SkTypes.h"
robertphillips643b8bd2014-06-08 05:55:05 -070018
mtkleinfeaadee2015-04-08 11:25:48 -070019SkPictureRecorder::SkPictureRecorder() {
20 fActivelyRecording = false;
21 fRecorder.reset(SkNEW_ARGS(SkRecorder, (nullptr, SkRect::MakeWH(0,0))));
22}
mtklein887f3972014-06-17 12:08:15 -070023
Mike Kleinf22b6b52014-06-23 13:29:10 -040024SkPictureRecorder::~SkPictureRecorder() {}
robertphillips@google.com770963f2014-04-18 18:04:41 +000025
reed78e27682014-11-19 08:04:34 -080026SkCanvas* SkPictureRecorder::beginRecording(const SkRect& cullRect,
robertphillips@google.com770963f2014-04-18 18:04:41 +000027 SkBBHFactory* bbhFactory /* = NULL */,
28 uint32_t recordFlags /* = 0 */) {
reed78e27682014-11-19 08:04:34 -080029 fCullRect = cullRect;
robertphillips81f71b62014-11-11 04:54:49 -080030 fFlags = recordFlags;
mtklein887f3972014-06-17 12:08:15 -070031
bsalomon49f085d2014-09-05 13:34:00 -070032 if (bbhFactory) {
reed78e27682014-11-19 08:04:34 -080033 fBBH.reset((*bbhFactory)(cullRect));
bsalomon49f085d2014-09-05 13:34:00 -070034 SkASSERT(fBBH.get());
mtklein5ad6ee12014-08-11 08:08:43 -070035 }
36
Mike Kleinf22b6b52014-06-23 13:29:10 -040037 fRecord.reset(SkNEW(SkRecord));
mtkleinfeaadee2015-04-08 11:25:48 -070038 fRecorder->reset(fRecord.get(), cullRect);
39 fActivelyRecording = true;
mtklein887f3972014-06-17 12:08:15 -070040 return this->getRecordingCanvas();
robertphillips643b8bd2014-06-08 05:55:05 -070041}
42
43SkCanvas* SkPictureRecorder::getRecordingCanvas() {
mtkleinfeaadee2015-04-08 11:25:48 -070044 return fActivelyRecording ? fRecorder.get() : nullptr;
robertphillips643b8bd2014-06-08 05:55:05 -070045}
46
reed1bdfd3f2014-11-24 14:41:51 -080047SkPicture* SkPictureRecorder::endRecordingAsPicture() {
mtkleinfeaadee2015-04-08 11:25:48 -070048 fActivelyRecording = false;
49 fRecorder->restoreToCount(1); // If we were missing any restores, add them now.
robertphillips81f71b62014-11-11 04:54:49 -080050 // TODO: delay as much of this work until just before first playback?
51 SkRecordOptimize(fRecord);
52
robertphillips82365912014-11-12 09:32:34 -080053 SkAutoTUnref<SkLayerInfo> saveLayerData;
robertphillips81f71b62014-11-11 04:54:49 -080054
55 if (fBBH && (fFlags & kComputeSaveLayerInfo_RecordFlag)) {
robertphillips82365912014-11-12 09:32:34 -080056 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
robertphillips81f71b62014-11-11 04:54:49 -080057
robertphillips82365912014-11-12 09:32:34 -080058 saveLayerData.reset(SkNEW_ARGS(SkLayerInfo, (key)));
robertphillips81f71b62014-11-11 04:54:49 -080059 }
robertphillips81f71b62014-11-11 04:54:49 -080060
reed3cb38402015-02-06 08:36:15 -080061 SkDrawableList* drawableList = fRecorder->getDrawableList();
reed1bdfd3f2014-11-24 14:41:51 -080062 SkPicture::SnapshotArray* pictList = drawableList ? drawableList->newDrawableSnapshot() : NULL;
63
robertphillips81f71b62014-11-11 04:54:49 -080064 if (fBBH.get()) {
robertphillips81f71b62014-11-11 04:54:49 -080065 if (saveLayerData) {
reed1bdfd3f2014-11-24 14:41:51 -080066 SkRecordComputeLayers(fCullRect, *fRecord, pictList, fBBH.get(), saveLayerData);
robertphillips81f71b62014-11-11 04:54:49 -080067 } else {
reed78e27682014-11-19 08:04:34 -080068 SkRecordFillBounds(fCullRect, *fRecord, fBBH.get());
robertphillips81f71b62014-11-11 04:54:49 -080069 }
schenney23d85932015-03-06 16:20:28 -080070 SkRect bbhBound = fBBH->getRootBound();
71 SkASSERT((bbhBound.isEmpty() || fCullRect.contains(bbhBound))
72 || (bbhBound.isEmpty() && fCullRect.isEmpty()));
73 fCullRect = bbhBound;
robertphillips81f71b62014-11-11 04:54:49 -080074 }
75
mtklein98b84852015-04-21 15:23:59 -070076 size_t subPictureBytes = fRecorder->approxBytesUsedBySubPictures();
77 for (int i = 0; pictList && i < pictList->count(); i++) {
78 subPictureBytes += SkPictureUtils::ApproximateBytesUsed(pictList->begin()[i]);
79 }
80 SkPicture* pict =
81 SkNEW_ARGS(SkPicture, (fCullRect, fRecord, pictList, fBBH, subPictureBytes));
robertphillips81f71b62014-11-11 04:54:49 -080082
robertphillips81f71b62014-11-11 04:54:49 -080083 if (saveLayerData) {
84 pict->EXPERIMENTAL_addAccelData(saveLayerData);
85 }
reed26a6bf62014-11-24 19:59:22 -080086
87 // release our refs now, so only the picture will be the owner.
reed26a6bf62014-11-24 19:59:22 -080088 fRecord.reset(NULL);
89 fBBH.reset(NULL);
90
robertphillips81f71b62014-11-11 04:54:49 -080091 return pict;
robertphillips643b8bd2014-06-08 05:55:05 -070092}
93
commit-bot@chromium.org2246e322014-05-29 15:57:11 +000094void SkPictureRecorder::partialReplay(SkCanvas* canvas) const {
mtklein887f3972014-06-17 12:08:15 -070095 if (NULL == canvas) {
commit-bot@chromium.org6d3eaea2014-05-27 23:41:45 +000096 return;
97 }
reed6be2aa92014-11-18 11:08:05 -080098
99 int drawableCount = 0;
reed3cb38402015-02-06 08:36:15 -0800100 SkDrawable* const* drawables = NULL;
101 SkDrawableList* drawableList = fRecorder->getDrawableList();
reed1bdfd3f2014-11-24 14:41:51 -0800102 if (drawableList) {
103 drawableCount = drawableList->count();
104 drawables = drawableList->begin();
105 }
106 SkRecordDraw(*fRecord, canvas, NULL, drawables, drawableCount, NULL/*bbh*/, NULL/*callback*/);
107}
108
109///////////////////////////////////////////////////////////////////////////////////////////////////
110
reed3cb38402015-02-06 08:36:15 -0800111class SkRecordedDrawable : public SkDrawable {
112 SkAutoTUnref<SkRecord> fRecord;
113 SkAutoTUnref<SkBBoxHierarchy> fBBH;
114 SkAutoTDelete<SkDrawableList> fDrawableList;
115 const SkRect fBounds;
116 const bool fDoSaveLayerInfo;
reed1bdfd3f2014-11-24 14:41:51 -0800117
118public:
reed3cb38402015-02-06 08:36:15 -0800119 SkRecordedDrawable(SkRecord* record, SkBBoxHierarchy* bbh, SkDrawableList* drawableList,
reed1bdfd3f2014-11-24 14:41:51 -0800120 const SkRect& bounds, bool doSaveLayerInfo)
121 : fRecord(SkRef(record))
122 , fBBH(SkSafeRef(bbh))
123 , fDrawableList(drawableList) // we take ownership
124 , fBounds(bounds)
125 , fDoSaveLayerInfo(doSaveLayerInfo)
126 {}
127
128protected:
mtklein36352bf2015-03-25 18:17:31 -0700129 SkRect onGetBounds() override { return fBounds; }
reed1bdfd3f2014-11-24 14:41:51 -0800130
mtklein36352bf2015-03-25 18:17:31 -0700131 void onDraw(SkCanvas* canvas) override {
reed3cb38402015-02-06 08:36:15 -0800132 SkDrawable* const* drawables = NULL;
reed1bdfd3f2014-11-24 14:41:51 -0800133 int drawableCount = 0;
134 if (fDrawableList) {
135 drawables = fDrawableList->begin();
136 drawableCount = fDrawableList->count();
137 }
138 SkRecordDraw(*fRecord, canvas, NULL, drawables, drawableCount, fBBH, NULL/*callback*/);
139 }
140
mtklein36352bf2015-03-25 18:17:31 -0700141 SkPicture* onNewPictureSnapshot() override {
reed1bdfd3f2014-11-24 14:41:51 -0800142 SkPicture::SnapshotArray* pictList = NULL;
143 if (fDrawableList) {
144 // TODO: should we plumb-down the BBHFactory and recordFlags from our host
145 // PictureRecorder?
146 pictList = fDrawableList->newDrawableSnapshot();
147 }
148
149 SkAutoTUnref<SkLayerInfo> saveLayerData;
150
151 if (fBBH && fDoSaveLayerInfo) {
152 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
153
154 saveLayerData.reset(SkNEW_ARGS(SkLayerInfo, (key)));
155
156 SkBBoxHierarchy* bbh = NULL; // we've already computed fBBH (received in constructor)
157 // TODO: update saveLayer info computation to reuse the already computed
158 // bounds in 'fBBH'
159 SkRecordComputeLayers(fBounds, *fRecord, pictList, bbh, saveLayerData);
160 }
161
mtklein98b84852015-04-21 15:23:59 -0700162 size_t subPictureBytes = 0;
163 for (int i = 0; pictList && i < pictList->count(); i++) {
164 subPictureBytes += SkPictureUtils::ApproximateBytesUsed(pictList->begin()[i]);
165 }
166 SkPicture* pict =
167 SkNEW_ARGS(SkPicture, (fBounds, fRecord, pictList, fBBH, subPictureBytes));
reed1bdfd3f2014-11-24 14:41:51 -0800168
169 if (saveLayerData) {
170 pict->EXPERIMENTAL_addAccelData(saveLayerData);
171 }
172 return pict;
173 }
174};
175
reed3cb38402015-02-06 08:36:15 -0800176SkDrawable* SkPictureRecorder::endRecordingAsDrawable() {
mtkleinfeaadee2015-04-08 11:25:48 -0700177 fActivelyRecording = false;
178 fRecorder->restoreToCount(1); // If we were missing any restores, add them now.
reed1bdfd3f2014-11-24 14:41:51 -0800179 // TODO: delay as much of this work until just before first playback?
180 SkRecordOptimize(fRecord);
181
182 if (fBBH.get()) {
183 SkRecordFillBounds(fCullRect, *fRecord, fBBH.get());
184 }
185
reed3cb38402015-02-06 08:36:15 -0800186 SkDrawable* drawable = SkNEW_ARGS(SkRecordedDrawable,
187 (fRecord, fBBH, fRecorder->detachDrawableList(),
188 fCullRect,
189 SkToBool(fFlags & kComputeSaveLayerInfo_RecordFlag)));
reed26a6bf62014-11-24 19:59:22 -0800190
191 // release our refs now, so only the drawable will be the owner.
reed26a6bf62014-11-24 19:59:22 -0800192 fRecord.reset(NULL);
193 fBBH.reset(NULL);
194
195 return drawable;
commit-bot@chromium.org6d3eaea2014-05-27 23:41:45 +0000196}