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 174269 3856aa97c77c16d5ef2b86892c4c94dc45cfef53
parent 174268 bac9d5883f366bde9b6d8c1a8728fc9df93e3258
child 174270 101f294ad43cef67b1d0319e317eb252da48d829
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs942505
milestone28.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 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)
 {