Bug 814159 - Part 4: Split TextureImageEGL into separate files - r=benwa
authorBenoit Jacob <bjacob@mozilla.com>
Fri, 11 Oct 2013 09:16:44 -0400
changeset 165241 f76526b044af992e21dc0f243c1edf974e9a5109
parent 165240 4dbbf905f83c39a371bdecfed8f20bbe7f5c5be6
child 165242 751bcb37cdb6404b8d4582aad47f96af8fcd4839
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbenwa
bugs814159
milestone27.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 814159 - Part 4: Split TextureImageEGL into separate files - r=benwa
gfx/gl/GLContextProviderEGL.cpp
gfx/gl/GLLibraryEGL.h
gfx/gl/TextureImageEGL.cpp
gfx/gl/TextureImageEGL.h
gfx/gl/moz.build
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -96,16 +96,17 @@ public:
 #include "mozilla/Preferences.h"
 #include "gfxUtils.h"
 #include "gfxFailure.h"
 #include "gfxASurface.h"
 #include "gfxImageSurface.h"
 #include "gfxPlatform.h"
 #include "GLContextProvider.h"
 #include "GLLibraryEGL.h"
+#include "TextureImageEGL.h"
 #include "nsDebug.h"
 #include "nsThreadUtils.h"
 
 #include "nsIWidget.h"
 
 #include "gfxCrashReporterUtils.h"
 
 using namespace mozilla::gfx;
@@ -963,346 +964,16 @@ bool GLContextEGL::AttachSharedHandle(Sh
 }
 
 bool
 GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize)
 {
 	return ResizeScreenBuffer(aNewSize);
 }
 
