Bug 980684 - Actually use IOSurfaces on Mac. - r=snorp
authorJeff Gilbert <jgilbert@mozilla.com>
Mon, 10 Mar 2014 19:08:50 -0700
changeset 191120 7d62c468b48b16637872106664ba2c264fb85a63
parent 191119 d6e7ed4cd0a62cd94b8f0946d41cf1468c2c3710
child 191121 dfc89871248c89eed76f37da7c90b4644b17a0f2
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs980684
milestone30.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 980684 - Actually use IOSurfaces on Mac. - r=snorp
gfx/gl/GLContext.h
gfx/gl/SharedSurfaceGL.cpp
gfx/gl/SharedSurfaceGL.h
gfx/gl/SharedSurfaceIO.cpp
gfx/gl/SharedSurfaceIO.h
gfx/layers/opengl/TextureHostOGL.cpp
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -2693,23 +2693,22 @@ protected:
 #ifdef DEBUG
     // GLDebugMode will check that we don't send call
     // to a GLContext that isn't current on the current
     // thread.
     // Store the current context when binding to thread local
     // storage to support DebugMode on an arbitrary thread.
     static unsigned sCurrentGLContextTLS;
 #endif
-
+    
     ScopedDeletePtr<GLBlitHelper> mBlitHelper;
     ScopedDeletePtr<GLBlitTextureImageHelper> mBlitTextureImageHelper;
     ScopedDeletePtr<GLReadTexImageHelper> mReadTexImageHelper;
 
 public:
-
     GLBlitHelper* BlitHelper();
     GLBlitTextureImageHelper* BlitTextureImageHelper();
     GLReadTexImageHelper* ReadTexImageHelper();
 
     // Assumes shares are created by all sharing with the same global context.
     bool SharesWith(const GLContext* other) const {
         MOZ_ASSERT(!this->mSharedContext || !this->mSharedContext->mSharedContext);
         MOZ_ASSERT(!other->mSharedContext || !other->mSharedContext->mSharedContext);
--- a/gfx/gl/SharedSurfaceGL.cpp
+++ b/gfx/gl/SharedSurfaceGL.cpp
@@ -402,32 +402,35 @@ bool
 SharedSurface_GLTexture::WaitSync()
 {
     MutexAutoLock lock(mMutex);
     if (!mSync) {
         // We must have used glFinish instead of glFenceSync.
         return true;
     }
 
-    MOZ_ASSERT(mConsGL, "Did you forget to call a deferred `SetConsumerGL()`?");
     mConsGL->MakeCurrent();
     MOZ_ASSERT(mConsGL->IsExtensionSupported(GLContext::ARB_sync));
 
     mConsGL->fWaitSync(mSync,
                        0,
                        LOCAL_GL_TIMEOUT_IGNORED);
     mConsGL->fDeleteSync(mSync);
     mSync = 0;
 
     return true;
 }
 
-void
-SharedSurface_GLTexture::SetConsumerGL(GLContext* consGL)
+GLuint
+SharedSurface_GLTexture::ConsTexture(GLContext* consGL)
 {
     MutexAutoLock lock(mMutex);
     MOZ_ASSERT(consGL);
     MOZ_ASSERT(mGL->SharesWith(consGL));
+    MOZ_ASSERT_IF(mConsGL, consGL == mConsGL);
+
     mConsGL = consGL;
+
+    return mTex;
 }
 
 } /* namespace gfx */
 } /* namespace mozilla */
--- a/gfx/gl/SharedSurfaceGL.h
+++ b/gfx/gl/SharedSurfaceGL.h
@@ -255,17 +255,22 @@ public:
     virtual bool WaitSync() MOZ_OVERRIDE;
 
 
     virtual GLuint ProdTexture() MOZ_OVERRIDE {
         return mTex;
     }
 
     // Custom:
