diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp index b5b61943077f..0f9d6369a8af 100644 --- a/dom/canvas/WebGLContext.cpp +++ b/dom/canvas/WebGLContext.cpp @@ -1257,10 +1257,13 @@ bool WebGLContext::PushRemoteTexture( ownerClient->PushTexture(textureId, ownerId, keepAlive, size, surfaceFormat, *desc); - auto recycledSurface = ownerClient->GetRecycledSharedSurface( - size, surfaceFormat, desc->type(), ownerId); - if (recycledSurface) { - swapChain.StoreRecycledSurface(recycledSurface); + + // Look for a recycled surface that matches the swap chain. + while (auto recycledSurface = ownerClient->GetRecycledSharedSurface( + size, surfaceFormat, desc->type(), ownerId)) { + if (swapChain.StoreRecycledSurface(recycledSurface)) { + break; + } } return true; } diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp index 1120c18af419..8e6a403b07b7 100644 --- a/gfx/gl/GLScreenBuffer.cpp +++ b/gfx/gl/GLScreenBuffer.cpp @@ -75,9 +75,16 @@ void SwapChain::ClearPool() { mPrevFrontBuffer = nullptr; } -void SwapChain::StoreRecycledSurface( +bool SwapChain::StoreRecycledSurface( const std::shared_ptr& surf) { + MOZ_ASSERT(mFactory); + if (!mFactory || NS_WARN_IF(surf->mDesc.gl != mFactory->mDesc.gl)) { + // Ensure we don't accidentally store an expired shared surface or from a + // different context. + return false; + } mPool.push(surf); + return true; } // - diff --git a/gfx/gl/GLScreenBuffer.h b/gfx/gl/GLScreenBuffer.h index d3fe2d131e3e..0fc3df2a9da8 100644 --- a/gfx/gl/GLScreenBuffer.h +++ b/gfx/gl/GLScreenBuffer.h @@ -71,7 +71,7 @@ class SwapChain final { virtual ~SwapChain(); void ClearPool(); - void StoreRecycledSurface(const std::shared_ptr& surf); + bool StoreRecycledSurface(const std::shared_ptr& surf); const auto& FrontBuffer() const { return mFrontBuffer; } UniquePtr Acquire(const gfx::IntSize&, gfx::ColorSpace2); diff --git a/gfx/layers/ipc/CanvasTranslator.cpp b/gfx/layers/ipc/CanvasTranslator.cpp index 9b001c4300a9..96a921d835f0 100644 --- a/gfx/layers/ipc/CanvasTranslator.cpp +++ b/gfx/layers/ipc/CanvasTranslator.cpp @@ -114,6 +114,10 @@ bool CanvasTranslator::EnsureSharedContextWebgl() { if (!mSharedContext || mSharedContext->IsContextLost()) { if (mSharedContext) { ForceDrawTargetWebglFallback(); + if (mRemoteTextureOwner) { + // Ensure any shared surfaces referring to the old context go away. + mRemoteTextureOwner->ClearRecycledTextures(); + } } mSharedContext = gfx::SharedContextWebgl::Create(); if (!mSharedContext || mSharedContext->IsContextLost()) {