-static GLenum
-GLFormatForImage(gfxImageFormat aFormat)
-{
-    switch (aFormat) {
-    case gfxImageFormatARGB32:
-    case gfxImageFormatRGB24:
-        // Thebes only supports RGBX, not packed RGB.
-        return LOCAL_GL_RGBA;
-    case gfxImageFormatRGB16_565:
-        return LOCAL_GL_RGB;
-    case gfxImageFormatA8:
-        return LOCAL_GL_LUMINANCE;
-    default:
-        NS_WARNING("Unknown GL format for Image format");
-    }
-    return 0;
-}
-
-static GLenum
-GLTypeForImage(gfxImageFormat aFormat)
-{
-    switch (aFormat) {
-    case gfxImageFormatARGB32:
-    case gfxImageFormatRGB24:
-    case gfxImageFormatA8:
-        return LOCAL_GL_UNSIGNED_BYTE;
-    case gfxImageFormatRGB16_565:
-        return LOCAL_GL_UNSIGNED_SHORT_5_6_5;
-    default:
-        NS_WARNING("Unknown GL format for Image format");
-    }
-    return 0;
-}
-
-class TextureImageEGL
-    : public TextureImage
-{
-public:
-    TextureImageEGL(GLuint aTexture,
-                    const nsIntSize& aSize,
-                    GLenum aWrapMode,
-                    ContentType aContentType,
-                    GLContext* aContext,
-                    Flags aFlags = TextureImage::NoFlags,
-                    TextureState aTextureState = Created,
-                    TextureImage::ImageFormat aImageFormat = gfxImageFormatUnknown)
-        : TextureImage(aSize, aWrapMode, aContentType, aFlags)
-        , mGLContext(aContext)
-        , mUpdateFormat(aImageFormat)
-        , mEGLImage(nullptr)
-        , mTexture(aTexture)
-        , mSurface(nullptr)
-        , mConfig(nullptr)
-        , mTextureState(aTextureState)
-        , mBound(false)
-    {
-        if (mUpdateFormat == gfxImageFormatUnknown) {
-            mUpdateFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType());
-        }
-
-        if (mUpdateFormat == gfxImageFormatRGB16_565) {
-            mTextureFormat = FORMAT_R8G8B8X8;
-        } else if (mUpdateFormat == gfxImageFormatRGB24) {
-            // RGB24 means really RGBX for Thebes, which means we have to
-            // use the right shader and ignore the uninitialized alpha
-            // value.
-            mTextureFormat = FORMAT_B8G8R8X8;
-        } else {
-            mTextureFormat = FORMAT_B8G8R8A8;
-        }
-    }
-
-    virtual ~TextureImageEGL()
-    {
-        if (mGLContext->IsDestroyed() || !mGLContext->IsOwningThreadCurrent()) {
-            return;
-        }
-
-        // If we have a context, then we need to delete the texture;
-        // if we don't have a context (either real or shared),
-        // then they went away when the contex was deleted, because it
-        // was the only one that had access to it.
-        mGLContext->MakeCurrent();
-        mGLContext->fDeleteTextures(1, &mTexture);
-        ReleaseTexImage();
-        DestroyEGLSurface();
-    }
-
-    virtual void GetUpdateRegion(nsIntRegion& aForRegion)
-    {
-        if (mTextureState != Valid) {
-            // if the texture hasn't been initialized yet, force the
-            // client to paint everything
-            aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
-        }
-
-        // We can only draw a rectangle, not subregions due to
-        // the way that our texture upload functions work.  If
-        // needed, we /could/ do multiple texture uploads if we have
-        // non-overlapping rects, but that's a tradeoff.
-        aForRegion = nsIntRegion(aForRegion.GetBounds());
-    }
-
-    virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion)
-    {
-        NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
-
-        // determine the region the client will need to repaint
-        GetUpdateRegion(aRegion);
-        mUpdateRect = aRegion.GetBounds();
-
-        //printf_stderr("BeginUpdate with updateRect [%d %d %d %d]\n", mUpdateRect.x, mUpdateRect.y, mUpdateRect.width, mUpdateRect.height);
-        if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(mUpdateRect)) {
-            NS_ERROR("update outside of image");
-            return nullptr;
-        }
-
-        //printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat);
-
-        mUpdateSurface =
-            new gfxImageSurface(gfxIntSize(mUpdateRect.width, mUpdateRect.height),
-                                mUpdateFormat);
-
-        mUpdateSurface->SetDeviceOffset(gfxPoint(-mUpdateRect.x, -mUpdateRect.y));
-
-        return mUpdateSurface;
-    }
-
-    virtual void EndUpdate()
-    {
-        NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
-
-        //printf_stderr("EndUpdate: slow path");
-
-        // This is the slower path -- we didn't have any way to set up
-        // a fast mapping between our cairo target surface and the GL
-        // texture, so we have to upload data.
-
-        // Undo the device offset that BeginUpdate set; doesn't much
-        // matter for us here, but important if we ever do anything
-        // directly with the surface.
-        mUpdateSurface->SetDeviceOffset(gfxPoint(0, 0));
-
-        nsRefPtr<gfxImageSurface> uploadImage = nullptr;
-        gfxIntSize updateSize(mUpdateRect.width, mUpdateRect.height);
-
-        NS_ASSERTION(mUpdateSurface->GetType() == gfxSurfaceTypeImage &&
-                     mUpdateSurface->GetSize() == updateSize,
-                     "Upload image isn't an image surface when one is expected, or is wrong size!");
-
-        uploadImage = static_cast<gfxImageSurface*>(mUpdateSurface.get());
-
-        if (!uploadImage) {
-            return;
-        }
-
-        mGLContext->MakeCurrent();
-        mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
-
-        if (mTextureState != Valid) {
-            NS_ASSERTION(mUpdateRect.x == 0 && mUpdateRect.y == 0 &&
-                         mUpdateRect.Size() == mSize,
-                         "Bad initial update on non-created texture!");
-
-            mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
-                                    0,
-                                    GLFormatForImage(mUpdateFormat),
-                                    mUpdateRect.width,
-                                    mUpdateRect.height,
-                                    0,
-                                    GLFormatForImage(uploadImage->Format()),
-                                    GLTypeForImage(uploadImage->Format()),
-                                    uploadImage->Data());
-        } else {
-            mGLContext->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
-                                       0,
-                                       mUpdateRect.x,
-                                       mUpdateRect.y,
-                                       mUpdateRect.width,
-                                       mUpdateRect.height,
-                                       GLFormatForImage(uploadImage->Format()),
-                                       GLTypeForImage(uploadImage->Format()),
-                                       uploadImage->Data());
-        }
-
-        mUpdateSurface = nullptr;
-        mTextureState = Valid;
-        return;         // mTexture is bound
-    }
-
-    virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
-    {
-        nsIntRect bounds = aRegion.GetBounds();
-
-        nsIntRegion region;
-        if (mTextureState != Valid) {
-            bounds = nsIntRect(0, 0, mSize.width, mSize.height);
-            region = nsIntRegion(bounds);
-        } else {
-            region = aRegion;
-        }
-
-        mTextureFormat =
-          mGLContext->UploadSurfaceToTexture(aSurf,
-                                              region,
-                                              mTexture,
-                                              mTextureState == Created,
-                                              bounds.TopLeft() + aFrom,
-                                              false);
-
-        mTextureState = Valid;
-        return true;
-    }
-
-    virtual void BindTexture(GLenum aTextureUnit)
-    {
-        // Ensure the texture is allocated before it is used.
-        if (mTextureState == Created) {
-            Resize(mSize);
-        }
-
-        mGLContext->fActiveTexture(aTextureUnit);
-        mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
-        mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
-    }
-
-    virtual GLuint GetTextureID() 
-    {
-        // Ensure the texture is allocated before it is used.
-        if (mTextureState == Created) {
-            Resize(mSize);
-        }
-        return mTexture;
-    };
-
-    virtual bool InUpdate() const { return !!mUpdateSurface; }
-
-    virtual void Resize(const nsIntSize& aSize)
-    {
-        NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
-
-        if (mSize == aSize && mTextureState != Created)
-            return;
-
-        mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
-
-        mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
-                                0,
-                                GLFormatForImage(mUpdateFormat),
-                                aSize.width,
-                                aSize.height,
-                                0,
-                                GLFormatForImage(mUpdateFormat),
-                                GLTypeForImage(mUpdateFormat),
-                                nullptr);
-
-        mTextureState = Allocated;
-        mSize = aSize;
-    }
-
-    bool BindTexImage()
-    {
-        if (mBound && !ReleaseTexImage())
-            return false;
-
-        EGLBoolean success =
-            sEGLLibrary.fBindTexImage(EGL_DISPLAY(),
-                                      (EGLSurface)mSurface,
-                                      LOCAL_EGL_BACK_BUFFER);
-
-        if (success == LOCAL_EGL_FALSE)
-            return false;
-
-        mBound = true;
-        return true;
-    }
-
-    bool ReleaseTexImage()
-    {
-        if (!mBound)
-            return true;
-
-        EGLBoolean success =
-            sEGLLibrary.fReleaseTexImage(EGL_DISPLAY(),
-                                         (EGLSurface)mSurface,
-                                         LOCAL_EGL_BACK_BUFFER);
-
-        if (success == LOCAL_EGL_FALSE)
-            return false;
-
-        mBound = false;
-        return true;
-    }
-
-    virtual bool CreateEGLSurface(gfxASurface* aSurface)
-    {
-        return false;
-    }
-
-    virtual void DestroyEGLSurface(void)
-    {
-        if (!mSurface)
-            return;
-
-        sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface);
-        mSurface = nullptr;
-    }
-
-protected:
-    typedef gfxImageFormat ImageFormat;
-
-    GLContext* mGLContext;
-
-    nsIntRect mUpdateRect;
-    ImageFormat mUpdateFormat;
-    nsRefPtr<gfxASurface> mUpdateSurface;
-    EGLImage mEGLImage;
-    GLuint mTexture;
-    EGLSurface mSurface;
-    EGLConfig mConfig;
-    TextureState mTextureState;
-
-    bool mBound;
-
-    virtual void ApplyFilter()
-    {
-        mGLContext->ApplyFilterToBoundTexture(mFilter);
-    }
-};
-
 already_AddRefed<TextureImage>
 GLContextEGL::CreateTextureImage(const nsIntSize& aSize,
                                  TextureImage::ContentType aContentType,
                                  GLenum aWrapMode,
                                  TextureImage::Flags aFlags,
                                  TextureImage::ImageFormat aImageFormat)
 {
     nsRefPtr<TextureImage> t = new gl::TiledTextureImage(this, aSize, aContentType, aFlags, aImageFormat);
--- a/gfx/gl/GLLibraryEGL.h
+++ b/gfx/gl/GLLibraryEGL.h
@@ -525,13 +525,16 @@ public:
 private:
     bool mInitialized;
     PRLibrary* mEGLLibrary;
     EGLDisplay mEGLDisplay;
 
     bool mIsANGLE;
 };
 
