robertphillips@google.com | 770963f | 2014-04-18 18:04:41 +0000 | [diff] [blame] | 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 | |
reed | 6be2aa9 | 2014-11-18 11:08:05 -0800 | [diff] [blame] | 8 | #include "SkData.h" |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 9 | #include "SkDrawable.h" |
robertphillips | 8236591 | 2014-11-12 09:32:34 -0800 | [diff] [blame] | 10 | #include "SkLayerInfo.h" |
robertphillips@google.com | 770963f | 2014-04-18 18:04:41 +0000 | [diff] [blame] | 11 | #include "SkPictureRecorder.h" |
mtklein | 98b8485 | 2015-04-21 15:23:59 -0700 | [diff] [blame^] | 12 | #include "SkPictureUtils.h" |
mtklein | 887f397 | 2014-06-17 12:08:15 -0700 | [diff] [blame] | 13 | #include "SkRecord.h" |
| 14 | #include "SkRecordDraw.h" |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 15 | #include "SkRecordOpts.h" |
mtklein | 98b8485 | 2015-04-21 15:23:59 -0700 | [diff] [blame^] | 16 | #include "SkRecorder.h" |
mtklein | 887f397 | 2014-06-17 12:08:15 -0700 | [diff] [blame] | 17 | #include "SkTypes.h" |
robertphillips | 643b8bd | 2014-06-08 05:55:05 -0700 | [diff] [blame] | 18 | |
mtklein | feaadee | 2015-04-08 11:25:48 -0700 | [diff] [blame] | 19 | SkPictureRecorder::SkPictureRecorder() { |
| 20 | fActivelyRecording = false; |
| 21 | fRecorder.reset(SkNEW_ARGS(SkRecorder, (nullptr, SkRect::MakeWH(0,0)))); |
| 22 | } |
mtklein | 887f397 | 2014-06-17 12:08:15 -0700 | [diff] [blame] | 23 | |
Mike Klein | f22b6b5 | 2014-06-23 13:29:10 -0400 | [diff] [blame] | 24 | SkPictureRecorder::~SkPictureRecorder() {} |
robertphillips@google.com | 770963f | 2014-04-18 18:04:41 +0000 | [diff] [blame] | 25 | |
reed | 78e2768 | 2014-11-19 08:04:34 -0800 | [diff] [blame] | 26 | SkCanvas* SkPictureRecorder::beginRecording(const SkRect& cullRect, |
robertphillips@google.com | 770963f | 2014-04-18 18:04:41 +0000 | [diff] [blame] | 27 | SkBBHFactory* bbhFactory /* = NULL */, |
| 28 | uint32_t recordFlags /* = 0 */) { |
reed | 78e2768 | 2014-11-19 08:04:34 -0800 | [diff] [blame] | 29 | fCullRect = cullRect; |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 30 | fFlags = recordFlags; |
mtklein | 887f397 | 2014-06-17 12:08:15 -0700 | [diff] [blame] | 31 | |
bsalomon | 49f085d | 2014-09-05 13:34:00 -0700 | [diff] [blame] | 32 | if (bbhFactory) { |
reed | 78e2768 | 2014-11-19 08:04:34 -0800 | [diff] [blame] | 33 | fBBH.reset((*bbhFactory)(cullRect)); |
bsalomon | 49f085d | 2014-09-05 13:34:00 -0700 | [diff] [blame] | 34 | SkASSERT(fBBH.get()); |
mtklein | 5ad6ee1 | 2014-08-11 08:08:43 -0700 | [diff] [blame] | 35 | } |
| 36 | |
Mike Klein | f22b6b5 | 2014-06-23 13:29:10 -0400 | [diff] [blame] | 37 | fRecord.reset(SkNEW(SkRecord)); |
mtklein | feaadee | 2015-04-08 11:25:48 -0700 | [diff] [blame] | 38 | fRecorder->reset(fRecord.get(), cullRect); |
| 39 | fActivelyRecording = true; |
mtklein | 887f397 | 2014-06-17 12:08:15 -0700 | [diff] [blame] | 40 | return this->getRecordingCanvas(); |
robertphillips | 643b8bd | 2014-06-08 05:55:05 -0700 | [diff] [blame] | 41 | } |
| 42 | |
| 43 | SkCanvas* SkPictureRecorder::getRecordingCanvas() { |
mtklein | feaadee | 2015-04-08 11:25:48 -0700 | [diff] [blame] | 44 | return fActivelyRecording ? fRecorder.get() : nullptr; |
robertphillips | 643b8bd | 2014-06-08 05:55:05 -0700 | [diff] [blame] | 45 | } |
| 46 | |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 47 | SkPicture* SkPictureRecorder::endRecordingAsPicture() { |
mtklein | feaadee | 2015-04-08 11:25:48 -0700 | [diff] [blame] | 48 | fActivelyRecording = false; |
| 49 | fRecorder->restoreToCount(1); // If we were missing any restores, add them now. |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 50 | // TODO: delay as much of this work until just before first playback? |
| 51 | SkRecordOptimize(fRecord); |
| 52 | |
robertphillips | 8236591 | 2014-11-12 09:32:34 -0800 | [diff] [blame] | 53 | SkAutoTUnref<SkLayerInfo> saveLayerData; |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 54 | |
| 55 | if (fBBH && (fFlags & kComputeSaveLayerInfo_RecordFlag)) { |
robertphillips | 8236591 | 2014-11-12 09:32:34 -0800 | [diff] [blame] | 56 | SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey(); |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 57 | |
robertphillips | 8236591 | 2014-11-12 09:32:34 -0800 | [diff] [blame] | 58 | saveLayerData.reset(SkNEW_ARGS(SkLayerInfo, (key))); |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 59 | } |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 60 | |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 61 | SkDrawableList* drawableList = fRecorder->getDrawableList(); |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 62 | SkPicture::SnapshotArray* pictList = drawableList ? drawableList->newDrawableSnapshot() : NULL; |
| 63 | |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 64 | if (fBBH.get()) { |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 65 | if (saveLayerData) { |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 66 | SkRecordComputeLayers(fCullRect, *fRecord, pictList, fBBH.get(), saveLayerData); |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 67 | } else { |
reed | 78e2768 | 2014-11-19 08:04:34 -0800 | [diff] [blame] | 68 | SkRecordFillBounds(fCullRect, *fRecord, fBBH.get()); |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 69 | } |
schenney | 23d8593 | 2015-03-06 16:20:28 -0800 | [diff] [blame] | 70 | SkRect bbhBound = fBBH->getRootBound(); |
| 71 | SkASSERT((bbhBound.isEmpty() || fCullRect.contains(bbhBound)) |
| 72 | || (bbhBound.isEmpty() && fCullRect.isEmpty())); |
| 73 | fCullRect = bbhBound; |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 74 | } |
| 75 | |
mtklein | 98b8485 | 2015-04-21 15:23:59 -0700 | [diff] [blame^] | 76 | 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)); |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 82 | |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 83 | if (saveLayerData) { |
| 84 | pict->EXPERIMENTAL_addAccelData(saveLayerData); |
| 85 | } |
reed | 26a6bf6 | 2014-11-24 19:59:22 -0800 | [diff] [blame] | 86 | |
| 87 | // release our refs now, so only the picture will be the owner. |
reed | 26a6bf6 | 2014-11-24 19:59:22 -0800 | [diff] [blame] | 88 | fRecord.reset(NULL); |
| 89 | fBBH.reset(NULL); |
| 90 | |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 91 | return pict; |
robertphillips | 643b8bd | 2014-06-08 05:55:05 -0700 | [diff] [blame] | 92 | } |
| 93 | |
commit-bot@chromium.org | 2246e32 | 2014-05-29 15:57:11 +0000 | [diff] [blame] | 94 | void SkPictureRecorder::partialReplay(SkCanvas* canvas) const { |
mtklein | 887f397 | 2014-06-17 12:08:15 -0700 | [diff] [blame] | 95 | if (NULL == canvas) { |
commit-bot@chromium.org | 6d3eaea | 2014-05-27 23:41:45 +0000 | [diff] [blame] | 96 | return; |
| 97 | } |
reed | 6be2aa9 | 2014-11-18 11:08:05 -0800 | [diff] [blame] | 98 | |
| 99 | int drawableCount = 0; |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 100 | SkDrawable* const* drawables = NULL; |
| 101 | SkDrawableList* drawableList = fRecorder->getDrawableList(); |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 102 | 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 | |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 111 | class SkRecordedDrawable : public SkDrawable { |
| 112 | SkAutoTUnref<SkRecord> fRecord; |
| 113 | SkAutoTUnref<SkBBoxHierarchy> fBBH; |
| 114 | SkAutoTDelete<SkDrawableList> fDrawableList; |
| 115 | const SkRect fBounds; |
| 116 | const bool fDoSaveLayerInfo; |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 117 | |
| 118 | public: |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 119 | SkRecordedDrawable(SkRecord* record, SkBBoxHierarchy* bbh, SkDrawableList* drawableList, |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 120 | 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 | |
| 128 | protected: |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 129 | SkRect onGetBounds() override { return fBounds; } |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 130 | |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 131 | void onDraw(SkCanvas* canvas) override { |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 132 | SkDrawable* const* drawables = NULL; |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 133 | 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 | |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 141 | SkPicture* onNewPictureSnapshot() override { |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 142 | 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 | |
mtklein | 98b8485 | 2015-04-21 15:23:59 -0700 | [diff] [blame^] | 162 | 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)); |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 168 | |
| 169 | if (saveLayerData) { |
| 170 | pict->EXPERIMENTAL_addAccelData(saveLayerData); |
| 171 | } |
| 172 | return pict; |
| 173 | } |
| 174 | }; |
| 175 | |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 176 | SkDrawable* SkPictureRecorder::endRecordingAsDrawable() { |
mtklein | feaadee | 2015-04-08 11:25:48 -0700 | [diff] [blame] | 177 | fActivelyRecording = false; |
| 178 | fRecorder->restoreToCount(1); // If we were missing any restores, add them now. |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 179 | // 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 | |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 186 | SkDrawable* drawable = SkNEW_ARGS(SkRecordedDrawable, |
| 187 | (fRecord, fBBH, fRecorder->detachDrawableList(), |
| 188 | fCullRect, |
| 189 | SkToBool(fFlags & kComputeSaveLayerInfo_RecordFlag))); |
reed | 26a6bf6 | 2014-11-24 19:59:22 -0800 | [diff] [blame] | 190 | |
| 191 | // release our refs now, so only the drawable will be the owner. |
reed | 26a6bf6 | 2014-11-24 19:59:22 -0800 | [diff] [blame] | 192 | fRecord.reset(NULL); |
| 193 | fBBH.reset(NULL); |
| 194 | |
| 195 | return drawable; |
commit-bot@chromium.org | 6d3eaea | 2014-05-27 23:41:45 +0000 | [diff] [blame] | 196 | } |