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 | |
mtklein | 9db912c | 2015-05-19 11:11:26 -0700 | [diff] [blame] | 8 | #include "SkBigPicture.h" |
reed | 6be2aa9 | 2014-11-18 11:08:05 -0800 | [diff] [blame] | 9 | #include "SkData.h" |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 10 | #include "SkDrawable.h" |
robertphillips | 8236591 | 2014-11-12 09:32:34 -0800 | [diff] [blame] | 11 | #include "SkLayerInfo.h" |
robertphillips@google.com | 770963f | 2014-04-18 18:04:41 +0000 | [diff] [blame] | 12 | #include "SkPictureRecorder.h" |
mtklein | 98b8485 | 2015-04-21 15:23:59 -0700 | [diff] [blame] | 13 | #include "SkPictureUtils.h" |
mtklein | 887f397 | 2014-06-17 12:08:15 -0700 | [diff] [blame] | 14 | #include "SkRecord.h" |
| 15 | #include "SkRecordDraw.h" |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 16 | #include "SkRecordOpts.h" |
mtklein | 98b8485 | 2015-04-21 15:23:59 -0700 | [diff] [blame] | 17 | #include "SkRecorder.h" |
mtklein | 887f397 | 2014-06-17 12:08:15 -0700 | [diff] [blame] | 18 | #include "SkTypes.h" |
robertphillips | 643b8bd | 2014-06-08 05:55:05 -0700 | [diff] [blame] | 19 | |
mtklein | feaadee | 2015-04-08 11:25:48 -0700 | [diff] [blame] | 20 | SkPictureRecorder::SkPictureRecorder() { |
| 21 | fActivelyRecording = false; |
mtklein | 9db912c | 2015-05-19 11:11:26 -0700 | [diff] [blame] | 22 | fRecorder.reset(SkNEW_ARGS(SkRecorder, (nullptr, SkRect::MakeWH(0,0), &fMiniRecorder))); |
mtklein | feaadee | 2015-04-08 11:25:48 -0700 | [diff] [blame] | 23 | } |
mtklein | 887f397 | 2014-06-17 12:08:15 -0700 | [diff] [blame] | 24 | |
Mike Klein | f22b6b5 | 2014-06-23 13:29:10 -0400 | [diff] [blame] | 25 | SkPictureRecorder::~SkPictureRecorder() {} |
robertphillips@google.com | 770963f | 2014-04-18 18:04:41 +0000 | [diff] [blame] | 26 | |
reed | 78e2768 | 2014-11-19 08:04:34 -0800 | [diff] [blame] | 27 | SkCanvas* SkPictureRecorder::beginRecording(const SkRect& cullRect, |
robertphillips@google.com | 770963f | 2014-04-18 18:04:41 +0000 | [diff] [blame] | 28 | SkBBHFactory* bbhFactory /* = NULL */, |
| 29 | uint32_t recordFlags /* = 0 */) { |
reed | 78e2768 | 2014-11-19 08:04:34 -0800 | [diff] [blame] | 30 | fCullRect = cullRect; |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 31 | fFlags = recordFlags; |
mtklein | 887f397 | 2014-06-17 12:08:15 -0700 | [diff] [blame] | 32 | |
bsalomon | 49f085d | 2014-09-05 13:34:00 -0700 | [diff] [blame] | 33 | if (bbhFactory) { |
reed | 78e2768 | 2014-11-19 08:04:34 -0800 | [diff] [blame] | 34 | fBBH.reset((*bbhFactory)(cullRect)); |
bsalomon | 49f085d | 2014-09-05 13:34:00 -0700 | [diff] [blame] | 35 | SkASSERT(fBBH.get()); |
mtklein | 5ad6ee1 | 2014-08-11 08:08:43 -0700 | [diff] [blame] | 36 | } |
| 37 | |
mtklein | 9db912c | 2015-05-19 11:11:26 -0700 | [diff] [blame] | 38 | if (!fRecord) { |
| 39 | fRecord.reset(SkNEW(SkRecord)); |
| 40 | } |
mtklein | d711d11 | 2015-07-01 07:04:37 -0700 | [diff] [blame^] | 41 | SkRecorder::DrawPictureMode dpm = (recordFlags & kPlaybackDrawPicture_RecordFlag) |
| 42 | ? SkRecorder::Playback_DrawPictureMode |
| 43 | : SkRecorder::Record_DrawPictureMode; |
| 44 | fRecorder->reset(fRecord.get(), cullRect, dpm, &fMiniRecorder); |
mtklein | feaadee | 2015-04-08 11:25:48 -0700 | [diff] [blame] | 45 | fActivelyRecording = true; |
mtklein | 887f397 | 2014-06-17 12:08:15 -0700 | [diff] [blame] | 46 | return this->getRecordingCanvas(); |
robertphillips | 643b8bd | 2014-06-08 05:55:05 -0700 | [diff] [blame] | 47 | } |
| 48 | |
| 49 | SkCanvas* SkPictureRecorder::getRecordingCanvas() { |
mtklein | feaadee | 2015-04-08 11:25:48 -0700 | [diff] [blame] | 50 | return fActivelyRecording ? fRecorder.get() : nullptr; |
robertphillips | 643b8bd | 2014-06-08 05:55:05 -0700 | [diff] [blame] | 51 | } |
| 52 | |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 53 | SkPicture* SkPictureRecorder::endRecordingAsPicture() { |
mtklein | feaadee | 2015-04-08 11:25:48 -0700 | [diff] [blame] | 54 | fActivelyRecording = false; |
| 55 | fRecorder->restoreToCount(1); // If we were missing any restores, add them now. |
mtklein | 9db912c | 2015-05-19 11:11:26 -0700 | [diff] [blame] | 56 | |
| 57 | if (fRecord->count() == 0) { |
| 58 | return fMiniRecorder.detachAsPicture(fCullRect); |
| 59 | } |
| 60 | |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 61 | // TODO: delay as much of this work until just before first playback? |
| 62 | SkRecordOptimize(fRecord); |
| 63 | |
robertphillips | 8236591 | 2014-11-12 09:32:34 -0800 | [diff] [blame] | 64 | SkAutoTUnref<SkLayerInfo> saveLayerData; |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 65 | |
| 66 | if (fBBH && (fFlags & kComputeSaveLayerInfo_RecordFlag)) { |
mtklein | 9db912c | 2015-05-19 11:11:26 -0700 | [diff] [blame] | 67 | saveLayerData.reset(SkNEW(SkLayerInfo)); |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 68 | } |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 69 | |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 70 | SkDrawableList* drawableList = fRecorder->getDrawableList(); |
mtklein | 9db912c | 2015-05-19 11:11:26 -0700 | [diff] [blame] | 71 | SkBigPicture::SnapshotArray* pictList = |
| 72 | drawableList ? drawableList->newDrawableSnapshot() : NULL; |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 73 | |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 74 | if (fBBH.get()) { |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 75 | if (saveLayerData) { |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 76 | SkRecordComputeLayers(fCullRect, *fRecord, pictList, fBBH.get(), saveLayerData); |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 77 | } else { |
reed | 78e2768 | 2014-11-19 08:04:34 -0800 | [diff] [blame] | 78 | SkRecordFillBounds(fCullRect, *fRecord, fBBH.get()); |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 79 | } |
schenney | 23d8593 | 2015-03-06 16:20:28 -0800 | [diff] [blame] | 80 | SkRect bbhBound = fBBH->getRootBound(); |
| 81 | SkASSERT((bbhBound.isEmpty() || fCullRect.contains(bbhBound)) |
| 82 | || (bbhBound.isEmpty() && fCullRect.isEmpty())); |
| 83 | fCullRect = bbhBound; |
robertphillips | 81f71b6 | 2014-11-11 04:54:49 -0800 | [diff] [blame] | 84 | } |
| 85 | |
mtklein | 98b8485 | 2015-04-21 15:23:59 -0700 | [diff] [blame] | 86 | size_t subPictureBytes = fRecorder->approxBytesUsedBySubPictures(); |
| 87 | for (int i = 0; pictList && i < pictList->count(); i++) { |
| 88 | subPictureBytes += SkPictureUtils::ApproximateBytesUsed(pictList->begin()[i]); |
| 89 | } |
mtklein | 9db912c | 2015-05-19 11:11:26 -0700 | [diff] [blame] | 90 | return SkNEW_ARGS(SkBigPicture, (fCullRect, |
| 91 | fRecord.detach(), |
| 92 | pictList, |
| 93 | fBBH.detach(), |
| 94 | saveLayerData.detach(), |
| 95 | subPictureBytes)); |
robertphillips | 643b8bd | 2014-06-08 05:55:05 -0700 | [diff] [blame] | 96 | } |
| 97 | |
commit-bot@chromium.org | 2246e32 | 2014-05-29 15:57:11 +0000 | [diff] [blame] | 98 | void SkPictureRecorder::partialReplay(SkCanvas* canvas) const { |
mtklein | 887f397 | 2014-06-17 12:08:15 -0700 | [diff] [blame] | 99 | if (NULL == canvas) { |
commit-bot@chromium.org | 6d3eaea | 2014-05-27 23:41:45 +0000 | [diff] [blame] | 100 | return; |
| 101 | } |
reed | 6be2aa9 | 2014-11-18 11:08:05 -0800 | [diff] [blame] | 102 | |
| 103 | int drawableCount = 0; |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 104 | SkDrawable* const* drawables = NULL; |
| 105 | SkDrawableList* drawableList = fRecorder->getDrawableList(); |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 106 | if (drawableList) { |
| 107 | drawableCount = drawableList->count(); |
| 108 | drawables = drawableList->begin(); |
| 109 | } |
| 110 | SkRecordDraw(*fRecord, canvas, NULL, drawables, drawableCount, NULL/*bbh*/, NULL/*callback*/); |
| 111 | } |
| 112 | |
| 113 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 114 | |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 115 | class SkRecordedDrawable : public SkDrawable { |
| 116 | SkAutoTUnref<SkRecord> fRecord; |
| 117 | SkAutoTUnref<SkBBoxHierarchy> fBBH; |
| 118 | SkAutoTDelete<SkDrawableList> fDrawableList; |
| 119 | const SkRect fBounds; |
| 120 | const bool fDoSaveLayerInfo; |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 121 | |
| 122 | public: |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 123 | SkRecordedDrawable(SkRecord* record, SkBBoxHierarchy* bbh, SkDrawableList* drawableList, |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 124 | const SkRect& bounds, bool doSaveLayerInfo) |
| 125 | : fRecord(SkRef(record)) |
| 126 | , fBBH(SkSafeRef(bbh)) |
| 127 | , fDrawableList(drawableList) // we take ownership |
| 128 | , fBounds(bounds) |
| 129 | , fDoSaveLayerInfo(doSaveLayerInfo) |
| 130 | {} |
| 131 | |
| 132 | protected: |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 133 | SkRect onGetBounds() override { return fBounds; } |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 134 | |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 135 | void onDraw(SkCanvas* canvas) override { |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 136 | SkDrawable* const* drawables = NULL; |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 137 | int drawableCount = 0; |
| 138 | if (fDrawableList) { |
| 139 | drawables = fDrawableList->begin(); |
| 140 | drawableCount = fDrawableList->count(); |
| 141 | } |
| 142 | SkRecordDraw(*fRecord, canvas, NULL, drawables, drawableCount, fBBH, NULL/*callback*/); |
| 143 | } |
| 144 | |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 145 | SkPicture* onNewPictureSnapshot() override { |
mtklein | 9db912c | 2015-05-19 11:11:26 -0700 | [diff] [blame] | 146 | SkBigPicture::SnapshotArray* pictList = NULL; |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 147 | if (fDrawableList) { |
| 148 | // TODO: should we plumb-down the BBHFactory and recordFlags from our host |
| 149 | // PictureRecorder? |
| 150 | pictList = fDrawableList->newDrawableSnapshot(); |
| 151 | } |
| 152 | |
| 153 | SkAutoTUnref<SkLayerInfo> saveLayerData; |
| 154 | |
| 155 | if (fBBH && fDoSaveLayerInfo) { |
mtklein | 9db912c | 2015-05-19 11:11:26 -0700 | [diff] [blame] | 156 | saveLayerData.reset(SkNEW(SkLayerInfo)); |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 157 | |
| 158 | SkBBoxHierarchy* bbh = NULL; // we've already computed fBBH (received in constructor) |
| 159 | // TODO: update saveLayer info computation to reuse the already computed |
| 160 | // bounds in 'fBBH' |
| 161 | SkRecordComputeLayers(fBounds, *fRecord, pictList, bbh, saveLayerData); |
| 162 | } |
| 163 | |
mtklein | 98b8485 | 2015-04-21 15:23:59 -0700 | [diff] [blame] | 164 | size_t subPictureBytes = 0; |
| 165 | for (int i = 0; pictList && i < pictList->count(); i++) { |
| 166 | subPictureBytes += SkPictureUtils::ApproximateBytesUsed(pictList->begin()[i]); |
| 167 | } |
mtklein | 9db912c | 2015-05-19 11:11:26 -0700 | [diff] [blame] | 168 | // SkBigPicture will take ownership of a ref on both fRecord and fBBH. |
mtklein | 00c2af8 | 2015-04-27 08:54:23 -0700 | [diff] [blame] | 169 | // We're not willing to give up our ownership, so we must ref them for SkPicture. |
mtklein | 9db912c | 2015-05-19 11:11:26 -0700 | [diff] [blame] | 170 | return SkNEW_ARGS(SkBigPicture, (fBounds, |
| 171 | SkRef(fRecord.get()), |
| 172 | pictList, |
| 173 | SkSafeRef(fBBH.get()), |
| 174 | saveLayerData.detach(), |
| 175 | subPictureBytes)); |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 176 | } |
| 177 | }; |
| 178 | |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 179 | SkDrawable* SkPictureRecorder::endRecordingAsDrawable() { |
mtklein | feaadee | 2015-04-08 11:25:48 -0700 | [diff] [blame] | 180 | fActivelyRecording = false; |
mtklein | 9db912c | 2015-05-19 11:11:26 -0700 | [diff] [blame] | 181 | fRecorder->flushMiniRecorder(); |
mtklein | feaadee | 2015-04-08 11:25:48 -0700 | [diff] [blame] | 182 | fRecorder->restoreToCount(1); // If we were missing any restores, add them now. |
mtklein | 9db912c | 2015-05-19 11:11:26 -0700 | [diff] [blame] | 183 | |
reed | 1bdfd3f | 2014-11-24 14:41:51 -0800 | [diff] [blame] | 184 | // TODO: delay as much of this work until just before first playback? |
| 185 | SkRecordOptimize(fRecord); |
| 186 | |
| 187 | if (fBBH.get()) { |
| 188 | SkRecordFillBounds(fCullRect, *fRecord, fBBH.get()); |
| 189 | } |
| 190 | |
reed | 3cb3840 | 2015-02-06 08:36:15 -0800 | [diff] [blame] | 191 | SkDrawable* drawable = SkNEW_ARGS(SkRecordedDrawable, |
| 192 | (fRecord, fBBH, fRecorder->detachDrawableList(), |
| 193 | fCullRect, |
| 194 | SkToBool(fFlags & kComputeSaveLayerInfo_RecordFlag))); |
reed | 26a6bf6 | 2014-11-24 19:59:22 -0800 | [diff] [blame] | 195 | |
| 196 | // release our refs now, so only the drawable will be the owner. |
reed | 26a6bf6 | 2014-11-24 19:59:22 -0800 | [diff] [blame] | 197 | fRecord.reset(NULL); |
| 198 | fBBH.reset(NULL); |
| 199 | |
| 200 | return drawable; |
commit-bot@chromium.org | 6d3eaea | 2014-05-27 23:41:45 +0000 | [diff] [blame] | 201 | } |