Plumb abandonment throughout GrContext hierarchy
When the GrImageContext & GrRecordingContext are actually GrDirectContexts it is useful for them to report the abandonment state of the GrDirectContext. When the GrImageContext & GrRecordingContext are actually GrImageCreationContext or GrDDLContexts then they will just never be abandoned. This CL also strips the GrProxyProvider and GrDrawingManager of their tracking on abandonment and centralizes it in the GrImageContext. ImageContext can't abandon can only check abandonment privately RecordingContext can't abandon can only check abandonment privately DirectContext (aka GrContext) can abandon publicly can check abandonment publicly Note that abandoning the DirectContext won't alter the abandonment status of any of the other contexts in its group (e.g., DDL contexts that may be being used to record). Change-Id: Ib790f74d90ab18da58a127fed2aad20e2477bd21 Reviewed-on: https://skia-review.googlesource.com/c/190669 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
cd2c3db480
commit
a9162dfb9c
@ -111,12 +111,12 @@ public:
|
||||
* The typical use case for this function is that the underlying 3D context was lost and further
|
||||
* API calls may crash.
|
||||
*/
|
||||
virtual void abandonContext();
|
||||
void abandonContext() override;
|
||||
|
||||
/**
|
||||
* Returns true if the context was abandoned.
|
||||
*/
|
||||
bool abandoned() const;
|
||||
using GrImageContext::abandoned;
|
||||
|
||||
/**
|
||||
* This is similar to abandonContext() however the underlying 3D context is not yet lost and
|
||||
|
@ -27,6 +27,9 @@ protected:
|
||||
|
||||
GrImageContext(GrBackendApi, const GrContextOptions&, uint32_t contextID);
|
||||
|
||||
virtual void abandonContext();
|
||||
bool abandoned() const;
|
||||
|
||||
GrProxyProvider* proxyProvider() { return fProxyProvider.get(); }
|
||||
const GrProxyProvider* proxyProvider() const { return fProxyProvider.get(); }
|
||||
|
||||
@ -37,11 +40,12 @@ protected:
|
||||
|
||||
private:
|
||||
std::unique_ptr<GrProxyProvider> fProxyProvider;
|
||||
bool fAbandoned = false;
|
||||
|
||||
// In debug builds we guard against improper thread handling
|
||||
// This guard is passed to the GrDrawingManager and, from there to all the
|
||||
// GrRenderTargetContexts. It is also passed to the GrResourceProvider and SkGpuDevice.
|
||||
mutable GrSingleOwner fSingleOwner;
|
||||
mutable GrSingleOwner fSingleOwner;
|
||||
|
||||
typedef GrContext_Base INHERITED;
|
||||
};
|
||||
|
@ -27,6 +27,8 @@ protected:
|
||||
|
||||
GrRecordingContext(GrBackendApi, const GrContextOptions&, uint32_t contextID);
|
||||
|
||||
void abandonContext() override;
|
||||
|
||||
sk_sp<GrOpMemoryPool> refOpMemoryPool();
|
||||
GrOpMemoryPool* opMemoryPool();
|
||||
|
||||
|
@ -39,9 +39,9 @@
|
||||
#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
|
||||
#define ASSERT_SINGLE_OWNER \
|
||||
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
|
||||
#define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; }
|
||||
#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; }
|
||||
#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; }
|
||||
#define RETURN_IF_ABANDONED if (this->abandoned()) { return; }
|
||||
#define RETURN_FALSE_IF_ABANDONED if (this->abandoned()) { return false; }
|
||||
#define RETURN_NULL_IF_ABANDONED if (this->abandoned()) { return nullptr; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -146,14 +146,17 @@ sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrContext::abandonContext() {
|
||||
ASSERT_SINGLE_OWNER
|
||||
if (this->abandoned()) {
|
||||
return;
|
||||
}
|
||||
|
||||
INHERITED::abandonContext();
|
||||
|
||||
this->proxyProvider()->abandon();
|
||||
fResourceProvider->abandon();
|
||||
|
||||
// Need to abandon the drawing manager first so all the render targets
|
||||
// Need to cleanup the drawing manager first so all the render targets
|
||||
// will be released/forgotten before they too are abandoned.
|
||||
fDrawingManager->abandon();
|
||||
fDrawingManager->cleanup();
|
||||
|
||||
// abandon first to so destructors
|
||||
// don't try to free the resources in the API.
|
||||
@ -163,26 +166,21 @@ void GrContext::abandonContext() {
|
||||
|
||||
fGlyphCache->freeAll();
|
||||
fTextBlobCache->freeAll();
|
||||
}
|
||||
|
||||
bool GrContext::abandoned() const {
|
||||
ASSERT_SINGLE_OWNER
|
||||
// If called from ~GrContext(), the drawing manager may already be gone.
|
||||
return !fDrawingManager || fDrawingManager->wasAbandoned();
|
||||
}
|
||||
|
||||
void GrContext::releaseResourcesAndAbandonContext() {
|
||||
ASSERT_SINGLE_OWNER
|
||||
|
||||
if (this->abandoned()) {
|
||||
return;
|
||||
}
|
||||
this->proxyProvider()->abandon();
|
||||
|
||||
INHERITED::abandonContext();
|
||||
|
||||
fResourceProvider->abandon();
|
||||
|
||||
// Need to abandon the drawing manager first so all the render targets
|
||||
// Need to cleanup the drawing manager first so all the render targets
|
||||
// will be released/forgotten before they too are abandoned.
|
||||
fDrawingManager->abandon();
|
||||
fDrawingManager->cleanup();
|
||||
|
||||
// Release all resources in the backend 3D API.
|
||||
fResourceCache->releaseAll();
|
||||
@ -298,7 +296,9 @@ void GrContext::flush() {
|
||||
GrSemaphoresSubmitted GrContext::flushAndSignalSemaphores(int numSemaphores,
|
||||
GrBackendSemaphore signalSemaphores[]) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
if (fDrawingManager->wasAbandoned()) { return GrSemaphoresSubmitted::kNo; }
|
||||
if (this->abandoned()) {
|
||||
return GrSemaphoresSubmitted::kNo;
|
||||
}
|
||||
|
||||
return fDrawingManager->flush(nullptr, numSemaphores, signalSemaphores);
|
||||
}
|
||||
|
@ -28,8 +28,8 @@
|
||||
SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == fContext)
|
||||
#define ASSERT_SINGLE_OWNER_PRIV \
|
||||
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->singleOwner());)
|
||||
#define RETURN_IF_ABANDONED_PRIV if (fContext->fDrawingManager->wasAbandoned()) { return; }
|
||||
#define RETURN_FALSE_IF_ABANDONED_PRIV if (fContext->fDrawingManager->wasAbandoned()) { return false; }
|
||||
#define RETURN_IF_ABANDONED_PRIV if (fContext->abandoned()) { return; }
|
||||
#define RETURN_FALSE_IF_ABANDONED_PRIV if (fContext->abandoned()) { return false; }
|
||||
|
||||
sk_sp<const GrCaps> GrContextPriv::refCaps() const {
|
||||
return fContext->refCaps();
|
||||
|
@ -156,7 +156,6 @@ GrDrawingManager::GrDrawingManager(GrContext* context,
|
||||
, fOptionsForPathRendererChain(optionsForPathRendererChain)
|
||||
, fOptionsForTextContext(optionsForTextContext)
|
||||
, fSingleOwner(singleOwner)
|
||||
, fAbandoned(false)
|
||||
, fDAG(explicitlyAllocating, sortOpLists)
|
||||
, fTextContext(nullptr)
|
||||
, fPathRendererChain(nullptr)
|
||||
@ -186,9 +185,8 @@ GrDrawingManager::~GrDrawingManager() {
|
||||
this->cleanup();
|
||||
}
|
||||
|
||||
void GrDrawingManager::abandon() {
|
||||
fAbandoned = true;
|
||||
this->cleanup();
|
||||
bool GrDrawingManager::wasAbandoned() const {
|
||||
return fContext->abandoned();
|
||||
}
|
||||
|
||||
void GrDrawingManager::freeGpuResources() {
|
||||
|
@ -38,7 +38,6 @@ class GrDrawingManager {
|
||||
public:
|
||||
~GrDrawingManager();
|
||||
|
||||
bool wasAbandoned() const { return fAbandoned; }
|
||||
void freeGpuResources();
|
||||
|
||||
sk_sp<GrRenderTargetContext> makeRenderTargetContext(sk_sp<GrSurfaceProxy>,
|
||||
@ -140,7 +139,8 @@ private:
|
||||
bool explicitlyAllocating, GrContextOptions::Enable sortRenderTargets,
|
||||
GrContextOptions::Enable reduceOpListSplitting);
|
||||
|
||||
void abandon();
|
||||
bool wasAbandoned() const;
|
||||
|
||||
void cleanup();
|
||||
|
||||
// return true if any opLists were actually executed; false otherwise
|
||||
@ -168,7 +168,6 @@ private:
|
||||
// In debug builds we guard against improper thread handling
|
||||
GrSingleOwner* fSingleOwner;
|
||||
|
||||
bool fAbandoned;
|
||||
OpListDAG fDAG;
|
||||
GrOpList* fActiveOpList = nullptr;
|
||||
// These are the IDs of the opLists currently being flushed (in internalFlush)
|
||||
|
@ -12,6 +12,10 @@
|
||||
#include "GrProxyProvider.h"
|
||||
#include "GrSkSLFPFactoryCache.h"
|
||||
|
||||
#define ASSERT_SINGLE_OWNER \
|
||||
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
GrImageContext::GrImageContext(GrBackendApi backend,
|
||||
const GrContextOptions& options,
|
||||
uint32_t contextID)
|
||||
@ -21,6 +25,18 @@ GrImageContext::GrImageContext(GrBackendApi backend,
|
||||
|
||||
GrImageContext::~GrImageContext() {}
|
||||
|
||||
void GrImageContext::abandonContext() {
|
||||
ASSERT_SINGLE_OWNER
|
||||
|
||||
fAbandoned = true;
|
||||
}
|
||||
|
||||
bool GrImageContext::abandoned() const {
|
||||
ASSERT_SINGLE_OWNER
|
||||
|
||||
return fAbandoned;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
sk_sp<const GrCaps> GrImageContextPriv::refCaps() const {
|
||||
return fContext->refCaps();
|
||||
|
@ -35,6 +35,8 @@ public:
|
||||
GrProxyProvider* proxyProvider() { return fContext->proxyProvider(); }
|
||||
const GrProxyProvider* proxyProvider() const { return fContext->proxyProvider(); }
|
||||
|
||||
bool abandoned() const { return fContext->abandoned(); }
|
||||
|
||||
/** This is only useful for debug purposes */
|
||||
SkDEBUGCODE(GrSingleOwner* singleOwner() const { return fContext->singleOwner(); } )
|
||||
|
||||
|
@ -34,10 +34,7 @@
|
||||
#define ASSERT_SINGLE_OWNER \
|
||||
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fImageContext->priv().singleOwner());)
|
||||
|
||||
GrProxyProvider::GrProxyProvider(GrImageContext* imageContext)
|
||||
: fImageContext(imageContext)
|
||||
, fAbandoned(false) {
|
||||
}
|
||||
GrProxyProvider::GrProxyProvider(GrImageContext* imageContext) : fImageContext(imageContext) {}
|
||||
|
||||
GrProxyProvider::~GrProxyProvider() {
|
||||
if (this->renderingDirectly()) {
|
||||
@ -837,6 +834,10 @@ sk_sp<const GrCaps> GrProxyProvider::refCaps() const {
|
||||
return fImageContext->priv().refCaps();
|
||||
}
|
||||
|
||||
bool GrProxyProvider::isAbandoned() const {
|
||||
return fImageContext->priv().abandoned();
|
||||
}
|
||||
|
||||
void GrProxyProvider::orphanAllUniqueKeys() {
|
||||
UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies);
|
||||
for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
|
||||
|
@ -216,12 +216,6 @@ public:
|
||||
const GrCaps* caps() const;
|
||||
sk_sp<const GrCaps> refCaps() const;
|
||||
|
||||
void abandon() {
|
||||
fAbandoned = true;
|
||||
}
|
||||
|
||||
bool isAbandoned() const { return fAbandoned; }
|
||||
|
||||
int numUniqueKeyProxies_TestOnly() const;
|
||||
|
||||
// This is called on a DDL's proxyprovider when the DDL is finished. The uniquely keyed
|
||||
@ -250,6 +244,8 @@ private:
|
||||
friend class GrAHardwareBufferImageGenerator; // for createWrapped
|
||||
friend class GrResourceProvider; // for createWrapped
|
||||
|
||||
bool isAbandoned() const;
|
||||
|
||||
sk_sp<GrTextureProxy> createWrapped(sk_sp<GrTexture> tex, GrSurfaceOrigin origin);
|
||||
|
||||
struct UniquelyKeyedProxyHashTraits {
|
||||
@ -264,7 +260,6 @@ private:
|
||||
UniquelyKeyedProxyHash fUniquelyKeyedProxies;
|
||||
|
||||
GrImageContext* fImageContext;
|
||||
bool fAbandoned;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,10 @@ GrRecordingContext::GrRecordingContext(GrBackendApi backend,
|
||||
|
||||
GrRecordingContext::~GrRecordingContext() { }
|
||||
|
||||
void GrRecordingContext::abandonContext() {
|
||||
INHERITED::abandonContext();
|
||||
}
|
||||
|
||||
sk_sp<GrOpMemoryPool> GrRecordingContext::refOpMemoryPool() {
|
||||
if (!fOpMemoryPool) {
|
||||
// DDL TODO: should the size of the memory pool be decreased in DDL mode? CPU-side memory
|
||||
|
@ -35,6 +35,8 @@ public:
|
||||
GrProxyProvider* proxyProvider() { return fContext->proxyProvider(); }
|
||||
const GrProxyProvider* proxyProvider() const { return fContext->proxyProvider(); }
|
||||
|
||||
bool abandoned() const { return fContext->abandoned(); }
|
||||
|
||||
/** This is only useful for debug purposes */
|
||||
SkDEBUGCODE(GrSingleOwner* singleOwner() const { return fContext->singleOwner(); } )
|
||||
|
||||
|
@ -106,11 +106,11 @@ private:
|
||||
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
|
||||
#define ASSERT_SINGLE_OWNER_PRIV \
|
||||
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
|
||||
#define RETURN_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return; }
|
||||
#define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return; }
|
||||
#define RETURN_FALSE_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return false; }
|
||||
#define RETURN_FALSE_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return false; }
|
||||
#define RETURN_NULL_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return nullptr; }
|
||||
#define RETURN_IF_ABANDONED if (fContext->abandoned()) { return; }
|
||||
#define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->fContext->abandoned()) { return; }
|
||||
#define RETURN_FALSE_IF_ABANDONED if (fContext->abandoned()) { return false; }
|
||||
#define RETURN_FALSE_IF_ABANDONED_PRIV if (fRenderTargetContext->fContext->abandoned()) { return false; }
|
||||
#define RETURN_NULL_IF_ABANDONED if (fContext->abandoned()) { return nullptr; }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -150,10 +150,6 @@ private:
|
||||
GrDrawingManager* fDrawingManager;
|
||||
};
|
||||
|
||||
bool GrRenderTargetContext::wasAbandoned() const {
|
||||
return this->drawingManager()->wasAbandoned();
|
||||
}
|
||||
|
||||
// In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress
|
||||
// GrOpLists to be picked up and added to by renderTargetContexts lower in the call
|
||||
// stack. When this occurs with a closed GrOpList, a new one will be allocated
|
||||
@ -1153,7 +1149,7 @@ bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
|
||||
const SkPath& path,
|
||||
const SkDrawShadowRec& rec) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
if (this->drawingManager()->wasAbandoned()) {
|
||||
if (fContext->abandoned()) {
|
||||
return true;
|
||||
}
|
||||
SkDEBUGCODE(this->validate();)
|
||||
@ -1623,7 +1619,9 @@ void GrRenderTargetContext::drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHand
|
||||
GrSemaphoresSubmitted GrRenderTargetContext::prepareForExternalIO(
|
||||
int numSemaphores, GrBackendSemaphore backendSemaphores[]) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
if (this->drawingManager()->wasAbandoned()) { return GrSemaphoresSubmitted::kNo; }
|
||||
if (fContext->abandoned()) {
|
||||
return GrSemaphoresSubmitted::kNo;
|
||||
}
|
||||
SkDEBUGCODE(this->validate();)
|
||||
GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "prepareForExternalIO", fContext);
|
||||
|
||||
@ -1807,7 +1805,7 @@ bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip,
|
||||
SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
|
||||
ASSERT_SINGLE_OWNER_PRIV
|
||||
|
||||
if (fRenderTargetContext->wasAbandoned()) {
|
||||
if (fRenderTargetContext->fContext->abandoned()) {
|
||||
return SkBudgeted::kNo;
|
||||
}
|
||||
|
||||
@ -1933,7 +1931,7 @@ static void op_bounds(SkRect* bounds, const GrOp* op) {
|
||||
void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op,
|
||||
const std::function<WillAddOpFn>& willAddFn) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
if (this->drawingManager()->wasAbandoned()) {
|
||||
if (fContext->abandoned()) {
|
||||
fContext->priv().opMemoryPool()->release(std::move(op));
|
||||
return;
|
||||
}
|
||||
|
@ -388,8 +388,6 @@ public:
|
||||
bool wrapsVkSecondaryCB() const { return fRenderTargetProxy->wrapsVkSecondaryCB(); }
|
||||
GrMipMapped mipMapped() const;
|
||||
|
||||
bool wasAbandoned() const;
|
||||
|
||||
void setNeedsStencil() { fRenderTargetProxy->setNeedsStencil(); }
|
||||
|
||||
GrRenderTarget* accessRenderTarget() {
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#define ASSERT_SINGLE_OWNER \
|
||||
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
|
||||
#define RETURN_FALSE_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return false; }
|
||||
#define RETURN_FALSE_IF_ABANDONED if (this->fContext->abandoned()) { return false; }
|
||||
|
||||
// In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress
|
||||
// GrOpLists to be picked up and added to by renderTargetContexts lower in the call
|
||||
|
@ -87,7 +87,7 @@ sk_sp<SkGpuDevice> SkGpuDevice::Make(GrContext* context,
|
||||
sk_sp<GrRenderTargetContext> renderTargetContext,
|
||||
int width, int height,
|
||||
InitContents init) {
|
||||
if (!renderTargetContext || renderTargetContext->wasAbandoned()) {
|
||||
if (!renderTargetContext || context->abandoned()) {
|
||||
return nullptr;
|
||||
}
|
||||
unsigned flags;
|
||||
@ -268,7 +268,7 @@ void SkGpuDevice::replaceRenderTargetContext(bool shouldRetainContent) {
|
||||
SkASSERT(newRTC->asSurfaceProxy()->priv().isExact());
|
||||
|
||||
if (shouldRetainContent) {
|
||||
if (fRenderTargetContext->wasAbandoned()) {
|
||||
if (this->context()->abandoned()) {
|
||||
return;
|
||||
}
|
||||
newRTC->copy(fRenderTargetContext->asSurfaceProxy());
|
||||
|
@ -82,7 +82,7 @@ void GrRenderTargetContextPriv::testingOnly_addDrawOp(
|
||||
std::unique_ptr<GrDrawOp> op,
|
||||
const std::function<GrRenderTargetContext::WillAddOpFn>& willAddFn) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
if (fRenderTargetContext->drawingManager()->wasAbandoned()) {
|
||||
if (fRenderTargetContext->fContext->abandoned()) {
|
||||
fRenderTargetContext->fContext->priv().opMemoryPool()->release(std::move(op));
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user