summaryrefslogtreecommitdiffstats
path: root/gfx/skia/skia/src/core/SkPictureRecorder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/skia/skia/src/core/SkPictureRecorder.cpp')
-rw-r--r--gfx/skia/skia/src/core/SkPictureRecorder.cpp145
1 files changed, 145 insertions, 0 deletions
diff --git a/gfx/skia/skia/src/core/SkPictureRecorder.cpp b/gfx/skia/skia/src/core/SkPictureRecorder.cpp
new file mode 100644
index 0000000000..caf7d3df92
--- /dev/null
+++ b/gfx/skia/skia/src/core/SkPictureRecorder.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <memory>
+
+#include "include/core/SkData.h"
+#include "include/core/SkDrawable.h"
+#include "include/core/SkPictureRecorder.h"
+#include "include/core/SkTypes.h"
+#include "src/core/SkBigPicture.h"
+#include "src/core/SkRecord.h"
+#include "src/core/SkRecordDraw.h"
+#include "src/core/SkRecordOpts.h"
+#include "src/core/SkRecordedDrawable.h"
+#include "src/core/SkRecorder.h"
+
+using namespace skia_private;
+
+SkPictureRecorder::SkPictureRecorder() {
+ fActivelyRecording = false;
+ fRecorder = std::make_unique<SkRecorder>(nullptr, SkRect::MakeEmpty());
+}
+
+SkPictureRecorder::~SkPictureRecorder() {}
+
+SkCanvas* SkPictureRecorder::beginRecording(const SkRect& userCullRect,
+ sk_sp<SkBBoxHierarchy> bbh) {
+ const SkRect cullRect = userCullRect.isEmpty() ? SkRect::MakeEmpty() : userCullRect;
+
+ fCullRect = cullRect;
+ fBBH = std::move(bbh);
+
+ if (!fRecord) {
+ fRecord.reset(new SkRecord);
+ }
+ fRecorder->reset(fRecord.get(), cullRect);
+ fActivelyRecording = true;
+ return this->getRecordingCanvas();
+}
+
+SkCanvas* SkPictureRecorder::beginRecording(const SkRect& bounds, SkBBHFactory* factory) {
+ return this->beginRecording(bounds, factory ? (*factory)() : nullptr);
+}
+
+SkCanvas* SkPictureRecorder::getRecordingCanvas() {
+ return fActivelyRecording ? fRecorder.get() : nullptr;
+}
+
+class SkEmptyPicture final : public SkPicture {
+public:
+ void playback(SkCanvas*, AbortCallback*) const override { }
+
+ size_t approximateBytesUsed() const override { return sizeof(*this); }
+ int approximateOpCount(bool nested) const override { return 0; }
+ SkRect cullRect() const override { return SkRect::MakeEmpty(); }
+};
+
+sk_sp<SkPicture> SkPictureRecorder::finishRecordingAsPicture() {
+ fActivelyRecording = false;
+ fRecorder->restoreToCount(1); // If we were missing any restores, add them now.
+
+ if (fRecord->count() == 0) {
+ return sk_make_sp<SkEmptyPicture>();
+ }
+
+ // TODO: delay as much of this work until just before first playback?
+ SkRecordOptimize(fRecord.get());
+
+ SkDrawableList* drawableList = fRecorder->getDrawableList();
+ std::unique_ptr<SkBigPicture::SnapshotArray> pictList{
+ drawableList ? drawableList->newDrawableSnapshot() : nullptr
+ };
+
+ if (fBBH) {
+ AutoTMalloc<SkRect> bounds(fRecord->count());
+ AutoTMalloc<SkBBoxHierarchy::Metadata> meta(fRecord->count());
+ SkRecordFillBounds(fCullRect, *fRecord, bounds, meta);
+
+ fBBH->insert(bounds, meta, fRecord->count());
+
+ // Now that we've calculated content bounds, we can update fCullRect, often trimming it.
+ SkRect bbhBound = SkRect::MakeEmpty();
+ for (int i = 0; i < fRecord->count(); i++) {
+ bbhBound.join(bounds[i]);
+ }
+ SkASSERT((bbhBound.isEmpty() || fCullRect.contains(bbhBound))
+ || (bbhBound.isEmpty() && fCullRect.isEmpty()));
+ fCullRect = bbhBound;
+ }
+
+ size_t subPictureBytes = fRecorder->approxBytesUsedBySubPictures();
+ for (int i = 0; pictList && i < pictList->count(); i++) {
+ subPictureBytes += pictList->begin()[i]->approximateBytesUsed();
+ }
+ return sk_make_sp<SkBigPicture>(fCullRect,
+ std::move(fRecord),
+ std::move(pictList),
+ std::move(fBBH),
+ subPictureBytes);
+}
+
+sk_sp<SkPicture> SkPictureRecorder::finishRecordingAsPictureWithCull(const SkRect& cullRect) {
+ fCullRect = cullRect;
+ return this->finishRecordingAsPicture();
+}
+
+
+void SkPictureRecorder::partialReplay(SkCanvas* canvas) const {
+ if (nullptr == canvas) {
+ return;
+ }
+
+ int drawableCount = 0;
+ SkDrawable* const* drawables = nullptr;
+ SkDrawableList* drawableList = fRecorder->getDrawableList();
+ if (drawableList) {
+ drawableCount = drawableList->count();
+ drawables = drawableList->begin();
+ }
+ SkRecordDraw(*fRecord, canvas, nullptr, drawables, drawableCount, nullptr/*bbh*/, nullptr/*callback*/);
+}
+
+sk_sp<SkDrawable> SkPictureRecorder::finishRecordingAsDrawable() {
+ fActivelyRecording = false;
+ fRecorder->restoreToCount(1); // If we were missing any restores, add them now.
+
+ SkRecordOptimize(fRecord.get());
+
+ if (fBBH) {
+ AutoTMalloc<SkRect> bounds(fRecord->count());
+ AutoTMalloc<SkBBoxHierarchy::Metadata> meta(fRecord->count());
+ SkRecordFillBounds(fCullRect, *fRecord, bounds, meta);
+ fBBH->insert(bounds, meta, fRecord->count());
+ }
+
+ sk_sp<SkDrawable> drawable =
+ sk_make_sp<SkRecordedDrawable>(std::move(fRecord), std::move(fBBH),
+ fRecorder->detachDrawableList(), fCullRect);
+
+ return drawable;
+}