aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Robert Phillips <robertphillips@google.com>2018-02-01 09:10:04 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-01 15:00:53 +0000
commit620003692923dc6c6df5a1b66288988b6783a69f (patch)
tree5010067f4d26fb23f28964e74b5e37c38e3dddc3
parent5f9ee7cc53d28c8ff2d000436bfee195c493ccdf (diff)
Implement GPU/OpList DDLs
This relies on https://skia-review.googlesource.com/c/skia/+/102101 (Add SkSurface_Gpu::MakeWrappedRenderTarget method) landing first TBR=bsalomon@google.com Change-Id: I4d2d66af5800407f638ef32d7b19ce49084bd4e4 Reviewed-on: https://skia-review.googlesource.com/102263 Commit-Queue: Robert Phillips <robertphillips@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com>
-rw-r--r--gn/core.gni1
-rw-r--r--gn/gpu.gni6
-rw-r--r--include/core/SkDeferredDisplayListRecorder.h13
-rw-r--r--include/private/GrOpList.h (renamed from src/gpu/GrOpList.h)4
-rw-r--r--include/private/GrSurfaceProxyRef.h71
-rw-r--r--include/private/SkDeferredDisplayList.h54
-rw-r--r--include/private/SkSurfaceCharacterization.h10
-rw-r--r--src/core/SkDeferredDisplayList.cpp28
-rw-r--r--src/core/SkDeferredDisplayListRecorder.cpp95
-rw-r--r--src/gpu/GrContext.cpp9
-rw-r--r--src/gpu/GrContextPriv.h5
-rw-r--r--src/gpu/GrDrawingManager.cpp18
-rw-r--r--src/gpu/GrDrawingManager.h3
-rw-r--r--src/gpu/GrGpuResourceRef.cpp112
-rw-r--r--src/gpu/GrGpuResourceRef.h60
-rw-r--r--src/gpu/GrProcessor.h1
-rw-r--r--src/gpu/GrSurfaceProxyRef.cpp118
-rw-r--r--src/image/SkSurface_Gpu.cpp8
18 files changed, 407 insertions, 209 deletions
diff --git a/gn/core.gni b/gn/core.gni
index f0612cb973..d94bda4c4c 100644
--- a/gn/core.gni
+++ b/gn/core.gni
@@ -100,6 +100,7 @@ skia_core_sources = [
"$_src/core/SkData.cpp",
"$_src/core/SkDataTable.cpp",
"$_src/core/SkDebug.cpp",
+ "$_src/core/SkDeferredDisplayList.cpp",
"$_src/core/SkDeferredDisplayListRecorder.cpp",
"$_src/core/SkDeque.cpp",
"$_src/core/SkDescriptor.h",
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 97d5df9135..4d8f3d8973 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -35,9 +35,11 @@ skia_gpu_sources = [
# Private includes
"$_include/private/GrAuditTrail.h",
"$_include/private/GrGLSL.h",
+ "$_include/private/GrOpList.h",
"$_include/private/GrSingleOwner.h",
"$_include/private/GrRenderTargetProxy.h",
"$_include/private/GrSurfaceProxy.h",
+ "$_include/private/GrSurfaceProxyRef.h",
"$_include/private/GrSwizzle.h",
"$_include/private/GrTextureProxy.h",
"$_include/private/GrTypesPriv.h",
@@ -95,6 +97,7 @@ skia_gpu_sources = [
"$_src/gpu/GrGpuCommandBuffer.h",
"$_src/gpu/GrGpuResourcePriv.h",
"$_src/gpu/GrGpuResource.cpp",
+ "$_src/gpu/GrGpuResourceRef.cpp",
"$_src/gpu/GrGpuResourceRef.h",
"$_src/gpu/GrGpuFactory.cpp",
"$_src/gpu/GrGpuFactory.h",
@@ -107,7 +110,6 @@ skia_gpu_sources = [
"$_src/gpu/GrOpFlushState.cpp",
"$_src/gpu/GrOpFlushState.h",
"$_src/gpu/GrOpList.cpp",
- "$_src/gpu/GrOpList.h",
"$_src/gpu/GrPaint.cpp",
"$_src/gpu/GrPaint.h",
"$_src/gpu/GrPath.cpp",
@@ -144,7 +146,6 @@ skia_gpu_sources = [
"$_src/gpu/GrProcessorUnitTest.h",
"$_src/gpu/GrProxyProvider.cpp",
"$_src/gpu/GrProxyProvider.h",
- "$_src/gpu/GrGpuResourceRef.cpp",
"$_src/gpu/GrQuad.h",
"$_src/gpu/GrRect.h",
"$_src/gpu/GrRectanizer.h",
@@ -186,6 +187,7 @@ skia_gpu_sources = [
"$_src/gpu/GrStyle.h",
"$_src/gpu/GrSurfaceContextPriv.h",
"$_src/gpu/GrSurfaceProxyPriv.h",
+ "$_src/gpu/GrSurfaceProxyRef.cpp",
"$_src/gpu/GrTessellator.cpp",
"$_src/gpu/GrTessellator.h",
"$_src/gpu/GrTextureOpList.cpp",
diff --git a/include/core/SkDeferredDisplayListRecorder.h b/include/core/SkDeferredDisplayListRecorder.h
index b50d4f8c1f..f0a71c27d6 100644
--- a/include/core/SkDeferredDisplayListRecorder.h
+++ b/include/core/SkDeferredDisplayListRecorder.h
@@ -18,8 +18,6 @@ class GrContext;
class SkCanvas;
class SkSurface;
-#define SK_RASTER_RECORDER_IMPLEMENTATION 1
-
/*
* This class is intended to be used as:
* Get an SkSurfaceCharacterization representing the intended gpu-backed destination SkSurface
@@ -35,6 +33,7 @@ class SkSurface;
class SkDeferredDisplayListRecorder {
public:
SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&);
+ ~SkDeferredDisplayListRecorder();
const SkSurfaceCharacterization& characterization() const {
return fCharacterization;
@@ -50,11 +49,15 @@ public:
private:
bool init();
- const SkSurfaceCharacterization fCharacterization;
+ const SkSurfaceCharacterization fCharacterization;
+
#ifndef SK_RASTER_RECORDER_IMPLEMENTATION
- sk_sp<GrContext> fContext;
+#if SK_SUPPORT_GPU
+ sk_sp<GrContext> fContext;
+#endif
+ sk_sp<SkDeferredDisplayList::LazyProxyData> fLazyProxyData;
#endif
- sk_sp<SkSurface> fSurface;
+ sk_sp<SkSurface> fSurface;
};
#endif
diff --git a/src/gpu/GrOpList.h b/include/private/GrOpList.h
index f1989fd591..c9abd6d4e5 100644
--- a/src/gpu/GrOpList.h
+++ b/include/private/GrOpList.h
@@ -9,7 +9,8 @@
#define GrOpList_DEFINED
#include "GrColor.h"
-#include "GrGpuResourceRef.h"
+#include "GrSurfaceProxyRef.h"
+#include "GrTextureProxy.h"
#include "SkRefCnt.h"
#include "SkTDArray.h"
@@ -31,7 +32,6 @@ class GrRenderTargetOpList;
class GrResourceAllocator;
class GrResourceProvider;
class GrSurfaceProxy;
-class GrTextureProxy;
class GrTextureOpList;
struct SkIPoint;
diff --git a/include/private/GrSurfaceProxyRef.h b/include/private/GrSurfaceProxyRef.h
new file mode 100644
index 0000000000..2319357251
--- /dev/null
+++ b/include/private/GrSurfaceProxyRef.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrSurfaceProxyRef_DEFINED
+#define GrSurfaceProxyRef_DEFINED
+
+#include "GrTypesPriv.h"
+
+class GrSurfaceProxy;
+
+class GrSurfaceProxyRef : SkNoncopyable {
+public:
+ virtual ~GrSurfaceProxyRef();
+
+ GrSurfaceProxy* get() const { return fProxy; }
+
+ /** Does this object own a pending read or write on the resource it is wrapping. */
+ bool ownsPendingIO() const { return fPendingIO; }
+
+ /** What type of IO does this represent? This is independent of whether a normal ref or a
+ pending IO is currently held. */
+ GrIOType ioType() const { return fIOType; }
+
+ /** Shortcut for calling setProxy() with NULL. It cannot be called after markingPendingIO
+ is called. */
+ void reset();
+
+protected:
+ GrSurfaceProxyRef();
+
+ /** ioType expresses what type of IO operations will be marked as
+ pending on the resource when markPendingIO is called. */
+ GrSurfaceProxyRef(sk_sp<GrSurfaceProxy>, GrIOType);
+
+ /** ioType expresses what type of IO operations will be marked as
+ pending on the resource when markPendingIO is called. */
+ void setProxy(sk_sp<GrSurfaceProxy>, GrIOType);
+
+private:
+ /** Called by owning GrProgramElement when the program element is first scheduled for
+ execution. It can only be called once. */
+ void markPendingIO() const;
+
+ /** Called when the program element/draw state is no longer owned by GrOpList-client code.
+ This lets the cache know that the drawing code will no longer schedule additional reads or
+ writes to the resource using the program element or draw state. It can only be called once.
+ */
+ void removeRef() const;
+
+ /** Called to indicate that the previous pending IO is complete. Useful when the owning object
+ still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously
+ pending executions have been complete. Can only be called if removeRef() was not previously
+ called. */
+ void pendingIOComplete() const;
+
+ friend class GrResourceIOProcessor;
+ friend class GrOpList; // for setProxy
+
+ GrSurfaceProxy* fProxy;
+ mutable bool fOwnRef;
+ mutable bool fPendingIO;
+ GrIOType fIOType;
+
+ typedef SkNoncopyable INHERITED;
+};
+
+#endif
diff --git a/include/private/SkDeferredDisplayList.h b/include/private/SkDeferredDisplayList.h
index 392a952a1d..a3517bb6a0 100644
--- a/include/private/SkDeferredDisplayList.h
+++ b/include/private/SkDeferredDisplayList.h
@@ -10,7 +10,14 @@
#include "SkSurfaceCharacterization.h"
-class SkImage; // TODO: rm this since it is just for the temporary placeholder implementation
+#if SK_SUPPORT_GPU
+#include "GrOpList.h"
+#endif
+
+#ifdef SK_RASTER_RECORDER_IMPLEMENTATION
+class SkImage; // DDL TODO: rm this since it is just for the temporary placeholder implementation
+#endif
+
class SkSurface;
/*
@@ -21,24 +28,55 @@ class SkSurface;
*/
class SkDeferredDisplayList {
public:
- SkDeferredDisplayList(const SkSurfaceCharacterization& characterization,
- sk_sp<SkImage> image) // TODO rm this parameter
+
+#ifdef SK_RASTER_RECORDER_IMPLEMENTATION
+ SkDeferredDisplayList(const SkSurfaceCharacterization& characterization, sk_sp<SkImage> image)
: fCharacterization(characterization)
, fImage(std::move(image)) {
}
+ // DDL TODO: remove this. It is just scaffolding to get something up & running
+ bool draw(SkSurface*) const;
+#endif
+
+#if SK_SUPPORT_GPU
+ // This object is the source from which the lazy proxy backing the DDL will pull its backing
+ // texture when the DDL is replayed. It has to be separately ref counted bc the lazy proxy
+ // can outlive the DDL.
+ class LazyProxyData : public SkRefCnt {
+ public:
+ // Upon being replayed - this field will be filled in (by the DrawingManager) with the proxy
+ // backing the destination SkSurface. Note that, since there is no good place to clear it
+ // it can become a dangling pointer.
+ GrRenderTargetProxy* fReplayDest = nullptr;
+ };
+#else
+ class LazyProxyData : public SkRefCnt {};
+#endif
+
+ SkDeferredDisplayList(const SkSurfaceCharacterization& characterization,
+ sk_sp<LazyProxyData>);
+
const SkSurfaceCharacterization& characterization() const {
return fCharacterization;
}
- // TODO: remove this. It is just scaffolding to get something up & running
- bool draw(SkSurface*) const;
-
private:
+ friend class GrDrawingManager; // for access to 'fOpLists' and 'fLazyProxyData'
+ friend class SkDeferredDisplayListRecorder; // for access to 'fLazyProxyData'
+
const SkSurfaceCharacterization fCharacterization;
- // TODO: actually store the GPU opLists
- sk_sp<SkImage> fImage;
+#ifdef SK_RASTER_RECORDER_IMPLEMENTATION
+ sk_sp<SkImage> fImage;
+#else
+
+#if SK_SUPPORT_GPU
+ SkTArray<sk_sp<GrOpList>> fOpLists;
+#endif
+ sk_sp<LazyProxyData> fLazyProxyData;
+
+#endif
};
#endif
diff --git a/include/private/SkSurfaceCharacterization.h b/include/private/SkSurfaceCharacterization.h
index 40be90c685..07838968b9 100644
--- a/include/private/SkSurfaceCharacterization.h
+++ b/include/private/SkSurfaceCharacterization.h
@@ -10,14 +10,18 @@
#include "GrTypes.h"
+#include "SkColorSpace.h"
+#include "SkRefCnt.h"
#include "SkSurfaceProps.h"
class SkColorSpace;
-#if SK_SUPPORT_GPU
-#include "GrTypesPriv.h"
+// This define can be used to swap between the default (raster) DDL implementation and the
+// gpu implementation.
+#define SK_RASTER_RECORDER_IMPLEMENTATION 1
-class GrContextThreadSafeProxy;
+#if SK_SUPPORT_GPU
+#include "GrContext.h"
/** \class SkSurfaceCharacterization
A surface characterization contains all the information Ganesh requires to makes its internal
diff --git a/src/core/SkDeferredDisplayList.cpp b/src/core/SkDeferredDisplayList.cpp
new file mode 100644
index 0000000000..c4cf0686e6
--- /dev/null
+++ b/src/core/SkDeferredDisplayList.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkDeferredDisplayList.h"
+
+#include "SkCanvas.h"
+#include "SkSurface.h"
+
+#ifndef SK_RASTER_RECORDER_IMPLEMENTATION
+SkDeferredDisplayList::SkDeferredDisplayList(const SkSurfaceCharacterization& characterization,
+ sk_sp<LazyProxyData> lazyProxyData)
+ : fCharacterization(characterization)
+ , fLazyProxyData(std::move(lazyProxyData)) {
+}
+#endif
+
+#ifdef SK_RASTER_RECORDER_IMPLEMENTATION
+// Placeholder. Ultimately, the SkSurface_Gpu will pass the wrapped opLists to its
+// renderTargetContext.
+bool SkDeferredDisplayList::draw(SkSurface* surface) const {
+ surface->getCanvas()->drawImage(fImage.get(), 0, 0);
+ return true;
+}
+#endif
diff --git a/src/core/SkDeferredDisplayListRecorder.cpp b/src/core/SkDeferredDisplayListRecorder.cpp
index 3f703733bc..b5442c69f8 100644
--- a/src/core/SkDeferredDisplayListRecorder.cpp
+++ b/src/core/SkDeferredDisplayListRecorder.cpp
@@ -9,7 +9,12 @@
#if SK_SUPPORT_GPU
#include "GrContextPriv.h"
+#include "GrProxyProvider.h"
+#include "GrTexture.h"
+
+#include "SkGpuDevice.h"
#include "SkGr.h"
+#include "SkSurface_Gpu.h"
#endif
#include "SkCanvas.h" // TODO: remove
@@ -22,6 +27,17 @@ SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(
: fCharacterization(characterization) {
}
+SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {
+#if SK_SUPPORT_GPU && !defined(SK_RASTER_RECORDER_IMPLEMENTATION)
+ auto proxyProvider = fContext->contextPriv().proxyProvider();
+
+ // DDL TODO: Remove this. DDL contexts should allow for deletion while still having live
+ // uniquely keyed proxies.
+ proxyProvider->removeAllUniqueKeys();
+#endif
+}
+
+
bool SkDeferredDisplayListRecorder::init() {
SkASSERT(!fSurface);
@@ -32,7 +48,11 @@ bool SkDeferredDisplayListRecorder::init() {
fCharacterization.refColorSpace());
fSurface = SkSurface::MakeRaster(ii, &fCharacterization.surfaceProps());
+ return SkToBool(fSurface.get());
#else
+ SkASSERT(!fLazyProxyData);
+
+#if SK_SUPPORT_GPU
if (!fContext) {
fContext = GrContextPriv::MakeDDL(fCharacterization.contextInfo());
if (!fContext) {
@@ -40,21 +60,51 @@ bool SkDeferredDisplayListRecorder::init() {
}
}
- SkColorType colorType = kUnknown_SkColorType;
- if (!GrPixelConfigToColorType(fCharacterization.config(), &colorType)) {
- return false;
- }
+ fLazyProxyData = sk_sp<SkDeferredDisplayList::LazyProxyData>(
+ new SkDeferredDisplayList::LazyProxyData);
- const SkImageInfo ii = SkImageInfo::Make(fCharacterization.width(), fCharacterization.height(),
- colorType, kPremul_SkAlphaType,
- fCharacterization.refColorSpace());
+ auto proxyProvider = fContext->contextPriv().proxyProvider();
- fSurface = SkSurface::MakeRenderTarget(fContext.get(), SkBudgeted::kYes,
- ii, fCharacterization.stencilCount(),
- fCharacterization.origin(),
- &fCharacterization.surfaceProps());
-#endif
+ GrSurfaceDesc desc;
+ desc.fFlags = kRenderTarget_GrSurfaceFlag;
+ desc.fOrigin = fCharacterization.origin();
+ desc.fWidth = fCharacterization.width();
+ desc.fHeight = fCharacterization.height();
+ desc.fConfig = fCharacterization.config();
+ desc.fSampleCnt = fCharacterization.stencilCount();
+
+ sk_sp<SkDeferredDisplayList::LazyProxyData> lazyProxyData = fLazyProxyData;
+
+ // What we're doing here is we're creating a lazy proxy to back the SkSurface. The lazy
+ // proxy, when instantiated, will use the GrTexture that backs the SkSurface that the
+ // DDL is being replayed into.
+
+ sk_sp<GrSurfaceProxy> proxy = proxyProvider->createLazyProxy(
+ [ lazyProxyData ] (GrResourceProvider* resourceProvider, GrSurfaceOrigin* /* outOrigin */) {
+ if (!resourceProvider) {
+ return sk_sp<GrTexture>();
+ }
+
+ // The proxy backing the destination surface had better have been instantiated
+ // prior to the proxy backing the DLL's surface. Steal its GrTexture.
+ // DDL TODO: What do we do in the case where the Surface we're replaying into
+ // isn't texturable?
+ SkASSERT(lazyProxyData->fReplayDest->priv().peekTexture());
+ return sk_ref_sp<GrTexture>(lazyProxyData->fReplayDest->priv().peekTexture());
+ }, desc, GrMipMapped::kNo, SkBackingFit::kExact, SkBudgeted::kYes);
+
+ sk_sp<GrSurfaceContext> c = fContext->contextPriv().makeWrappedSurfaceContext(
+ std::move(proxy),
+ fCharacterization.refColorSpace(),
+ &fCharacterization.surfaceProps());
+ fSurface = SkSurface_Gpu::MakeWrappedRenderTarget(fContext.get(),
+ sk_ref_sp(c->asRenderTargetContext()));
return SkToBool(fSurface.get());
+#else
+ return false;
+#endif
+
+#endif
}
SkCanvas* SkDeferredDisplayListRecorder::getCanvas() {
@@ -68,6 +118,7 @@ SkCanvas* SkDeferredDisplayListRecorder::getCanvas() {
}
std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() {
+#ifdef SK_RASTER_RECORDER_IMPLEMENTATION
sk_sp<SkImage> img = fSurface->makeImageSnapshot();
fSurface.reset();
@@ -75,11 +126,19 @@ std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() {
// in the SkDeferredDisplayList.
return std::unique_ptr<SkDeferredDisplayList>(
new SkDeferredDisplayList(fCharacterization, std::move(img)));
-}
+#else
+
+#if SK_SUPPORT_GPU
+ auto ddl = std::unique_ptr<SkDeferredDisplayList>(
+ new SkDeferredDisplayList(fCharacterization, std::move(fLazyProxyData)));
+
+ fContext->contextPriv().moveOpListsToDDL(ddl.get());
+ return ddl;
+#else
+ return nullptr;
+#endif
+
+#endif // SK_RASTER_RECORDER_IMPLEMENTATION
-// Placeholder. Ultimately, the SkSurface_Gpu will pass the wrapped opLists to its
-// renderTargetContext.
-bool SkDeferredDisplayList::draw(SkSurface* surface) const {
- surface->getCanvas()->drawImage(fImage.get(), 0, 0);
- return true;
}
+
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 0d7705dea3..b427e70beb 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -914,6 +914,15 @@ void GrContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBO
fContext->fDrawingManager->addOnFlushCallbackObject(onFlushCBObject);
}
+void GrContextPriv::moveOpListsToDDL(SkDeferredDisplayList* ddl) {
+ fContext->fDrawingManager->moveOpListsToDDL(ddl);
+}
+
+void GrContextPriv::copyOpListsFromDDL(const SkDeferredDisplayList* ddl,
+ GrRenderTargetProxy* newDest) {
+ fContext->fDrawingManager->copyOpListsFromDDL(ddl, newDest);
+}
+
static inline GrPixelConfig GrPixelConfigFallback(GrPixelConfig config) {
switch (config) {
case kAlpha_8_GrPixelConfig:
diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h
index cf74e70fd6..bd0931cc08 100644
--- a/src/gpu/GrContextPriv.h
+++ b/src/gpu/GrContextPriv.h
@@ -17,6 +17,8 @@ class GrSemaphore;
class GrSurfaceProxy;
class GrTextureContext;
+class SkDeferredDisplayList;
+
/** Class that adds methods to GrContext that are only intended for use internal to Skia.
This class is purely a privileged window into GrContext. It should never have additional
data members or virtual methods. */
@@ -183,6 +185,9 @@ public:
GrAtlasGlyphCache* getAtlasGlyphCache() { return fContext->fAtlasGlyphCache; }
GrTextBlobCache* getTextBlobCache() { return fContext->fTextBlobCache.get(); }
+ void moveOpListsToDDL(SkDeferredDisplayList*);
+ void copyOpListsFromDDL(const SkDeferredDisplayList*, GrRenderTargetProxy* newDest);
+
private:
explicit GrContextPriv(GrContext* context) : fContext(context) {}
GrContextPriv(const GrContextPriv&); // unimpl
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 616ac581e4..3bcff1106b 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -24,6 +24,8 @@
#include "GrTextureOpList.h"
#include "GrTextureProxy.h"
#include "GrTextureProxyPriv.h"
+
+#include "SkDeferredDisplayList.h"
#include "SkSurface_Gpu.h"
#include "SkTTopoSort.h"
@@ -320,6 +322,22 @@ void GrDrawingManager::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlush
fOnFlushCBObjects.push_back(onFlushCBObject);
}
+void GrDrawingManager::moveOpListsToDDL(SkDeferredDisplayList* ddl) {
+#ifndef SK_RASTER_RECORDER_IMPLEMENTATION
+ ddl->fOpLists = std::move(fOpLists);
+#endif
+}
+
+void GrDrawingManager::copyOpListsFromDDL(const SkDeferredDisplayList* ddl,
+ GrRenderTargetProxy* newDest) {
+#ifndef SK_RASTER_RECORDER_IMPLEMENTATION
+ // Here we jam the proxy that backs the current replay SkSurface into the LazyProxyData.
+ // The lazy proxy that references it (in the copied opLists) will steal its GrTexture.
+ ddl->fLazyProxyData->fReplayDest = newDest;
+ fOpLists.push_back_n(ddl->fOpLists.count(), ddl->fOpLists.begin());
+#endif
+}
+
sk_sp<GrRenderTargetOpList> GrDrawingManager::newRTOpList(GrRenderTargetProxy* rtp,
bool managedOpList) {
SkASSERT(fContext);
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index 2b01fc3119..58b755f005 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -79,6 +79,9 @@ public:
void addOnFlushCallbackObject(GrOnFlushCallbackObject*);
void testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject*);
+ void moveOpListsToDDL(SkDeferredDisplayList* ddl);
+ void copyOpListsFromDDL(const SkDeferredDisplayList*, GrRenderTargetProxy* newDest);
+
private:
GrDrawingManager(GrContext* context,
const GrPathRendererChain::Options& optionsForPathRendererChain,
diff --git a/src/gpu/GrGpuResourceRef.cpp b/src/gpu/GrGpuResourceRef.cpp
index b4703830ec..532e0655d8 100644
--- a/src/gpu/GrGpuResourceRef.cpp
+++ b/src/gpu/GrGpuResourceRef.cpp
@@ -125,115 +125,3 @@ void GrGpuResourceRef::removeRef() const {
fResource->unref();
fOwnRef = false;
}
-
-///////////////////////////////////////////////////////////////////////////////
-#include "GrTextureProxy.h"
-
-GrSurfaceProxyRef::GrSurfaceProxyRef() {
- fProxy = nullptr;
- fOwnRef = false;
- fPendingIO = false;
-}
-
-GrSurfaceProxyRef::GrSurfaceProxyRef(sk_sp<GrSurfaceProxy> proxy, GrIOType ioType) {
- fProxy = nullptr;
- fOwnRef = false;
- fPendingIO = false;
- this->setProxy(std::move(proxy), ioType);
-}
-
-GrSurfaceProxyRef::~GrSurfaceProxyRef() {
- this->reset();
-}
-
-void GrSurfaceProxyRef::reset() {
- if (fPendingIO) {
- SkASSERT(fProxy);
- switch (fIOType) {
- case kRead_GrIOType:
- fProxy->completedRead();
- break;
- case kWrite_GrIOType:
- fProxy->completedWrite();
- break;
- case kRW_GrIOType:
- fProxy->completedRead();
- fProxy->completedWrite();
- break;
- }
- fPendingIO = false;
- }
- if (fOwnRef) {
- SkASSERT(fProxy);
- fProxy->unref();
- fOwnRef = false;
- }
-
- fProxy = nullptr;
-}
-
-void GrSurfaceProxyRef::setProxy(sk_sp<GrSurfaceProxy> proxy, GrIOType ioType) {
- SkASSERT(!fPendingIO);
- SkASSERT(SkToBool(fProxy) == fOwnRef);
- SkSafeUnref(fProxy);
- if (!proxy) {
- fProxy = nullptr;
- fOwnRef = false;
- } else {
- fProxy = proxy.release(); // due to the semantics of this class we unpack from sk_sp
- fOwnRef = true;
- fIOType = ioType;
- }
-}
-
-void GrSurfaceProxyRef::markPendingIO() const {
- // This should only be called when the owning GrProgramElement gets its first
- // pendingExecution ref.
- SkASSERT(!fPendingIO);
- SkASSERT(fProxy);
- fPendingIO = true;
- switch (fIOType) {
- case kRead_GrIOType:
- fProxy->addPendingRead();
- break;
- case kWrite_GrIOType:
- fProxy->addPendingWrite();
- break;
- case kRW_GrIOType:
- fProxy->addPendingRead();
- fProxy->addPendingWrite();
- break;
- }
-}
-
-void GrSurfaceProxyRef::pendingIOComplete() const {
- // This should only be called when the owner's pending executions have ocurred but it is still
- // reffed.
- SkASSERT(fOwnRef);
- SkASSERT(fPendingIO);
- switch (fIOType) {
- case kRead_GrIOType:
- fProxy->completedRead();
- break;
- case kWrite_GrIOType:
- fProxy->completedWrite();
- break;
- case kRW_GrIOType:
- fProxy->completedRead();
- fProxy->completedWrite();
- break;
-
- }
- fPendingIO = false;
-}
-
-void GrSurfaceProxyRef::removeRef() const {
- // This should only be called once, when the owners last ref goes away and
- // there is a pending execution.
- SkASSERT(fOwnRef);
- SkASSERT(fPendingIO);
- SkASSERT(fProxy);
- fProxy->unref();
- fOwnRef = false;
-}
-
diff --git a/src/gpu/GrGpuResourceRef.h b/src/gpu/GrGpuResourceRef.h
index f9e122d9e8..410513944f 100644
--- a/src/gpu/GrGpuResourceRef.h
+++ b/src/gpu/GrGpuResourceRef.h
@@ -87,65 +87,6 @@ private:
typedef SkNoncopyable INHERITED;
};
-class GrSurfaceProxy;
-
-class GrSurfaceProxyRef : SkNoncopyable {
-public:
- virtual ~GrSurfaceProxyRef();
-
- GrSurfaceProxy* get() const { return fProxy; }
-
- /** Does this object own a pending read or write on the resource it is wrapping. */
- bool ownsPendingIO() const { return fPendingIO; }
-
- /** What type of IO does this represent? This is independent of whether a normal ref or a
- pending IO is currently held. */
- GrIOType ioType() const { return fIOType; }
-
- /** Shortcut for calling setProxy() with NULL. It cannot be called after markingPendingIO
- is called. */
- void reset();
-
-protected:
- GrSurfaceProxyRef();
-
- /** ioType expresses what type of IO operations will be marked as
- pending on the resource when markPendingIO is called. */
- GrSurfaceProxyRef(sk_sp<GrSurfaceProxy>, GrIOType);
-
- /** ioType expresses what type of IO operations will be marked as
- pending on the resource when markPendingIO is called. */
- void setProxy(sk_sp<GrSurfaceProxy>, GrIOType);
-
-private:
- /** Called by owning GrProgramElement when the program element is first scheduled for
- execution. It can only be called once. */
- void markPendingIO() const;
-
- /** Called when the program element/draw state is no longer owned by GrOpList-client code.
- This lets the cache know that the drawing code will no longer schedule additional reads or
- writes to the resource using the program element or draw state. It can only be called once.
- */
- void removeRef() const;
-
- /** Called to indicate that the previous pending IO is complete. Useful when the owning object
- still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously
- pending executions have been complete. Can only be called if removeRef() was not previously
- called. */
- void pendingIOComplete() const;
-
- friend class GrResourceIOProcessor;
- friend class GrOpList; // for setProxy
-
- GrSurfaceProxy* fProxy;
- mutable bool fOwnRef;
- mutable bool fPendingIO;
- GrIOType fIOType;
-
- typedef SkNoncopyable INHERITED;
-};
-
-
/**
* Templated version of GrGpuResourceRef to enforce type safety.
*/
@@ -233,4 +174,5 @@ private:
T* fResource;
};
+
#endif
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index 9fae1b01ef..c87d4ff262 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -17,6 +17,7 @@
#include "GrSamplerState.h"
#include "GrShaderVar.h"
#include "GrSurfaceProxyPriv.h"
+#include "GrSurfaceProxyRef.h"
#include "GrTextureProxy.h"
#include "SkMath.h"
#include "SkString.h"
diff --git a/src/gpu/GrSurfaceProxyRef.cpp b/src/gpu/GrSurfaceProxyRef.cpp
new file mode 100644
index 0000000000..ad13e4a450
--- /dev/null
+++ b/src/gpu/GrSurfaceProxyRef.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrSurfaceProxyRef.h"
+#include "GrTextureProxy.h"
+
+GrSurfaceProxyRef::GrSurfaceProxyRef() {
+ fProxy = nullptr;
+ fOwnRef = false;
+ fPendingIO = false;
+}
+
+GrSurfaceProxyRef::GrSurfaceProxyRef(sk_sp<GrSurfaceProxy> proxy, GrIOType ioType) {
+ fProxy = nullptr;
+ fOwnRef = false;
+ fPendingIO = false;
+ this->setProxy(std::move(proxy), ioType);
+}
+
+GrSurfaceProxyRef::~GrSurfaceProxyRef() {
+ this->reset();
+}
+
+void GrSurfaceProxyRef::reset() {
+ if (fPendingIO) {
+ SkASSERT(fProxy);
+ switch (fIOType) {
+ case kRead_GrIOType:
+ fProxy->completedRead();
+ break;
+ case kWrite_GrIOType:
+ fProxy->completedWrite();
+ break;
+ case kRW_GrIOType:
+ fProxy->completedRead();
+ fProxy->completedWrite();
+ break;
+ }
+ fPendingIO = false;
+ }
+ if (fOwnRef) {
+ SkASSERT(fProxy);
+ fProxy->unref();
+ fOwnRef = false;
+ }
+
+ fProxy = nullptr;
+}
+
+void GrSurfaceProxyRef::setProxy(sk_sp<GrSurfaceProxy> proxy, GrIOType ioType) {
+ SkASSERT(!fPendingIO);
+ SkASSERT(SkToBool(fProxy) == fOwnRef);
+ SkSafeUnref(fProxy);
+ if (!proxy) {
+ fProxy = nullptr;
+ fOwnRef = false;
+ } else {
+ fProxy = proxy.release(); // due to the semantics of this class we unpack from sk_sp
+ fOwnRef = true;
+ fIOType = ioType;
+ }
+}
+
+void GrSurfaceProxyRef::markPendingIO() const {
+ // This should only be called when the owning GrProgramElement gets its first
+ // pendingExecution ref.
+ SkASSERT(!fPendingIO);
+ SkASSERT(fProxy);
+ fPendingIO = true;
+ switch (fIOType) {
+ case kRead_GrIOType:
+ fProxy->addPendingRead();
+ break;
+ case kWrite_GrIOType:
+ fProxy->addPendingWrite();
+ break;
+ case kRW_GrIOType:
+ fProxy->addPendingRead();
+ fProxy->addPendingWrite();
+ break;
+ }
+}
+
+void GrSurfaceProxyRef::pendingIOComplete() const {
+ // This should only be called when the owner's pending executions have ocurred but it is still
+ // reffed.
+ SkASSERT(fOwnRef);
+ SkASSERT(fPendingIO);
+ switch (fIOType) {
+ case kRead_GrIOType:
+ fProxy->completedRead();
+ break;
+ case kWrite_GrIOType:
+ fProxy->completedWrite();
+ break;
+ case kRW_GrIOType:
+ fProxy->completedRead();
+ fProxy->completedWrite();
+ break;
+
+ }
+ fPendingIO = false;
+}
+
+void GrSurfaceProxyRef::removeRef() const {
+ // This should only be called once, when the owners last ref goes away and
+ // there is a pending execution.
+ SkASSERT(fOwnRef);
+ SkASSERT(fPendingIO);
+ SkASSERT(fProxy);
+ fProxy->unref();
+ fOwnRef = false;
+}
+
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index ab2a64f707..9f7ec3b7f5 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -200,9 +200,17 @@ bool SkSurface_Gpu::onDraw(const SkDeferredDisplayList* ddl) {
return false;
}
+#ifdef SK_RASTER_RECORDER_IMPLEMENTATION
// Ultimately need to pass opLists from the DeferredDisplayList on to the
// SkGpuDevice's renderTargetContext.
return ddl->draw(this);
+#else
+ GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
+ GrContext* ctx = fDevice->context();
+
+ ctx->contextPriv().copyOpListsFromDDL(ddl, rtc->asRenderTargetProxy());
+ return true;
+#endif
}