-    void SetConsumerGL(GLContext* consGL);
+
+    GLuint ConsTexture(GLContext* consGL);
+
+    GLenum ConsTextureTarget() const {
+        return ProdTextureTarget();
+    }
 };
 
 class SurfaceFactory_GLTexture
     : public SurfaceFactory_GL
 {
 protected:
     GLContext* const mConsGL;
 
--- a/gfx/gl/SharedSurfaceIO.cpp
+++ b/gfx/gl/SharedSurfaceIO.cpp
@@ -36,67 +36,104 @@ bool
 SharedSurface_IOSurface::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
                                     GLenum format, GLenum type, GLvoid *pixels)
 {
     // Calling glReadPixels when an IOSurface is bound to the current framebuffer
     // can cause corruption in following glReadPixel calls (even if they aren't
     // reading from an IOSurface).
     // We workaround this by copying to a temporary texture, and doing the readback
     // from that.
-    ScopedTexture texture(mGL);
-    ScopedBindTexture bindTex(mGL, texture.Texture());
-    mGL->fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0,
-                         HasAlpha() ? LOCAL_GL_RGBA : LOCAL_GL_RGB,
-                         x, y,
-                         width, height, 0);
+    MOZ_ASSERT(mGL->IsCurrent());
+
+
+    ScopedTexture destTex(mGL);
+    {
+        ScopedFramebufferForTexture srcFB(mGL, ProdTexture(), ProdTextureTarget());
 
-    ScopedFramebufferForTexture fb(mGL, texture.Texture());
-    ScopedBindFramebuffer bindFB(mGL, fb.FB());
+        ScopedBindFramebuffer bindFB(mGL, srcFB.FB());
+        ScopedBindTexture bindTex(mGL, destTex.Texture());
+        mGL->fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0,
+                             HasAlpha() ? LOCAL_GL_RGBA : LOCAL_GL_RGB,
+                             x, y,
+                             width, height, 0);
+    }
 
+    ScopedFramebufferForTexture destFB(mGL, destTex.Texture());
+
+    ScopedBindFramebuffer bindFB(mGL, destFB.FB());
     mGL->fReadPixels(0, 0, width, height, format, type, pixels);
     return true;
 }
 
+static void
+BackTextureWithIOSurf(GLContext* gl, GLuint tex, MacIOSurface* ioSurf)
+{
+    MOZ_ASSERT(gl->IsCurrent());
+
+    ScopedBindTexture texture(gl, tex, LOCAL_GL_TEXTURE_RECTANGLE_ARB);
+
+    gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
+                        LOCAL_GL_TEXTURE_MIN_FILTER,
+                        LOCAL_GL_LINEAR);
+    gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
+                        LOCAL_GL_TEXTURE_MAG_FILTER,
+                        LOCAL_GL_LINEAR);
+    gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
+                        LOCAL_GL_TEXTURE_WRAP_S,
+                        LOCAL_GL_CLAMP_TO_EDGE);
+    gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
+                        LOCAL_GL_TEXTURE_WRAP_T,
+                        LOCAL_GL_CLAMP_TO_EDGE);
+
+    CGLContextObj cgl = GLContextCGL::Cast(gl)->GetCGLContext();
+    MOZ_ASSERT(cgl);
+
+    ioSurf->CGLTexImageIOSurface2D(cgl);
+}
+
 SharedSurface_IOSurface::SharedSurface_IOSurface(MacIOSurface* surface,
                                                  GLContext* gl,
                                                  const gfx::IntSize& size,
                                                  bool hasAlpha)
   : SharedSurface_GL(SharedSurfaceType::IOSurface, AttachmentType::GLTexture, gl, size, hasAlpha)
   , mSurface(surface)
+  , mCurConsGL(nullptr)
+  , mConsTex(0)
 {
-    mGL->MakeCurrent();
-    mGL->fGenTextures(1, &mTexture);
-
-    ScopedBindTexture texture(mGL, mTexture, LOCAL_GL_TEXTURE_RECTANGLE_ARB);
+    gl->MakeCurrent();
+    mProdTex = 0;
+    gl->fGenTextures(1, &mProdTex);
+    BackTextureWithIOSurf(gl, mProdTex, surface);
+}
 
