Revert "Remove deferred proxy machinery"
This reverts commit a3987cc5873c9bce758fa3843bb801c95d282bbd.
Reason for revert: Keeping it
Original change's description:
> Remove deferred proxy machinery
>
> These aren't used any more in favor of lazy proxies.
>
> Bug: skia:11288
> Change-Id: I992e1a3dd343e0ebc7f3a4f18c0054453dfebbaf
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/366896
> Commit-Queue: Adlai Holler <adlai@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>
TBR=bsalomon@google.com,robertphillips@google.com,adlai@google.com
Bug: skia:11288
Change-Id: Iafa9ed18a772e451349dfad61ee462df963028be
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/368376
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Adlai Holler <adlai@google.com>
Commit-Queue: Adlai Holler <adlai@google.com>
diff --git a/src/gpu/GrBackendTextureImageGenerator.cpp b/src/gpu/GrBackendTextureImageGenerator.cpp
index ab7d2ba..4e08ecc 100644
--- a/src/gpu/GrBackendTextureImageGenerator.cpp
+++ b/src/gpu/GrBackendTextureImageGenerator.cpp
@@ -19,6 +19,7 @@
#include "src/gpu/GrSemaphore.h"
#include "src/gpu/GrSurfaceDrawContext.h"
#include "src/gpu/GrTexture.h"
+#include "src/gpu/GrTextureProxyPriv.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/gl/GrGLTexture.h"
diff --git a/src/gpu/GrClipStack.cpp b/src/gpu/GrClipStack.cpp
index 8ba5a8b..8664fa8 100644
--- a/src/gpu/GrClipStack.cpp
+++ b/src/gpu/GrClipStack.cpp
@@ -12,6 +12,7 @@
#include "src/core/SkRectPriv.h"
#include "src/core/SkTaskGroup.h"
#include "src/gpu/GrClip.h"
+#include "src/gpu/GrDeferredProxyUploader.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp
index 0a6b39e..54b29c3 100644
--- a/src/gpu/GrClipStackClip.cpp
+++ b/src/gpu/GrClipStackClip.cpp
@@ -14,6 +14,7 @@
#include "src/core/SkTraceEvent.h"
#include "src/gpu/GrAppliedClip.h"
#include "src/gpu/GrAttachment.h"
+#include "src/gpu/GrDeferredProxyUploader.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrDrawingManager.h"
#include "src/gpu/GrGpuResourcePriv.h"
diff --git a/src/gpu/GrDeferredProxyUploader.h b/src/gpu/GrDeferredProxyUploader.h
new file mode 100644
index 0000000..33e62a5
--- /dev/null
+++ b/src/gpu/GrDeferredProxyUploader.h
@@ -0,0 +1,120 @@
+/*
+ * 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 GrDeferredProxyUploader_DEFINED
+#define GrDeferredProxyUploader_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "include/private/SkSemaphore.h"
+#include "src/core/SkAutoPixmapStorage.h"
+
+#include "src/gpu/GrOpFlushState.h"
+#include "src/gpu/GrTextureProxyPriv.h"
+
+/**
+ * GrDeferredProxyUploader assists with threaded generation of textures. Currently used by both
+ * software clip masks, and the software path renderer. The calling code typically needs to store
+ * some additional data (T) for use on the worker thread. GrTDeferredProxyUploader allows storing
+ * such data. The common flow is:
+ *
+ * 1) A GrTDeferredProxyUploader is created, with some payload (eg an SkPath to draw).
+ * The uploader is owned by the proxy that it's going to populate.
+ * 2) A task is created with a pointer to the uploader. A worker thread executes that task, using
+ * the payload data to allocate and fill in the fPixels pixmap.
+ * 3) The worker thread calls signalAndFreeData(), which notifies the main thread that the pixmap
+ * is ready, and then deletes the payload data (which is no longer needed).
+ * 4) In parallel to 2-3, on the main thread... Some op is created that refers to the proxy. When
+ * that op is added to an op list, the op list retains a pointer to the "deferred" proxies.
+ * 5) At flush time, the op list ensures that the deferred proxies are instantiated, then calls
+ * scheduleUpload on those proxies, which calls scheduleUpload on the uploader (below).
+ * 6) scheduleUpload defers the upload even further, by adding an ASAPUpload to the flush.
+ * 7) When the ASAP upload happens, we wait to make sure that the pixels are marked ready
+ * (from step #3 on the worker thread). Then we perform the actual upload to the texture.
+ * Finally, we call resetDeferredUploader, which deletes the uploader object, causing fPixels
+ * to be freed.
+ */
+class GrDeferredProxyUploader : public SkNoncopyable {
+public:
+ GrDeferredProxyUploader() : fScheduledUpload(false), fWaited(false) {}
+
+ virtual ~GrDeferredProxyUploader() {
+ // In normal usage (i.e., through GrTDeferredProxyUploader) this will be redundant
+ this->wait();
+ }
+
+ void scheduleUpload(GrOpFlushState* flushState, GrTextureProxy* proxy) {
+ if (fScheduledUpload) {
+ // Multiple references to the owning proxy may have caused us to already execute
+ return;
+ }
+
+ auto uploadMask = [this, proxy](GrDeferredTextureUploadWritePixelsFn& writePixelsFn) {
+ this->wait();
+ GrColorType pixelColorType = SkColorTypeToGrColorType(this->fPixels.info().colorType());
+ // If the worker thread was unable to allocate pixels, this check will fail, and we'll
+ // end up drawing with an uninitialized mask texture, but at least we won't crash.
+ if (this->fPixels.addr()) {
+ writePixelsFn(proxy, 0, 0, this->fPixels.width(), this->fPixels.height(),
+ pixelColorType, this->fPixels.addr(), this->fPixels.rowBytes());
+ }
+ // Upload has finished, so tell the proxy to release this GrDeferredProxyUploader
+ proxy->texPriv().resetDeferredUploader();
+ };
+ flushState->addASAPUpload(std::move(uploadMask));
+ fScheduledUpload = true;
+ }
+
+ void signalAndFreeData() {
+ this->freeData();
+ fPixelsReady.signal();
+ }
+
+ SkAutoPixmapStorage* getPixels() { return &fPixels; }
+
+protected:
+ void wait() {
+ if (!fWaited) {
+ fPixelsReady.wait();
+ fWaited = true;
+ }
+ }
+
+private:
+ virtual void freeData() {}
+
+ SkAutoPixmapStorage fPixels;
+ SkSemaphore fPixelsReady;
+ bool fScheduledUpload;
+ bool fWaited;
+};
+
+template <typename T>
+class GrTDeferredProxyUploader : public GrDeferredProxyUploader {
+public:
+ template <typename... Args>
+ GrTDeferredProxyUploader(Args&&... args)
+ : fData(std::make_unique<T>(std::forward<Args>(args)...)) {
+ }
+
+ ~GrTDeferredProxyUploader() override {
+ // We need to wait here, so that we don't free fData before the worker thread is done
+ // with it. (This happens if the proxy is deleted early due to a full clear or failure
+ // of an op list to instantiate).
+ this->wait();
+ }
+
+ T& data() { return *fData; }
+
+private:
+ void freeData() override {
+ fData.reset();
+ }
+
+ std::unique_ptr<T> fData;
+};
+
+#endif
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 71125b1..9b44856 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -37,6 +37,7 @@
#include "src/gpu/GrTTopoSort.h"
#include "src/gpu/GrTexture.h"
#include "src/gpu/GrTextureProxy.h"
+#include "src/gpu/GrTextureProxyPriv.h"
#include "src/gpu/GrTextureResolveRenderTask.h"
#include "src/gpu/GrTracing.h"
#include "src/gpu/GrTransferFromRenderTask.h"
@@ -170,9 +171,10 @@
onFlushRenderTask->makeClosed(*fContext->priv().caps());
#ifdef SK_DEBUG
// OnFlush callbacks are invoked during flush, and are therefore expected to handle
- // resource allocation & usage on their own. (No lazy proxies!)
+ // resource allocation & usage on their own. (No deferred or lazy proxies!)
onFlushRenderTask->visitTargetAndSrcProxies_debugOnly(
[](GrSurfaceProxy* p, GrMipmapped mipMapped) {
+ SkASSERT(!p->asTextureProxy() || !p->asTextureProxy()->texPriv().isDeferred());
SkASSERT(!p->isLazy());
if (p->requiresManualMSAAResolve()) {
// The onFlush callback is responsible for ensuring MSAA gets resolved.
@@ -316,6 +318,8 @@
continue;
}
+ SkASSERT(renderTask->deferredProxiesAreInstantiated());
+
renderTask->prepare(flushState);
}
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 22012d0..43df47f 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -31,6 +31,7 @@
#include "src/gpu/GrSemaphore.h"
#include "src/gpu/GrStagingBufferManager.h"
#include "src/gpu/GrStencilSettings.h"
+#include "src/gpu/GrTextureProxyPriv.h"
#include "src/gpu/GrTracing.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/utils/SkJSONWriter.h"
diff --git a/src/gpu/GrOpsRenderPass.h b/src/gpu/GrOpsRenderPass.h
index 99fb87c..25da976 100644
--- a/src/gpu/GrOpsRenderPass.h
+++ b/src/gpu/GrOpsRenderPass.h
@@ -9,7 +9,6 @@
#define GrOpsRenderPass_DEFINED
#include "include/core/SkDrawable.h"
-#include "src/gpu/GrDeferredUpload.h"
#include "src/gpu/GrPipeline.h"
#include "src/gpu/ops/GrDrawOp.h"
diff --git a/src/gpu/GrOpsTask.cpp b/src/gpu/GrOpsTask.cpp
index 8eb03cc..e9add24 100644
--- a/src/gpu/GrOpsTask.cpp
+++ b/src/gpu/GrOpsTask.cpp
@@ -432,6 +432,7 @@
this->deleteOps();
fClipAllocators.reset();
+ fDeferredProxies.reset();
fSampledProxies.reset();
fAuditTrail = nullptr;
@@ -674,6 +675,7 @@
}
void GrOpsTask::reset() {
+ fDeferredProxies.reset();
fSampledProxies.reset();
fClipAllocators.reset();
fClippedContentBounds = SkIRect::MakeEmpty();
@@ -722,9 +724,11 @@
fColorLoadOp = GrLoadOp::kClear;
fLoadClearColor = opsTasks.front()->fLoadClearColor;
}
+ int addlDeferredProxyCount = 0;
int addlProxyCount = 0;
int addlOpChainCount = 0;
for (const auto& opsTask : opsTasks) {
+ addlDeferredProxyCount += opsTask->fDeferredProxies.count();
addlProxyCount += opsTask->fSampledProxies.count();
addlOpChainCount += opsTask->fOpChains.count();
fClippedContentBounds.join(opsTask->fClippedContentBounds);
@@ -734,10 +738,13 @@
}
fLastClipStackGenID = SK_InvalidUniqueID;
+ fDeferredProxies.reserve_back(addlDeferredProxyCount);
fSampledProxies.reserve_back(addlProxyCount);
fOpChains.reserve_back(addlOpChainCount);
fClipAllocators.reserve_back(opsTasks.count());
for (const auto& opsTask : opsTasks) {
+ fDeferredProxies.move_back_n(opsTask->fDeferredProxies.count(),
+ opsTask->fDeferredProxies.data());
fSampledProxies.move_back_n(opsTask->fSampledProxies.count(),
opsTask->fSampledProxies.data());
fOpChains.move_back_n(opsTask->fOpChains.count(),
@@ -745,6 +752,7 @@
SkASSERT(1 == opsTask->fClipAllocators.count());
fClipAllocators.push_back(std::move(opsTask->fClipAllocators[0]));
opsTask->fClipAllocators.reset();
+ opsTask->fDeferredProxies.reset();
opsTask->fSampledProxies.reset();
opsTask->fOpChains.reset();
}
@@ -755,6 +763,7 @@
bool GrOpsTask::resetForFullscreenClear(CanDiscardPreviousOps canDiscardPreviousOps) {
if (CanDiscardPreviousOps::kYes == canDiscardPreviousOps || this->isEmpty()) {
this->deleteOps();
+ fDeferredProxies.reset();
fSampledProxies.reset();
// If the opsTask is using a render target which wraps a vulkan command buffer, we can't do
@@ -892,6 +901,16 @@
}
void GrOpsTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
+ for (int i = 0; i < fDeferredProxies.count(); ++i) {
+ SkASSERT(!fDeferredProxies[i]->isInstantiated());
+ // We give all the deferred proxies a write usage at the very start of flushing. This
+ // locks them out of being reused for the entire flush until they are read - and then
+ // they can be recycled. This is a bit unfortunate because a flush can proceed in waves
+ // with sub-flushes. The deferred proxies only need to be pinned from the start of
+ // the sub-flush in which they appear.
+ alloc->addInterval(fDeferredProxies[i], 0, 0, GrResourceAllocator::ActualUse::kNo);
+ }
+
GrSurfaceProxy* targetProxy = this->target(0);
// Add the interval for all the writes to this GrOpsTasks's target
diff --git a/src/gpu/GrRenderTask.cpp b/src/gpu/GrRenderTask.cpp
index f939455..074f4a9 100644
--- a/src/gpu/GrRenderTask.cpp
+++ b/src/gpu/GrRenderTask.cpp
@@ -9,6 +9,7 @@
#include "src/gpu/GrAttachment.h"
#include "src/gpu/GrRenderTarget.h"
+#include "src/gpu/GrTextureProxyPriv.h"
#include "src/gpu/GrTextureResolveRenderTask.h"
uint32_t GrRenderTask::CreateUniqueID() {
@@ -46,6 +47,15 @@
SkASSERT(this->isSetFlag(kDisowned_Flag));
}
+bool GrRenderTask::deferredProxiesAreInstantiated() const {
+ for (int i = 0; i < fDeferredProxies.count(); ++i) {
+ if (!fDeferredProxies[i]->isInstantiated()) {
+ return false;
+ }
+ }
+
+ return true;
+}
#endif
void GrRenderTask::makeClosed(const GrCaps& caps) {
@@ -75,6 +85,14 @@
this->setFlag(kClosed_Flag);
}
+void GrRenderTask::prepare(GrOpFlushState* flushState) {
+ for (int i = 0; i < fDeferredProxies.count(); ++i) {
+ fDeferredProxies[i]->texPriv().scheduleUpload(flushState);
+ }
+
+ this->onPrepare(flushState);
+}
+
// Add a GrRenderTask-based dependency
void GrRenderTask::addDependency(GrRenderTask* dependedOn) {
SkASSERT(!dependedOn->dependsOn(this)); // loops are bad
@@ -113,6 +131,8 @@
SkASSERT(GrMipmapped::kNo == mipMapped);
// We should never attempt a self-read on a surface that has a separate MSAA renderbuffer.
SkASSERT(!dependedOn->requiresManualMSAAResolve());
+ SkASSERT(!dependedOn->asTextureProxy() ||
+ !dependedOn->asTextureProxy()->texPriv().isDeferred());
return;
}
@@ -166,6 +186,9 @@
if (dependedOnTask) {
SkASSERT(fTextureResolveTask->dependsOn(dependedOnTask));
}
+ if (textureProxy && textureProxy->texPriv().isDeferred()) {
+ SkASSERT(fTextureResolveTask->fDeferredProxies.back() == textureProxy);
+ }
// The GrTextureResolveRenderTask factory should have also marked the proxy clean, set the
// last renderTask on the textureProxy to textureResolveTask, and closed textureResolveTask.
@@ -180,6 +203,10 @@
return;
}
+ if (textureProxy && textureProxy->texPriv().isDeferred()) {
+ fDeferredProxies.push_back(textureProxy);
+ }
+
if (dependedOnTask) {
this->addDependency(dependedOnTask);
}
diff --git a/src/gpu/GrRenderTask.h b/src/gpu/GrRenderTask.h
index 0df5d9f..218267f 100644
--- a/src/gpu/GrRenderTask.h
+++ b/src/gpu/GrRenderTask.h
@@ -35,7 +35,7 @@
void prePrepare(GrRecordingContext* context) { this->onPrePrepare(context); }
// These two methods are only invoked at flush time
- void prepare(GrOpFlushState* flushState) { this->onPrepare(flushState); }
+ void prepare(GrOpFlushState* flushState);
bool execute(GrOpFlushState* flushState) { return this->onExecute(flushState); }
virtual bool requiresExplicitCleanup() const { return false; }
@@ -133,6 +133,8 @@
SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrRenderTask);
protected:
+ SkDEBUGCODE(bool deferredProxiesAreInstantiated() const;)
+
// Add a target surface proxy to the list of targets for this task.
// This also informs the drawing manager to update the lastRenderTask association.
void addTarget(GrDrawingManager*, sk_sp<GrSurfaceProxy>);
@@ -156,6 +158,11 @@
SkSTArray<1, sk_sp<GrSurfaceProxy>> fTargets;
+ // List of texture proxies whose contents are being prepared on a worker thread
+ // TODO: this list exists so we can fire off the proper upload when an renderTask begins
+ // executing. Can this be replaced?
+ SkTArray<GrTextureProxy*, true> fDeferredProxies;
+
enum Flags {
kClosed_Flag = 0x01, //!< This task can't accept any more dependencies.
kDisowned_Flag = 0x02, //!< This task is disowned by its creating GrDrawingManager.
diff --git a/src/gpu/GrResourceAllocator.cpp b/src/gpu/GrResourceAllocator.cpp
index d7e6851..2a1d44d 100644
--- a/src/gpu/GrResourceAllocator.cpp
+++ b/src/gpu/GrResourceAllocator.cpp
@@ -94,7 +94,12 @@
if (Interval* intvl = fIntvlHash.find(proxy->uniqueID().asUInt())) {
// Revise the interval for an existing use
#ifdef SK_DEBUG
- if (isDirectDstRead) {
+ if (0 == start && 0 == end) {
+ // This interval is for the initial upload to a deferred proxy. Due to the vagaries
+ // of how deferred proxies are collected they can appear as uploads multiple times
+ // in a single opsTasks' list and as uploads in several opsTasks.
+ SkASSERT(0 == intvl->start());
+ } else if (isDirectDstRead) {
// Direct reads from the render target itself should occur w/in the existing
// interval
SkASSERT(intvl->start() <= start && intvl->end() >= end);
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index d3138f1..0f43d27 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -14,6 +14,7 @@
#include "src/gpu/GrAuditTrail.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrClip.h"
+#include "src/gpu/GrDeferredProxyUploader.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrGpuResourcePriv.h"
#include "src/gpu/GrOpFlushState.h"
diff --git a/src/gpu/GrTextureProxy.cpp b/src/gpu/GrTextureProxy.cpp
index 4884d45..d7be2fe 100644
--- a/src/gpu/GrTextureProxy.cpp
+++ b/src/gpu/GrTextureProxy.cpp
@@ -6,12 +6,13 @@
*/
#include "src/gpu/GrTextureProxy.h"
+#include "src/gpu/GrTextureProxyPriv.h"
#include "include/gpu/GrDirectContext.h"
+#include "src/gpu/GrDeferredProxyUploader.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrSurface.h"
-#include "src/gpu/GrSurfaceProxyPriv.h"
#include "src/gpu/GrTexture.h"
// Deferred version - no data
@@ -30,7 +31,8 @@
, fMipmapStatus(mipmapStatus)
SkDEBUGCODE(, fInitialMipmapStatus(fMipmapStatus))
, fCreatingProvider(creatingProvider)
- , fProxyProvider(nullptr) {
+ , fProxyProvider(nullptr)
+ , fDeferredUploader(nullptr) {
SkASSERT(!(fSurfaceFlags & GrInternalSurfaceFlags::kFramebufferOnly));
if (this->textureType() == GrTextureType::kExternal) {
fSurfaceFlags |= GrInternalSurfaceFlags::kReadOnly;
@@ -55,7 +57,8 @@
, fMipmapStatus(mipmapStatus)
SkDEBUGCODE(, fInitialMipmapStatus(fMipmapStatus))
, fCreatingProvider(creatingProvider)
- , fProxyProvider(nullptr) {
+ , fProxyProvider(nullptr)
+ , fDeferredUploader(nullptr) {
SkASSERT(!(fSurfaceFlags & GrInternalSurfaceFlags::kFramebufferOnly));
if (this->textureType() == GrTextureType::kExternal) {
fSurfaceFlags |= GrInternalSurfaceFlags::kReadOnly;
@@ -71,7 +74,8 @@
, fMipmapStatus(fTarget->asTexture()->mipmapStatus())
SkDEBUGCODE(, fInitialMipmapStatus(fMipmapStatus))
, fCreatingProvider(creatingProvider)
- , fProxyProvider(nullptr) {
+ , fProxyProvider(nullptr)
+ , fDeferredUploader(nullptr) {
if (fTarget->getUniqueKey().isValid()) {
fProxyProvider = fTarget->asTexture()->getContext()->priv().proxyProvider();
fProxyProvider->adoptUniqueKeyFromSurface(this, fTarget.get());
@@ -123,6 +127,23 @@
return surface;
}
+void GrTextureProxyPriv::setDeferredUploader(std::unique_ptr<GrDeferredProxyUploader> uploader) {
+ SkASSERT(!fTextureProxy->fDeferredUploader);
+ fTextureProxy->fDeferredUploader = std::move(uploader);
+}
+
+void GrTextureProxyPriv::scheduleUpload(GrOpFlushState* flushState) {
+ // The texture proxy's contents may already have been uploaded or instantiation may have failed
+ if (fTextureProxy->fDeferredUploader && fTextureProxy->isInstantiated()) {
+ fTextureProxy->fDeferredUploader->scheduleUpload(flushState, fTextureProxy);
+ }
+}
+
+void GrTextureProxyPriv::resetDeferredUploader() {
+ SkASSERT(fTextureProxy->fDeferredUploader);
+ fTextureProxy->fDeferredUploader.reset();
+}
+
GrMipmapped GrTextureProxy::mipmapped() const {
if (this->isInstantiated()) {
return this->peekTexture()->mipmapped();
diff --git a/src/gpu/GrTextureProxy.h b/src/gpu/GrTextureProxy.h
index cf8cbe5..3839e52 100644
--- a/src/gpu/GrTextureProxy.h
+++ b/src/gpu/GrTextureProxy.h
@@ -12,8 +12,10 @@
#include "src/gpu/GrSurfaceProxy.h"
class GrCaps;
+class GrDeferredProxyUploader;
class GrProxyProvider;
class GrResourceProvider;
+class GrTextureProxyPriv;
// This class delays the acquisition of textures until they are actually required
class GrTextureProxy : virtual public GrSurfaceProxy {
@@ -92,12 +94,17 @@
inline CacheAccess cacheAccess();
inline const CacheAccess cacheAccess() const; // NOLINT(readability-const-return-type)
+ // Provides access to special purpose functions.
+ GrTextureProxyPriv texPriv();
+ const GrTextureProxyPriv texPriv() const; // NOLINT(readability-const-return-type)
+
SkDEBUGCODE(GrDDLProvider creatingProvider() const { return fCreatingProvider; })
protected:
// DDL TODO: rm the GrSurfaceProxy friending
friend class GrSurfaceProxy; // for ctors
friend class GrProxyProvider; // for ctors
+ friend class GrTextureProxyPriv;
friend class GrSurfaceProxyPriv; // ability to change key sync state after lazy instantiation.
// Deferred version - no data.
@@ -182,6 +189,11 @@
LazySurfaceDesc callbackDesc() const override;
+ // Only used for proxies whose contents are being prepared on a worker thread. This object
+ // stores the texture data, allowing the proxy to remain uninstantiated until flush. At that
+ // point, the proxy is instantiated, and this data is used to perform an ASAP upload.
+ std::unique_ptr<GrDeferredProxyUploader> fDeferredUploader;
+
size_t onUninstantiatedGpuMemorySize() const override;
// Methods made available via GrTextureProxy::CacheAccess
diff --git a/src/gpu/GrTextureProxyPriv.h b/src/gpu/GrTextureProxyPriv.h
new file mode 100644
index 0000000..cb99688
--- /dev/null
+++ b/src/gpu/GrTextureProxyPriv.h
@@ -0,0 +1,51 @@
+/*
+ * 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 GrTextureProxyPriv_DEFINED
+#define GrTextureProxyPriv_DEFINED
+
+#include "src/gpu/GrTextureProxy.h"
+
+class GrDeferredProxyUploader;
+class GrOpFlushState;
+
+/**
+ * This class hides the more specialized capabilities of GrTextureProxy.
+ */
+class GrTextureProxyPriv {
+public:
+ // Attach a deferred uploader to the proxy. Holds data being prepared by a worker thread.
+ void setDeferredUploader(std::unique_ptr<GrDeferredProxyUploader>);
+ bool isDeferred() const { return SkToBool(fTextureProxy->fDeferredUploader.get()); }
+ // For a deferred proxy (one that has a deferred uploader attached), this schedules an ASAP
+ // upload of that data to the instantiated texture.
+ void scheduleUpload(GrOpFlushState*);
+ // Clears any deferred uploader object on the proxy. Used to free the CPU data after the
+ // contents have been uploaded.
+ void resetDeferredUploader();
+
+private:
+ explicit GrTextureProxyPriv(GrTextureProxy* textureProxy) : fTextureProxy(textureProxy) {}
+ GrTextureProxyPriv(const GrTextureProxyPriv&) = delete;
+ GrTextureProxyPriv& operator=(const GrTextureProxyPriv&) = delete;
+
+ // No taking addresses of this type.
+ const GrTextureProxyPriv* operator&() const;
+ GrTextureProxyPriv* operator&();
+
+ GrTextureProxy* fTextureProxy;
+
+ friend class GrTextureProxy; // to construct/copy this type.
+};
+
+inline GrTextureProxyPriv GrTextureProxy::texPriv() { return GrTextureProxyPriv(this); }
+
+inline const GrTextureProxyPriv GrTextureProxy::texPriv() const { // NOLINT(readability-const-return-type)
+ return GrTextureProxyPriv(const_cast<GrTextureProxy*>(this));
+}
+
+#endif
diff --git a/src/gpu/GrTextureRenderTargetProxy.cpp b/src/gpu/GrTextureRenderTargetProxy.cpp
index 7145e7f..8cf8266 100644
--- a/src/gpu/GrTextureRenderTargetProxy.cpp
+++ b/src/gpu/GrTextureRenderTargetProxy.cpp
@@ -12,6 +12,7 @@
#include "src/gpu/GrSurface.h"
#include "src/gpu/GrSurfaceProxyPriv.h"
#include "src/gpu/GrTexture.h"
+#include "src/gpu/GrTextureProxyPriv.h"
#ifdef SK_DEBUG
#include "include/gpu/GrDirectContext.h"
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 55c0b9a..ceef385 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -16,6 +16,7 @@
#include "src/gpu/GrProgramDesc.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrSurfaceProxyPriv.h"
+#include "src/gpu/GrTextureProxyPriv.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/gl/GrGLContext.h"
#include "src/gpu/gl/GrGLRenderTarget.h"
diff --git a/src/gpu/ops/GrDrawOp.h b/src/gpu/ops/GrDrawOp.h
index 33fb95c..f023eb3 100644
--- a/src/gpu/ops/GrDrawOp.h
+++ b/src/gpu/ops/GrDrawOp.h
@@ -9,6 +9,7 @@
#define GrDrawOp_DEFINED
#include <functional>
+#include "src/gpu/GrDeferredUpload.h"
#include "src/gpu/GrPipeline.h"
#include "src/gpu/ops/GrOp.h"