diff options
author | bsalomon <bsalomon@google.com> | 2016-04-01 11:54:31 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-04-01 11:54:31 -0700 |
commit | 6e2aad4e9f6280aa2b710e7324458fdc6d699ec5 (patch) | |
tree | 77bf09c049b5afe4aaccd66b7926050c53bbebff /src | |
parent | 895f3f0544ce38d35999771754cbb1d876c14b5a (diff) |
Add GrContext::releaseAndAbandonContext()
Like abandonContext() this disconnects the GrContext from the underlying 3D API. However, unlike abandonContext it first frees all allocated GPU resources.
BUG=skia:5142
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1852733002
Review URL: https://codereview.chromium.org/1852733002
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrContext.cpp | 21 | ||||
-rw-r--r-- | src/gpu/GrGpu.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrGpu.h | 16 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 52 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLPathRendering.cpp | 5 | ||||
-rw-r--r-- | src/gpu/gl/GrGLPathRendering.h | 6 |
7 files changed, 88 insertions, 16 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 1f6934d441..1d6bb32142 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -148,7 +148,26 @@ void GrContext::abandonContext() { // don't try to free the resources in the API. fResourceCache->abandonAll(); - fGpu->contextAbandoned(); + fGpu->disconnect(GrGpu::DisconnectType::kAbandon); + + fBatchFontCache->freeAll(); + fLayerCache->freeAll(); + fTextBlobCache->freeAll(); +} + +void GrContext::releaseResourcesAndAbandonContext() { + ASSERT_SINGLE_OWNER + + fResourceProvider->abandon(); + + // Need to abandon the drawing manager first so all the render targets + // will be released/forgotten before they too are abandoned. + fDrawingManager->abandon(); + + // Release all resources in the backend 3D API. + fResourceCache->releaseAll(); + + fGpu->disconnect(GrGpu::DisconnectType::kCleanup); fBatchFontCache->freeAll(); fLayerCache->freeAll(); diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 960526635e..bc11b4b9c6 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -51,7 +51,7 @@ GrGpu::GrGpu(GrContext* context) GrGpu::~GrGpu() {} -void GrGpu::contextAbandoned() {} +void GrGpu::disconnect(DisconnectType) {} //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 0da1aa6399..b3251dc14f 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -61,11 +61,17 @@ public: GrPathRendering* pathRendering() { return fPathRendering.get(); } - // Called by GrContext when the underlying backend context has been destroyed. - // GrGpu should use this to ensure that no backend API calls will be made from - // here onward, including in its destructor. Subclasses should call - // INHERITED::contextAbandoned() if they override this. - virtual void contextAbandoned(); + enum class DisconnectType { + // No cleanup should be attempted, immediately cease making backend API calls + kAbandon, + // Free allocated resources (not known by GrResourceCache) before returning and + // ensure no backend backend 3D API calls will be made after disconnect() returns. + kCleanup, + }; + + // Called by GrContext when the underlying backend context is already or will be destroyed + // before GrContext. + virtual void disconnect(DisconnectType); /** * The GrGpu object normally assumes that no outsider is setting state diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 34223f1cc8..c8c12a388d 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -386,9 +386,51 @@ void GrGLGpu::createPLSSetupProgram() { GR_GL_STATIC_DRAW)); } -void GrGLGpu::contextAbandoned() { - INHERITED::contextAbandoned(); - fProgramCache->abandon(); +void GrGLGpu::disconnect(DisconnectType type) { + INHERITED::disconnect(type); + if (DisconnectType::kCleanup == type) { + if (fHWProgramID) { + GL_CALL(UseProgram(0)); + } + if (fTempSrcFBOID) { + GL_CALL(DeleteFramebuffers(1, &fTempSrcFBOID)); + } + if (fTempDstFBOID) { + GL_CALL(DeleteFramebuffers(1, &fTempDstFBOID)); + } + if (fStencilClearFBOID) { + GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID)); + } + if (fCopyProgramArrayBuffer) { + GL_CALL(DeleteBuffers(1, &fCopyProgramArrayBuffer)); + } + for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) { + if (fCopyPrograms[i].fProgram) { + GL_CALL(DeleteProgram(fCopyPrograms[i].fProgram)); + } + } + if (fWireRectProgram.fProgram) { + GL_CALL(DeleteProgram(fWireRectProgram.fProgram)); + } + if (fWireRectArrayBuffer) { + GL_CALL(DeleteBuffers(1, &fWireRectArrayBuffer)); + } + + if (fPLSSetupProgram.fProgram) { + GL_CALL(DeleteProgram(fPLSSetupProgram.fProgram)); + } + if (fPLSSetupProgram.fArrayBuffer) { + GL_CALL(DeleteBuffers(1, &fPLSSetupProgram.fArrayBuffer)); + } + } else { + if (fProgramCache) { + fProgramCache->abandon(); + } + } + + delete fProgramCache; + fProgramCache = nullptr; + fHWProgramID = 0; fTempSrcFBOID = 0; fTempDstFBOID = 0; @@ -399,8 +441,10 @@ void GrGLGpu::contextAbandoned() { } fWireRectProgram.fProgram = 0; fWireRectArrayBuffer = 0; + fPLSSetupProgram.fProgram = 0; + fPLSSetupProgram.fArrayBuffer = 0; if (this->glCaps().shaderCaps()->pathRenderingSupport()) { - this->glPathRendering()->abandonGpuResources(); + this->glPathRendering()->disconnect(type); } } diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 6d851ee1dd..c77076fc51 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -38,7 +38,7 @@ public: GrContext* context); ~GrGLGpu() override; - void contextAbandoned() override; + void disconnect(DisconnectType) override; const GrGLContext& glContext() const { return *fGLContext; } diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp index 47274f9d69..0ecf58a8e1 100644 --- a/src/gpu/gl/GrGLPathRendering.cpp +++ b/src/gpu/gl/GrGLPathRendering.cpp @@ -91,7 +91,10 @@ GrGLPathRendering::~GrGLPathRendering() { } } -void GrGLPathRendering::abandonGpuResources() { +void GrGLPathRendering::disconnect(GrGpu::DisconnectType type) { + if (GrGpu::DisconnectType::kCleanup == type) { + this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount); + }; fPreallocatedPathCount = 0; } diff --git a/src/gpu/gl/GrGLPathRendering.h b/src/gpu/gl/GrGLPathRendering.h index cd4668fc88..b39c866c6f 100644 --- a/src/gpu/gl/GrGLPathRendering.h +++ b/src/gpu/gl/GrGLPathRendering.h @@ -41,10 +41,10 @@ public: void resetContext(); /** - * Called when the GPU resources have been lost and need to be abandoned - * (for example after a context loss). + * Called when the context either is about to be lost or is lost. DisconnectType indicates + * whether GPU resources should be cleaned up or abandoned when this is called. */ - void abandonGpuResources(); + void disconnect(GrGpu::DisconnectType); bool shouldBindFragmentInputs() const { return fCaps.bindFragmentInputSupport; |