Revert "Revert "Revert "Revert "Make threaded proxy generation MDB-friendly, and defer instantiation""""
This reverts commit 9f8d4d36b5
.
Bug: skia:
Change-Id: I8d7c1df24d8b13b94404f3d9ba69a1ab55ee00c0
Reviewed-on: https://skia-review.googlesource.com/52920
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
5fdee443e7
commit
fdd2cb52b7
@ -72,6 +72,7 @@ skia_gpu_sources = [
|
|||||||
"$_src/gpu/GrCoordTransform.h",
|
"$_src/gpu/GrCoordTransform.h",
|
||||||
"$_src/gpu/GrDefaultGeoProcFactory.cpp",
|
"$_src/gpu/GrDefaultGeoProcFactory.cpp",
|
||||||
"$_src/gpu/GrDefaultGeoProcFactory.h",
|
"$_src/gpu/GrDefaultGeoProcFactory.h",
|
||||||
|
"$_src/gpu/GrDeferredProxyUploader.h",
|
||||||
"$_src/gpu/GrDistanceFieldGenFromVector.cpp",
|
"$_src/gpu/GrDistanceFieldGenFromVector.cpp",
|
||||||
"$_src/gpu/GrDistanceFieldGenFromVector.h",
|
"$_src/gpu/GrDistanceFieldGenFromVector.h",
|
||||||
"$_src/gpu/GrDrawingManager.cpp",
|
"$_src/gpu/GrDrawingManager.cpp",
|
||||||
@ -127,7 +128,6 @@ skia_gpu_sources = [
|
|||||||
"$_src/gpu/GrOnFlushResourceProvider.h",
|
"$_src/gpu/GrOnFlushResourceProvider.h",
|
||||||
"$_src/gpu/GrPipeline.cpp",
|
"$_src/gpu/GrPipeline.cpp",
|
||||||
"$_src/gpu/GrPipeline.h",
|
"$_src/gpu/GrPipeline.h",
|
||||||
"$_src/gpu/GrPrepareCallback.h",
|
|
||||||
"$_src/gpu/GrPrimitiveProcessor.cpp",
|
"$_src/gpu/GrPrimitiveProcessor.cpp",
|
||||||
"$_src/gpu/GrPrimitiveProcessor.h",
|
"$_src/gpu/GrPrimitiveProcessor.h",
|
||||||
"$_src/gpu/GrProcessorSet.cpp",
|
"$_src/gpu/GrProcessorSet.cpp",
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "GrSurfaceProxy.h"
|
#include "GrSurfaceProxy.h"
|
||||||
|
|
||||||
class GrCaps;
|
class GrCaps;
|
||||||
|
class GrDeferredProxyUploader;
|
||||||
class GrResourceCache;
|
class GrResourceCache;
|
||||||
class GrResourceProvider;
|
class GrResourceProvider;
|
||||||
class GrTextureOpList;
|
class GrTextureOpList;
|
||||||
@ -69,6 +70,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class GrSurfaceProxy; // for ctors
|
friend class GrSurfaceProxy; // for ctors
|
||||||
|
friend class GrTextureProxyPriv;
|
||||||
|
|
||||||
// Deferred version
|
// Deferred version
|
||||||
GrTextureProxy(const GrSurfaceDesc& srcDesc, SkBackingFit, SkBudgeted,
|
GrTextureProxy(const GrSurfaceDesc& srcDesc, SkBackingFit, SkBudgeted,
|
||||||
@ -89,6 +91,11 @@ private:
|
|||||||
GrUniqueKey fUniqueKey;
|
GrUniqueKey fUniqueKey;
|
||||||
GrResourceCache* fCache; // only set when fUniqueKey is valid
|
GrResourceCache* fCache; // only set when fUniqueKey is valid
|
||||||
|
|
||||||
|
// 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;
|
size_t onUninstantiatedGpuMemorySize() const override;
|
||||||
|
|
||||||
// Methods made available via GrTextureProxy::CacheAccess
|
// Methods made available via GrTextureProxy::CacheAccess
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
|
|
||||||
#include "GrAppliedClip.h"
|
#include "GrAppliedClip.h"
|
||||||
#include "GrContextPriv.h"
|
#include "GrContextPriv.h"
|
||||||
|
#include "GrDeferredProxyUploader.h"
|
||||||
#include "GrDrawingManager.h"
|
#include "GrDrawingManager.h"
|
||||||
#include "GrRenderTargetContextPriv.h"
|
#include "GrRenderTargetContextPriv.h"
|
||||||
#include "GrFixedClip.h"
|
#include "GrFixedClip.h"
|
||||||
#include "GrGpuResourcePriv.h"
|
#include "GrGpuResourcePriv.h"
|
||||||
#include "GrPrepareCallback.h"
|
|
||||||
#include "GrResourceProvider.h"
|
#include "GrResourceProvider.h"
|
||||||
#include "GrStencilAttachment.h"
|
#include "GrStencilAttachment.h"
|
||||||
#include "GrSWMaskHelper.h"
|
#include "GrSWMaskHelper.h"
|
||||||
@ -428,7 +428,7 @@ sk_sp<GrTextureProxy> GrClipStackClip::createAlphaClipMask(GrContext* context,
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Payload class for use with GrMaskUploaderPrepareCallback. The clip mask code renders multiple
|
* Payload class for use with GrTDeferredProxyUploader. The clip mask code renders multiple
|
||||||
* elements, each storing their own AA setting (and already transformed into device space). This
|
* elements, each storing their own AA setting (and already transformed into device space). This
|
||||||
* stores all of the information needed by the worker thread to draw all clip elements (see below,
|
* stores all of the information needed by the worker thread to draw all clip elements (see below,
|
||||||
* in createSoftwareClipMask).
|
* in createSoftwareClipMask).
|
||||||
@ -526,15 +526,8 @@ sk_sp<GrTextureProxy> GrClipStackClip::createSoftwareClipMask(
|
|||||||
proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(), desc,
|
proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(), desc,
|
||||||
SkBackingFit::kApprox, SkBudgeted::kYes);
|
SkBackingFit::kApprox, SkBudgeted::kYes);
|
||||||
|
|
||||||
// TODO: I believe the assignUniqueKeyToProxy below used to instantiate the proxy before
|
auto uploader = skstd::make_unique<GrTDeferredProxyUploader<ClipMaskData>>(reducedClip);
|
||||||
// the draw that used the result was being flushed, so the upload was succeeding. With
|
GrTDeferredProxyUploader<ClipMaskData>* uploaderRaw = uploader.get();
|
||||||
// assignUniqueKeyToProxy no longer forcing an instantiation it will have to happen
|
|
||||||
// explicitly elsewhere.
|
|
||||||
proxy->instantiate(context->resourceProvider());
|
|
||||||
|
|
||||||
auto uploader = skstd::make_unique<GrMaskUploaderPrepareCallback<ClipMaskData>>(
|
|
||||||
proxy, reducedClip);
|
|
||||||
GrMaskUploaderPrepareCallback<ClipMaskData>* uploaderRaw = uploader.get();
|
|
||||||
auto drawAndUploadMask = [uploaderRaw, maskSpaceIBounds] {
|
auto drawAndUploadMask = [uploaderRaw, maskSpaceIBounds] {
|
||||||
TRACE_EVENT0("skia", "Threaded SW Clip Mask Render");
|
TRACE_EVENT0("skia", "Threaded SW Clip Mask Render");
|
||||||
GrSWMaskHelper helper(uploaderRaw->getPixels());
|
GrSWMaskHelper helper(uploaderRaw->getPixels());
|
||||||
@ -545,11 +538,11 @@ sk_sp<GrTextureProxy> GrClipStackClip::createSoftwareClipMask(
|
|||||||
} else {
|
} else {
|
||||||
SkDEBUGFAIL("Unable to allocate SW clip mask.");
|
SkDEBUGFAIL("Unable to allocate SW clip mask.");
|
||||||
}
|
}
|
||||||
uploaderRaw->getSemaphore()->signal();
|
uploaderRaw->signalAndFreeData();
|
||||||
};
|
};
|
||||||
|
|
||||||
taskGroup->add(std::move(drawAndUploadMask));
|
taskGroup->add(std::move(drawAndUploadMask));
|
||||||
renderTargetContext->getOpList()->addPrepareCallback(std::move(uploader));
|
proxy->texPriv().setDeferredUploader(std::move(uploader));
|
||||||
} else {
|
} else {
|
||||||
GrSWMaskHelper helper;
|
GrSWMaskHelper helper;
|
||||||
if (!helper.init(maskSpaceIBounds)) {
|
if (!helper.init(maskSpaceIBounds)) {
|
||||||
|
120
src/gpu/GrDeferredProxyUploader.h
Normal file
120
src/gpu/GrDeferredProxyUploader.h
Normal file
@ -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 "SkAutoPixmapStorage.h"
|
||||||
|
#include "SkMakeUnique.h"
|
||||||
|
#include "SkRefCnt.h"
|
||||||
|
#include "SkSemaphore.h"
|
||||||
|
|
||||||
|
#include "GrOpFlushState.h"
|
||||||
|
#include "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](GrDrawOp::WritePixelsFn& writePixelsFn) {
|
||||||
|
this->wait();
|
||||||
|
// 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(),
|
||||||
|
proxy->config(), 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(skstd::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
|
@ -195,6 +195,8 @@ GrSemaphoresSubmitted GrDrawingManager::internalFlush(GrSurfaceProxy*,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Instantiate all deferred proxies (being built on worker threads) so we can upload them
|
||||||
|
fOpLists[i]->instantiateDeferredProxies(fContext->resourceProvider());
|
||||||
fOpLists[i]->prepare(&fFlushState);
|
fOpLists[i]->prepare(&fFlushState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,9 @@
|
|||||||
#include "GrOpList.h"
|
#include "GrOpList.h"
|
||||||
|
|
||||||
#include "GrContext.h"
|
#include "GrContext.h"
|
||||||
#include "GrPrepareCallback.h"
|
#include "GrDeferredProxyUploader.h"
|
||||||
#include "GrSurfaceProxy.h"
|
#include "GrSurfaceProxy.h"
|
||||||
|
#include "GrTextureProxyPriv.h"
|
||||||
|
|
||||||
#include "SkAtomics.h"
|
#include "SkAtomics.h"
|
||||||
|
|
||||||
@ -57,17 +58,19 @@ void GrOpList::reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fTarget.reset();
|
fTarget.reset();
|
||||||
fPrepareCallbacks.reset();
|
fDeferredProxies.reset();
|
||||||
fAuditTrail = nullptr;
|
fAuditTrail = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrOpList::addPrepareCallback(std::unique_ptr<GrPrepareCallback> callback) {
|
void GrOpList::instantiateDeferredProxies(GrResourceProvider* resourceProvider) {
|
||||||
fPrepareCallbacks.push_back(std::move(callback));
|
for (int i = 0; i < fDeferredProxies.count(); ++i) {
|
||||||
|
fDeferredProxies[i]->instantiate(resourceProvider);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrOpList::prepare(GrOpFlushState* flushState) {
|
void GrOpList::prepare(GrOpFlushState* flushState) {
|
||||||
for (int i = 0; i < fPrepareCallbacks.count(); ++i) {
|
for (int i = 0; i < fDeferredProxies.count(); ++i) {
|
||||||
(*fPrepareCallbacks[i])(flushState);
|
fDeferredProxies[i]->texPriv().scheduleUpload(flushState);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->onPrepare(flushState);
|
this->onPrepare(flushState);
|
||||||
@ -100,6 +103,12 @@ void GrOpList::addDependency(GrSurfaceProxy* dependedOn, const GrCaps& caps) {
|
|||||||
opList->makeClosed(caps);
|
opList->makeClosed(caps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GrTextureProxy* textureProxy = dependedOn->asTextureProxy()) {
|
||||||
|
if (textureProxy->texPriv().isDeferred()) {
|
||||||
|
fDeferredProxies.push_back(textureProxy);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
class GrAuditTrail;
|
class GrAuditTrail;
|
||||||
class GrCaps;
|
class GrCaps;
|
||||||
class GrOpFlushState;
|
class GrOpFlushState;
|
||||||
class GrPrepareCallback;
|
|
||||||
class GrRenderTargetOpList;
|
class GrRenderTargetOpList;
|
||||||
class GrResourceAllocator;
|
class GrResourceAllocator;
|
||||||
class GrResourceProvider;
|
class GrResourceProvider;
|
||||||
@ -39,8 +38,10 @@ public:
|
|||||||
GrOpList(GrResourceProvider*, GrSurfaceProxy*, GrAuditTrail*);
|
GrOpList(GrResourceProvider*, GrSurfaceProxy*, GrAuditTrail*);
|
||||||
~GrOpList() override;
|
~GrOpList() override;
|
||||||
|
|
||||||
// These three methods are invoked at flush time
|
// These four methods are invoked at flush time
|
||||||
bool instantiate(GrResourceProvider* resourceProvider);
|
bool instantiate(GrResourceProvider* resourceProvider);
|
||||||
|
// Instantiates any "threaded" texture proxies that are being prepared elsewhere
|
||||||
|
void instantiateDeferredProxies(GrResourceProvider* resourceProvider);
|
||||||
void prepare(GrOpFlushState* flushState);
|
void prepare(GrOpFlushState* flushState);
|
||||||
bool execute(GrOpFlushState* flushState) { return this->onExecute(flushState); }
|
bool execute(GrOpFlushState* flushState) { return this->onExecute(flushState); }
|
||||||
|
|
||||||
@ -59,8 +60,6 @@ public:
|
|||||||
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
|
||||||
void addPrepareCallback(std::unique_ptr<GrPrepareCallback> callback);
|
|
||||||
|
|
||||||
// TODO: in an MDB world, where the OpLists don't allocate GPU resources, it seems like
|
// TODO: in an MDB world, where the OpLists don't allocate GPU resources, it seems like
|
||||||
// these could go away
|
// these could go away
|
||||||
virtual void abandonGpuResources() = 0;
|
virtual void abandonGpuResources() = 0;
|
||||||
@ -119,6 +118,9 @@ protected:
|
|||||||
GrColor fLoadClearColor = 0x0;
|
GrColor fLoadClearColor = 0x0;
|
||||||
GrLoadOp fStencilLoadOp = GrLoadOp::kLoad;
|
GrLoadOp fStencilLoadOp = GrLoadOp::kLoad;
|
||||||
|
|
||||||
|
// List of texture proxies whose contents are being prepared on a worker thread
|
||||||
|
SkTArray<GrTextureProxy*, true> fDeferredProxies;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class GrDrawingManager; // for resetFlag, TopoSortTraits & gatherProxyIntervals
|
friend class GrDrawingManager; // for resetFlag, TopoSortTraits & gatherProxyIntervals
|
||||||
|
|
||||||
@ -181,9 +183,6 @@ private:
|
|||||||
// 'this' GrOpList relies on the output of the GrOpLists in 'fDependencies'
|
// 'this' GrOpList relies on the output of the GrOpLists in 'fDependencies'
|
||||||
SkSTArray<1, GrOpList*, true> fDependencies;
|
SkSTArray<1, GrOpList*, true> fDependencies;
|
||||||
|
|
||||||
// These are used rarely, most clients never produce any
|
|
||||||
SkTArray<std::unique_ptr<GrPrepareCallback>> fPrepareCallbacks;
|
|
||||||
|
|
||||||
typedef SkRefCnt INHERITED;
|
typedef SkRefCnt INHERITED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 GrPrepareCallback_DEFINED
|
|
||||||
#define GrPrepareCallback_DEFINED
|
|
||||||
|
|
||||||
#include "SkAutoPixmapStorage.h"
|
|
||||||
#include "SkRefCnt.h"
|
|
||||||
#include "SkSemaphore.h"
|
|
||||||
|
|
||||||
#include "GrOpFlushState.h"
|
|
||||||
|
|
||||||
class GrTextureProxy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An instance of any class derived from GrPrepareCallback can be passed to
|
|
||||||
* GrOpList::addPrepareCallback. At flush time, all callbacks (on op lists being flushed) will be
|
|
||||||
* invoked (via operator()). Note that the callback receives the GrOpFlushState, so it can trigger
|
|
||||||
* ASAP uploads (similar to an Op's onPrepare).
|
|
||||||
*
|
|
||||||
* All callbacks are invoked at the beginning of flush, before prepare is called.
|
|
||||||
*/
|
|
||||||
class GrPrepareCallback : SkNoncopyable {
|
|
||||||
public:
|
|
||||||
virtual ~GrPrepareCallback() {}
|
|
||||||
virtual void operator()(GrOpFlushState*) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GrMaskUploaderPrepareCallback assists with threaded generation of mask 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. That payload is accessed by the
|
|
||||||
* worker thread to populate the mask in fPixels (using GrSWMaskHelper). This callback's operator()
|
|
||||||
* handles scheduling the texture upload at flush time.
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
class GrMaskUploaderPrepareCallback : public GrPrepareCallback {
|
|
||||||
public:
|
|
||||||
template <typename... Args>
|
|
||||||
GrMaskUploaderPrepareCallback(sk_sp<GrTextureProxy> proxy, Args&&... args)
|
|
||||||
: fProxy(std::move(proxy))
|
|
||||||
, fWaited(false)
|
|
||||||
, fData(std::forward<Args>(args)...) {}
|
|
||||||
|
|
||||||
~GrMaskUploaderPrepareCallback() override {
|
|
||||||
if (!fWaited) {
|
|
||||||
// This can happen if our owning op list fails to instantiate (so it never prepares)
|
|
||||||
fPixelsReady.wait();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(GrOpFlushState* flushState) override {
|
|
||||||
auto uploadMask = [this](GrDrawOp::WritePixelsFn& writePixelsFn) {
|
|
||||||
this->fPixelsReady.wait();
|
|
||||||
this->fWaited = true;
|
|
||||||
// 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(this->fProxy.get(), 0, 0,
|
|
||||||
this->fPixels.width(), this->fPixels.height(),
|
|
||||||
kAlpha_8_GrPixelConfig,
|
|
||||||
this->fPixels.addr(), this->fPixels.rowBytes());
|
|
||||||
// Free this memory immediately, so it can be recycled. This avoids memory pressure
|
|
||||||
// when there is a large amount of threaded work still running during flush.
|
|
||||||
this->fPixels.reset();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
flushState->addASAPUpload(std::move(uploadMask));
|
|
||||||
}
|
|
||||||
|
|
||||||
SkAutoPixmapStorage* getPixels() { return &fPixels; }
|
|
||||||
SkSemaphore* getSemaphore() { return &fPixelsReady; }
|
|
||||||
T& data() { return fData; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
sk_sp<GrTextureProxy> fProxy;
|
|
||||||
SkAutoPixmapStorage fPixels;
|
|
||||||
SkSemaphore fPixelsReady;
|
|
||||||
bool fWaited;
|
|
||||||
|
|
||||||
T fData;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -221,6 +221,7 @@ void GrRenderTargetOpList::fullClear(const GrCaps& caps, GrColor color) {
|
|||||||
// buffer we will need a more elaborate tracking system (skbug.com/7002).
|
// buffer we will need a more elaborate tracking system (skbug.com/7002).
|
||||||
if (this->isEmpty() || !fTarget.get()->asRenderTargetProxy()->needsStencil()) {
|
if (this->isEmpty() || !fTarget.get()->asRenderTargetProxy()->needsStencil()) {
|
||||||
fRecordedOps.reset();
|
fRecordedOps.reset();
|
||||||
|
fDeferredProxies.reset();
|
||||||
fColorLoadOp = GrLoadOp::kClear;
|
fColorLoadOp = GrLoadOp::kClear;
|
||||||
fLoadClearColor = color;
|
fLoadClearColor = color;
|
||||||
return;
|
return;
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
#include "GrAuditTrail.h"
|
#include "GrAuditTrail.h"
|
||||||
#include "GrClip.h"
|
#include "GrClip.h"
|
||||||
#include "GrContextPriv.h"
|
#include "GrContextPriv.h"
|
||||||
|
#include "GrDeferredProxyUploader.h"
|
||||||
#include "GrGpuResourcePriv.h"
|
#include "GrGpuResourcePriv.h"
|
||||||
#include "GrOpFlushState.h"
|
#include "GrOpFlushState.h"
|
||||||
#include "GrOpList.h"
|
#include "GrOpList.h"
|
||||||
#include "GrPrepareCallback.h"
|
|
||||||
#include "GrResourceProvider.h"
|
#include "GrResourceProvider.h"
|
||||||
#include "GrSWMaskHelper.h"
|
#include "GrSWMaskHelper.h"
|
||||||
#include "SkMakeUnique.h"
|
#include "SkMakeUnique.h"
|
||||||
@ -175,7 +175,7 @@ static sk_sp<GrTextureProxy> make_deferred_mask_texture_proxy(GrContext* context
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Payload class for use with GrMaskUploaderPrepareCallback. The software path renderer only draws
|
* Payload class for use with GrTDeferredProxyUploader. The software path renderer only draws
|
||||||
* a single path into the mask texture. This stores all of the information needed by the worker
|
* a single path into the mask texture. This stores all of the information needed by the worker
|
||||||
* thread's call to drawShape (see below, in onDrawPath).
|
* thread's call to drawShape (see below, in onDrawPath).
|
||||||
*/
|
*/
|
||||||
@ -318,15 +318,9 @@ bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: I believe the assignUniqueKeyToProxy below used to instantiate the proxy before
|
auto uploader = skstd::make_unique<GrTDeferredProxyUploader<SoftwarePathData>>(
|
||||||
// before the draw that used the result was being flushed, so the upload was succeeding.
|
*boundsForMask, *args.fViewMatrix, *args.fShape, aa);
|
||||||
// With assignUniqueKeyToProxy no longer forcing an instantiation it will have to happen
|
GrTDeferredProxyUploader<SoftwarePathData>* uploaderRaw = uploader.get();
|
||||||
// explicitly elsewhere.
|
|
||||||
proxy->instantiate(fResourceProvider);
|
|
||||||
|
|
||||||
auto uploader = skstd::make_unique<GrMaskUploaderPrepareCallback<SoftwarePathData>>(
|
|
||||||
proxy, *boundsForMask, *args.fViewMatrix, *args.fShape, aa);
|
|
||||||
GrMaskUploaderPrepareCallback<SoftwarePathData>* uploaderRaw = uploader.get();
|
|
||||||
|
|
||||||
auto drawAndUploadMask = [uploaderRaw] {
|
auto drawAndUploadMask = [uploaderRaw] {
|
||||||
TRACE_EVENT0("skia", "Threaded SW Mask Render");
|
TRACE_EVENT0("skia", "Threaded SW Mask Render");
|
||||||
@ -338,10 +332,10 @@ bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) {
|
|||||||
} else {
|
} else {
|
||||||
SkDEBUGFAIL("Unable to allocate SW mask.");
|
SkDEBUGFAIL("Unable to allocate SW mask.");
|
||||||
}
|
}
|
||||||
uploaderRaw->getSemaphore()->signal();
|
uploaderRaw->signalAndFreeData();
|
||||||
};
|
};
|
||||||
taskGroup->add(std::move(drawAndUploadMask));
|
taskGroup->add(std::move(drawAndUploadMask));
|
||||||
args.fRenderTargetContext->getOpList()->addPrepareCallback(std::move(uploader));
|
proxy->texPriv().setDeferredUploader(std::move(uploader));
|
||||||
} else {
|
} else {
|
||||||
GrSWMaskHelper helper;
|
GrSWMaskHelper helper;
|
||||||
if (!helper.init(*boundsForMask)) {
|
if (!helper.init(*boundsForMask)) {
|
||||||
|
@ -6,10 +6,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "GrTextureProxy.h"
|
#include "GrTextureProxy.h"
|
||||||
|
#include "GrTextureProxyPriv.h"
|
||||||
|
|
||||||
#include "GrContext.h"
|
#include "GrContext.h"
|
||||||
|
#include "GrDeferredProxyUploader.h"
|
||||||
#include "GrResourceCache.h"
|
#include "GrResourceCache.h"
|
||||||
|
|
||||||
#include "GrTexturePriv.h"
|
#include "GrTexturePriv.h"
|
||||||
|
|
||||||
GrTextureProxy::GrTextureProxy(const GrSurfaceDesc& srcDesc, SkBackingFit fit, SkBudgeted budgeted,
|
GrTextureProxy::GrTextureProxy(const GrSurfaceDesc& srcDesc, SkBackingFit fit, SkBudgeted budgeted,
|
||||||
@ -17,7 +18,8 @@ GrTextureProxy::GrTextureProxy(const GrSurfaceDesc& srcDesc, SkBackingFit fit, S
|
|||||||
: INHERITED(srcDesc, fit, budgeted, flags)
|
: INHERITED(srcDesc, fit, budgeted, flags)
|
||||||
, fIsMipMapped(false)
|
, fIsMipMapped(false)
|
||||||
, fMipColorMode(SkDestinationSurfaceColorMode::kLegacy)
|
, fMipColorMode(SkDestinationSurfaceColorMode::kLegacy)
|
||||||
, fCache(nullptr) {
|
, fCache(nullptr)
|
||||||
|
, fDeferredUploader(nullptr) {
|
||||||
SkASSERT(!srcData); // currently handled in Make()
|
SkASSERT(!srcData); // currently handled in Make()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +27,8 @@ GrTextureProxy::GrTextureProxy(sk_sp<GrSurface> surf, GrSurfaceOrigin origin)
|
|||||||
: INHERITED(std::move(surf), origin, SkBackingFit::kExact)
|
: INHERITED(std::move(surf), origin, SkBackingFit::kExact)
|
||||||
, fIsMipMapped(fTarget->asTexture()->texturePriv().hasMipMaps())
|
, fIsMipMapped(fTarget->asTexture()->texturePriv().hasMipMaps())
|
||||||
, fMipColorMode(fTarget->asTexture()->texturePriv().mipColorMode())
|
, fMipColorMode(fTarget->asTexture()->texturePriv().mipColorMode())
|
||||||
, fCache(nullptr) {
|
, fCache(nullptr)
|
||||||
|
, fDeferredUploader(nullptr) {
|
||||||
if (fTarget->getUniqueKey().isValid()) {
|
if (fTarget->getUniqueKey().isValid()) {
|
||||||
fCache = fTarget->asTexture()->getContext()->getResourceCache();
|
fCache = fTarget->asTexture()->getContext()->getResourceCache();
|
||||||
fCache->adoptUniqueKeyFromSurface(this, fTarget);
|
fCache->adoptUniqueKeyFromSurface(this, fTarget);
|
||||||
@ -67,6 +70,25 @@ sk_sp<GrSurface> GrTextureProxy::createSurface(GrResourceProvider* resourceProvi
|
|||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GrTextureProxyPriv::setDeferredUploader(std::unique_ptr<GrDeferredProxyUploader> uploader) {
|
||||||
|
SkASSERT(!fTextureProxy->fDeferredUploader);
|
||||||
|
fTextureProxy->fDeferredUploader = std::move(uploader);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GrTextureProxyPriv::scheduleUpload(GrOpFlushState* flushState) {
|
||||||
|
SkASSERT(fTextureProxy->fDeferredUploader);
|
||||||
|
|
||||||
|
// Instantiate might have failed
|
||||||
|
if (fTextureProxy->fTarget) {
|
||||||
|
fTextureProxy->fDeferredUploader->scheduleUpload(flushState, fTextureProxy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GrTextureProxyPriv::resetDeferredUploader() {
|
||||||
|
SkASSERT(fTextureProxy->fDeferredUploader);
|
||||||
|
fTextureProxy->fDeferredUploader.reset();
|
||||||
|
}
|
||||||
|
|
||||||
// This method parallels the highest_filter_mode functions in GrGLTexture & GrVkTexture.
|
// This method parallels the highest_filter_mode functions in GrGLTexture & GrVkTexture.
|
||||||
GrSamplerState::Filter GrTextureProxy::highestFilterMode() const {
|
GrSamplerState::Filter GrTextureProxy::highestFilterMode() const {
|
||||||
if (fTarget) {
|
if (fTarget) {
|
||||||
|
@ -10,11 +10,23 @@
|
|||||||
|
|
||||||
#include "GrTextureProxy.h"
|
#include "GrTextureProxy.h"
|
||||||
|
|
||||||
|
class GrDeferredProxyUploader;
|
||||||
|
class GrOpFlushState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class hides the more specialized capabilities of GrTextureProxy.
|
* This class hides the more specialized capabilities of GrTextureProxy.
|
||||||
*/
|
*/
|
||||||
class GrTextureProxyPriv {
|
class GrTextureProxyPriv {
|
||||||
public:
|
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:
|
private:
|
||||||
explicit GrTextureProxyPriv(GrTextureProxy* textureProxy) : fTextureProxy(textureProxy) {}
|
explicit GrTextureProxyPriv(GrTextureProxy* textureProxy) : fTextureProxy(textureProxy) {}
|
||||||
|
Loading…
Reference in New Issue
Block a user