Bug 942505 - Move everything SharedHandle-related out of GLContext - r=jgilbert
authorBenoit Jacob <bjacob@mozilla.com>
Tue, 03 Dec 2013 13:44:38 -0500
changeset 158910 3856aa97c77c16d5ef2b86892c4c94dc45cfef53
parent 158909 bac9d5883f366bde9b6d8c1a8728fc9df93e3258
child 158911 101f294ad43cef67b1d0319e317eb252da48d829
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersjgilbert
bugs942505
milestone28.0a1
Bug 942505 - Move everything SharedHandle-related out of GLContext - r=jgilbert
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextProviderEGL.cpp
gfx/gl/GLSharedHandleHelpers.cpp
gfx/gl/GLSharedHandleHelpers.h
gfx/gl/moz.build
gfx/layers/opengl/TextureHostOGL.cpp
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -49,16 +49,17 @@ using namespace mozilla;
 #include "mozilla/Mutex.h"
 #include "mozilla/CondVar.h"
 #include "AndroidBridge.h"
 #include "mozilla/dom/ScreenOrientation.h"
 #include "mozilla/Hal.h"
 #include "GLContextProvider.h"
 #include "GLContext.h"
 #include "TexturePoolOGL.h"
+#include "GLSharedHandleHelpers.h"
 
 using namespace mozilla::gl;
 
 typedef nsNPAPIPluginInstance::VideoInfo VideoInfo;
 
 class PluginEventRunnable : public nsRunnable
 {
 public:
@@ -133,19 +134,20 @@ public:
 
     if (!EnsureGLContext())
       return 0;
 
     if (mTextureInfo.mWidth == 0 || mTextureInfo.mHeight == 0)
       return 0;
 
     SharedTextureHandle handle =
-      sPluginContext->CreateSharedHandle(gl::SameProcess,
-                                         (void*)mTextureInfo.mTexture,
-                                         gl::TextureID);
+      gl::CreateSharedHandle(sPluginContext,
+                             gl::SameProcess,
+                             (void*)mTextureInfo.mTexture,
+                             gl::TextureID);
 
     // We want forget about this now, so delete the texture. Assigning it to zero
     // ensures that we create a new one in Lock()
     sPluginContext->fDeleteTextures(1, &mTextureInfo.mTexture);
     mTextureInfo.mTexture = 0;
     
     return handle;
   }
@@ -1013,19 +1015,20 @@ void* nsNPAPIPluginInstance::AcquireCont
 }
 
 SharedTextureHandle nsNPAPIPluginInstance::CreateSharedHandle()
 {
   if (mContentTexture) {
     return mContentTexture->CreateSharedHandle();
   } else if (mContentSurface) {
     EnsureGLContext();
-    return sPluginContext->CreateSharedHandle(gl::SameProcess,
-                                              mContentSurface,
-                                              gl::SurfaceTexture);
+    return gl::CreateSharedHandle(sPluginContext,
+                                  gl::SameProcess,
+                                  mContentSurface,
+                                  gl::SurfaceTexture);
   } else return 0;
 }
 
 void* nsNPAPIPluginInstance::AcquireVideoWindow()
 {
   nsSurfaceTexture* surface = CreateSurfaceTexture();
   if (!surface)
     return nullptr;
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -54,16 +54,17 @@ using mozilla::DefaultXDisplay;
 #include "nsIFocusManager.h"
 #include "nsFocusManager.h"
 #include "nsIDOMDragEvent.h"
 #include "nsIScrollableFrame.h"
 #include "nsIDocShell.h"
 #include "ImageContainer.h"
 #include "nsIDOMHTMLCollection.h"
 #include "GLContext.h"
+#include "GLSharedHandleHelpers.h"
 #include "nsIContentInlines.h"
 #include "mozilla/MiscEvents.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/TextEvents.h"
 
 #include "nsContentCID.h"
 #include "nsWidgetsCID.h"
 static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
@@ -1503,19 +1504,20 @@ already_AddRefed<ImageContainer> nsPlugi
   nsRefPtr<ImageContainer> container = LayerManager::CreateImageContainer();
 
   ImageFormat format = ImageFormat::SHARED_TEXTURE;
   nsRefPtr<Image> img = container->CreateImage(&format, 1);
 
   SharedTextureImage::Data data;
 
   data.mShareType = gl::SameProcess;
-  data.mHandle = mInstance->GLContext()->CreateSharedHandle(data.mShareType,
-                                                            aVideoInfo->mSurfaceTexture,
-                                                            gl::SurfaceTexture);
+  data.mHandle = gl::CreateSharedHandle(mInstance->GLContext(),
+                                        data.mShareType,
+                                        aVideoInfo->mSurfaceTexture,
+                                        gl::SurfaceTexture);
 
   // The logic below for Honeycomb is just a guess, but seems to work. We don't have a separate
   // inverted flag for video.
   data.mInverted = AndroidBridge::Bridge()->IsHoneycomb() ? true : mInstance->Inverted();
   data.mSize = gfxIntSize(aVideoInfo->mDimensions.width, aVideoInfo->mDimensions.height);
 
   SharedTextureImage* pluginImage = static_cast<SharedTextureImage*>(img.get());
   pluginImage->SetData(data);
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -2544,81 +2544,16 @@ public:
 
     /*
      * Return size of this offscreen context.
      *
      * Only valid if IsOffscreen() returns true.
      */
     const gfxIntSize& OffscreenSize() const;
 
-    /*
-     * Create a new shared GLContext content handle, using the passed buffer as a source.
-     * Must be released by ReleaseSharedHandle. UpdateSharedHandle will have no effect
-     * on handles created with this method, as the caller owns the source (the passed buffer)
-     * and is responsible for updating it accordingly.
-     */
-    virtual SharedTextureHandle CreateSharedHandle(SharedTextureShareType shareType,
-                                                   void* buffer,
-                                                   SharedTextureBufferType bufferType)
-    { return 0; }
-    /**
-     * Publish GLContext content to intermediate buffer attached to shared handle.
-     * Shared handle content is ready to be used after call returns, and no need extra Flush/Finish are required.
-     * GLContext must be current before this call
-     */
-    virtual void UpdateSharedHandle(SharedTextureShareType shareType,
-                                    SharedTextureHandle sharedHandle)
-    { }
-    /**
-     * - It is better to call ReleaseSharedHandle before original GLContext destroyed,
-     *     otherwise warning will be thrown on attempt to destroy Texture associated with SharedHandle, depends on backend implementation.
-     * - It does not require to be called on context where it was created,
-     *     because SharedHandle suppose to keep Context reference internally,
-     *     or don't require specific context at all, for example IPC SharedHandle.
-     * - Not recommended to call this between AttachSharedHandle and Draw Target call.
-     *      if it is really required for some special backend, then DetachSharedHandle API must be added with related implementation.
-     * - It is recommended to stop any possible access to SharedHandle (Attachments, pending GL calls) before calling Release,
-     *      otherwise some artifacts might appear or even crash if API backend implementation does not expect that.
-     * SharedHandle (currently EGLImage) does not require GLContext because it is EGL call, and can be destroyed
-     *   at any time, unless EGLImage have siblings (which are not expected with current API).
-     */
-    virtual void ReleaseSharedHandle(SharedTextureShareType shareType,
-                                     SharedTextureHandle sharedHandle)
-    { }
-
-
-    typedef struct {
-        GLenum mTarget;
-        SurfaceFormat mTextureFormat;
-        gfx3DMatrix mTextureTransform;
-    } SharedHandleDetails;
-
-    /**
-     * Returns information necessary for rendering a shared handle.
-     * These values change depending on what sharing mechanism is in use
-     */
-    virtual bool GetSharedHandleDetails(SharedTextureShareType shareType,
-                                        SharedTextureHandle sharedHandle,
-                                        SharedHandleDetails& details)
-    { return false; }
-    /**
-     * Attach Shared GL Handle to GL_TEXTURE_2D target
-     * GLContext must be current before this call
-     */
-    virtual bool AttachSharedHandle(SharedTextureShareType shareType,
-                                    SharedTextureHandle sharedHandle)
-    { return false; }
-
-    /**
-     * Detach Shared GL Handle from GL_TEXTURE_2D target
-     */
-    virtual void DetachSharedHandle(SharedTextureShareType shareType,
-                                    SharedTextureHandle sharedHandle)
-    { }
-
     void BindFB(GLuint fb) {
         fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb);
         MOZ_ASSERT(!fb || fIsFramebuffer(fb));
     }
 
     void BindDrawFB(GLuint fb) {
         fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, fb);
     }
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -266,17 +266,16 @@ public:
         , mSurfaceOverride(EGL_NO_SURFACE)
         , mContext(context)
         , mThebesSurface(nullptr)
         , mBound(false)
         , mIsPBuffer(false)
         , mIsDoubleBuffered(false)
         , mCanBindToTexture(false)
         , mShareWithEGLImage(false)