+extern GLLibraryEGL sEGLLibrary;
+#define EGL_DISPLAY()        sEGLLibrary.Display()
+
 } /* namespace gl */
 } /* namespace mozilla */
 
 #endif /* GLLIBRARYEGL_H_ */
 
new file mode 100644
--- /dev/null
+++ b/gfx/gl/TextureImageEGL.cpp
@@ -0,0 +1,319 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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 "TextureImageEGL.h"
+#include "GLLibraryEGL.h"
+#include "GLContext.h"
+#include "gfxPlatform.h"
+#include "mozilla/gfx/Types.h"
+
+namespace mozilla {
+namespace gl {
+
+static GLenum
+GLFormatForImage(gfxImageFormat aFormat)
+{
+    switch (aFormat) {
+    case gfxImageFormatARGB32:
+    case gfxImageFormatRGB24:
+        // Thebes only supports RGBX, not packed RGB.
+        return LOCAL_GL_RGBA;
+    case gfxImageFormatRGB16_565:
+        return LOCAL_GL_RGB;
+    case gfxImageFormatA8:
+        return LOCAL_GL_LUMINANCE;
+    default:
+        NS_WARNING("Unknown GL format for Image format");
+    }
+    return 0;
+}
+
+static GLenum
+GLTypeForImage(gfxImageFormat aFormat)
+{
+    switch (aFormat) {
+    case gfxImageFormatARGB32:
+    case gfxImageFormatRGB24:
+    case gfxImageFormatA8:
+        return LOCAL_GL_UNSIGNED_BYTE;
+    case gfxImageFormatRGB16_565:
+        return LOCAL_GL_UNSIGNED_SHORT_5_6_5;
+    default:
+        NS_WARNING("Unknown GL format for Image format");
+    }
+    return 0;
+}
+
+TextureImageEGL::TextureImageEGL(GLuint aTexture,
+                                 const nsIntSize& aSize,
+                                 GLenum aWrapMode,
+                                 ContentType aContentType,
+                                 GLContext* aContext,
+                                 Flags aFlags,
+                                 TextureState aTextureState,
+                                 TextureImage::ImageFormat aImageFormat)
+    : TextureImage(aSize, aWrapMode, aContentType, aFlags)
+    , mGLContext(aContext)
+    , mUpdateFormat(aImageFormat)
+    , mEGLImage(nullptr)
+    , mTexture(aTexture)
+    , mSurface(nullptr)
+    , mConfig(nullptr)
+    , mTextureState(aTextureState)
+    , mBound(false)
+{
+    if (mUpdateFormat == gfxImageFormatUnknown) {
+        mUpdateFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType());
+    }
+
+    if (mUpdateFormat == gfxImageFormatRGB16_565) {
+        mTextureFormat = gfx::FORMAT_R8G8B8X8;
+    } else if (mUpdateFormat == gfxImageFormatRGB24) {
+        // RGB24 means really RGBX for Thebes, which means we have to
+        // use the right shader and ignore the uninitialized alpha
+        // value.
+        mTextureFormat = gfx::FORMAT_B8G8R8X8;
+    } else {
+        mTextureFormat = gfx::FORMAT_B8G8R8A8;
+    }
+}
+
+TextureImageEGL::~TextureImageEGL()
+{
+    if (mGLContext->IsDestroyed() || !mGLContext->IsOwningThreadCurrent()) {
+        return;
+    }
+
+    // If we have a context, then we need to delete the texture;
+    // if we don't have a context (either real or shared),
+    // then they went away when the contex was deleted, because it
+    // was the only one that had access to it.
+    mGLContext->MakeCurrent();
+    mGLContext->fDeleteTextures(1, &mTexture);
+    ReleaseTexImage();
+    DestroyEGLSurface();
+}
+
+void
+TextureImageEGL::GetUpdateRegion(nsIntRegion& aForRegion)
+{
+    if (mTextureState != Valid) {
+        // if the texture hasn't been initialized yet, force the
+        // client to paint everything
+        aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
+    }
+
+    // We can only draw a rectangle, not subregions due to
+    // the way that our texture upload functions work.  If
+    // needed, we /could/ do multiple texture uploads if we have
+    // non-overlapping rects, but that's a tradeoff.
+    aForRegion = nsIntRegion(aForRegion.GetBounds());
+}
+
+gfxASurface*
+TextureImageEGL::BeginUpdate(nsIntRegion& aRegion)
+{
+    NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
+
+    // determine the region the client will need to repaint
+    GetUpdateRegion(aRegion);
+    mUpdateRect = aRegion.GetBounds();
+
+    //printf_stderr("BeginUpdate with updateRect [%d %d %d %d]\n", mUpdateRect.x, mUpdateRect.y, mUpdateRect.width, mUpdateRect.height);
+    if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(mUpdateRect)) {
+        NS_ERROR("update outside of image");
+        return nullptr;
+    }
+
+    //printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat);
+
+    mUpdateSurface =
+        new gfxImageSurface(gfxIntSize(mUpdateRect.width, mUpdateRect.height),
+                            mUpdateFormat);
+
+    mUpdateSurface->SetDeviceOffset(gfxPoint(-mUpdateRect.x, -mUpdateRect.y));
+
+    return mUpdateSurface;
+}
+
+void
+TextureImageEGL::EndUpdate()
+{
+    NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
+
+    //printf_stderr("EndUpdate: slow path");
+
+    // This is the slower path -- we didn't have any way to set up
+    // a fast mapping between our cairo target surface and the GL
+    // texture, so we have to upload data.
+
+    // Undo the device offset that BeginUpdate set; doesn't much
+    // matter for us here, but important if we ever do anything
+    // directly with the surface.
+    mUpdateSurface->SetDeviceOffset(gfxPoint(0, 0));
+
+    nsRefPtr<gfxImageSurface> uploadImage = nullptr;
+    gfxIntSize updateSize(mUpdateRect.width, mUpdateRect.height);
+
+    NS_ASSERTION(mUpdateSurface->GetType() == gfxSurfaceTypeImage &&
+                  mUpdateSurface->GetSize() == updateSize,
+                  "Upload image isn't an image surface when one is expected, or is wrong size!");
+
+    uploadImage = static_cast<gfxImageSurface*>(mUpdateSurface.get());
+
+    if (!uploadImage) {
+        return;
+    }
+
+    mGLContext->MakeCurrent();
+    mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
+
+    if (mTextureState != Valid) {
+        NS_ASSERTION(mUpdateRect.x == 0 && mUpdateRect.y == 0 &&
+                      mUpdateRect.Size() == mSize,
+                      "Bad initial update on non-created texture!");
+
+        mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
+                                0,
+                                GLFormatForImage(mUpdateFormat),
+                                mUpdateRect.width,
+                                mUpdateRect.height,
+                                0,
+                                GLFormatForImage(uploadImage->Format()),
+                                GLTypeForImage(uploadImage->Format()),
+                                uploadImage->Data());
+    } else {
+        mGLContext->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
+                                    0,
+                                    mUpdateRect.x,
+                                    mUpdateRect.y,
+                                    mUpdateRect.width,
+                                    mUpdateRect.height,
+                                    GLFormatForImage(uploadImage->Format()),
+                                    GLTypeForImage(uploadImage->Format()),
+                                    uploadImage->Data());
+    }
+
+    mUpdateSurface = nullptr;
+    mTextureState = Valid;
+    return;         // mTexture is bound
+}
+
+bool
+TextureImageEGL::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
+{
+    nsIntRect bounds = aRegion.GetBounds();
+
+    nsIntRegion region;
+    if (mTextureState != Valid) {
+        bounds = nsIntRect(0, 0, mSize.width, mSize.height);
+        region = nsIntRegion(bounds);
+    } else {
+        region = aRegion;
+    }
+
+    mTextureFormat =
+      mGLContext->UploadSurfaceToTexture(aSurf,
+                                          region,
+                                          mTexture,
+                                          mTextureState == Created,
+                                          bounds.TopLeft() + aFrom,
+                                          false);
+
+    mTextureState = Valid;
+    return true;
+}
+
+void
+TextureImageEGL::BindTexture(GLenum aTextureUnit)
+{
+    // Ensure the texture is allocated before it is used.
+    if (mTextureState == Created) {
+        Resize(mSize);
+    }
+
+    mGLContext->fActiveTexture(aTextureUnit);
+    mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
+    mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
+}
+
+void
+TextureImageEGL::Resize(const nsIntSize& aSize)
+{
+    NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
+
+    if (mSize == aSize && mTextureState != Created)
+        return;
+
+    mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
+
+    mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
+                            0,
+                            GLFormatForImage(mUpdateFormat),
+                            aSize.width,
+                            aSize.height,
+                            0,
+                            GLFormatForImage(mUpdateFormat),
+                            GLTypeForImage(mUpdateFormat),
+                            nullptr);
+
+    mTextureState = Allocated;
+    mSize = aSize;
+}
+
+bool
+TextureImageEGL::BindTexImage()
+{
+    if (mBound && !ReleaseTexImage())
+        return false;
+
+    EGLBoolean success =
+        sEGLLibrary.fBindTexImage(EGL_DISPLAY(),
+                                  (EGLSurface)mSurface,
+                                  LOCAL_EGL_BACK_BUFFER);
+
+    if (success == LOCAL_EGL_FALSE)
+        return false;
+
+    mBound = true;
+    return true;
+}
+
+bool
+TextureImageEGL::ReleaseTexImage()
+{
+    if (!mBound)
+        return true;
+
+    EGLBoolean success =
+        sEGLLibrary.fReleaseTexImage(EGL_DISPLAY(),
+                                      (EGLSurface)mSurface,
+                                      LOCAL_EGL_BACK_BUFFER);
+
+    if (success == LOCAL_EGL_FALSE)
+        return false;
+
+    mBound = false;
+    return true;
+}
+
+void
+TextureImageEGL::DestroyEGLSurface(void)
+{
+    if (!mSurface)
+        return;
+
+    sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface);
+    mSurface = nullptr;
+}
+
+void
+TextureImageEGL::ApplyFilter()
+{
+    mGLContext->ApplyFilterToBoundTexture(mFilter);
+}
+
+}
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/gl/TextureImageEGL.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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 TEXTUREIMAGEEGL_H_
+#define TEXTUREIMAGEEGL_H_
+
+#include "GLTextureImage.h"
+
+namespace mozilla {
+namespace gl {
+
+class TextureImageEGL
+    : public TextureImage
+{
+public:
+    TextureImageEGL(GLuint aTexture,
+                    const nsIntSize& aSize,
+                    GLenum aWrapMode,
+                    ContentType aContentType,
+                    GLContext* aContext,
+                    Flags aFlags = TextureImage::NoFlags,
+                    TextureState aTextureState = Created,
+                    TextureImage::ImageFormat aImageFormat = gfxImageFormatUnknown);
+
+    virtual ~TextureImageEGL();
+
+    virtual void GetUpdateRegion(nsIntRegion& aForRegion);
+
+    virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
+
+    virtual void EndUpdate();
+
+    virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */);
+
+    virtual void BindTexture(GLenum aTextureUnit);
+
+    virtual GLuint GetTextureID()
+    {
+        // Ensure the texture is allocated before it is used.
+        if (mTextureState == Created) {
+            Resize(mSize);
+        }
+        return mTexture;
+    };
+
+    virtual bool InUpdate() const { return !!mUpdateSurface; }
+
+    virtual void Resize(const nsIntSize& aSize);
+
+    bool BindTexImage();
+
+    bool ReleaseTexImage();
+
+    virtual bool CreateEGLSurface(gfxASurface* aSurface)
+    {
+        return false;
+    }
+
+    virtual void DestroyEGLSurface(void);
+
+protected:
+    typedef gfxImageFormat ImageFormat;
+
+    GLContext* mGLContext;
+
+    nsIntRect mUpdateRect;
+    ImageFormat mUpdateFormat;
+    nsRefPtr<gfxASurface> mUpdateSurface;
+    EGLImage mEGLImage;
+    GLuint mTexture;
+    EGLSurface mSurface;
+    EGLConfig mConfig;
+    TextureState mTextureState;
+
+    bool mBound;
+
+    virtual void ApplyFilter();
+};
+
+
+}
+}
+
+#endif // TEXTUREIMAGEEGL_H_
\ No newline at end of file
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -97,16 +97,17 @@ CPP_SOURCES += [
     'GLContextUtils.cpp',
     'GLLibraryLoader.cpp',
     'GLScreenBuffer.cpp',
     'GLTextureImage.cpp',
     'GfxTexturesReporter.cpp',
     'SharedSurface.cpp',
     'GLLibraryEGL.cpp',
     'SharedSurfaceEGL.cpp',
+    'TextureImageEGL.cpp',
     'SharedSurfaceGL.cpp',
     'SurfaceFactory.cpp',
     'SurfaceStream.cpp',
     'VBOArena.cpp',
     'TextureGarbageBin.cpp',
 ]
 
 FAIL_ON_WARNINGS = True