From 3cea37c9c2d1bf12eca916e0f9af1cf7ec2e8171 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Fri, 10 Aug 2018 17:14:57 +0200 Subject: [PATCH] Bug 1469496 - Handle video memory purge with WebRender. r=sotaro --- gfx/layers/ipc/CompositorBridgeParent.cpp | 8 ++++++++ gfx/layers/ipc/CompositorBridgeParent.h | 1 + gfx/webrender_bindings/RendererOGL.cpp | 18 ++++++++++++++++++ gfx/webrender_bindings/WebRenderAPI.cpp | 6 ++++++ gfx/webrender_bindings/WebRenderAPI.h | 2 ++ gfx/webrender_bindings/src/bindings.rs | 6 ++++++ .../webrender_ffi_generated.h | 4 ++++ 7 files changed, 45 insertions(+) diff --git a/gfx/layers/ipc/CompositorBridgeParent.cpp b/gfx/layers/ipc/CompositorBridgeParent.cpp index 536e9b4c6d45..bf90584b6ba1 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -2354,6 +2354,14 @@ CompositorBridgeParent::NotifyWebRenderError(wr::WebRenderError aError) Unused << SendNotifyWebRenderError(aError); } +void +CompositorBridgeParent::NotifyWebRenderContextPurge() +{ + MOZ_ASSERT(CompositorLoop() == MessageLoop::current()); + RefPtr api = mWrBridge->GetWebRenderAPI(); + api->ClearAllCaches(); +} + #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) //#define PLUGINS_LOG(...) printf_stderr("CP [%s]: ", __FUNCTION__); // printf_stderr(__VA_ARGS__); diff --git a/gfx/layers/ipc/CompositorBridgeParent.h b/gfx/layers/ipc/CompositorBridgeParent.h index 996f6e948088..ab758d472d4c 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.h +++ b/gfx/layers/ipc/CompositorBridgeParent.h @@ -274,6 +274,7 @@ public: bool IsSameProcess() const override; void NotifyWebRenderError(wr::WebRenderError aError); + void NotifyWebRenderContextPurge(); void NotifyPipelineRendered(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, TimeStamp& aCompositeStart, diff --git a/gfx/webrender_bindings/RendererOGL.cpp b/gfx/webrender_bindings/RendererOGL.cpp index a0a6634888de..7beba4fe1af0 100644 --- a/gfx/webrender_bindings/RendererOGL.cpp +++ b/gfx/webrender_bindings/RendererOGL.cpp @@ -95,6 +95,12 @@ RendererOGL::Update() } } +static void +DoNotifyWebRenderContextPurge(layers::CompositorBridgeParent* aBridge) +{ + aBridge->NotifyWebRenderContextPurge(); +} + bool RendererOGL::UpdateAndRender(bool aReadback) { @@ -150,6 +156,18 @@ RendererOGL::UpdateAndRender(bool aReadback) mFrameStartTime = TimeStamp(); #endif + gl::GLContext* gl = mCompositor->gl(); + if (gl->IsSupported(gl::GLFeature::robustness)) { + GLenum resetStatus = gl->fGetGraphicsResetStatus(); + if (resetStatus == LOCAL_GL_PURGED_CONTEXT_RESET_NV) { + layers::CompositorThreadHolder::Loop()->PostTask(NewRunnableFunction( + "DoNotifyWebRenderContextPurgeRunnable", + &DoNotifyWebRenderContextPurge, + mBridge + )); + } + } + // TODO: Flush pending actions such as texture deletions/unlocks and // textureHosts recycling. diff --git a/gfx/webrender_bindings/WebRenderAPI.cpp b/gfx/webrender_bindings/WebRenderAPI.cpp index eed72056f25c..74b33f070f8c 100644 --- a/gfx/webrender_bindings/WebRenderAPI.cpp +++ b/gfx/webrender_bindings/WebRenderAPI.cpp @@ -422,6 +422,12 @@ WebRenderAPI::Readback(const TimeStamp& aStartTime, task.Wait(); } +void +WebRenderAPI::ClearAllCaches() +{ + wr_api_clear_all_caches(mDocHandle); +} + void WebRenderAPI::Pause() { diff --git a/gfx/webrender_bindings/WebRenderAPI.h b/gfx/webrender_bindings/WebRenderAPI.h index b33b40139035..b768abb6dd5e 100644 --- a/gfx/webrender_bindings/WebRenderAPI.h +++ b/gfx/webrender_bindings/WebRenderAPI.h @@ -198,6 +198,8 @@ public: void Readback(const TimeStamp& aStartTime, gfx::IntSize aSize, uint8_t *aBuffer, uint32_t aBufferSize); + void ClearAllCaches(); + void Pause(); bool Resume(); diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index 2b37489659a9..9d7a8df4d76d 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -1029,6 +1029,12 @@ pub unsafe extern "C" fn wr_api_shut_down(dh: &mut DocumentHandle) { dh.api.shut_down(); } +/// cbindgen:postfix=WR_DESTRUCTOR_SAFE_FUNC +#[no_mangle] +pub unsafe extern "C" fn wr_api_clear_all_caches(dh: &mut DocumentHandle) { + dh.api.send_debug_cmd(DebugCommand::ClearCaches(ClearCache::all())); +} + fn make_transaction(do_async: bool) -> Transaction { let mut transaction = Transaction::new(); // Ensure that we either use async scene building or not based on the diff --git a/gfx/webrender_bindings/webrender_ffi_generated.h b/gfx/webrender_bindings/webrender_ffi_generated.h index 032c7f4f3bf0..2291c25ef712 100644 --- a/gfx/webrender_bindings/webrender_ffi_generated.h +++ b/gfx/webrender_bindings/webrender_ffi_generated.h @@ -1050,6 +1050,10 @@ void wr_api_capture(DocumentHandle *aDh, uint32_t aBitsRaw) WR_FUNC; +WR_INLINE +void wr_api_clear_all_caches(DocumentHandle *aDh) +WR_DESTRUCTOR_SAFE_FUNC; + WR_INLINE void wr_api_clone(DocumentHandle *aDh, DocumentHandle **aOutHandle)