diff --git a/gfx/layers/TextureSourceProvider.cpp b/gfx/layers/TextureSourceProvider.cpp index 826acc37f03a..edfa620b5f32 100644 --- a/gfx/layers/TextureSourceProvider.cpp +++ b/gfx/layers/TextureSourceProvider.cpp @@ -46,6 +46,7 @@ TextureSourceProvider::ReadUnlockTextures() texture->ReadUnlock(); } #endif + mReferenceUntilAfterComposition.Clear(); mUnlockAfterComposition.Clear(); } @@ -55,6 +56,12 @@ TextureSourceProvider::UnlockAfterComposition(TextureHost* aTexture) mUnlockAfterComposition.AppendElement(aTexture); } +void +TextureSourceProvider::ReferenceUntilAfterComposition(DataTextureSource* aTextureSource) +{ + mReferenceUntilAfterComposition.AppendElement(aTextureSource); +} + bool TextureSourceProvider::NotifyNotUsedAfterComposition(TextureHost* aTextureHost) { diff --git a/gfx/layers/TextureSourceProvider.h b/gfx/layers/TextureSourceProvider.h index 830c0be21110..08c8a2686ac5 100644 --- a/gfx/layers/TextureSourceProvider.h +++ b/gfx/layers/TextureSourceProvider.h @@ -64,6 +64,13 @@ public: /// the texture itself requires it. virtual void UnlockAfterComposition(TextureHost* aTexture); + /// This is used for client storage support on OSX. On Nvidia hardware, it + /// seems that if we glDeleteTextures on a texture too early, even if we've + /// waited on the texture with glFinishObjectAPPLE, we'll see visual defects. + /// This just holds a reference to the texture until ReadUnlockTextures, + /// but we don't need to unlock it since we have already done so. + void ReferenceUntilAfterComposition(DataTextureSource* aTextureSource); + /// Most compositor backends operate asynchronously under the hood. This /// means that when a layer stops using a texture it is often desirable to /// wait for the end of the next composition before NotifyNotUsed() call. @@ -131,6 +138,9 @@ private: // An array of locks that will need to be unlocked after the next composition. nsTArray> mUnlockAfterComposition; + // See ReferenceUntilAfterComposition. + nsTArray> mReferenceUntilAfterComposition; + // An array of TextureHosts that will need to call NotifyNotUsed() after the next composition. nsTArray> mNotifyNotUsedAfterComposition; }; diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index f9c20258f19d..b47f1f41c1df 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -927,6 +927,10 @@ BufferTextureHost::UnbindTextureSource() mFirstSource->Unbind(); } + if (mFirstSource && mFirstSource->IsDirectMap() && mProvider) { + mProvider->ReferenceUntilAfterComposition(mFirstSource); + } + // This texture is not used by any layer anymore. // If the texture doesn't have an intermediate buffer, it means we are // compositing synchronously on the CPU, so we don't need to wait until