Back out d0b4c5c28fb0 (bug 956993) for Android test failures
authorPhil Ringnalda <philringnalda@gmail.com>
Thu, 27 Feb 2014 20:25:55 -0800
changeset 171474 416792ed8ef5377d4d521da2bfb1f0bdfc52aa1e
parent 171473 9b295844b85b57a2141491cf26f516a4e2e55e86
child 171475 b282d197d23f84f049e1667103cc760848bda7c9
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
bugs956993
milestone30.0a1
backs outd0b4c5c28fb0c42fd13cb91a6fce284b8ef169e1
Back out d0b4c5c28fb0 (bug 956993) for Android test failures CLOSED TREE
gfx/gl/ScopedGLHelpers.cpp
gfx/gl/SharedSurfaceEGL.cpp
gfx/gl/SharedSurfaceEGL.h
gfx/layers/opengl/TextureHostOGL.cpp
--- a/gfx/gl/ScopedGLHelpers.cpp
+++ b/gfx/gl/ScopedGLHelpers.cpp
@@ -119,17 +119,16 @@ ScopedTexture::UnwrapImpl()
 void
 ScopedBindTexture::Init(GLenum aTarget)
 {
     mTarget = aTarget;
     mOldTex = 0;
     GLenum bindingTarget = (aTarget == LOCAL_GL_TEXTURE_2D) ? LOCAL_GL_TEXTURE_BINDING_2D
                          : (aTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) ? LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB
                          : (aTarget == LOCAL_GL_TEXTURE_CUBE_MAP) ? LOCAL_GL_TEXTURE_BINDING_CUBE_MAP
-                         : (aTarget == LOCAL_GL_TEXTURE_EXTERNAL) ? LOCAL_GL_TEXTURE_EXTERNAL
                          : LOCAL_GL_NONE;
     MOZ_ASSERT(bindingTarget != LOCAL_GL_NONE);
     mGL->GetUIntegerv(bindingTarget, &mOldTex);
 }
 
 ScopedBindTexture::ScopedBindTexture(GLContext* aGL, GLuint aNewTex, GLenum aTarget)
         : ScopedGLWrapper<ScopedBindTexture>(aGL)
     {
--- a/gfx/gl/SharedSurfaceEGL.cpp
+++ b/gfx/gl/SharedSurfaceEGL.cpp
@@ -22,102 +22,180 @@ SharedSurface_EGLImage*
 SharedSurface_EGLImage::Create(GLContext* prodGL,
                                const GLFormats& formats,
                                const gfx::IntSize& size,
                                bool hasAlpha,
                                EGLContext context)
 {
     GLLibraryEGL* egl = &sEGLLibrary;
     MOZ_ASSERT(egl);
-    MOZ_ASSERT(context);
 
-    if (!HasExtensions(egl, prodGL)) {
+    if (!HasExtensions(egl, prodGL))
         return nullptr;
-    }
 
     MOZ_ALWAYS_TRUE(prodGL->MakeCurrent());
     GLuint prodTex = CreateTextureForOffscreen(prodGL, formats, size);
-    if (!prodTex) {
+    if (!prodTex)
         return nullptr;
-    }
-
-    EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(prodTex);
-    EGLImage image = egl->fCreateImage(egl->Display(), context,
-                                       LOCAL_EGL_GL_TEXTURE_2D, buffer,
-                                       nullptr);
-    if (!image) {
-        prodGL->fDeleteTextures(1, &prodTex);
-        return nullptr;
-    }
 
     return new SharedSurface_EGLImage(prodGL, egl,
                                       size, hasAlpha,
-                                      formats, prodTex, image);
+                                      formats, prodTex);
 }
 
 
 bool
 SharedSurface_EGLImage::HasExtensions(GLLibraryEGL* egl, GLContext* gl)
 {
     return egl->HasKHRImageBase() &&
            egl->IsExtensionSupported(GLLibraryEGL::KHR_gl_texture_2D_image) &&
-           gl->IsExtensionSupported(GLContext::OES_EGL_image_external);
+           gl->IsExtensionSupported(GLContext::OES_EGL_image);
 }
 
 SharedSurface_EGLImage::SharedSurface_EGLImage(GLContext* gl,
                                                GLLibraryEGL* egl,
                                                const gfx::IntSize& size,
                                                bool hasAlpha,
                                                const GLFormats& formats,
-                                               GLuint prodTex,
-                                               EGLImage image)
+                                               GLuint prodTex)
     : SharedSurface_GL(SharedSurfaceType::EGLImageShare,
                         AttachmentType::GLTexture,
                         gl,
                         size,
                         hasAlpha)
     , mMutex("SharedSurface_EGLImage mutex")
     , mEGL(egl)
     , mFormats(formats)
     , mProdTex(prodTex)
-    , mImage(image)
+    , mProdTexForPipe(0)
+    , mImage(0)
     , mCurConsGL(nullptr)
     , mConsTex(0)
     , mSync(0)
