Bug 942509 - Move Upload* functions to new GLUploadHelpers files - r=gal,jgilbert
authorBenoit Jacob <bjacob@mozilla.com>
Tue, 03 Dec 2013 13:44:38 -0500
changeset 174281 3f08f279aec71e1f8c3248d49db58a3a4c978d83
parent 174280 17964f955e0cfbe306b4afdc427643686fef8936
child 174282 11d9777debba413f62c1c16dc8c91eab70789cb2
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)
reviewersgal, jgilbert
bugs942509
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 942509 - Move Upload* functions to new GLUploadHelpers files - r=gal,jgilbert
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLTextureImage.cpp
gfx/gl/GLUploadHelpers.cpp
gfx/gl/GLUploadHelpers.h
gfx/gl/TextureImageEGL.cpp
gfx/gl/moz.build
gfx/layers/opengl/TextureHostOGL.cpp
widget/cocoa/nsChildView.mm
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -2512,257 +2512,16 @@ GLContext::ReadPixelsIntoImageSurface(gf
                 }
             }
             dest->MarkDirty();
         }
     }
 #endif
 }
 
-static unsigned int
-DataOffset(const nsIntPoint &aPoint, int32_t aStride, gfxImageFormat aFormat)
-{
-  unsigned int data = aPoint.y * aStride;
-  data += aPoint.x * gfxASurface::BytePerPixelFromFormat(aFormat);
-  return data;
-}
-
-GLContext::SurfaceFormat
-GLContext::UploadImageDataToTexture(unsigned char* aData,
-                                    int32_t aStride,
-                                    gfxImageFormat aFormat,
-                                    const nsIntRegion& aDstRegion,
-                                    GLuint& aTexture,
-                                    bool aOverwrite,
-                                    bool aPixelBuffer,
-                                    GLenum aTextureUnit,
-                                    GLenum aTextureTarget)
-{
-    bool textureInited = aOverwrite ? false : true;
-    MakeCurrent();
-    fActiveTexture(aTextureUnit);
-
-    if (!aTexture) {
-        fGenTextures(1, &aTexture);
-        fBindTexture(aTextureTarget, aTexture);
-        fTexParameteri(aTextureTarget,
-                       LOCAL_GL_TEXTURE_MIN_FILTER,
-                       LOCAL_GL_LINEAR);
-        fTexParameteri(aTextureTarget,
-                       LOCAL_GL_TEXTURE_MAG_FILTER,
-                       LOCAL_GL_LINEAR);
-        fTexParameteri(aTextureTarget,
-                       LOCAL_GL_TEXTURE_WRAP_S,
-                       LOCAL_GL_CLAMP_TO_EDGE);
-        fTexParameteri(aTextureTarget,
-                       LOCAL_GL_TEXTURE_WRAP_T,
-                       LOCAL_GL_CLAMP_TO_EDGE);
-        textureInited = false;
-    } else {
-        fBindTexture(aTextureTarget, aTexture);
-    }
-
-    nsIntRegion paintRegion;
-    if (!textureInited) {
-        paintRegion = nsIntRegion(aDstRegion.GetBounds());
-    } else {
-        paintRegion = aDstRegion;
-    }
-
-    GLenum format;
-    GLenum internalFormat;
-    GLenum type;
-    int32_t pixelSize = gfxASurface::BytePerPixelFromFormat(aFormat);
-    SurfaceFormat surfaceFormat;
-
-    MOZ_ASSERT(GetPreferredARGB32Format() == LOCAL_GL_BGRA ||
-               GetPreferredARGB32Format() == LOCAL_GL_RGBA);
-    switch (aFormat) {
-        case gfxImageFormatARGB32:
-            if (GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
-              format = LOCAL_GL_BGRA;
-              surfaceFormat = FORMAT_R8G8B8A8;
-              type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
-            } else {
-              format = LOCAL_GL_RGBA;
-              surfaceFormat = FORMAT_B8G8R8A8;
-              type = LOCAL_GL_UNSIGNED_BYTE;
-            }
-            internalFormat = LOCAL_GL_RGBA;
-            break;
-        case gfxImageFormatRGB24:
-            // Treat RGB24 surfaces as RGBA32 except for the surface
-            // format used.
-            if (GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
-              format = LOCAL_GL_BGRA;
-              surfaceFormat = FORMAT_R8G8B8X8;
-              type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
-            } else {
-              format = LOCAL_GL_RGBA;
-              surfaceFormat = FORMAT_B8G8R8X8;
-              type = LOCAL_GL_UNSIGNED_BYTE;
-            }
-            internalFormat = LOCAL_GL_RGBA;
-            break;
-        case gfxImageFormatRGB16_565:
-            internalFormat = format = LOCAL_GL_RGB;
-            type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
-            surfaceFormat = FORMAT_R5G6B5;
-            break;
-        case gfxImageFormatA8:
-            internalFormat = format = LOCAL_GL_LUMINANCE;
-            type = LOCAL_GL_UNSIGNED_BYTE;
-            // We don't have a specific luminance shader
-            surfaceFormat = FORMAT_A8;
-            break;
-        default:
-            NS_ASSERTION(false, "Unhandled image surface format!");
-            format = 0;
-            type = 0;
-            surfaceFormat = FORMAT_UNKNOWN;
-    }
-
-    nsIntRegionRectIterator iter(paintRegion);
-    const nsIntRect *iterRect;
-
-    // Top left point of the region's bounding rectangle.
-    nsIntPoint topLeft = paintRegion.GetBounds().TopLeft();
-
-    while ((iterRect = iter.Next())) {
-        // The inital data pointer is at the top left point of the region's
-        // bounding rectangle. We need to find the offset of this rect
-        // within the region and adjust the data pointer accordingly.
-        unsigned char *rectData =
-            aData + DataOffset(iterRect->TopLeft() - topLeft, aStride, aFormat);
-
-        NS_ASSERTION(textureInited || (iterRect->x == 0 && iterRect->y == 0),
-                     "Must be uploading to the origin when we don't have an existing texture");
-
-        if (textureInited && CanUploadSubTextures()) {
-            TexSubImage2D(aTextureTarget,
-                          0,
-                          iterRect->x,
-                          iterRect->y,
-                          iterRect->width,
-                          iterRect->height,
-                          aStride,
-                          pixelSize,
-                          format,
-                          type,
-                          rectData);
-        } else {
-            TexImage2D(aTextureTarget,
-                       0,
-                       internalFormat,
-                       iterRect->width,
-                       iterRect->height,
-                       aStride,
-                       pixelSize,
-                       0,
-                       format,
-                       type,
-                       rectData);
-        }
-
-    }
-
-    return surfaceFormat;
-}
-
-GLContext::SurfaceFormat
-GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
-                                  const nsIntRegion& aDstRegion,
-                                  GLuint& aTexture,
-                                  bool aOverwrite,
-                                  const nsIntPoint& aSrcPoint,
-                                  bool aPixelBuffer,
-                                  GLenum aTextureUnit,
-                                  GLenum aTextureTarget)
-{
-
-    nsRefPtr<gfxImageSurface> imageSurface = aSurface->GetAsImageSurface();
-    unsigned char* data = nullptr;
-
-    if (!imageSurface ||
-        (imageSurface->Format() != gfxImageFormatARGB32 &&
-         imageSurface->Format() != gfxImageFormatRGB24 &&
-         imageSurface->Format() != gfxImageFormatRGB16_565 &&
-         imageSurface->Format() != gfxImageFormatA8)) {
-        // We can't get suitable pixel data for the surface, make a copy
-        nsIntRect bounds = aDstRegion.GetBounds();
-        imageSurface =
-          new gfxImageSurface(gfxIntSize(bounds.width, bounds.height),
-                              gfxImageFormatARGB32);
-
-        nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
-
-        context->Translate(-gfxPoint(aSrcPoint.x, aSrcPoint.y));
-        context->SetSource(aSurface);
-        context->Paint();
-        data = imageSurface->Data();
-        NS_ASSERTION(!aPixelBuffer,
-                     "Must be using an image compatible surface with pixel buffers!");
-    } else {
-        // If a pixel buffer is bound the data pointer parameter is relative
-        // to the start of the data block.
-        if (!aPixelBuffer) {
-              data = imageSurface->Data();
-        }
-        data += DataOffset(aSrcPoint, imageSurface->Stride(),
-                           imageSurface->Format());
-    }
-
-    MOZ_ASSERT(imageSurface);
-    imageSurface->Flush();
-
-    return UploadImageDataToTexture(data,
-                                    imageSurface->Stride(),
-                                    imageSurface->Format(),
-                                    aDstRegion, aTexture, aOverwrite,
-                                    aPixelBuffer, aTextureUnit, aTextureTarget);
-}
-
-static gfxImageFormat
-ImageFormatForSurfaceFormat(gfx::SurfaceFormat aFormat)
-{
-    switch (aFormat) {
-        case gfx::FORMAT_B8G8R8A8:
-            return gfxImageFormatARGB32;
-        case gfx::FORMAT_B8G8R8X8:
-            return gfxImageFormatRGB24;
-        case gfx::FORMAT_R5G6B5:
-            return gfxImageFormatRGB16_565;
-        case gfx::FORMAT_A8:
-            return gfxImageFormatA8;
-        default:
-            return gfxImageFormatUnknown;
-    }
-}
-
-GLContext::SurfaceFormat
-GLContext::UploadSurfaceToTexture(gfx::DataSourceSurface *aSurface,
-                                  const nsIntRegion& aDstRegion,
-                                  GLuint& aTexture,
-                                  bool aOverwrite,
-                                  const nsIntPoint& aSrcPoint,
-                                  bool aPixelBuffer,
-                                  GLenum aTextureUnit,
-                                  GLenum aTextureTarget)
-{
-    unsigned char* data = aPixelBuffer ? nullptr : aSurface->GetData();
-    int32_t stride = aSurface->Stride();
-    gfxImageFormat format =
-        ImageFormatForSurfaceFormat(aSurface->GetFormat());
-    data += DataOffset(aSrcPoint, stride, format);
-    return UploadImageDataToTexture(data, stride, format,
-                                    aDstRegion, aTexture, aOverwrite,
-                                    aPixelBuffer, aTextureUnit,
-                                    aTextureTarget);
-}
-
 static GLint GetAddressAlignment(ptrdiff_t aAddress)
 {
     if (!(aAddress & 0x7)) {
        return 8;
     } else if (!(aAddress & 0x3)) {
         return 4;
     } else if (!(aAddress & 0x1)) {
         return 2;
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -2668,81 +2668,16 @@ public:
     void ReadPixelsIntoImageSurface(gfxImageSurface* dest);
 
     // Similar to ReadPixelsIntoImageSurface, but pulls from the screen
     // instead of the currently bound framebuffer.
     void ReadScreenIntoImageSurface(gfxImageSurface* dest);
 
     TemporaryRef<gfx::SourceSurface> ReadPixelsToSourceSurface(const gfx::IntSize &aSize);
 
-    /**
-     * Creates a RGB/RGBA texture (or uses one provided) and uploads the surface
-     * contents to it within aSrcRect.
-     *
-     * aSrcRect.x/y will be uploaded to 0/0 in the texture, and the size
-     * of the texture with be aSrcRect.width/height.
-     *
-     * If an existing texture is passed through aTexture, it is assumed it
-     * has already been initialised with glTexImage2D (or this function),
-     * and that its size is equal to or greater than aSrcRect + aDstPoint.
-     * You can alternatively set the overwrite flag to true and have a new
-     * texture memory block allocated.
-     *
-     * The aDstPoint parameter is ignored if no texture was provided
-     * or aOverwrite is true.
-     *
-     * \param aData Image data to upload.
-     * \param aDstRegion Region of texture to upload to.
-     * \param aTexture Texture to use, or 0 to have one created for you.
-     * \param aOverwrite Over an existing texture with a new one.
-     * \param aSrcPoint Offset into aSrc where the region's bound's
-     *  TopLeft() sits.
-     * \param aPixelBuffer Pass true to upload texture data with an
-     *  offset from the base data (generally for pixel buffer objects),
-     *  otherwise textures are upload with an absolute pointer to the data.
-     * \param aTextureUnit, the texture unit used temporarily to upload the
-     *  surface. This testure may be overridden, clients should not rely on
-     *  the contents of this texture after this call or even on this
-     *  texture unit being active.
-     * \return Surface format of this texture.
-     */
-    SurfaceFormat UploadImageDataToTexture(unsigned char* aData,
-                                           int32_t aStride,
-                                           gfxImageFormat aFormat,
-                                           const nsIntRegion& aDstRegion,
-                                           GLuint& aTexture,
-                                           bool aOverwrite = false,
-                                           bool aPixelBuffer = false,
-                                           GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
-                                           GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
-
-    /**
-     * Convenience wrapper around UploadImageDataToTexture for gfxASurfaces.
-     */
-    SurfaceFormat UploadSurfaceToTexture(gfxASurface *aSurface,
-                                         const nsIntRegion& aDstRegion,
-                                         GLuint& aTexture,
-                                         bool aOverwrite = false,
-                                         const nsIntPoint& aSrcPoint = nsIntPoint(0, 0),
-                                         bool aPixelBuffer = false,
-                                         GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
-                                         GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
-
-    /**
-     * Same as above, for DataSourceSurfaces.
-     */
-    SurfaceFormat UploadSurfaceToTexture(gfx::DataSourceSurface *aSurface,
-                                         const nsIntRegion& aDstRegion,
-                                         GLuint& aTexture,
-                                         bool aOverwrite = false,
-                                         const nsIntPoint& aSrcPoint = nsIntPoint(0, 0),
-                                         bool aPixelBuffer = false,
-                                         GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
-                                         GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
-
     void TexImage2D(GLenum target, GLint level, GLint internalformat,
                     GLsizei width, GLsizei height, GLsizei stride,
                     GLint pixelsize, GLint border, GLenum format,
                     GLenum type, const GLvoid *pixels);
 
     void TexSubImage2D(GLenum target, GLint level,
                        GLint xoffset, GLint yoffset,
                        GLsizei width, GLsizei height, GLsizei stride,
--- a/gfx/gl/GLTextureImage.cpp
+++ b/gfx/gl/GLTextureImage.cpp
@@ -5,16 +5,17 @@
 
 #include "GLTextureImage.h"
 #include "GLContext.h"
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include "gfxUtils.h"
 #include "gfx2DGlue.h"
 #include "ScopedGLHelpers.h"
+#include "GLUploadHelpers.h"
 
 #include "TextureImageEGL.h"
 #ifdef XP_MACOSX
 #include "TextureImageCGL.h"
 #endif
 
 namespace mozilla {
 namespace gl {
@@ -178,22 +179,23 @@ BasicTextureImage::EndUpdate()
 
     // 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));
 
     bool relative = FinishedSurfaceUpdate();
 
     mTextureFormat =
-        mGLContext->UploadSurfaceToTexture(mUpdateSurface,
-                                           mUpdateRegion,
-                                           mTexture,
-                                           mTextureState == Created,
-                                           mUpdateOffset,
-                                           relative);
+        UploadSurfaceToTexture(mGLContext,
+                               mUpdateSurface,
+                               mUpdateRegion,
+                               mTexture,
+                               mTextureState == Created,
+                               mUpdateOffset,
+                               relative);
     FinishedSurfaceUpload();
 
     mUpdateSurface = nullptr;
     mTextureState = Valid;
 }
 
 void
 BasicTextureImage::BindTexture(GLenum aTextureUnit)
@@ -236,22 +238,23 @@ BasicTextureImage::DirectUpdate(gfxASurf
     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);
+        UploadSurfaceToTexture(mGLContext,
+                               aSurf,
+                               region,
+                               mTexture,
+                               mTextureState == Created,
+                               bounds.TopLeft() + aFrom,
+                               false);
     mTextureState = Valid;
     return true;
 }
 
 void
 BasicTextureImage::Resize(const nsIntSize& aSize)
 {
     NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
new file mode 100644
--- /dev/null
+++ b/gfx/gl/GLUploadHelpers.cpp
@@ -0,0 +1,267 @@
+/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
+/* 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 "GLUploadHelpers.h"
+
+#include "GLContext.h"
+#include "mozilla/gfx/2D.h"
+#include "gfxASurface.h"
+#include "gfxUtils.h"
+#include "gfxContext.h"
+#include "nsRegion.h"
+
+namespace mozilla {
+
+using gfx::SurfaceFormat;
+
+namespace gl {
+
+static unsigned int
+DataOffset(const nsIntPoint &aPoint, int32_t aStride, gfxImageFormat aFormat)
+{
+  unsigned int data = aPoint.y * aStride;
+  data += aPoint.x * gfxASurface::BytePerPixelFromFormat(aFormat);
+  return data;
+}
+
+static gfxImageFormat
+ImageFormatForSurfaceFormat(gfx::SurfaceFormat aFormat)
+{
+    switch (aFormat) {
+        case gfx::FORMAT_B8G8R8A8:
+            return gfxImageFormatARGB32;
+        case gfx::FORMAT_B8G8R8X8:
+            return gfxImageFormatRGB24;
+        case gfx::FORMAT_R5G6B5:
+            return gfxImageFormatRGB16_565;
+        case gfx::FORMAT_A8:
+            return gfxImageFormatA8;
+        default:
+            return gfxImageFormatUnknown;
+    }
+}
+
+SurfaceFormat
+UploadImageDataToTexture(GLContext* gl,
+                         unsigned char* aData,
+                         int32_t aStride,
+                         gfxImageFormat aFormat,
+                         const nsIntRegion& aDstRegion,
+                         GLuint& aTexture,
+                         bool aOverwrite,
+                         bool aPixelBuffer,
+                         GLenum aTextureUnit,
+                         GLenum aTextureTarget)
+{
+    bool textureInited = aOverwrite ? false : true;
+    gl->MakeCurrent();
+    gl->fActiveTexture(aTextureUnit);
+
+    if (!aTexture) {
+        gl->fGenTextures(1, &aTexture);
+        gl->fBindTexture(aTextureTarget, aTexture);
+        gl->fTexParameteri(aTextureTarget,
+                           LOCAL_GL_TEXTURE_MIN_FILTER,
+                           LOCAL_GL_LINEAR);
+        gl->fTexParameteri(aTextureTarget,
+                           LOCAL_GL_TEXTURE_MAG_FILTER,
+                           LOCAL_GL_LINEAR);
+        gl->fTexParameteri(aTextureTarget,
+                           LOCAL_GL_TEXTURE_WRAP_S,
+                           LOCAL_GL_CLAMP_TO_EDGE);
+        gl->fTexParameteri(aTextureTarget,
+                           LOCAL_GL_TEXTURE_WRAP_T,
+                           LOCAL_GL_CLAMP_TO_EDGE);
+        textureInited = false;
+    } else {
+        gl->fBindTexture(aTextureTarget, aTexture);
+    }
+
+    nsIntRegion paintRegion;
+    if (!textureInited) {
+        paintRegion = nsIntRegion(aDstRegion.GetBounds());
+    } else {
+        paintRegion = aDstRegion;
+    }
+
+    GLenum format;
+    GLenum internalFormat;
+    GLenum type;
+    int32_t pixelSize = gfxASurface::BytePerPixelFromFormat(aFormat);
+    SurfaceFormat surfaceFormat;
+
+    MOZ_ASSERT(gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA ||
+               gl->GetPreferredARGB32Format() == LOCAL_GL_RGBA);
+    switch (aFormat) {
+        case gfxImageFormatARGB32:
+            if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
+              format = LOCAL_GL_BGRA;
+              surfaceFormat = gfx::FORMAT_R8G8B8A8;
+              type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
+            } else {
+              format = LOCAL_GL_RGBA;
+              surfaceFormat = gfx::FORMAT_B8G8R8A8;
+              type = LOCAL_GL_UNSIGNED_BYTE;
+            }
+            internalFormat = LOCAL_GL_RGBA;
+            break;
+        case gfxImageFormatRGB24:
+            // Treat RGB24 surfaces as RGBA32 except for the surface
+            // format used.
+            if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
+              format = LOCAL_GL_BGRA;
+              surfaceFormat = gfx::FORMAT_R8G8B8X8;
+              type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
+            } else {
+              format = LOCAL_GL_RGBA;
+              surfaceFormat = gfx::FORMAT_B8G8R8X8;
+              type = LOCAL_GL_UNSIGNED_BYTE;
+            }
+            internalFormat = LOCAL_GL_RGBA;
+            break;
+        case gfxImageFormatRGB16_565:
+            internalFormat = format = LOCAL_GL_RGB;
+            type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
+            surfaceFormat = gfx::FORMAT_R5G6B5;
+            break;
+        case gfxImageFormatA8:
+            internalFormat = format = LOCAL_GL_LUMINANCE;
+            type = LOCAL_GL_UNSIGNED_BYTE;
+            // We don't have a specific luminance shader
+            surfaceFormat = gfx::FORMAT_A8;
+            break;
+        default:
+            NS_ASSERTION(false, "Unhandled image surface format!");
+            format = 0;
+            type = 0;
+            surfaceFormat = gfx::FORMAT_UNKNOWN;
+    }
+
+    nsIntRegionRectIterator iter(paintRegion);
+    const nsIntRect *iterRect;
+
+    // Top left point of the region's bounding rectangle.
+    nsIntPoint topLeft = paintRegion.GetBounds().TopLeft();
+
+    while ((iterRect = iter.Next())) {
+        // The inital data pointer is at the top left point of the region's
+        // bounding rectangle. We need to find the offset of this rect
+        // within the region and adjust the data pointer accordingly.
+        unsigned char *rectData =
+            aData + DataOffset(iterRect->TopLeft() - topLeft, aStride, aFormat);
+
+        NS_ASSERTION(textureInited || (iterRect->x == 0 && iterRect->y == 0),
+                     "Must be uploading to the origin when we don't have an existing texture");
+
+        if (textureInited && gl->CanUploadSubTextures()) {
+            gl->TexSubImage2D(aTextureTarget,
+                              0,
+                              iterRect->x,
+                              iterRect->y,
+                              iterRect->width,
+                              iterRect->height,
+                              aStride,
+                              pixelSize,
+                              format,
+                              type,
+                              rectData);
+        } else {
+            gl->TexImage2D(aTextureTarget,
+                           0,
+                           internalFormat,
+                           iterRect->width,
+                           iterRect->height,
+                           aStride,
+                           pixelSize,
+                           0,
+                           format,
+                           type,
+                          rectData);
+        }
+
+    }
+
+    return surfaceFormat;
+}
+
+SurfaceFormat
+UploadSurfaceToTexture(GLContext* gl,
+                       gfxASurface *aSurface,
+                       const nsIntRegion& aDstRegion,
+                       GLuint& aTexture,
+                       bool aOverwrite,
+                       const nsIntPoint& aSrcPoint,
+                       bool aPixelBuffer,
+                       GLenum aTextureUnit,
+                       GLenum aTextureTarget)
+{
+
+    nsRefPtr<gfxImageSurface> imageSurface = aSurface->GetAsImageSurface();
+    unsigned char* data = nullptr;
+
+    if (!imageSurface ||
+        (imageSurface->Format() != gfxImageFormatARGB32 &&
+         imageSurface->Format() != gfxImageFormatRGB24 &&
+         imageSurface->Format() != gfxImageFormatRGB16_565 &&
+         imageSurface->Format() != gfxImageFormatA8)) {
+        // We can't get suitable pixel data for the surface, make a copy
+        nsIntRect bounds = aDstRegion.GetBounds();
+        imageSurface =
+          new gfxImageSurface(gfxIntSize(bounds.width, bounds.height),
+                              gfxImageFormatARGB32);
+
+        nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
+
+        context->Translate(-gfxPoint(aSrcPoint.x, aSrcPoint.y));
+        context->SetSource(aSurface);
+        context->Paint();
+        data = imageSurface->Data();
+        NS_ASSERTION(!aPixelBuffer,
+                     "Must be using an image compatible surface with pixel buffers!");
+    } else {
+        // If a pixel buffer is bound the data pointer parameter is relative
+        // to the start of the data block.
+        if (!aPixelBuffer) {
+              data = imageSurface->Data();
+        }
+        data += DataOffset(aSrcPoint, imageSurface->Stride(),
+                           imageSurface->Format());
+    }
+
+    MOZ_ASSERT(imageSurface);
+    imageSurface->Flush();
+
+    return UploadImageDataToTexture(gl,
+                                    data,
+                                    imageSurface->Stride(),
+                                    imageSurface->Format(),
+                                    aDstRegion, aTexture, aOverwrite,
+                                    aPixelBuffer, aTextureUnit, aTextureTarget);
+}
+
+SurfaceFormat
+UploadSurfaceToTexture(GLContext* gl,
+                       gfx::DataSourceSurface *aSurface,
+                       const nsIntRegion& aDstRegion,
+                       GLuint& aTexture,
+                       bool aOverwrite,
+                       const nsIntPoint& aSrcPoint,
+                       bool aPixelBuffer,
+                       GLenum aTextureUnit,
+                       GLenum aTextureTarget)
+{
+    unsigned char* data = aPixelBuffer ? nullptr : aSurface->GetData();
+    int32_t stride = aSurface->Stride();
+    gfxImageFormat format =
+        ImageFormatForSurfaceFormat(aSurface->GetFormat());
+    data += DataOffset(aSrcPoint, stride, format);
+    return UploadImageDataToTexture(gl, data, stride, format,
+                                    aDstRegion, aTexture, aOverwrite,
+                                    aPixelBuffer, aTextureUnit,
+                                    aTextureTarget);
+}
+
+}
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/gl/GLUploadHelpers.h
@@ -0,0 +1,101 @@
+/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
+/* 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 GLUploadHelpers_h_
+#define GLUploadHelpers_h_
+
+#include "GLDefs.h"
+#include "gfxTypes.h"
+#include "mozilla/gfx/Types.h"
+#include "nsPoint.h"
+
+class gfxASurface;
+class nsIntRegion;
+
+namespace mozilla {
+
+namespace gfx {
+class DataSourceSurface;
+}
+
+namespace gl {
+
+class GLContext;
+
+/**
+  * Creates a RGB/RGBA texture (or uses one provided) and uploads the surface
+  * contents to it within aSrcRect.
+  *
+  * aSrcRect.x/y will be uploaded to 0/0 in the texture, and the size
+  * of the texture with be aSrcRect.width/height.
+  *
+  * If an existing texture is passed through aTexture, it is assumed it
+  * has already been initialised with glTexImage2D (or this function),
+  * and that its size is equal to or greater than aSrcRect + aDstPoint.
+  * You can alternatively set the overwrite flag to true and have a new
+  * texture memory block allocated.
+  *
+  * The aDstPoint parameter is ignored if no texture was provided
+  * or aOverwrite is true.
+  *
+  * \param aData Image data to upload.
+  * \param aDstRegion Region of texture to upload to.
+  * \param aTexture Texture to use, or 0 to have one created for you.
+  * \param aOverwrite Over an existing texture with a new one.
+  * \param aSrcPoint Offset into aSrc where the region's bound's
+  *  TopLeft() sits.
+  * \param aPixelBuffer Pass true to upload texture data with an
+  *  offset from the base data (generally for pixel buffer objects),
+  *  otherwise textures are upload with an absolute pointer to the data.
+  * \param aTextureUnit, the texture unit used temporarily to upload the
+  *  surface. This testure may be overridden, clients should not rely on
+  *  the contents of this texture after this call or even on this
+  *  texture unit being active.
+  * \return Surface format of this texture.
+  */
+gfx::SurfaceFormat
+UploadImageDataToTexture(GLContext* gl,
+                         unsigned char* aData,
+                         int32_t aStride,
+                         gfxImageFormat aFormat,
+                         const nsIntRegion& aDstRegion,
+                         GLuint& aTexture,
+                         bool aOverwrite = false,
+                         bool aPixelBuffer = false,
+                         GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
+                         GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
+
+/**
+  * Convenience wrapper around UploadImageDataToTexture for gfxASurfaces.
+  */
+gfx::SurfaceFormat
+UploadSurfaceToTexture(GLContext* gl,
+                       gfxASurface *aSurface,
+                       const nsIntRegion& aDstRegion,
+                       GLuint& aTexture,
+                       bool aOverwrite = false,
+                       const nsIntPoint& aSrcPoint = nsIntPoint(0, 0),
+                       bool aPixelBuffer = false,
+                       GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
+                       GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
+
+/**
+  * Convenience wrapper around UploadImageDataToTexture for gfx::DataSourceSurface's.
+  */
+gfx::SurfaceFormat
+UploadSurfaceToTexture(GLContext* gl,
+                       gfx::DataSourceSurface *aSurface,
+                       const nsIntRegion& aDstRegion,
+                       GLuint& aTexture,
+                       bool aOverwrite,
+                       const nsIntPoint& aSrcPoint,
+                       bool aPixelBuffer,
+                       GLenum aTextureUnit,
+                       GLenum aTextureTarget);
+
+}
+}
+
+#endif
--- a/gfx/gl/TextureImageEGL.cpp
+++ b/gfx/gl/TextureImageEGL.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "GLUploadHelpers.h"
 #include "gfxPlatform.h"
 #include "mozilla/gfx/Types.h"
 
 namespace mozilla {
 namespace gl {
 
 static GLenum
 GLFormatForImage(gfxImageFormat aFormat)
@@ -210,22 +211,23 @@ TextureImageEGL::DirectUpdate(gfxASurfac
     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);
+      UploadSurfaceToTexture(mGLContext,
+                             aSurf,
+                             region,
+                             mTexture,
+                             mTextureState == Created,
+                             bounds.TopLeft() + aFrom,
+                             false);
 
     mTextureState = Valid;
     return true;
 }
 
 void
 TextureImageEGL::BindTexture(GLenum aTextureUnit)
 {
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -39,16 +39,17 @@ EXPORTS += [
     'GLContextUtils.h',
     'GLDefs.h',
     'GLLibraryEGL.h',
     'GLLibraryLoader.h',
     'GLScreenBuffer.h',
     'GLSharedHandleHelpers.h',
     'GLTextureImage.h',
     'GLTypes.h',
+    'GLUploadHelpers.h',
     'ScopedGLHelpers.h',
     'SharedSurface.h',
     'SharedSurfaceEGL.h',
     'SharedSurfaceGL.h',
     'SurfaceFactory.h',
     'SurfaceStream.h',
     'SurfaceTypes.h',
     'TextureGarbageBin.h',
@@ -115,16 +116,17 @@ UNIFIED_SOURCES += [
     'GLContextFeatures.cpp',
     'GLContextTypes.cpp',
     'GLContextUtils.cpp',
     'GLLibraryEGL.cpp',
     'GLLibraryLoader.cpp',
     'GLScreenBuffer.cpp',
     'GLSharedHandleHelpers.cpp',
     'GLTextureImage.cpp',
+    'GLUploadHelpers.cpp',
     'ScopedGLHelpers.cpp',
     'SharedSurface.cpp',
     'SharedSurfaceEGL.cpp',
     'SharedSurfaceGL.cpp',
     'SurfaceFactory.cpp',
     'SurfaceStream.cpp',
     'SurfaceTypes.cpp',
     'TextureGarbageBin.cpp',
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "GLUploadHelpers.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
@@ -818,20 +819,21 @@ SurfaceStreamHostOGL::Lock()
       MOZ_CRASH("Invalid SharedSurface type.");
   }
 
   if (toUpload) {
     // mBounds seems to end up as (0,0,0,0) a lot, so don't use it?
     nsIntSize size(toUpload->GetSize());
     nsIntRect rect(nsIntPoint(0,0), size);
     nsIntRegion bounds(rect);
-    mFormat = mGL->UploadSurfaceToTexture(toUpload,
-                                          bounds,
-                                          mUploadTexture,
-                                          true);
+    mFormat = UploadSurfaceToTexture(mGL,
+                                     toUpload,
+                                     bounds,
+                                     mUploadTexture,
+                                     true);
     mTextureHandle = mUploadTexture;
     mTextureTarget = LOCAL_GL_TEXTURE_2D;
   }
 
   MOZ_ASSERT(mTextureHandle);
   mGL->fBindTexture(mTextureTarget, mTextureHandle);
   mGL->fTexParameteri(mTextureTarget,
                       LOCAL_GL_TEXTURE_WRAP_S,
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -56,16 +56,17 @@
 #include "gfxUtils.h"
 #include "nsRegion.h"
 #include "Layers.h"
 #include "ClientLayerManager.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "GLTextureImage.h"
 #include "GLContextProvider.h"
 #include "GLContext.h"
+#include "GLUploadHelpers.h"
 #include "mozilla/layers/GLManager.h"
 #include "mozilla/layers/CompositorCocoaWidgetHelper.h"
 #include "mozilla/layers/CompositorOGL.h"
 #include "mozilla/layers/BasicCompositor.h"
 #include "gfxUtils.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/BorrowedContext.h"
 #ifdef ACCESSIBILITY
@@ -2629,24 +2630,25 @@ RectTextureImage::EndUpdate(bool aKeepSu
 
   if (overwriteTexture || !CanUploadSubtextures()) {
     updateRegion = nsIntRect(nsIntPoint(0, 0), mTextureSize);
   }
 
   RefPtr<gfx::SourceSurface> snapshot = mUpdateDrawTarget->Snapshot();
   RefPtr<gfx::DataSourceSurface> dataSnapshot = snapshot->GetDataSurface();
 
-  mGLContext->UploadSurfaceToTexture(dataSnapshot,
-                                     updateRegion,
-                                     mTexture,
-                                     overwriteTexture,
-                                     updateRegion.GetBounds().TopLeft(),
-                                     false,
-                                     LOCAL_GL_TEXTURE0,
-                                     LOCAL_GL_TEXTURE_RECTANGLE_ARB);
+  UploadSurfaceToTexture(mGLContext,
+                         dataSnapshot,
+                         updateRegion,
+                         mTexture,
+                         overwriteTexture,
+                         updateRegion.GetBounds().TopLeft(),
+                         false,
+                         LOCAL_GL_TEXTURE0,
+                         LOCAL_GL_TEXTURE_RECTANGLE_ARB);
 
   if (!aKeepSurface) {
     mUpdateDrawTarget = nullptr;
   }
 
   mInUpdate = false;
 }