Bug 894405 - Ref GLContext before sending SurfaceStream to compositor r=jgilbert
authorJames Willcox <jwillcox@mozilla.com>
Wed, 17 Jul 2013 13:03:18 -0400
changeset 139191 fbdfcb52c475b98af44d26ce282143682ddca132
parent 139190 ad853510b4d5ad26254efd2faa7a80112d69791b
child 139192 4303c1af09f62c5494089494c82e26d1c9926390
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjgilbert
bugs894405
milestone25.0a1
Bug 894405 - Ref GLContext before sending SurfaceStream to compositor r=jgilbert
gfx/gl/GLScreenBuffer.cpp
gfx/gl/SurfaceStream.cpp
gfx/gl/SurfaceStream.h
gfx/layers/client/CanvasClient.cpp
gfx/layers/opengl/TextureHostOGL.cpp
gfx/layers/opengl/TextureHostOGL.h
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -53,16 +53,17 @@ GLScreenBuffer::Create(GLContext* gl,
 #endif
 
     if (!factory)
         factory = new SurfaceFactory_Basic(gl, caps);
 
     SurfaceStream* stream = SurfaceStream::CreateForType(
         SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread,
                                           caps.preserve),
+        gl,
         nullptr);
 
     return new GLScreenBuffer(gl, caps, factory, stream);
 }
 
 GLScreenBuffer::~GLScreenBuffer()
 {
     delete mFactory;
@@ -359,17 +360,17 @@ GLScreenBuffer::Morph(SurfaceFactory_GL*
     if (newFactory) {
         delete mFactory;
         mFactory = newFactory;
     }
 
     if (mStream->mType == streamType)
         return;
 
-    SurfaceStream* newStream = SurfaceStream::CreateForType(streamType, mStream);
+    SurfaceStream* newStream = SurfaceStream::CreateForType(streamType, mGL, mStream);
     MOZ_ASSERT(newStream);
 
     delete mStream;
     mStream = newStream;
 }
 
 void
 GLScreenBuffer::Attach(SharedSurface* surface, const gfxIntSize& size)
--- a/gfx/gl/SurfaceStream.cpp
+++ b/gfx/gl/SurfaceStream.cpp
@@ -26,30 +26,39 @@ SurfaceStream::ChooseGLStreamType(Surfac
         if (preserveBuffer)
             return SurfaceStreamType::SingleBuffer;
         else
             return SurfaceStreamType::TripleBuffer;
     }
 }
 
 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
 SurfaceStream::New(SurfaceFactory* factory, const gfxIntSize& size,
                    SharedSurface*& surf)
 {
     MOZ_ASSERT(!surf);
     surf = factory->NewSharedSurface(size);
--- a/gfx/gl/SurfaceStream.h
+++ b/gfx/gl/SurfaceStream.h
@@ -7,16 +7,17 @@
 #define SURFACESTREAM_H_
 
 #include <stack>
 #include <set>
 #include "mozilla/Monitor.h"
 #include "mozilla/Attributes.h"
 #include "gfxPoint.h"
 #include "SurfaceTypes.h"
+#include "GLContext.h"
 
 namespace mozilla {
 namespace gfx {
 class SharedSurface;
 class SurfaceFactory;
 
 // Owned by: ScreenBuffer
 class SurfaceStream
@@ -26,36 +27,43 @@ public:
         MainThread,
         OffMainThread
     } OMTC;
 
     static SurfaceStreamType ChooseGLStreamType(OMTC omtc,
                                                 bool preserveBuffer);
 
     static SurfaceStream* CreateForType(SurfaceStreamType type,
+                                        mozilla::gl::GLContext* glContext,
                                         SurfaceStream* prevStream = nullptr);
 
     SurfaceStreamHandle GetShareHandle() {
         return reinterpret_cast<SurfaceStreamHandle>(this);
     }
 
     static SurfaceStream* FromHandle(SurfaceStreamHandle handle) {
         return (SurfaceStream*)handle;
     }
 
     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.
     SharedSurface* mProducer;
     std::set<SharedSurface*> mSurfaces;
     std::stack<SharedSurface*> mScraps;
     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)
         : mType(type)
         , mProducer(nullptr)
         , mMonitor("SurfaceStream monitor")
         , mIsAlive(true)
     {
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -120,15 +120,21 @@ CanvasClientWebGL::Update(gfx::IntSize a
     mDeprecatedTextureClient->SetDescriptor(grallocSurf->GetDescriptor());
 #else
     printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!");
     MOZ_ASSERT(false);
 #endif
   } 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();
 }
 
 }
 }
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -917,16 +917,38 @@ SurfaceStreamHostOGL::GetAsSurface() {
   nsRefPtr<gfxImageSurface> surf = IsValid() ?
     mGL->GetTexImage(mTextureHandle,
                      false,
                      GetTextureFormat())
     : nullptr;
   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<gfxImageSurface>
 TiledDeprecatedTextureHostOGL::GetAsSurface() {
   nsRefPtr<gfxImageSurface> surf = IsValid() ?
     mGL->GetTexImage(mTextureHandle,
                      false,
                      GetTextureFormat())
     : nullptr;
   return surf.forget();
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -480,16 +480,18 @@ public:
   ContentType GetContentType() {
     return (mFormat == gfx::FORMAT_B8G8R8A8) ?
              gfxASurface::CONTENT_COLOR_ALPHA :
              gfxASurface::CONTENT_COLOR;
   }
 
   virtual already_AddRefed<gfxImageSurface> GetAsSurface() MOZ_OVERRIDE;
 
+  virtual void SetBuffer(SurfaceDescriptor* aBuffer, ISurfaceAllocator* aAllocator) MOZ_OVERRIDE;
+
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() { return "SurfaceStreamHostOGL"; }
 #endif
 
   SurfaceStreamHostOGL()
     : mGL(nullptr)
     , mTextureHandle(0)
     , mTextureTarget(LOCAL_GL_TEXTURE_2D)
@@ -501,16 +503,17 @@ protected:
   void DeleteTextures();
 
   gfx::IntSize mSize;
   nsRefPtr<GLContext> mGL;
   GLuint mTextureHandle;
   GLenum mTextureTarget;
   GLuint mUploadTexture;
   GLenum mWrapMode;
+  nsRefPtr<GLContext> mStreamGL;
 };
 
 class TiledDeprecatedTextureHostOGL : public DeprecatedTextureHost
                           , public TextureSourceOGL
 {
 public:
   TiledDeprecatedTextureHostOGL()
     : mTextureHandle(0)