+    , mPipeFailed(false)
+    , mPipeComplete(false)
+    , mPipeActive(false)
 {}
 
 SharedSurface_EGLImage::~SharedSurface_EGLImage()
 {
     mEGL->fDestroyImage(Display(), mImage);
     mImage = 0;
 
     mGL->MakeCurrent();
     mGL->fDeleteTextures(1, &mProdTex);
     mProdTex = 0;
 
+    if (mProdTexForPipe) {
+        mGL->fDeleteTextures(1, &mProdTexForPipe);
+        mProdTexForPipe = 0;
+    }
+
     if (mConsTex) {
         MOZ_ASSERT(mGarbageBin);
         mGarbageBin->Trash(mConsTex);
         mConsTex = 0;
     }
 
     if (mSync) {
         // We can't call this unless we have the ext, but we will always have
         // the ext if we have something to destroy.
         mEGL->fDestroySync(Display(), mSync);
         mSync = 0;
     }
 }
 
 void
+SharedSurface_EGLImage::LockProdImpl()
+{
+    MutexAutoLock lock(mMutex);
+
+    if (!mPipeComplete)
+        return;
+
+    if (mPipeActive)
+        return;
+
+    mGL->BlitHelper()->BlitTextureToTexture(mProdTex, mProdTexForPipe, Size(), Size());
+    mGL->fDeleteTextures(1, &mProdTex);
+    mProdTex = mProdTexForPipe;
+    mProdTexForPipe = 0;
+    mPipeActive = true;
+}
+
+static bool
+CreateTexturePipe(GLLibraryEGL* const egl, GLContext* const gl,
+                  const GLFormats& formats, const gfx::IntSize& size,
+                  GLuint* const out_tex, EGLImage* const out_image)
+{
+    MOZ_ASSERT(out_tex && out_image);
+    *out_tex = 0;
+    *out_image = 0;
+
+    GLuint tex = CreateTextureForOffscreen(gl, formats, size);
+    if (!tex)
+        return false;
+
+    EGLContext context = GLContextEGL::Cast(gl)->GetEGLContext();
+    MOZ_ASSERT(context);
+    EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(tex);
+    EGLImage image = egl->fCreateImage(egl->Display(), context,
+                                       LOCAL_EGL_GL_TEXTURE_2D, buffer,
+                                       nullptr);
+    if (!image) {
+        gl->fDeleteTextures(1, &tex);
+        return false;
+    }
+
+    // Success.
+    *out_tex = tex;
+    *out_image = image;
+    return true;
+}
+
+void
 SharedSurface_EGLImage::Fence()
 {
     MutexAutoLock lock(mMutex);
     mGL->MakeCurrent();
 
+    if (!mPipeActive) {
+        MOZ_ASSERT(!mSync);
+        MOZ_ASSERT(!mPipeComplete);
+
+        if (!mPipeFailed) {
+            if (!CreateTexturePipe(mEGL, mGL, mFormats, Size(),
+                                   &mProdTexForPipe, &mImage))
+            {
+                mPipeFailed = true;
+            }
+        }
+
+        if (!mPixels) {
+            SurfaceFormat format =
+                  HasAlpha() ? SurfaceFormat::B8G8R8A8
+                             : SurfaceFormat::B8G8R8X8;
+            mPixels = Factory::CreateDataSourceSurface(Size(), format);
+        }
+
+        DataSourceSurface::MappedSurface map;
+        mPixels->Map(DataSourceSurface::MapType::WRITE, &map);
+
+        nsRefPtr<gfxImageSurface> wrappedData =
+            new gfxImageSurface(map.mData,
+                                ThebesIntSize(mPixels->GetSize()),
+                                map.mStride,
+                                SurfaceFormatToImageFormat(mPixels->GetFormat()));
+        ReadScreenIntoImageSurface(mGL, wrappedData);
+        mPixels->Unmap();
+        return;
+    }
+    MOZ_ASSERT(mPipeActive);
+    MOZ_ASSERT(mCurConsGL);
+
     if (mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync) &&
         mGL->IsExtensionSupported(GLContext::OES_EGL_sync))
     {
         if (mSync) {
             MOZ_ALWAYS_TRUE( mEGL->fDestroySync(Display(), mSync) );
             mSync = 0;
         }
 
@@ -166,38 +244,52 @@ SharedSurface_EGLImage::WaitSync()
 
 
 EGLDisplay
 SharedSurface_EGLImage::Display() const
 {
     return mEGL->Display();
 }
 
-void
-SharedSurface_EGLImage::AcquireConsumerTexture(GLContext* consGL, GLuint* out_texture, GLuint* out_target)
+GLuint
+SharedSurface_EGLImage::AcquireConsumerTexture(GLContext* consGL)
 {
     MutexAutoLock lock(mMutex);
     MOZ_ASSERT(!mCurConsGL || consGL == mCurConsGL);
+    if (mPipeFailed)
+        return 0;
+
+    if (mPipeActive) {
+        MOZ_ASSERT(mConsTex);
+
+        return mConsTex;
+    }
 
     if (!mConsTex) {
         consGL->fGenTextures(1, &mConsTex);
-        MOZ_ASSERT(mConsTex);
+        ScopedBindTexture autoTex(consGL, mConsTex);
+        consGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, mImage);
 
-        ScopedBindTexture autoTex(consGL, mConsTex, LOCAL_GL_TEXTURE_EXTERNAL);
-        consGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_EXTERNAL, mImage);
-
+        mPipeComplete = true;
         mCurConsGL = consGL;
         mGarbageBin = consGL->TexGarbageBin();
     }
 
     MOZ_ASSERT(consGL == mCurConsGL);