-        , mTemporaryEGLImageTexture(0)
     {
         // any EGL contexts will always be GLESv2
         SetProfileVersion(ContextProfile::OpenGLES, 200);
 
 #ifdef DEBUG
         printf_stderr("Initializing context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
 #endif
 #if defined(MOZ_WIDGET_GONK)
@@ -289,23 +288,16 @@ public:
                 mHwc = nullptr;
             }
         }
 #endif
     }
 
     ~GLContextEGL()
     {
-        if (MakeCurrent()) {
-            if (mTemporaryEGLImageTexture != 0) {
-                fDeleteTextures(1, &mTemporaryEGLImageTexture);
-                mTemporaryEGLImageTexture = 0;
-            }
-        }
-
         MarkDestroyed();
 
 #ifdef DEBUG
         printf_stderr("Destroying context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
 #endif
 
         sEGLLibrary.fDestroyContext(EGL_DISPLAY(), mContext);
         mozilla::gl::DestroySurface(mSurface);
@@ -572,29 +564,16 @@ public:
     void BindOffscreenFramebuffer();
 
     static already_AddRefed<GLContextEGL>
     CreateEGLPixmapOffscreenContext(const gfxIntSize& size);
 
     static already_AddRefed<GLContextEGL>
     CreateEGLPBufferOffscreenContext(const gfxIntSize& size);
 
-    virtual SharedTextureHandle CreateSharedHandle(SharedTextureShareType shareType,
-                                                   void* buffer,
-                                                   SharedTextureBufferType bufferType);
-    virtual void UpdateSharedHandle(SharedTextureShareType shareType,
-                                    SharedTextureHandle sharedHandle);
-    virtual void ReleaseSharedHandle(SharedTextureShareType shareType,
-                                     SharedTextureHandle sharedHandle);
-    virtual bool GetSharedHandleDetails(SharedTextureShareType shareType,
-                                        SharedTextureHandle sharedHandle,
-                                        SharedHandleDetails& details);
-    virtual bool AttachSharedHandle(SharedTextureShareType shareType,
-                                    SharedTextureHandle sharedHandle);
-
 protected:
     friend class GLContextProviderEGL;
 
     EGLConfig  mConfig;
     EGLSurface mSurface;
     EGLSurface mSurfaceOverride;
     EGLContext mContext;
     nsRefPtr<gfxASurface> mThebesSurface;
@@ -603,20 +582,16 @@ protected:
     bool mIsPBuffer;
     bool mIsDoubleBuffered;
     bool mCanBindToTexture;
     bool mShareWithEGLImage;
 #ifdef MOZ_WIDGET_GONK
     nsRefPtr<HwcComposer2D> mHwc;
 #endif
 
-    // A dummy texture ID that can be used when we need a texture object whose
-    // images we're going to define with EGLImageTargetTexture2D.
-    GLuint mTemporaryEGLImageTexture;
-
     static EGLSurface CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config,
                                                            EGLenum bindToTextureFormat,
                                                            gfxIntSize& pbsize)
     {
         nsTArray<EGLint> pbattrs(16);
         EGLSurface surface = nullptr;
 
     TRY_AGAIN_POWER_OF_TWO:
@@ -651,329 +626,16 @@ protected:
             NS_WARNING("Failed to create pbuffer surface");
             return nullptr;
         }
 
         return surface;
     }
 };
 
