From 2fed89ee3a4662cae8aaeb4e34b8068577698e8b Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 17 Jul 2013 13:03:18 -0400 Subject: [PATCH] Bug 894405 - Ref GLContext before sending SurfaceStream to compositor r=jgilbert --- gfx/gl/GLScreenBuffer.cpp | 3 ++- gfx/gl/SurfaceStream.cpp | 19 ++++++++++++++----- gfx/gl/SurfaceStream.h | 8 ++++++++ gfx/layers/client/CanvasClient.cpp | 6 ++++++ gfx/layers/opengl/TextureHostOGL.cpp | 22 ++++++++++++++++++++++ gfx/layers/opengl/TextureHostOGL.h | 3 +++ 6 files changed, 55 insertions(+), 6 deletions(-) diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp index b3771db14b26..21becd7212e9 100644 --- a/gfx/gl/GLScreenBuffer.cpp +++ b/gfx/gl/GLScreenBuffer.cpp @@ -58,6 +58,7 @@ GLScreenBuffer::Create(GLContext* gl, SurfaceStream* stream = SurfaceStream::CreateForType( SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread, caps.preserve), + gl, nullptr); return new GLScreenBuffer(gl, caps, factory, stream); @@ -364,7 +365,7 @@ GLScreenBuffer::Morph(SurfaceFactory_GL* newFactory, SurfaceStreamType streamTyp if (mStream->mType == streamType) return; - SurfaceStream* newStream = SurfaceStream::CreateForType(streamType, mStream); + SurfaceStream* newStream = SurfaceStream::CreateForType(streamType, mGL, mStream); MOZ_ASSERT(newStream); delete mStream; diff --git a/gfx/gl/SurfaceStream.cpp b/gfx/gl/SurfaceStream.cpp index ccbcdc3223e3..4048fe78abe0 100644 --- a/gfx/gl/SurfaceStream.cpp +++ b/gfx/gl/SurfaceStream.cpp @@ -31,20 +31,29 @@ SurfaceStream::ChooseGLStreamType(SurfaceStream::OMTC omtc, } SurfaceStream* -SurfaceStream::CreateForType(SurfaceStreamType type, SurfaceStream* prevStream) +SurfaceStream::CreateForType(SurfaceStreamType type, mozilla::gl::GLContext* glContext, SurfaceStream* prevStream) { + SurfaceStream* result = nullptr; + switch (type) { case SurfaceStreamType::SingleBuffer: - return new SurfaceStream_SingleBuffer(prevStream); + result = new SurfaceStream_SingleBuffer(prevStream); + break; case SurfaceStreamType::TripleBuffer_Copy: - return new SurfaceStream_TripleBuffer_Copy(prevStream); + result = new SurfaceStream_TripleBuffer_Copy(prevStream); + break; case SurfaceStreamType::TripleBuffer_Async: - return new SurfaceStream_TripleBuffer_Async(prevStream); + result = new SurfaceStream_TripleBuffer_Async(prevStream); + break; case SurfaceStreamType::TripleBuffer: - return new SurfaceStream_TripleBuffer(prevStream); + result = new SurfaceStream_TripleBuffer(prevStream); + break; default: MOZ_CRASH("Invalid Type."); } + + result->mGLContext = glContext; + return result; } void diff --git a/gfx/gl/SurfaceStream.h b/gfx/gl/SurfaceStream.h index a61ca53b0b09..57ea8f82c058 100644 --- a/gfx/gl/SurfaceStream.h +++ b/gfx/gl/SurfaceStream.h @@ -12,6 +12,7 @@ #include "mozilla/Attributes.h" #include "gfxPoint.h" #include "SurfaceTypes.h" +#include "GLContext.h" namespace mozilla { namespace gfx { @@ -31,6 +32,7 @@ public: bool preserveBuffer); static SurfaceStream* CreateForType(SurfaceStreamType type, + mozilla::gl::GLContext* glContext, SurfaceStream* prevStream = nullptr); SurfaceStreamHandle GetShareHandle() { @@ -42,6 +44,8 @@ public: } const SurfaceStreamType mType; + + mozilla::gl::GLContext* GLContext() const { return mGLContext; } protected: // |mProd| is owned by us, but can be ripped away when // creating a new GLStream from this one. @@ -51,6 +55,10 @@ protected: mutable Monitor mMonitor; bool mIsAlive; + // Do not use this. It exists solely so we can ref it in CanvasClientWebGL::Update() + // before sent up to the compositor. You have been warned (Bug 894405) + mozilla::gl::GLContext* mGLContext; + // |previous| can be null, indicating this is the first one. // Otherwise, we pull in |mProd| from |previous| an our initial surface. SurfaceStream(SurfaceStreamType type, SurfaceStream* prevStream) diff --git a/gfx/layers/client/CanvasClient.cpp b/gfx/layers/client/CanvasClient.cpp index 0a8ff3f1bfcf..2286ab87d156 100644 --- a/gfx/layers/client/CanvasClient.cpp +++ b/gfx/layers/client/CanvasClient.cpp @@ -125,6 +125,12 @@ CanvasClientWebGL::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) } else { SurfaceStreamHandle handle = stream->GetShareHandle(); mDeprecatedTextureClient->SetDescriptor(SurfaceStreamDescriptor(handle, false)); + + // Bug 894405 + // + // Ref this so the SurfaceStream doesn't disappear unexpectedly. The + // Compositor will need to unref it when finished. + aLayer->mGLContext->AddRef(); } aLayer->Painted(); diff --git a/gfx/layers/opengl/TextureHostOGL.cpp b/gfx/layers/opengl/TextureHostOGL.cpp index 92980652af67..be204f72e90f 100644 --- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -922,6 +922,28 @@ SurfaceStreamHostOGL::GetAsSurface() { return surf.forget(); } +void +SurfaceStreamHostOGL::SetBuffer(SurfaceDescriptor* aBuffer, ISurfaceAllocator* aAllocator) +{ + MOZ_ASSERT(!mBuffer, "Will leak the old mBuffer"); + mBuffer = aBuffer; + mDeAllocator = aAllocator; + + if (mBuffer && mBuffer->type() == SurfaceDescriptor::TSurfaceStreamDescriptor) { + // Bug 894405 + // + // The SurfaceStream's GLContext was refed before being passed up to us, so + // we need to ensure it gets unrefed when we are finished. + const SurfaceStreamDescriptor& streamDesc = + mBuffer->get_SurfaceStreamDescriptor(); + + SurfaceStream* surfStream = SurfaceStream::FromHandle(streamDesc.handle()); + if (surfStream) { + mStreamGL = dont_AddRef(surfStream->GLContext()); + } + } +} + already_AddRefed TiledDeprecatedTextureHostOGL::GetAsSurface() { nsRefPtr surf = IsValid() ? diff --git a/gfx/layers/opengl/TextureHostOGL.h b/gfx/layers/opengl/TextureHostOGL.h index b9f4313b4dd4..9cb47ce754ab 100644 --- a/gfx/layers/opengl/TextureHostOGL.h +++ b/gfx/layers/opengl/TextureHostOGL.h @@ -485,6 +485,8 @@ public: virtual already_AddRefed GetAsSurface() MOZ_OVERRIDE; + virtual void SetBuffer(SurfaceDescriptor* aBuffer, ISurfaceAllocator* aAllocator) MOZ_OVERRIDE; + #ifdef MOZ_LAYERS_HAVE_LOG virtual const char* Name() { return "SurfaceStreamHostOGL"; } #endif @@ -506,6 +508,7 @@ protected: GLenum mTextureTarget; GLuint mUploadTexture; GLenum mWrapMode; + nsRefPtr mStreamGL; }; class TiledDeprecatedTextureHostOGL : public DeprecatedTextureHost