Rearrange SkRecord public API to fit better with cc/resources/picture
BUG=skia:2378
R=reed@google.com, danakj@chromium.org, enne@chromium.org, mtklein@google.com, robertphillips@google.com
Author: mtklein@chromium.org
Review URL: https://codereview.chromium.org/248033002
git-svn-id: http://skia.googlecode.com/svn/trunk@14351 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/dm/DMRecordTask.cpp b/dm/DMRecordTask.cpp
index 95a8bbd..31c46a6 100644
--- a/dm/DMRecordTask.cpp
+++ b/dm/DMRecordTask.cpp
@@ -16,13 +16,10 @@
{}
void RecordTask::draw() {
- using EXPERIMENTAL::SkRecording;
- using EXPERIMENTAL::SkPlayback;
-
// Record the GM into an SkRecord.
- SkRecording* recording = SkRecording::Create(fReference.width(), fReference.height());
- fGM->draw(recording->canvas());
- SkAutoTDelete<const SkPlayback> playback(SkRecording::Delete(recording));
+ EXPERIMENTAL::SkRecording recording(fReference.width(), fReference.height());
+ fGM->draw(recording.canvas());
+ SkAutoTDelete<const EXPERIMENTAL::SkPlayback> playback(recording.releasePlayback());
// Draw the SkRecord back into a bitmap.
SkBitmap bitmap;
diff --git a/include/record/SkRecording.h b/include/record/SkRecording.h
index 0d04b90..2716ea6 100644
--- a/include/record/SkRecording.h
+++ b/include/record/SkRecording.h
@@ -8,8 +8,10 @@
#ifndef SkRecording_DEFINED
#define SkRecording_DEFINED
-#include "SkCanvas.h" // SkCanvas
-#include "SkTypes.h" // SkNoncopyable
+#include "SkCanvas.h" // SkCanvas
+#include "SkRefCnt.h" // SkAutoTUnref
+#include "SkTemplates.h" // SkAutoTDelete
+#include "SkTypes.h" // SkNoncopyable
// These are intentionally left opaque.
class SkRecord;
@@ -19,14 +21,15 @@
/** Easy mode interface to SkRecord-based SkCanvas recording.
*
- * SkRecording* recording = SkRecording::Create(1920, 1080);
+ * scoped_ptr<SkRecording> recording(new SkRecording(1920, 1080));
+ * skia::RefPtr<SkCanvas> canvas(skia::SharePtr(recording->canvas()));
*
- * SkCanvas* canvas = recording->canvas();
* canvas->drawThis();
* canvas->clipThat();
* ...
*
- * scoped_ptr<const SkPlayback> playback(SkRecording::Delete(recording));
+ * canvas.clear(); // You must deref the canvas before you may call releasePlayback().
+ * scoped_ptr<const SkPlayback> playback(recording->releasePlayback());
* playback->draw(&someCanvas);
* playback->draw(&someOtherCanvas);
*
@@ -44,29 +47,27 @@
private:
explicit SkPlayback(const SkRecord*);
- const SkRecord* fRecord;
+ SkAutoTDelete<const SkRecord> fRecord;
friend class SkRecording;
};
class SkRecording : SkNoncopyable {
public:
- // Result must be returned via SkRecording::Delete.
- static SkRecording* Create(int width, int height);
-
- // Caller takes ownership of SkPlayback.
- static const SkPlayback* Delete(SkRecording*);
-
- // Draws issued to this canvas will be replayed by SkPlayback::draw().
- // This pointer is owned by the SkRecording; the caller must not take ownership.
- SkCanvas* canvas();
-
-private:
SkRecording(int width, int height);
~SkRecording();
- SkRecorder* fRecorder;
- SkRecord* fRecord;
+ // Draws issued to this canvas will be replayed by SkPlayback::draw().
+ // Any refs held on canvas() must be dropped before you may call releasePlayback().
+ SkCanvas* canvas();
+
+ // Release exclusive ownership of an SkPlayback to the caller.
+ // Any refs held on canvas() must be dropped before you may call releasePlayback().
+ SkPlayback* releasePlayback();
+
+private:
+ SkAutoTDelete<SkRecord> fRecord;
+ SkAutoTUnref<SkRecorder> fRecorder;
};
} // namespace EXPERIMENTAL
diff --git a/src/record/SkRecorder.cpp b/src/record/SkRecorder.cpp
index 345597c..fe4f35f 100644
--- a/src/record/SkRecorder.cpp
+++ b/src/record/SkRecorder.cpp
@@ -12,6 +12,10 @@
SkRecorder::SkRecorder(SkRecorder::Mode mode, SkRecord* record, int width, int height)
: SkCanvas(width, height), fMode(mode), fRecord(record) {}
+void SkRecorder::forgetRecord() {
+ fRecord = NULL;
+}
+
// To make appending to fRecord a little less verbose.
#define APPEND(T, ...) \
SkNEW_PLACEMENT_ARGS(fRecord->append<SkRecords::T>(), SkRecords::T, (__VA_ARGS__))
diff --git a/src/record/SkRecorder.h b/src/record/SkRecorder.h
index dc3de29..e6bddd7 100644
--- a/src/record/SkRecorder.h
+++ b/src/record/SkRecorder.h
@@ -28,6 +28,9 @@
// Does not take ownership of the SkRecord.
SkRecorder(Mode mode, SkRecord*, int width, int height);
+ // Make SkRecorder forget entirely about its SkRecord*; all calls to SkRecorder will fail.
+ void forgetRecord();
+
void clear(SkColor) SK_OVERRIDE;
void drawPaint(const SkPaint& paint) SK_OVERRIDE;
void drawPoints(PointMode mode,
diff --git a/src/record/SkRecording.cpp b/src/record/SkRecording.cpp
index 6af1959..5774362 100644
--- a/src/record/SkRecording.cpp
+++ b/src/record/SkRecording.cpp
@@ -16,38 +16,29 @@
SkPlayback::SkPlayback(const SkRecord* record) : fRecord(record) {}
-SkPlayback::~SkPlayback() {
- SkDELETE(fRecord);
-}
+SkPlayback::~SkPlayback() {}
void SkPlayback::draw(SkCanvas* canvas) const {
- SkASSERT(fRecord != NULL);
+ SkASSERT(fRecord.get() != NULL);
SkRecordDraw(*fRecord, canvas);
}
-/*static*/ SkRecording* SkRecording::Create(int width, int height) {
- return SkNEW_ARGS(SkRecording, (width, height));
+SkRecording::SkRecording(int width, int height)
+ : fRecord(SkNEW(SkRecord))
+ , fRecorder(SkNEW_ARGS(SkRecorder, (SkRecorder::kReadWrite_Mode, fRecord.get(), width, height)))
+ {}
+
+SkPlayback* SkRecording::releasePlayback() {
+ SkASSERT(fRecorder->unique());
+ fRecorder->forgetRecord();
+ SkRecordOptimize(fRecord.get());
+ return SkNEW_ARGS(SkPlayback, (fRecord.detach()));
}
-SkRecording::SkRecording(int width, int height) {
- SkRecord* record = SkNEW(SkRecord);
- fRecorder = SkNEW_ARGS(SkRecorder, (SkRecorder::kReadWrite_Mode, record, width, height));
- fRecord = record;
-}
-
-/*static*/ const SkPlayback* SkRecording::Delete(SkRecording* recording) {
- SkRecord* record = recording->fRecord;
- SkRecordOptimize(record);
- SkDELETE(recording);
- return SkNEW_ARGS(SkPlayback, (record));
-}
-
-SkRecording::~SkRecording() {
- SkDELETE(fRecorder);
-}
+SkRecording::~SkRecording() {}
SkCanvas* SkRecording::canvas() {
- return fRecorder;
+ return fRecord.get() ? fRecorder.get() : NULL;
}
} // namespace EXPERIMENTAL
diff --git a/tests/RecordingTest.cpp b/tests/RecordingTest.cpp
index 7d1dbf1..fbe8448 100644
--- a/tests/RecordingTest.cpp
+++ b/tests/RecordingTest.cpp
@@ -12,14 +12,18 @@
// Minimally exercise the public SkRecording API.
DEF_TEST(RecordingTest, r) {
- EXPERIMENTAL::SkRecording* recording = EXPERIMENTAL::SkRecording::Create(1920, 1080);
+ EXPERIMENTAL::SkRecording recording(1920, 1080);
// Some very exciting commands here.
- recording->canvas()->clipRect(SkRect::MakeWH(320, 240));
+ recording.canvas()->clipRect(SkRect::MakeWH(320, 240));
- SkAutoTDelete<const EXPERIMENTAL::SkPlayback> playback(
- EXPERIMENTAL::SkRecording::Delete(recording));
+ SkAutoTDelete<const EXPERIMENTAL::SkPlayback> playback(recording.releasePlayback());
SkCanvas target;
playback->draw(&target);
+
+ // Here's another recording we never call releasePlayback().
+ // However pointless, this should be safe.
+ EXPERIMENTAL::SkRecording pointless(1920, 1080);
+ pointless.canvas()->clipRect(SkRect::MakeWH(320, 240));
}
diff --git a/tools/bench_record.cpp b/tools/bench_record.cpp
index b27aa56..63139d6 100644
--- a/tools/bench_record.cpp
+++ b/tools/bench_record.cpp
@@ -62,12 +62,12 @@
for (int i = 0; i < FLAGS_loops; i++) {
if (FLAGS_skr) {
- using EXPERIMENTAL::SkRecording;
- SkRecording* recording = SkRecording::Create(width, height);
+ EXPERIMENTAL::SkRecording recording(width, height);
if (NULL != src) {
- src->draw(recording->canvas());
+ src->draw(recording.canvas());
}
- SkDELETE(SkRecording::Delete(recording)); // delete the SkPlayback*.
+ // Release and delete the SkPlayback so that recording optimizes its SkRecord.
+ SkDELETE(recording.releasePlayback());
} else {
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(width, height, bbhFactory, FLAGS_flags);