-
-enum SharedHandleType {
-    SharedHandleType_Image
-#ifdef MOZ_WIDGET_ANDROID
-    , SharedHandleType_SurfaceTexture
-#endif
-};
-
-class SharedTextureHandleWrapper
-{
-public:
-    SharedTextureHandleWrapper(SharedHandleType aHandleType) : mHandleType(aHandleType)
-    {
-    }
-
-    virtual ~SharedTextureHandleWrapper()
-    {
-    }
-
-    SharedHandleType Type() { return mHandleType; }
-
-    SharedHandleType mHandleType;
-};
-
-#ifdef MOZ_WIDGET_ANDROID
-
-class SurfaceTextureWrapper: public SharedTextureHandleWrapper
-{
-public:
-    SurfaceTextureWrapper(nsSurfaceTexture* aSurfaceTexture) :
-        SharedTextureHandleWrapper(SharedHandleType_SurfaceTexture)
-        , mSurfaceTexture(aSurfaceTexture)
-    {
-    }
-
-    virtual ~SurfaceTextureWrapper() {
-        mSurfaceTexture = nullptr;
-    }
-
-    nsSurfaceTexture* SurfaceTexture() { return mSurfaceTexture; }
-
-    nsRefPtr<nsSurfaceTexture> mSurfaceTexture;
-};
-
-#endif // MOZ_WIDGET_ANDROID
-
-class EGLTextureWrapper : public SharedTextureHandleWrapper
-{
-public:
-    EGLTextureWrapper() :
-        SharedTextureHandleWrapper(SharedHandleType_Image)
-        , mEGLImage(nullptr)
-        , mSyncObject(nullptr)
-    {
-    }
-
-    // Args are the active GL context, and a texture in that GL
-    // context for which to create an EGLImage.  After the EGLImage
-    // is created, the texture is unused by EGLTextureWrapper.
-    bool CreateEGLImage(GLContextEGL *ctx, GLuint texture) {
-        MOZ_ASSERT(!mEGLImage && texture && sEGLLibrary.HasKHRImageBase());
-        static const EGLint eglAttributes[] = {
-            LOCAL_EGL_NONE
-        };
-        EGLContext eglContext = (EGLContext)ctx->GetEGLContext();
-        mEGLImage = sEGLLibrary.fCreateImage(EGL_DISPLAY(), eglContext, LOCAL_EGL_GL_TEXTURE_2D,
-                                             (EGLClientBuffer)texture, eglAttributes);
-        if (!mEGLImage) {
-#ifdef DEBUG
-            printf_stderr("Could not create EGL images: ERROR (0x%04x)\n", sEGLLibrary.fGetError());
-#endif
-            return false;
-        }
-        return true;
-    }
-
-    virtual ~EGLTextureWrapper() {
-        if (mEGLImage) {
-            sEGLLibrary.fDestroyImage(EGL_DISPLAY(), mEGLImage);
-            mEGLImage = nullptr;
-        }
-    }
-
-    const EGLImage GetEGLImage() {
-        return mEGLImage;
-    }
-
-    // Insert a sync point on the given context, which should be the current active
-    // context.
-    bool MakeSync(GLContext *ctx) {
-        MOZ_ASSERT(mSyncObject == nullptr);
-
-        if (sEGLLibrary.IsExtensionSupported(GLLibraryEGL::KHR_fence_sync)) {
-            mSyncObject = sEGLLibrary.fCreateSync(EGL_DISPLAY(), LOCAL_EGL_SYNC_FENCE, nullptr);
-            // We need to flush to make sure the sync object enters the command stream;
-            // we can't use EGL_SYNC_FLUSH_COMMANDS_BIT at wait time, because the wait
-            // happens on a different thread/context.
-            ctx->fFlush();
-        }
-
-        if (mSyncObject == EGL_NO_SYNC) {
-            // we failed to create one, so just do a finish
-            ctx->fFinish();
-        }
-
-        return true;
-    }
-
-    bool WaitSync() {
-        if (!mSyncObject) {
-            // if we have no sync object, then we did a Finish() earlier
-            return true;
-        }
-
-        // wait at most 1 second; this should really be never/rarely hit
-        const uint64_t ns_per_ms = 1000 * 1000;
-        EGLTime timeout = 1000 * ns_per_ms;
-
-        EGLint result = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), mSyncObject, 0, timeout);
-        sEGLLibrary.fDestroySync(EGL_DISPLAY(), mSyncObject);
-        mSyncObject = nullptr;
-
-        return result == LOCAL_EGL_CONDITION_SATISFIED;
-    }
-
-private:
-    EGLImage mEGLImage;
-    EGLSync mSyncObject;
-};
-
-void
-GLContextEGL::UpdateSharedHandle(SharedTextureShareType shareType,
-                                 SharedTextureHandle sharedHandle)
-{
-    if (shareType != SameProcess) {
-        NS_ERROR("Implementation not available for this sharing type");
-        return;
-    }
-
-    SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
-
-    NS_ASSERTION(wrapper->Type() == SharedHandleType_Image, "Expected EGLImage shared handle");
-    NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
-
-    EGLTextureWrapper* wrap = reinterpret_cast<EGLTextureWrapper*>(wrapper);
-    // We need to copy the current GLContext drawing buffer to the texture
-    // exported by the EGLImage.  Need to save both the read FBO and the texture
-    // binding, because we're going to munge them to do this.
-    ScopedBindTexture autoTex(this, mTemporaryEGLImageTexture);
-    fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, wrap->GetEGLImage());
-
-    // CopyTexSubImage2D, is ~2x slower than simple FBO render to texture with
-    // draw quads, but if we want that, we need to assure that our default
-    // framebuffer is texture-backed.
-    gfxIntSize size = OffscreenSize();
-    BlitHelper()->BlitFramebufferToTexture(0, mTemporaryEGLImageTexture, size, size);
-
-    // Make sure our copy is finished, so that we can be ready to draw
-    // in different thread GLContext.  If we have KHR_fence_sync, then
-    // we insert a sync object, otherwise we have to do a GuaranteeResolve.
-    wrap->MakeSync(this);
-}
-
-SharedTextureHandle
-GLContextEGL::CreateSharedHandle(SharedTextureShareType shareType,
-                                 void* buffer,
-                                 SharedTextureBufferType bufferType)
-{
-    // Both EGLImage and SurfaceTexture only support same-process currently, but
-    // it's possible to make SurfaceTexture work across processes. We should do that.
-    if (shareType != SameProcess)
-        return 0;
-
-    switch (bufferType) {
-#ifdef MOZ_WIDGET_ANDROID
-    case SharedTextureBufferType::SurfaceTexture:
-        if (!IsExtensionSupported(GLContext::OES_EGL_image_external)) {
-            NS_WARNING("Missing GL_OES_EGL_image_external");
-            return 0;
-        }
-
-        return (SharedTextureHandle) new SurfaceTextureWrapper(reinterpret_cast<nsSurfaceTexture*>(buffer));
-#endif
-    case SharedTextureBufferType::TextureID: {
-        if (!mShareWithEGLImage)
-            return 0;
-
-        GLuint texture = (uintptr_t)buffer;
-        EGLTextureWrapper* tex = new EGLTextureWrapper();
-        if (!tex->CreateEGLImage(this, texture)) {
-            NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
-            delete tex;
-            return 0;
-        }
-
-        return (SharedTextureHandle)tex;
-    }
-    default:
-        NS_ERROR("Unknown shared texture buffer type");
-        return 0;
-    }
-}
-
-void GLContextEGL::ReleaseSharedHandle(SharedTextureShareType shareType,
-                                       SharedTextureHandle sharedHandle)
-{
-    if (shareType != SameProcess) {
-        NS_ERROR("Implementation not available for this sharing type");
-        return;
-    }
-
-    SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
-
-    switch (wrapper->Type()) {
-#ifdef MOZ_WIDGET_ANDROID
-    case SharedHandleType_SurfaceTexture:
-        delete wrapper;
-        break;
-#endif
-    
-    case SharedHandleType_Image: {
-        NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
-
-        EGLTextureWrapper* wrap = (EGLTextureWrapper*)sharedHandle;
-        delete wrap;
-        break;
-    }
-
-    default:
-        NS_ERROR("Unknown shared handle type");
-        return;
-    }
-}
-
-bool GLContextEGL::GetSharedHandleDetails(SharedTextureShareType shareType,
-                                          SharedTextureHandle sharedHandle,
-                                          SharedHandleDetails& details)
-{
-    if (shareType != SameProcess)
-        return false;
-
-    SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
-
-    switch (wrapper->Type()) {
-#ifdef MOZ_WIDGET_ANDROID
-    case SharedHandleType_SurfaceTexture: {
-        SurfaceTextureWrapper* surfaceWrapper = reinterpret_cast<SurfaceTextureWrapper*>(wrapper);
-
-        details.mTarget = LOCAL_GL_TEXTURE_EXTERNAL;
-        details.mTextureFormat = FORMAT_R8G8B8A8;
-        surfaceWrapper->SurfaceTexture()->GetTransformMatrix(details.mTextureTransform);
-        break;
-    }
-#endif
-
-    case SharedHandleType_Image:
-        details.mTarget = LOCAL_GL_TEXTURE_2D;
-        details.mTextureFormat = FORMAT_R8G8B8A8;
-        break;
-
-    default:
-        NS_ERROR("Unknown shared handle type");
-        return false;
-    }
-
-    return true;
-}
-
-bool GLContextEGL::AttachSharedHandle(SharedTextureShareType shareType,
-                                      SharedTextureHandle sharedHandle)
-{
-    if (shareType != SameProcess)
-        return false;
-
-    SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
-
-    switch (wrapper->Type()) {
-#ifdef MOZ_WIDGET_ANDROID
-    case SharedHandleType_SurfaceTexture: {
-#ifndef DEBUG
-        /**
-         * NOTE: SurfaceTexture spams us if there are any existing GL errors, so we'll clear
-         * them here in order to avoid that.
-         */
-        GetAndClearError();
-#endif
-        SurfaceTextureWrapper* surfaceTextureWrapper = reinterpret_cast<SurfaceTextureWrapper*>(wrapper);
-
-        // FIXME: SurfaceTexture provides a transform matrix which is supposed to
-        // be applied to the texture coordinates. We should return that here
-        // so we can render correctly. Bug 775083
-        surfaceTextureWrapper->SurfaceTexture()->UpdateTexImage();
-        break;
-    }
-#endif // MOZ_WIDGET_ANDROID
-
-    case SharedHandleType_Image: {
-        NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
-
-        EGLTextureWrapper* wrap = (EGLTextureWrapper*)sharedHandle;
-        wrap->WaitSync();
-        fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, wrap->GetEGLImage());
-        break;
-    }
-
-    default:
-        NS_ERROR("Unknown shared handle type");
-        return false;
-    }
-
-    return true;
-}
-
 bool
 GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize)
 {
 	return ResizeScreenBuffer(aNewSize);
 }
 
 already_AddRefed<TextureImage>
 GLContextEGL::CreateTextureImage(const nsIntSize& aSize,
new file mode 100644
--- /dev/null
+++ b/gfx/gl/GLSharedHandleHelpers.cpp
@@ -0,0 +1,328 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLContext.h"
+#include "GLLibraryEGL.h"
+#include "GLSharedHandleHelpers.h"
+
+namespace mozilla {
+namespace gl {
+
+enum SharedHandleType {
+    SharedHandleType_Image
+#ifdef MOZ_WIDGET_ANDROID
+    , SharedHandleType_SurfaceTexture
+#endif
+};
+
+class SharedTextureHandleWrapper
+{
+public:
+    SharedTextureHandleWrapper(SharedHandleType aHandleType) : mHandleType(aHandleType)
+    {
+    }
+
+    virtual ~SharedTextureHandleWrapper()
+    {
+    }
+
+    SharedHandleType Type() { return mHandleType; }
+
+    SharedHandleType mHandleType;
+};
+
+#ifdef MOZ_WIDGET_ANDROID
+
+class SurfaceTextureWrapper: public SharedTextureHandleWrapper
+{
+public:
+    SurfaceTextureWrapper(nsSurfaceTexture* aSurfaceTexture) :
+        SharedTextureHandleWrapper(SharedHandleType_SurfaceTexture)
+        , mSurfaceTexture(aSurfaceTexture)
+    {
+    }
+
+    virtual ~SurfaceTextureWrapper() {
+        mSurfaceTexture = nullptr;
+    }
+
+    nsSurfaceTexture* SurfaceTexture() { return mSurfaceTexture; }
+
+    nsRefPtr<nsSurfaceTexture> mSurfaceTexture;
+};
+
+#endif // MOZ_WIDGET_ANDROID
+
+class EGLTextureWrapper : public SharedTextureHandleWrapper
+{
+public:
+    EGLTextureWrapper() :
+        SharedTextureHandleWrapper(SharedHandleType_Image)
+        , mEGLImage(nullptr)
+        , mSyncObject(nullptr)
+    {
+    }
+
+    // Args are the active GL context, and a texture in that GL
+    // context for which to create an EGLImage.  After the EGLImage
+    // is created, the texture is unused by EGLTextureWrapper.
+    bool CreateEGLImage(GLContext *ctx, uintptr_t texture) {
+        MOZ_ASSERT(!mEGLImage && texture && sEGLLibrary.HasKHRImageBase());
+        static const EGLint eglAttributes[] = {
+            LOCAL_EGL_NONE
+        };
+        EGLContext eglContext = (EGLContext)ctx->GetNativeData(GLContext::NativeGLContext);
+        mEGLImage = sEGLLibrary.fCreateImage(EGL_DISPLAY(), eglContext, LOCAL_EGL_GL_TEXTURE_2D,
+                                             (EGLClientBuffer)texture, eglAttributes);
+        if (!mEGLImage) {
+#ifdef DEBUG
+            printf_stderr("Could not create EGL images: ERROR (0x%04x)\n", sEGLLibrary.fGetError());
+#endif
+            return false;
+        }
+        return true;
+    }
+
+    virtual ~EGLTextureWrapper() {
+        if (mEGLImage) {
+            sEGLLibrary.fDestroyImage(EGL_DISPLAY(), mEGLImage);
+            mEGLImage = nullptr;
+        }
+    }
+
+    const EGLImage GetEGLImage() {
+        return mEGLImage;
+    }
+
+    // Insert a sync point on the given context, which should be the current active
+    // context.
+    bool MakeSync(GLContext *ctx) {
+        MOZ_ASSERT(mSyncObject == nullptr);
+
+        if (sEGLLibrary.IsExtensionSupported(GLLibraryEGL::KHR_fence_sync)) {
+            mSyncObject = sEGLLibrary.fCreateSync(EGL_DISPLAY(), LOCAL_EGL_SYNC_FENCE, nullptr);
+            // We need to flush to make sure the sync object enters the command stream;
+            // we can't use EGL_SYNC_FLUSH_COMMANDS_BIT at wait time, because the wait
+            // happens on a different thread/context.
+            ctx->fFlush();
+        }
+
+        if (mSyncObject == EGL_NO_SYNC) {
+            // we failed to create one, so just do a finish
+            ctx->fFinish();
+        }
+
+        return true;
+    }
+
+    bool WaitSync() {
+        if (!mSyncObject) {
+            // if we have no sync object, then we did a Finish() earlier
+            return true;
+        }
+
+        // wait at most 1 second; this should really be never/rarely hit
+        const uint64_t ns_per_ms = 1000 * 1000;
+        EGLTime timeout = 1000 * ns_per_ms;
+
+        EGLint result = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), mSyncObject, 0, timeout);
+        sEGLLibrary.fDestroySync(EGL_DISPLAY(), mSyncObject);
+        mSyncObject = nullptr;
+
+        return result == LOCAL_EGL_CONDITION_SATISFIED;
+    }
+
+private:
+    EGLImage mEGLImage;
+    EGLSync mSyncObject;
+};
+
+static bool DoesEGLContextSupportSharingWithEGLImage(GLContext *gl)
+{
+    return sEGLLibrary.HasKHRImageBase() &&
+           sEGLLibrary.HasKHRImageTexture2D() &&
+           gl->IsExtensionSupported(GLContext::OES_EGL_image);
+}
+
+SharedTextureHandle CreateSharedHandle(GLContext* gl,
+                                       SharedTextureShareType shareType,
+                                       void* buffer,
+                                       SharedTextureBufferType bufferType)
+{
+    // unimplemented outside of EGL
+    if (gl->GetContextType() != ContextTypeEGL)
+        return 0;
+
+    // Both EGLImage and SurfaceTexture only support same-process currently, but
+    // it's possible to make SurfaceTexture work across processes. We should do that.
+    if (shareType != SameProcess)
+        return 0;
+
+    switch (bufferType) {
+#ifdef MOZ_WIDGET_ANDROID
+    case SharedTextureBufferType::SurfaceTexture:
+        if (!gl->IsExtensionSupported(GLContext::OES_EGL_image_external)) {
+            NS_WARNING("Missing GL_OES_EGL_image_external");
+            return 0;
+        }
+
+        return (SharedTextureHandle) new SurfaceTextureWrapper(reinterpret_cast<nsSurfaceTexture*>(buffer));
+#endif
+    case SharedTextureBufferType::TextureID: {
+        if (!DoesEGLContextSupportSharingWithEGLImage(gl))
+            return 0;
+
+        GLuint texture = (uintptr_t)buffer;
+        EGLTextureWrapper* tex = new EGLTextureWrapper();
+        if (!tex->CreateEGLImage(gl, texture)) {
+            NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
+            delete tex;
+            return 0;
+        }
+
+        return (SharedTextureHandle)tex;
+    }
+    default:
+        NS_ERROR("Unknown shared texture buffer type");
+        return 0;
+    }
+}
+
+void ReleaseSharedHandle(GLContext* gl,
+                         SharedTextureShareType shareType,
+                         SharedTextureHandle sharedHandle)
+{
+    // unimplemented outside of EGL
+    if (gl->GetContextType() != ContextTypeEGL)
+        return;
+
+    if (shareType != SameProcess) {
+        NS_ERROR("Implementation not available for this sharing type");
+        return;
+    }
+
+    SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
+
+    switch (wrapper->Type()) {
+#ifdef MOZ_WIDGET_ANDROID
+    case SharedHandleType_SurfaceTexture:
+        delete wrapper;
+        break;
+#endif
+
+    case SharedHandleType_Image: {
+        NS_ASSERTION(DoesEGLContextSupportSharingWithEGLImage(gl), "EGLImage not supported or disabled in runtime");
+
+        EGLTextureWrapper* wrap = (EGLTextureWrapper*)sharedHandle;
+        delete wrap;
+        break;
+    }
+
+    default:
+        NS_ERROR("Unknown shared handle type");
+        return;
+    }
+}
+
+bool GetSharedHandleDetails(GLContext* gl,
+                            SharedTextureShareType shareType,
+                            SharedTextureHandle sharedHandle,
+                            SharedHandleDetails& details)
+{
+    // unimplemented outside of EGL
+    if (gl->GetContextType() != ContextTypeEGL)
+        return false;
+
+    if (shareType != SameProcess)
+        return false;
+
+    SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
+
+    switch (wrapper->Type()) {
+#ifdef MOZ_WIDGET_ANDROID
+    case SharedHandleType_SurfaceTexture: {
+        SurfaceTextureWrapper* surfaceWrapper = reinterpret_cast<SurfaceTextureWrapper*>(wrapper);
+
+        details.mTarget = LOCAL_GL_TEXTURE_EXTERNAL;
+        details.mTextureFormat = gfx::FORMAT_R8G8B8A8;
+        surfaceWrapper->SurfaceTexture()->GetTransformMatrix(details.mTextureTransform);
+        break;
+    }
+#endif
+
+    case SharedHandleType_Image:
+        details.mTarget = LOCAL_GL_TEXTURE_2D;
+        details.mTextureFormat = gfx::FORMAT_R8G8B8A8;
+        break;
+
+    default:
+        NS_ERROR("Unknown shared handle type");
+        return false;
+    }
+
+    return true;
+}
+
+bool AttachSharedHandle(GLContext* gl,
+                        SharedTextureShareType shareType,
+                        SharedTextureHandle sharedHandle)
+{
+    // unimplemented outside of EGL
+    if (gl->GetContextType() != ContextTypeEGL)
+        return false;
+
+    if (shareType != SameProcess)
+        return false;
+
+    SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
+
+    switch (wrapper->Type()) {
+#ifdef MOZ_WIDGET_ANDROID
+    case SharedHandleType_SurfaceTexture: {
+#ifndef DEBUG
+        /*
+         * NOTE: SurfaceTexture spams us if there are any existing GL errors, so we'll clear
+         * them here in order to avoid that.
+         */
+        gl->GetAndClearError();
+#endif
+        SurfaceTextureWrapper* surfaceTextureWrapper = reinterpret_cast<SurfaceTextureWrapper*>(wrapper);
+
+        // FIXME: SurfaceTexture provides a transform matrix which is supposed to
+        // be applied to the texture coordinates. We should return that here
+        // so we can render correctly. Bug 775083
+        surfaceTextureWrapper->SurfaceTexture()->UpdateTexImage();
+        break;
+    }
+#endif // MOZ_WIDGET_ANDROID
+
+    case SharedHandleType_Image: {
+        NS_ASSERTION(DoesEGLContextSupportSharingWithEGLImage(gl), "EGLImage not supported or disabled in runtime");
+
+        EGLTextureWrapper* wrap = (EGLTextureWrapper*)sharedHandle;
+        wrap->WaitSync();
+        gl->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, wrap->GetEGLImage());
+        break;
+    }
+
+    default:
+        NS_ERROR("Unknown shared handle type");
+        return false;
+    }
+
+    return true;
+}
+
+/**
+  * Detach Shared GL Handle from GL_TEXTURE_2D target
+  */
+void DetachSharedHandle(GLContext*,
+                        SharedTextureShareType,
+                        SharedTextureHandle)
+{
+  // currently a no-operation
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/gl/GLSharedHandleHelpers.h
@@ -0,0 +1,73 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLSHAREDHANDLEHELPERS_H_
+#define GLSHAREDHANDLEHELPERS_H_
+
+#include "GLContextTypes.h"
+#include "mozilla/gfx/Types.h"
+
+namespace mozilla {
+namespace gl {
+
+/**
+  * Create a new shared GLContext content handle, using the passed buffer as a source.
+  * Must be released by ReleaseSharedHandle.
+  */
+SharedTextureHandle CreateSharedHandle(GLContext* gl,
+                                       SharedTextureShareType shareType,
+                                       void* buffer,
+                                       SharedTextureBufferType bufferType);
+
+/**
+  * - It is better to call ReleaseSharedHandle before original GLContext destroyed,
+  *     otherwise warning will be thrown on attempt to destroy Texture associated with SharedHandle, depends on backend implementation.
+  * - It does not require to be called on context where it was created,
+  *     because SharedHandle suppose to keep Context reference internally,
+  *     or don't require specific context at all, for example IPC SharedHandle.
+  * - Not recommended to call this between AttachSharedHandle and Draw Target call.
+  *      if it is really required for some special backend, then DetachSharedHandle API must be added with related implementation.
+  * - It is recommended to stop any possible access to SharedHandle (Attachments, pending GL calls) before calling Release,
+  *      otherwise some artifacts might appear or even crash if API backend implementation does not expect that.
+  * SharedHandle (currently EGLImage) does not require GLContext because it is EGL call, and can be destroyed
+  *   at any time, unless EGLImage have siblings (which are not expected with current API).
+  */
+void ReleaseSharedHandle(GLContext* gl,
+                         SharedTextureShareType shareType,
+                         SharedTextureHandle sharedHandle);
+
+
+typedef struct {
+    GLenum mTarget;
+    gfx::SurfaceFormat mTextureFormat;
+    gfx3DMatrix mTextureTransform;
+} SharedHandleDetails;
+
+/**
+  * Returns information necessary for rendering a shared handle.
+  * These values change depending on what sharing mechanism is in use
+  */
+bool GetSharedHandleDetails(GLContext* gl,
+                            SharedTextureShareType shareType,
+                            SharedTextureHandle sharedHandle,
+                            SharedHandleDetails& details);
+/**
+  * Attach Shared GL Handle to GL_TEXTURE_2D target
+  * GLContext must be current before this call
+  */
+bool AttachSharedHandle(GLContext* gl,
+                        SharedTextureShareType shareType,
+                        SharedTextureHandle sharedHandle);
+
+/**
+  * Detach Shared GL Handle from GL_TEXTURE_2D target
+  */
+void DetachSharedHandle(GLContext* gl,
+                        SharedTextureShareType shareType,
+                        SharedTextureHandle sharedHandle);
+
+}
+}
+
+#endif
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -36,16 +36,17 @@ EXPORTS += [
     'GLContextProviderImpl.h',
     'GLContextSymbols.h',
     'GLContextTypes.h',
     'GLContextUtils.h',
     'GLDefs.h',
     'GLLibraryEGL.h',
     'GLLibraryLoader.h',
     'GLScreenBuffer.h',
+    'GLSharedHandleHelpers.h',
     'GLTextureImage.h',
     'GLTypes.h',
     'ScopedGLHelpers.h',
     'SharedSurface.h',
     'SharedSurfaceEGL.h',
     'SharedSurfaceGL.h',
     'SurfaceFactory.h',
     'SurfaceStream.h',
@@ -112,16 +113,17 @@ UNIFIED_SOURCES += [
     'GLBlitTextureImageHelper.cpp',
     'GLContext.cpp',
     'GLContextFeatures.cpp',
     'GLContextTypes.cpp',
     'GLContextUtils.cpp',
     'GLLibraryEGL.cpp',
     'GLLibraryLoader.cpp',
     'GLScreenBuffer.cpp',
+    'GLSharedHandleHelpers.cpp',
     'GLTextureImage.cpp',
     'ScopedGLHelpers.cpp',
     'SharedSurface.cpp',
     'SharedSurfaceEGL.cpp',
     'SharedSurfaceGL.cpp',
     'SurfaceFactory.cpp',
     'SurfaceStream.cpp',
     'TextureGarbageBin.cpp',
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "TextureHostOGL.h"
 #include "GLContext.h"                  // for GLContext, etc
+#include "GLSharedHandleHelpers.h"
 #include "GLContextUtils.h"             // for GLContextUtils
 #include "SharedSurface.h"              // for SharedSurface
 #include "SharedSurfaceEGL.h"           // for SharedSurface_EGLImage
 #include "SharedSurfaceGL.h"            // for SharedSurface_GLTexture, etc
 #include "SurfaceStream.h"              // for SurfaceStream
 #include "SurfaceTypes.h"               // for SharedSurfaceType, etc
 #include "TiledLayerBuffer.h"           // for TILEDLAYERBUFFER_TILE_SIZE
 #include "gfx2DGlue.h"                  // for ContentForFormat, etc
@@ -320,30 +321,30 @@ SharedTextureSourceOGL::BindTexture(GLen
   if (!gl()) {
     NS_WARNING("Trying to bind a texture without a GLContext");
     return;
   }
   GLuint tex = mCompositor->GetTemporaryTexture(aTextureUnit);
 
   gl()->fActiveTexture(aTextureUnit);
   gl()->fBindTexture(mTextureTarget, tex);
-  if (!gl()->AttachSharedHandle(mShareType, mSharedHandle)) {
+  if (!AttachSharedHandle(gl(), mShareType, mSharedHandle)) {
     NS_ERROR("Failed to bind shared texture handle");
     return;
   }
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
 }
 
 void
 SharedTextureSourceOGL::DetachSharedHandle()
 {
   if (!gl()) {
     return;
   }
-  gl()->DetachSharedHandle(mShareType, mSharedHandle);
+  gl::DetachSharedHandle(gl(), mShareType, mSharedHandle);
 }
 
 void
 SharedTextureSourceOGL::SetCompositor(CompositorOGL* aCompositor)
 {
   mCompositor = aCompositor;
 }
 
@@ -357,18 +358,18 @@ gl::GLContext*
 SharedTextureSourceOGL::gl() const
 {
   return mCompositor ? mCompositor->gl() : nullptr;
 }
 
 gfx3DMatrix
 SharedTextureSourceOGL::GetTextureTransform()
 {
-  GLContext::SharedHandleDetails handleDetails;
-  if (!gl()->GetSharedHandleDetails(mShareType, mSharedHandle, handleDetails)) {
+  SharedHandleDetails handleDetails;
+  if (!GetSharedHandleDetails(gl(), mShareType, mSharedHandle, handleDetails)) {
     NS_WARNING("Could not get shared handle details");
     return gfx3DMatrix();
   }
 
   return handleDetails.mTextureTransform;
 }
 
 SharedTextureHostOGL::SharedTextureHostOGL(uint64_t aID,
@@ -402,18 +403,18 @@ SharedTextureHostOGL::Lock()
 {
   if (!mCompositor) {
     return false;
   }
 
   if (!mTextureSource) {
     // XXX on android GetSharedHandleDetails can call into Java which we'd
     // rather not do from the compositor
-    GLContext::SharedHandleDetails handleDetails;
-    if (!gl()->GetSharedHandleDetails(mShareType, mSharedHandle, handleDetails)) {
+    SharedHandleDetails handleDetails;
+    if (!GetSharedHandleDetails(gl(), mShareType, mSharedHandle, handleDetails)) {
       NS_WARNING("Could not get shared handle details");
       return false;
     }
 
     GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
     mTextureSource = new SharedTextureSourceOGL(mCompositor,
                                                 mSharedHandle,
                                                 handleDetails.mTextureFormat,
@@ -611,17 +612,17 @@ SharedDeprecatedTextureHostOGL::DeleteTe
 {
   MOZ_ASSERT(mGL);
   if (!mGL->MakeCurrent()) {
     mSharedHandle = 0;
     mTextureHandle = 0;
     return;
   }
   if (mSharedHandle) {
-    mGL->ReleaseSharedHandle(mShareType, mSharedHandle);
+    ReleaseSharedHandle(mGL, mShareType, mSharedHandle);
     mSharedHandle = 0;
   }
   if (mTextureHandle) {
     mGL->fDeleteTextures(1, &mTextureHandle);
     mTextureHandle = 0;
   }
 }
 
@@ -645,60 +646,60 @@ SharedDeprecatedTextureHostOGL::SwapText
   SharedTextureHandle newHandle = texture.handle();
   nsIntSize size = texture.size();
   mSize = gfx::IntSize(size.width, size.height);
   if (texture.inverted()) {
     mFlags |= TEXTURE_NEEDS_Y_FLIP;
   }
 
   if (mSharedHandle && mSharedHandle != newHandle) {
-    mGL->ReleaseSharedHandle(mShareType, mSharedHandle);
+    ReleaseSharedHandle(mGL, mShareType, mSharedHandle);
   }
 
   mShareType = texture.shareType();
   mSharedHandle = newHandle;
 
-  GLContext::SharedHandleDetails handleDetails;
-  if (mSharedHandle && mGL->GetSharedHandleDetails(mShareType, mSharedHandle, handleDetails)) {
+  SharedHandleDetails handleDetails;
+  if (mSharedHandle && GetSharedHandleDetails(mGL, mShareType, mSharedHandle, handleDetails)) {
     mTextureTarget = handleDetails.mTarget;
     mFormat = handleDetails.mTextureFormat;
   }
 }
 
 bool
 SharedDeprecatedTextureHostOGL::Lock()
 {
   MakeTextureIfNeeded(mGL, mTextureTarget, mTextureHandle);
 
   mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
   mGL->fBindTexture(mTextureTarget, mTextureHandle);
-  if (!mGL->AttachSharedHandle(mShareType, mSharedHandle)) {
+  if (!AttachSharedHandle(mGL, mShareType, mSharedHandle)) {
     NS_ERROR("Failed to bind shared texture handle");
     return false;
   }
 
   return true;
 }
 
 void
 SharedDeprecatedTextureHostOGL::Unlock()
 {
-  mGL->DetachSharedHandle(mShareType, mSharedHandle);
+  DetachSharedHandle(mGL, mShareType, mSharedHandle);
   mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, 0);
 }
 
 
 gfx3DMatrix
 SharedDeprecatedTextureHostOGL::GetTextureTransform()
 {
-  GLContext::SharedHandleDetails handleDetails;
+  SharedHandleDetails handleDetails;
   // GetSharedHandleDetails can call into Java which we'd
   // rather not do from the compositor
   if (mSharedHandle) {
-    mGL->GetSharedHandleDetails(mShareType, mSharedHandle, handleDetails);
+    GetSharedHandleDetails(mGL, mShareType, mSharedHandle, handleDetails);
   }
   return handleDetails.mTextureTransform;
 }
 
 
 void
 SurfaceStreamHostOGL::SetCompositor(Compositor* aCompositor)
 {