-    *out_texture = mConsTex;
-    *out_target = LOCAL_GL_TEXTURE_EXTERNAL;
+    return 0;
 }
 
+DataSourceSurface*
+SharedSurface_EGLImage::GetPixels() const
+{
+    MutexAutoLock lock(mMutex);
+    return mPixels;
+}
+
+
 
 SurfaceFactory_EGLImage*
 SurfaceFactory_EGLImage::Create(GLContext* prodGL,
                                         const SurfaceCaps& caps)
 {
     EGLContext context = GLContextEGL::Cast(prodGL)->GetEGLContext();
 
     return new SurfaceFactory_EGLImage(prodGL, context, caps);
--- a/gfx/gl/SharedSurfaceEGL.h
+++ b/gfx/gl/SharedSurfaceEGL.h
@@ -35,52 +35,59 @@ public:
         return (SharedSurface_EGLImage*)surf;
     }
 
 protected:
     mutable Mutex mMutex;
     GLLibraryEGL* const mEGL;
     const GLFormats mFormats;
     GLuint mProdTex;
+    RefPtr<gfx::DataSourceSurface> mPixels;
+    GLuint mProdTexForPipe; // Moves to mProdTex when mPipeActive becomes true.
     EGLImage mImage;
     GLContext* mCurConsGL;
     GLuint mConsTex;
     nsRefPtr<TextureGarbageBin> mGarbageBin;
     EGLSync mSync;
+    bool mPipeFailed;   // Pipe creation failed, and has been abandoned.
+    bool mPipeComplete; // Pipe connects (mPipeActive ? mProdTex : mProdTexForPipe) to mConsTex.
+    bool mPipeActive;   // Pipe is complete and in use for production.
 
     SharedSurface_EGLImage(GLContext* gl,
                            GLLibraryEGL* egl,
                            const gfx::IntSize& size,
                            bool hasAlpha,
                            const GLFormats& formats,
-                           GLuint prodTex,
-                           EGLImage image);
+                           GLuint prodTex);
 
     EGLDisplay Display() const;
 
     static bool HasExtensions(GLLibraryEGL* egl, GLContext* gl);
 
 public:
     virtual ~SharedSurface_EGLImage();
 
-    virtual void LockProdImpl() {}
+    virtual void LockProdImpl();
     virtual void UnlockProdImpl() {}
 
 
     virtual void Fence();
     virtual bool WaitSync();
 
 
     virtual GLuint Texture() const {
         return mProdTex;
     }
 
     // Implementation-specific functions below:
-    // Returns texture and target
-    void AcquireConsumerTexture(GLContext* consGL, GLuint* out_texture, GLuint* out_target);
+    // Returns 0 if the pipe isn't ready. If 0, use GetPixels below.
+    GLuint AcquireConsumerTexture(GLContext* consGL);
+
+    // Will be void if AcquireConsumerTexture returns non-zero.
+    gfx::DataSourceSurface* GetPixels() const;
 };
 
 
 
 class SurfaceFactory_EGLImage
     : public SurfaceFactory_GL
 {
 public:
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -510,20 +510,25 @@ StreamTextureSourceOGL::RetrieveTextureF
       mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8
                                        : SurfaceFormat::R8G8B8X8;
       break;
     }
     case SharedSurfaceType::EGLImageShare: {
       SharedSurface_EGLImage* eglImageSurf =
           SharedSurface_EGLImage::Cast(sharedSurf);
 
-      eglImageSurf->AcquireConsumerTexture(gl(), &mTextureHandle, &mTextureTarget);
-      MOZ_ASSERT(mTextureHandle);
-      mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8
-                                       : SurfaceFormat::R8G8B8X8;
+      mTextureHandle = eglImageSurf->AcquireConsumerTexture(gl());
+      mTextureTarget = eglImageSurf->TextureTarget();
+      if (!mTextureHandle) {
+        toUpload = eglImageSurf->GetPixels();
+        MOZ_ASSERT(toUpload);
+      } else {
+        mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8
+                                         : SurfaceFormat::R8G8B8X8;
+      }
       break;
     }
 #ifdef XP_MACOSX
     case SharedSurfaceType::IOSurface: {
       SharedSurface_IOSurface* glTexSurf = SharedSurface_IOSurface::Cast(sharedSurf);
       mTextureHandle = glTexSurf->Texture();
       mTextureTarget = glTexSurf->TextureTarget();
       MOZ_ASSERT(mTextureHandle);