aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--dm/DM.cpp8
-rw-r--r--dm/DMSrcSink.cpp158
-rw-r--r--dm/DMSrcSink.h12
-rw-r--r--gn/core.gni4
-rw-r--r--include/core/SkDeferredDisplayListRecorder.h52
-rw-r--r--include/core/SkSurface.h17
-rw-r--r--include/private/SkDeferredDisplayList.h43
-rw-r--r--include/private/SkSurfaceCharacterization.h54
-rw-r--r--src/core/SkDeferredDisplayListRecorder.cpp46
-rw-r--r--src/image/SkSurface.cpp8
-rw-r--r--src/image/SkSurface_Base.h3
-rw-r--r--src/image/SkSurface_Gpu.cpp31
-rw-r--r--src/image/SkSurface_Gpu.h3
-rw-r--r--tools/flags/SkCommonFlags.h1
14 files changed, 427 insertions, 13 deletions
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 1c89ae0fdd..044fea5907 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -92,6 +92,8 @@ DEFINE_int32(shard, 0, "Which shard do I run?");
DEFINE_string(mskps, "", "Directory to read mskps from, or a single mskp file.");
DEFINE_bool(forceRasterPipeline, false, "sets gSkForceRasterPipelineBlitter");
+DEFINE_bool(ddl, false, "If true, use DeferredDisplayLists for GPU SKP rendering.");
+
#if SK_SUPPORT_GPU
DEFINE_pathrenderer_flag;
#endif
@@ -773,7 +775,11 @@ static bool gather_srcs() {
push_src("gm", "", new GMSrc(r->factory()));
}
- gather_file_srcs<SKPSrc>(FLAGS_skps, "skp");
+ if (FLAGS_ddl) {
+ gather_file_srcs<DDLSKPSrc>(FLAGS_skps, "skp");
+ } else {
+ gather_file_srcs<SKPSrc>(FLAGS_skps, "skp");
+ }
gather_file_srcs<MSKPSrc>(FLAGS_mskps, "mskp");
#if defined(SK_XML)
gather_file_srcs<SVGSrc>(FLAGS_svgs, "svg");
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index e14e1f9963..dc8a913fa1 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -19,6 +19,7 @@
#include "SkData.h"
#include "SkDebugCanvas.h"
#include "SkDeferredCanvas.h"
+#include "SkDeferredDisplayListRecorder.h"
#include "SkDocument.h"
#include "SkExecutor.h"
#include "SkImageGenerator.h"
@@ -39,9 +40,11 @@
#include "SkRandom.h"
#include "SkRecordDraw.h"
#include "SkRecorder.h"
+#include "SkSurfaceCharacterization.h"
#include "SkSVGCanvas.h"
#include "SkStream.h"
#include "SkSwizzler.h"
+#include "SkTaskGroup.h"
#include "SkTLogic.h"
#include <cmath>
#include <functional>
@@ -1140,37 +1143,51 @@ Name ColorCodecSrc::name() const {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-static const SkRect kSKPViewport = {0,0, 1000,1000};
+static const SkRect kSKPViewport = {0, 0, 1000, 1000};
-SKPSrc::SKPSrc(Path path) : fPath(path) {}
+SKPSrc::SKPSrc(Path path) : fPath(path) { }
-Error SKPSrc::draw(SkCanvas* canvas) const {
- std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(fPath.c_str());
+static sk_sp<SkPicture> read_skp(const char* path) {
+ std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(path);
if (!stream) {
- return SkStringPrintf("Couldn't read %s.", fPath.c_str());
+ return nullptr;
}
sk_sp<SkPicture> pic(SkPicture::MakeFromStream(stream.get()));
if (!pic) {
- return SkStringPrintf("Couldn't decode %s as a picture.", fPath.c_str());
+ return nullptr;
}
stream = nullptr; // Might as well drop this when we're done with it.
+ return pic;
+}
+
+Error SKPSrc::draw(SkCanvas* canvas) const {
+ sk_sp<SkPicture> pic = read_skp(fPath.c_str());
+ if (!pic) {
+ return SkStringPrintf("Couldn't read %s.", fPath.c_str());
+ }
+
canvas->clipRect(kSKPViewport);
canvas->drawPicture(pic);
return "";
}
-SkISize SKPSrc::size() const {
- std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(fPath.c_str());
+static SkRect get_cull_rect_for_skp(const char* path) {
+ std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(path);
if (!stream) {
- return {0, 0};
+ return SkRect::MakeEmpty();
}
SkPictInfo info;
if (!SkPicture::InternalOnly_StreamIsSKP(stream.get(), &info)) {
- return {0, 0};
+ return SkRect::MakeEmpty();
}
- SkRect viewport = kSKPViewport;
- if (!viewport.intersect(info.fCullRect)) {
+
+ return info.fCullRect;
+}
+
+SkISize SKPSrc::size() const {
+ SkRect viewport = get_cull_rect_for_skp(fPath.c_str());
+ if (!viewport.intersect(kSKPViewport)) {
return {0, 0};
}
return viewport.roundOut().size();
@@ -1179,6 +1196,123 @@ SkISize SKPSrc::size() const {
Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+static const int kNumDDLXTiles = 4;
+static const int kNumDDLYTiles = 4;
+static const int kDDLTileSize = 1024;
+static const SkRect kDDLSKPViewport = { 0, 0,
+ kNumDDLXTiles * kDDLTileSize,
+ kNumDDLYTiles * kDDLTileSize };
+
+DDLSKPSrc::DDLSKPSrc(Path path) : fPath(path) { }
+
+Error DDLSKPSrc::draw(SkCanvas* canvas) const {
+ class TileData {
+ public:
+ // Note: we could just pass in surface characterization
+ TileData(sk_sp<SkSurface> surf, const SkIRect& clip)
+ : fSurface(std::move(surf))
+ , fClip(clip) {
+ SkAssertResult(fSurface->characterize(&fCharacterization));
+ }
+
+ // This method operates in parallel
+ void preprocess(SkPicture* pic) {
+ SkDeferredDisplayListRecorder recorder(fCharacterization);
+
+ SkCanvas* subCanvas = recorder.getCanvas();
+
+ subCanvas->clipRect(SkRect::MakeWH(fClip.width(), fClip.height()));
+ subCanvas->translate(-fClip.fLeft, -fClip.fTop);
+
+ // Note: in this use case we only render a picture to the deferred canvas
+ // but, more generally, clients will use arbitrary draw calls.
+ subCanvas->drawPicture(pic);
+
+ fDisplayList = recorder.detach();
+ }
+
+ // This method operates serially
+ void draw() {
+ fSurface->draw(fDisplayList.get());
+ }
+
+ // This method also operates serially
+ void compose(SkCanvas* dst) {
+ sk_sp<SkImage> img = fSurface->makeImageSnapshot();
+ dst->save();
+ dst->clipRect(SkRect::Make(fClip));
+ dst->drawImage(std::move(img), fClip.fLeft, fClip.fTop);
+ dst->restore();
+ }
+
+ private:
+ sk_sp<SkSurface> fSurface;
+ SkIRect fClip; // in the device space of the destination canvas
+ std::unique_ptr<SkDeferredDisplayList> fDisplayList;
+ SkSurfaceCharacterization fCharacterization;
+ };
+
+ SkTArray<TileData> tileData;
+ tileData.reserve(16);
+
+ sk_sp<SkPicture> pic = read_skp(fPath.c_str());
+ if (!pic) {
+ return SkStringPrintf("Couldn't read %s.", fPath.c_str());
+ }
+
+ const SkRect cullRect = pic->cullRect();
+
+ // All the destination tiles are the same size
+ const SkImageInfo tileII = SkImageInfo::MakeN32Premul(kDDLTileSize, kDDLTileSize);
+
+ // First, create the destination tiles
+ for (int y = 0; y < kNumDDLYTiles; ++y) {
+ for (int x = 0; x < kNumDDLXTiles; ++x) {
+ SkRect clip = SkRect::MakeXYWH(x * kDDLTileSize, y * kDDLTileSize,
+ kDDLTileSize, kDDLTileSize);
+
+ if (!clip.intersect(cullRect)) {
+ continue;
+ }
+
+ tileData.push_back(TileData(canvas->makeSurface(tileII), clip.roundOut()));
+ }
+ }
+
+ // Second, run the cpu pre-processing in threads
+ SkTaskGroup().batch(tileData.count(), [&](int i) {
+ tileData[i].preprocess(pic.get());
+ });
+
+ // Third, synchronously render the display lists into the dest tiles
+ // TODO: it would be cool to not wait until all the tiles are drawn to begin
+ // drawing to the GPU
+ for (int i = 0; i < tileData.count(); ++i) {
+ tileData[i].draw();
+ }
+
+ // Finally, compose the drawn tiles into the result
+ // Note: the separation between the tiles and the final composition better
+ // matches Chrome but costs us a copy
+ for (int i = 0; i < tileData.count(); ++i) {
+ tileData[i].compose(canvas);
+ }
+
+ return "";
+}
+
+SkISize DDLSKPSrc::size() const {
+ SkRect viewport = get_cull_rect_for_skp(fPath.c_str());
+ if (!viewport.intersect(kDDLSKPViewport)) {
+ return {0, 0};
+ }
+ return viewport.roundOut().size();
+}
+
+Name DDLSKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#if defined(SK_XML)
// Used when the image doesn't have an intrinsic size.
static const SkSize kDefaultSVGSize = {1000, 1000};
diff --git a/dm/DMSrcSink.h b/dm/DMSrcSink.h
index c1af4d01b5..26c32f59b7 100644
--- a/dm/DMSrcSink.h
+++ b/dm/DMSrcSink.h
@@ -248,6 +248,18 @@ private:
Path fPath;
};
+// DeferredDisplayList flavor
+class DDLSKPSrc : public Src {
+public:
+ explicit DDLSKPSrc(Path path);
+
+ Error draw(SkCanvas*) const override;
+ SkISize size() const override;
+ Name name() const override;
+private:
+ Path fPath;
+};
+
#if defined(SK_XML)
} // namespace DM
diff --git a/gn/core.gni b/gn/core.gni
index 5cb3e094b2..862bdd0b9a 100644
--- a/gn/core.gni
+++ b/gn/core.gni
@@ -96,6 +96,7 @@ skia_core_sources = [
"$_src/core/SkData.cpp",
"$_src/core/SkDataTable.cpp",
"$_src/core/SkDebug.cpp",
+ "$_src/core/SkDeferredDisplayListRecorder.cpp",
"$_src/core/SkDeque.cpp",
"$_src/core/SkDescriptor.h",
"$_src/core/SkDevice.cpp",
@@ -371,6 +372,7 @@ skia_core_sources = [
"$_include/core/SkColorFilter.h",
"$_include/core/SkColorPriv.h",
"$_include/core/SkData.h",
+ "$_include/core/SkDeferredDisplayListRecorder.h",
"$_include/core/SkDeque.h",
"$_include/core/SkDrawable.h",
"$_include/core/SkDrawFilter.h",
@@ -429,6 +431,7 @@ skia_core_sources = [
# private
"$_include/private/SkAtomics.h",
"$_include/private/SkChecksum.h",
+ "$_include/private/SkDeferredDisplayList.h",
"$_include/private/SkFixed.h",
"$_include/private/SkFloatBits.h",
"$_include/private/SkFloatingPoint.h",
@@ -440,6 +443,7 @@ skia_core_sources = [
"$_include/private/SkSemaphore.h",
"$_include/private/SkShadowFlags.h",
"$_include/private/SkSpinlock.h",
+ "$_include/private/SkSurfaceCharacterization.h",
"$_include/private/SkTemplates.h",
"$_include/private/SkTArray.h",
"$_include/private/SkTDArray.h",
diff --git a/include/core/SkDeferredDisplayListRecorder.h b/include/core/SkDeferredDisplayListRecorder.h
new file mode 100644
index 0000000000..185adfa99b
--- /dev/null
+++ b/include/core/SkDeferredDisplayListRecorder.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDeferredDisplayListMaker_DEFINED
+#define SkDeferredDisplayListMaker_DEFINED
+
+#include "SkRefCnt.h"
+
+#include "../private/SkDeferredDisplayList.h"
+#include "../private/SkSurfaceCharacterization.h"
+
+class SkCanvas;
+class SkSurface; // TODO: remove
+
+/*
+ * This class is intended to be used as:
+ * Get an SkSurfaceCharacterization from the ultimate intended gpu-backed destination SkSurface
+ * Create one of these (an SkDDLMaker) on the stack
+ * Get the canvas and render into it
+ * Snap off and hold on to an SkDeferredDisplayList
+ * Once your app actually needs the pixels, call SkSurface::draw(SkDeferredDisplayList*)
+ *
+ * This class never accesses the GPU but performs all the cpu work it can. It
+ * is thread-safe (i.e., one can break a scene into tiles and perform their cpu-side
+ * work in parallel ahead of time).
+ */
+class SkDeferredDisplayListRecorder {
+public:
+ SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&);
+
+ const SkSurfaceCharacterization& characterization() const {
+ return fCharacterization;
+ }
+
+ // The backing canvas will become invalid (and this entry point will return
+ // null) once 'detach' is called.
+ // Note: ownership of the SkCanvas is not transfered via this call.
+ SkCanvas* getCanvas();
+
+ std::unique_ptr<SkDeferredDisplayList> detach();
+
+private:
+ SkSurfaceCharacterization fCharacterization;
+
+ sk_sp<SkSurface> fSurface; // temporary until we have a real implementation
+};
+
+#endif
diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h
index eaf55050b8..890532f983 100644
--- a/include/core/SkSurface.h
+++ b/include/core/SkSurface.h
@@ -15,7 +15,9 @@
#include "GrTypes.h"
class SkCanvas;
+class SkDeferredDisplayList;
class SkPaint;
+class SkSurfaceCharacterization;
class GrBackendRenderTarget;
class GrBackendSemaphore;
class GrContext;
@@ -335,6 +337,21 @@ public:
*/
bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores);
+ /**
+ * This creates a characterization of this SkSurface's properties that can
+ * be used to perform gpu-backend preprocessing in a separate thread (via
+ * the SkDeferredDisplayListRecorder).
+ * It will return false on failure (e.g., if the SkSurface is cpu-backed).
+ */
+ bool characterize(SkSurfaceCharacterization* characterization) const;
+
+ /**
+ * Draw a deferred display list (created via SkDeferredDisplayListRecorder).
+ * The draw will be skipped if the characterization stored in the display list
+ * isn't compatible with this surface.
+ */
+ void draw(SkDeferredDisplayList* deferredDisplayList);
+
protected:
SkSurface(int width, int height, const SkSurfaceProps*);
SkSurface(const SkImageInfo&, const SkSurfaceProps*);
diff --git a/include/private/SkDeferredDisplayList.h b/include/private/SkDeferredDisplayList.h
new file mode 100644
index 0000000000..37e792ff20
--- /dev/null
+++ b/include/private/SkDeferredDisplayList.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDeferredDisplayList_DEFINED
+#define SkDeferredDisplayList_DEFINED
+
+#include "SkSurfaceCharacterization.h"
+
+class SkImage; // TODO: rm this
+
+/*
+ * This class contains pre-processed gpu operations that can be replayed into
+ * an SkSurface via draw(SkDeferredDisplayList*).
+ *
+ * TODO: we probably need to expose this class so users can query it for memory usage.
+ */
+class SkDeferredDisplayList {
+public:
+ SkDeferredDisplayList(const SkSurfaceCharacterization& characterization,
+ sk_sp<SkImage> image) // TODO rm this parameter
+ : fCharacterization(characterization)
+ , fImage(std::move(image)) {
+ }
+
+ const SkSurfaceCharacterization& characterization() const {
+ return fCharacterization;
+ }
+
+ // TODO: remove this. It is just scaffolding to get something up & running
+ void draw(SkSurface*);
+
+private:
+ SkSurfaceCharacterization fCharacterization;
+
+ // TODO: actually store the GPU opLists
+ sk_sp<SkImage> fImage;
+};
+
+#endif
diff --git a/include/private/SkSurfaceCharacterization.h b/include/private/SkSurfaceCharacterization.h
new file mode 100644
index 0000000000..f3acb01236
--- /dev/null
+++ b/include/private/SkSurfaceCharacterization.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSurfaceCharacterization_DEFINED
+#define SkSurfaceCharacterization_DEFINED
+
+#include "GrTypes.h"
+
+class SkSurface;
+
+// This class captures all the pertinent data about an SkSurface required
+// to perform cpu-preprocessing for gpu-rendering.
+class SkSurfaceCharacterization {
+public:
+ SkSurfaceCharacterization()
+ : fOrigin(kBottomLeft_GrSurfaceOrigin)
+ , fWidth(0)
+ , fHeight(0)
+ , fConfig(kRGBA_8888_GrPixelConfig)
+ , fSampleCnt(0) {
+ }
+
+ void set(GrSurfaceOrigin origin,
+ int width, int height,
+ GrPixelConfig config,
+ int sampleCnt) {
+ fOrigin = origin;
+ fWidth = width;
+ fHeight = height;
+ fConfig = config;
+ fSampleCnt = sampleCnt;
+ }
+
+ GrSurfaceOrigin origin() const { return fOrigin; }
+ int width() const { return fWidth; }
+ int height() const { return fHeight; }
+ GrPixelConfig config() const { return fConfig; }
+ int sampleCount() const { return fSampleCnt; }
+
+private:
+ GrSurfaceOrigin fOrigin;
+ int fWidth;
+ int fHeight;
+ GrPixelConfig fConfig;
+ int fSampleCnt;
+ // TODO: need to include caps!
+ // Maybe use GrContextThreadSafeProxy (it has the caps & the unique Context ID already)
+};
+
+#endif
diff --git a/src/core/SkDeferredDisplayListRecorder.cpp b/src/core/SkDeferredDisplayListRecorder.cpp
new file mode 100644
index 0000000000..c47a79a77d
--- /dev/null
+++ b/src/core/SkDeferredDisplayListRecorder.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkDeferredDisplayListRecorder.h"
+
+#include "SkCanvas.h" // TODO: remove
+#include "SkDeferredDisplayList.h"
+#include "SkSurface.h" // TODO: remove
+
+SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(
+ const SkSurfaceCharacterization& characterization)
+ : fCharacterization(characterization) {
+}
+
+SkCanvas* SkDeferredDisplayListRecorder::getCanvas() {
+ if (!fSurface) {
+ SkImageInfo ii = SkImageInfo::MakeN32(fCharacterization.width(),
+ fCharacterization.height(),
+ kOpaque_SkAlphaType);
+
+ // Use raster right now to allow threading
+ fSurface = SkSurface::MakeRaster(ii, nullptr);
+ }
+
+ return fSurface->getCanvas();
+}
+
+std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() {
+ sk_sp<SkImage> img = fSurface->makeImageSnapshot();
+ fSurface.reset();
+
+ // TODO: need to wrap the opLists associated with the deferred draws
+ // in the SkDeferredDisplayList.
+ return std::unique_ptr<SkDeferredDisplayList>(
+ new SkDeferredDisplayList(fCharacterization, std::move(img)));
+}
+
+// Placeholder. Ultimately, the SkSurface_Gpu will pass the wrapped opLists to its
+// renderTargetContext.
+void SkDeferredDisplayList::draw(SkSurface* surface) {
+ surface->getCanvas()->drawImage(fImage.get(), 0, 0);
+}
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
index a196145c99..1de7b609e3 100644
--- a/src/image/SkSurface.cpp
+++ b/src/image/SkSurface.cpp
@@ -209,6 +209,14 @@ bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores
return asSB(this)->onWait(numSemaphores, waitSemaphores);
}
+bool SkSurface::characterize(SkSurfaceCharacterization* characterization) const {
+ return asSB(const_cast<SkSurface*>(this))->onCharacterize(characterization);
+}
+
+void SkSurface::draw(SkDeferredDisplayList* ddl) {
+ return asSB(this)->onDraw(ddl);
+}
+
//////////////////////////////////////////////////////////////////////////////////////
#include "SkNoDrawCanvas.h"
diff --git a/src/image/SkSurface_Base.h b/src/image/SkSurface_Base.h
index 8cf75b60e4..e05d371cd8 100644
--- a/src/image/SkSurface_Base.h
+++ b/src/image/SkSurface_Base.h
@@ -94,6 +94,9 @@ public:
return false;
}
+ virtual bool onCharacterize(SkSurfaceCharacterization*) const { return false; }
+ virtual void onDraw(SkDeferredDisplayList*) { }
+
inline SkCanvas* getCachedCanvas();
inline sk_sp<SkImage> refCachedImage();
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index a5acf4f95a..042fc32a67 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -15,11 +15,13 @@
#include "SkCanvas.h"
#include "SkColorSpace_Base.h"
+#include "SkDeferredDisplayList.h"
#include "SkGpuDevice.h"
#include "SkImage_Base.h"
#include "SkImage_Gpu.h"
#include "SkImagePriv.h"
#include "SkSurface_Base.h"
+#include "SkSurfaceCharacterization.h"
#if SK_SUPPORT_GPU
@@ -158,6 +160,35 @@ bool SkSurface_Gpu::onWait(int numSemaphores, const GrBackendSemaphore* waitSema
return fDevice->wait(numSemaphores, waitSemaphores);
}
+bool SkSurface_Gpu::onCharacterize(SkSurfaceCharacterization* data) const {
+ GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
+
+ data->set(rtc->origin(), rtc->width(), rtc->height(),
+ rtc->config(), rtc->numColorSamples());
+ return true;
+}
+
+bool SkSurface_Gpu::isCompatible(const SkSurfaceCharacterization& data) const {
+ GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
+
+ return data.origin() == rtc->origin() &&
+ data.width() == rtc->width() &&
+ data.height() == rtc->height() &&
+ data.config() == rtc->config() &&
+ data.sampleCount() == rtc->numColorSamples();
+}
+
+void SkSurface_Gpu::onDraw(SkDeferredDisplayList* dl) {
+ if (!this->isCompatible(dl->characterization())) {
+ return;
+ }
+
+ // Ultimately need to pass opLists from the DeferredDisplayList on to the
+ // SkGpuDevice's renderTargetContext.
+ dl->draw(this);
+}
+
+
///////////////////////////////////////////////////////////////////////////////
bool SkSurface_Gpu::Valid(const SkImageInfo& info) {
diff --git a/src/image/SkSurface_Gpu.h b/src/image/SkSurface_Gpu.h
index ebf7d4ed44..c95966370c 100644
--- a/src/image/SkSurface_Gpu.h
+++ b/src/image/SkSurface_Gpu.h
@@ -29,6 +29,9 @@ public:
GrSemaphoresSubmitted onFlush(int numSemaphores,
GrBackendSemaphore signalSemaphores[]) override;
bool onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) override;
+ bool onCharacterize(SkSurfaceCharacterization*) const override;
+ bool isCompatible(const SkSurfaceCharacterization&) const;
+ void onDraw(SkDeferredDisplayList*) override;
SkGpuDevice* getDevice() { return fDevice.get(); }
diff --git a/tools/flags/SkCommonFlags.h b/tools/flags/SkCommonFlags.h
index d35e9a8d51..ef1897b7bc 100644
--- a/tools/flags/SkCommonFlags.h
+++ b/tools/flags/SkCommonFlags.h
@@ -25,6 +25,7 @@ DECLARE_bool(preAbandonGpuContext);
DECLARE_bool(abandonGpuContext);
DECLARE_bool(releaseAndAbandonGpuContext);
DECLARE_string(skps);
+DECLARE_bool(ddl);
DECLARE_string(svgs);
DECLARE_int32(threads);
DECLARE_string(resourcePath);