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 151476 fbdfcb52c475b98af44d26ce282143682ddca132
parent 151475 ad853510b4d5ad26254efd2faa7a80112d69791b
child 151477 4303c1af09f62c5494089494c82e26d1c9926390
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs894405
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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)