-    mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
-                        LOCAL_GL_TEXTURE_MIN_FILTER,
-                        LOCAL_GL_LINEAR);
-    mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
-                        LOCAL_GL_TEXTURE_MAG_FILTER,
-                        LOCAL_GL_LINEAR);
-    mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
-                        LOCAL_GL_TEXTURE_WRAP_S,
-                        LOCAL_GL_CLAMP_TO_EDGE);
-    mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
-                        LOCAL_GL_TEXTURE_WRAP_T,
-                        LOCAL_GL_CLAMP_TO_EDGE);
+GLuint
+SharedSurface_IOSurface::ConsTexture(GLContext* consGL)
+{
+    if (!mCurConsGL) {
+        mCurConsGL = consGL;
+    }
+    MOZ_ASSERT(consGL == mCurConsGL);
 
-    CGLContextObj ctx = GLContextCGL::Cast(mGL)->GetCGLContext();
-    MOZ_ASSERT(ctx);
+    if (!mConsTex) {
+        consGL->MakeCurrent();
+        mConsTex = 0;
+        consGL->fGenTextures(1, &mConsTex);
+        BackTextureWithIOSurf(consGL, mConsTex, mSurface);
+    }
 
-    surface->CGLTexImageIOSurface2D(ctx);
+    return mConsTex;
 }
 
 SharedSurface_IOSurface::~SharedSurface_IOSurface()
 {
-    if (mTexture) {
+    if (mProdTex) {
         DebugOnly<bool> success = mGL->MakeCurrent();
         MOZ_ASSERT(success);
-        mGL->fDeleteTextures(1, &mTexture);
+        mGL->fDeleteTextures(1, &mProdTex);
+        mGL->fDeleteTextures(1, &mConsTex); // This will work if we're shared.
     }
 }
 
 SharedSurface*
 SurfaceFactory_IOSurface::CreateShared(const gfx::IntSize& size)
 {
     bool hasAlpha = mReadCaps.alpha;
     RefPtr<MacIOSurface> surf =
--- a/gfx/gl/SharedSurfaceIO.h
+++ b/gfx/gl/SharedSurfaceIO.h
@@ -26,36 +26,42 @@ public:
 
     virtual void Fence() MOZ_OVERRIDE;
     virtual bool WaitSync() MOZ_OVERRIDE { return true; }
 
     virtual bool ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
                             GLenum format, GLenum type, GLvoid *pixels) MOZ_OVERRIDE;
 
     virtual GLuint ProdTexture() MOZ_OVERRIDE {
-        return mTexture;
+        return mProdTex;
     }
 
     virtual GLenum ProdTextureTarget() const MOZ_OVERRIDE {
         return LOCAL_GL_TEXTURE_RECTANGLE_ARB;
     }
 
     static SharedSurface_IOSurface* Cast(SharedSurface *surf) {
         MOZ_ASSERT(surf->Type() == SharedSurfaceType::IOSurface);
         return static_cast<SharedSurface_IOSurface*>(surf);
     }
 
-    MacIOSurface* GetIOSurface() { return mSurface; }
+    GLuint ConsTexture(GLContext* consGL);
+
+    GLenum ConsTextureTarget() const {
+        return LOCAL_GL_TEXTURE_RECTANGLE_ARB;
+    }
 
 private:
     SharedSurface_IOSurface(MacIOSurface* surface, GLContext* gl, const gfx::IntSize& size, bool hasAlpha);
 
     RefPtr<MacIOSurface> mSurface;
     nsRefPtr<gfxImageSurface> mImageSurface;
-    GLuint mTexture;
+    GLuint mProdTex;
+    const GLContext* mCurConsGL;
+    GLuint mConsTex;
 };
 
 class SurfaceFactory_IOSurface : public SurfaceFactory_GL
 {
 public:
     SurfaceFactory_IOSurface(GLContext* gl,
                              const SurfaceCaps& caps)
         : SurfaceFactory_GL(gl, SharedSurfaceType::IOSurface, caps)
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -498,19 +498,18 @@ StreamTextureSourceOGL::RetrieveTextureF
   gl()->MakeCurrent();
 
   mSize = IntSize(sharedSurf->Size().width, sharedSurf->Size().height);
 
   DataSourceSurface* toUpload = nullptr;
   switch (sharedSurf->Type()) {
     case SharedSurfaceType::GLTextureShare: {
       SharedSurface_GLTexture* glTexSurf = SharedSurface_GLTexture::Cast(sharedSurf);
-      glTexSurf->SetConsumerGL(gl());
-      mTextureHandle = glTexSurf->ProdTexture();
-      mTextureTarget = glTexSurf->ProdTextureTarget();
+      mTextureHandle = glTexSurf->ConsTexture(gl());
+      mTextureTarget = glTexSurf->ConsTextureTarget();
       MOZ_ASSERT(mTextureHandle);
       mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8
                                        : SurfaceFormat::R8G8B8X8;
       break;
     }
     case SharedSurfaceType::EGLImageShare: {
       SharedSurface_EGLImage* eglImageSurf =
           SharedSurface_EGLImage::Cast(sharedSurf);
@@ -519,18 +518,18 @@ StreamTextureSourceOGL::RetrieveTextureF
       MOZ_ASSERT(mTextureHandle);
       mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8
                                        : SurfaceFormat::R8G8B8X8;
       break;
     }
 #ifdef XP_MACOSX
     case SharedSurfaceType::IOSurface: {
       SharedSurface_IOSurface* glTexSurf = SharedSurface_IOSurface::Cast(sharedSurf);
-      mTextureHandle = glTexSurf->ProdTexture();
-      mTextureTarget = glTexSurf->ProdTextureTarget();
+      mTextureHandle = glTexSurf->ConsTexture(gl());
+      mTextureTarget = glTexSurf->ConsTextureTarget();
       MOZ_ASSERT(mTextureHandle);
       mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8
                                        : SurfaceFormat::R8G8B8X8;
       break;
     }
 #endif
     case SharedSurfaceType::Basic: {
       toUpload = SharedSurface_Basic::Cast(sharedSurf)->GetData();