Bug 959154 - Part 7: Moz2Dify GLTextureImage::BeginUpdate/EndUpdate. r=nical
☠☠ backed out by 5749f2fc4f47 ☠ ☠
authorAndreas Pehrson <pehrsons@gmail.com>
Thu, 13 Feb 2014 19:00:01 +0100
changeset 168799 0f9be8d2caaf567398b4054d01b087bf43c45de8
parent 168798 6ca9ba706c9441c582cacdd09d00c237b9b6e79e
child 168800 00e465be0552d1e5099db9694729e1893bd45c06
push id39797
push userryanvm@gmail.com
push dateFri, 14 Feb 2014 16:44:24 +0000
treeherdermozilla-inbound@f73e612c9641 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs959154
milestone30.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 959154 - Part 7: Moz2Dify GLTextureImage::BeginUpdate/EndUpdate. r=nical
gfx/gl/GLTextureImage.cpp
gfx/gl/GLTextureImage.h
gfx/gl/TextureImageEGL.cpp
gfx/gl/TextureImageEGL.h
--- a/gfx/gl/GLTextureImage.cpp
+++ b/gfx/gl/GLTextureImage.cpp
@@ -114,103 +114,93 @@ BasicTextureImage::~BasicTextureImage()
     // 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.
     if (ctx && ctx->MakeCurrent()) {
         ctx->fDeleteTextures(1, &mTexture);
     }
 }
 
-gfxASurface*
+gfx::DrawTarget*
 BasicTextureImage::BeginUpdate(nsIntRegion& aRegion)
 {
-    NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
+    NS_ASSERTION(!mUpdateDrawTarget, "BeginUpdate() without EndUpdate()?");
 
     // determine the region the client will need to repaint
     if (CanUploadSubTextures(mGLContext)) {
         GetUpdateRegion(aRegion);
     } else {
         aRegion = nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize));
     }
 
     mUpdateRegion = aRegion;
 
     nsIntRect rgnSize = mUpdateRegion.GetBounds();
     if (!nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize)).Contains(rgnSize)) {
         NS_ERROR("update outside of image");
         return nullptr;
     }
 
-    ImageFormat format =
+    gfx::SurfaceFormat format =
         (GetContentType() == gfxContentType::COLOR) ?
-        gfxImageFormat::RGB24 : gfxImageFormat::ARGB32;
-    mUpdateSurface =
-        GetSurfaceForUpdate(gfxIntSize(rgnSize.width, rgnSize.height), format);
+        gfx::SurfaceFormat::B8G8R8X8 : gfx::SurfaceFormat::B8G8R8A8;
+    mUpdateDrawTarget =
+        GetDrawTargetForUpdate(gfx::IntSize(rgnSize.width, rgnSize.height), format);
 
-    if (!mUpdateSurface || mUpdateSurface->CairoStatus()) {
-        mUpdateSurface = nullptr;
-        return nullptr;
-    }
-
-    mUpdateSurface->SetDeviceOffset(gfxPoint(-rgnSize.x, -rgnSize.y));
-
-    return mUpdateSurface;
+    return mUpdateDrawTarget;
 }
 
 void
 BasicTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
 {
   // if the texture hasn't been initialized yet, or something important
   // changed, we need to recreate our backing surface and force the
   // client to paint everything
   if (mTextureState != Valid)
       aForRegion = nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize));
 }
 
 void
 BasicTextureImage::EndUpdate()
 {
-    NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
+    NS_ASSERTION(!!mUpdateDrawTarget, "EndUpdate() without BeginUpdate()?");
 
     // FIXME: this is the slow boat.  Make me fast (with GLXPixmap?).
 
-    // 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));
+    RefPtr<gfx::SourceSurface> updateSnapshot = mUpdateDrawTarget->Snapshot();
+    RefPtr<gfx::DataSourceSurface> updateData = updateSnapshot->GetDataSurface();
 
     bool relative = FinishedSurfaceUpdate();
 
     mTextureFormat =
-        DeprecatedUploadSurfaceToTexture(mGLContext,
-                               mUpdateSurface,
+        UploadSurfaceToTexture(mGLContext,
+                               updateData,
                                mUpdateRegion,
                                mTexture,
                                mTextureState == Created,
                                mUpdateOffset,
                                relative);
     FinishedSurfaceUpload();
 
-    mUpdateSurface = nullptr;
+    mUpdateDrawTarget = nullptr;
     mTextureState = Valid;
 }
 
 void
 BasicTextureImage::BindTexture(GLenum aTextureUnit)
 {
     mGLContext->fActiveTexture(aTextureUnit);
     mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
     mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
 }
 
-already_AddRefed<gfxASurface>
-BasicTextureImage::GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt)
+TemporaryRef<gfx::DrawTarget>
+BasicTextureImage::GetDrawTargetForUpdate(const gfx::IntSize& aSize, gfx::SurfaceFormat aFmt)
 {
-    return gfxPlatform::GetPlatform()->
-        CreateOffscreenSurface(aSize.ToIntSize(),
-                               gfxASurface::ContentFromFormat(aFmt));
+    return gfx::Factory::CreateDrawTarget(gfx::BackendType::CAIRO, aSize, aFmt);
 }
 
 bool
 BasicTextureImage::FinishedSurfaceUpdate()
 {
     return false;
 }
 
@@ -241,17 +231,17 @@ BasicTextureImage::DirectUpdate(gfx::Dat
                                false);
     mTextureState = Valid;
     return true;
 }
 
 void
 BasicTextureImage::Resize(const gfx::IntSize& aSize)
 {
-    NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
+    NS_ASSERTION(!mUpdateDrawTarget, "Resize() while in update?");
 
     mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
 
     mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
                             0,
                             LOCAL_GL_RGBA,
                             aSize.width,
                             aSize.height,
@@ -446,17 +436,17 @@ TiledTextureImage::GetUpdateRegion(nsInt
             // Add to the accumulated region
             newRegion.Or(newRegion, subRegion);
         }
     }
 
     aForRegion = newRegion;
 }
 
-gfxASurface*
+gfx::DrawTarget*
 TiledTextureImage::BeginUpdate(nsIntRegion& aRegion)
 {
     NS_ASSERTION(!mInUpdate, "nested update");
     mInUpdate = true;
 
     // Note, we don't call GetUpdateRegion here as if the updated region is
     // fully contained in a single tile, we get to avoid iterating through
     // the tiles again (and a little copying).
@@ -477,84 +467,86 @@ TiledTextureImage::BeginUpdate(nsIntRegi
           nsIntRegion(nsIntRect(nsIntPoint(xPos,yPos),
                                 ThebesIntSize(mImages[i]->GetSize())));
 
         // a single Image can handle this update request
         if (imageRegion.Contains(aRegion)) {
             // adjust for tile offset
             aRegion.MoveBy(-xPos, -yPos);
             // forward the actual call
-            nsRefPtr<gfxASurface> surface = mImages[i]->BeginUpdate(aRegion);
+            RefPtr<gfx::DrawTarget> drawTarget = mImages[i]->BeginUpdate(aRegion);
             // caller expects container space
             aRegion.MoveBy(xPos, yPos);
-            // Correct the device offset
-            gfxPoint offset = surface->GetDeviceOffset();
-            surface->SetDeviceOffset(gfxPoint(offset.x - xPos,
-                                              offset.y - yPos));
             // we don't have a temp surface
-            mUpdateSurface = nullptr;
+            mUpdateDrawTarget = nullptr;
             // remember which image to EndUpdate
             mCurrentImage = i;
-            return surface.get();
+            return drawTarget.get();
         }
     }
 
     // Get the real updated region, taking into account the capabilities of
     // each TextureImage tile
     GetUpdateRegion(aRegion);
     mUpdateRegion = aRegion;
     bounds = aRegion.GetBounds();
 
     // update covers multiple Images - create a temp surface to paint in
-    gfxImageFormat format =
+    gfx::SurfaceFormat format =
         (GetContentType() == gfxContentType::COLOR) ?
-        gfxImageFormat::RGB24 : gfxImageFormat::ARGB32;
-    mUpdateSurface = gfxPlatform::GetPlatform()->
-        CreateOffscreenSurface(bounds.Size().ToIntSize(),
-                               gfxASurface::ContentFromFormat(format));
-    mUpdateSurface->SetDeviceOffset(gfxPoint(-bounds.x, -bounds.y));
+        gfx::SurfaceFormat::B8G8R8X8: gfx::SurfaceFormat::B8G8R8A8;
+    mUpdateDrawTarget = gfx::Factory::CreateDrawTarget(gfx::BackendType::CAIRO,
+                                                       bounds.Size().ToIntSize(),
+                                                       format);
 
-    return mUpdateSurface;
+    return mUpdateDrawTarget;;
 }
 
 void
 TiledTextureImage::EndUpdate()
 {
     NS_ASSERTION(mInUpdate, "EndUpdate not in update");
-    if (!mUpdateSurface) { // update was to a single TextureImage
+    if (!mUpdateDrawTarget) { // update was to a single TextureImage
         mImages[mCurrentImage]->EndUpdate();
         mInUpdate = false;
         mTextureState = Valid;
         mTextureFormat = mImages[mCurrentImage]->GetTextureFormat();
         return;
     }
 
+    RefPtr<gfx::SourceSurface> updateSnapshot = mUpdateDrawTarget->Snapshot();
+    RefPtr<gfx::DataSourceSurface> updateData = updateSnapshot->GetDataSurface();
+    nsRefPtr<gfxASurface> updateSurface = new gfxImageSurface(updateData->GetData(),
+                                                              gfx::ThebesIntSize(updateData->GetSize()),
+                                                              updateData->Stride(),
+                                                              gfx::SurfaceFormatToImageFormat(updateData->GetFormat()));
+
     // upload tiles from temp surface
     for (unsigned i = 0; i < mImages.Length(); i++) {
         int xPos = (i % mColumns) * mTileSize;
         int yPos = (i / mColumns) * mTileSize;
         nsIntRect imageRect = nsIntRect(nsIntPoint(xPos,yPos),
                                         ThebesIntSize(mImages[i]->GetSize()));
 
         nsIntRegion subregion;
         subregion.And(mUpdateRegion, imageRect);
         if (subregion.IsEmpty())
             continue;
         subregion.MoveBy(-xPos, -yPos); // Tile-local space
-        // copy tile from temp surface
-        gfxASurface* surf = mImages[i]->BeginUpdate(subregion);
-        nsRefPtr<gfxContext> ctx = new gfxContext(surf);
+        // copy tile from temp target
+        gfx::DrawTarget* drawTarget = mImages[i]->BeginUpdate(subregion);
+        nsRefPtr<gfxContext> ctx = new gfxContext(drawTarget);
         gfxUtils::ClipToRegion(ctx, subregion);
         ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
-        ctx->SetSource(mUpdateSurface, gfxPoint(-xPos, -yPos));
+        ctx->SetSource(updateSurface, gfxPoint(-xPos, -yPos));
         ctx->Paint();
         mImages[i]->EndUpdate();
     }
 
-    mUpdateSurface = nullptr;
+    mUpdateDrawTarget = nullptr;
     mInUpdate = false;
     mTextureFormat = mImages[0]->GetTextureFormat();
     mTextureState = Valid;
 }
 
 void TiledTextureImage::BeginTileIteration()
 {
     mCurrentImage = 0;
--- a/gfx/gl/GLTextureImage.h
+++ b/gfx/gl/GLTextureImage.h
@@ -8,22 +8,24 @@
 
 #include "nsAutoPtr.h"
 #include "nsRegion.h"
 #include "nsTArray.h"
 #include "gfxTypes.h"
 #include "GLContextTypes.h"
 #include "GraphicsFilter.h"
 #include "mozilla/gfx/Rect.h"
+#include "mozilla/RefPtr.h"
 
 class gfxASurface;
 
 namespace mozilla {
 namespace gfx {
 class DataSourceSurface;
+class DrawTarget;
 }
 }
 
 namespace mozilla {
 namespace gl {
 class GLContext;
 
 /**
@@ -95,17 +97,17 @@ public:
      * in undefined behavior.
      *
      * BeginUpdate() calls cannot be "nested", and each successful
      * BeginUpdate() must be followed by exactly one EndUpdate() (see
      * below).  Failure to do so can leave this in a possibly
      * inconsistent state.  Unsuccessful BeginUpdate()s must not be
      * followed by EndUpdate().
      */
-    virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion) = 0;
+    virtual gfx::DrawTarget* BeginUpdate(nsIntRegion& aRegion) = 0;
     /**
      * Retrieves the region that will require updating, given a
      * region that needs to be updated. This can be used for
      * making decisions about updating before calling BeginUpdate().
      *
      * |aRegion| is an inout param.
      */
     virtual void GetUpdateRegion(nsIntRegion& aForRegion) {
@@ -273,44 +275,43 @@ public:
                       GLenum aWrapMode,
                       ContentType aContentType,
                       GLContext* aContext,
                       TextureImage::Flags aFlags = TextureImage::NoFlags,
                       TextureImage::ImageFormat aImageFormat = gfxImageFormat::Unknown);
 
     virtual void BindTexture(GLenum aTextureUnit);
 
-    virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
+    virtual gfx::DrawTarget* BeginUpdate(nsIntRegion& aRegion);
     virtual void GetUpdateRegion(nsIntRegion& aForRegion);
     virtual void EndUpdate();
     virtual bool DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom = gfx::IntPoint(0,0));
     virtual GLuint GetTextureID() { return mTexture; }
-    // Returns a surface to draw into
-    virtual already_AddRefed<gfxASurface>
-      GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt);
+    virtual TemporaryRef<gfx::DrawTarget>
+      GetDrawTargetForUpdate(const gfx::IntSize& aSize, gfx::SurfaceFormat aFmt);
 
     virtual void MarkValid() { mTextureState = Valid; }
 
     // Call when drawing into the update surface is complete.
     // Returns true if textures should be upload with a relative
     // offset - See UploadSurfaceToTexture.
     virtual bool FinishedSurfaceUpdate();
 
     // Call after surface data has been uploaded to a texture.
     virtual void FinishedSurfaceUpload();
 
-    virtual bool InUpdate() const { return !!mUpdateSurface; }
+    virtual bool InUpdate() const { return !!mUpdateDrawTarget; }
 
     virtual void Resize(const gfx::IntSize& aSize);
 
 protected:
     GLuint mTexture;
     TextureState mTextureState;
     nsRefPtr<GLContext> mGLContext;
-    nsRefPtr<gfxASurface> mUpdateSurface;
+    RefPtr<gfx::DrawTarget> mUpdateDrawTarget;
     nsIntRegion mUpdateRegion;
 
     // The offset into the update surface at which the update rect is located.
     nsIntPoint mUpdateOffset;
 };
 
 /**
  * A container class that complements many sub TextureImages into a big TextureImage.
@@ -323,17 +324,17 @@ class TiledTextureImage
 public:
     TiledTextureImage(GLContext* aGL,
                       gfx::IntSize aSize,
                       TextureImage::ContentType,
                       TextureImage::Flags aFlags = TextureImage::NoFlags,
                       TextureImage::ImageFormat aImageFormat = gfxImageFormat::Unknown);
     ~TiledTextureImage();
     void DumpDiv();
-    virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
+    virtual gfx::DrawTarget* BeginUpdate(nsIntRegion& aRegion);
     virtual void GetUpdateRegion(nsIntRegion& aForRegion);
     virtual void EndUpdate();
     virtual void Resize(const gfx::IntSize& aSize);
     virtual uint32_t GetTileCount();
     virtual void BeginTileIteration();
     virtual bool NextTile();
     virtual void SetIterationCallback(TileIterationCallback aCallback,
                                       void* aCallbackData);
@@ -352,18 +353,18 @@ protected:
     TileIterationCallback mIterationCallback;
     void* mIterationCallbackData;
     nsTArray< nsRefPtr<TextureImage> > mImages;
     bool mInUpdate;
     gfx::IntSize mSize;
     unsigned int mTileSize;
     unsigned int mRows, mColumns;
     GLContext* mGL;
-    // A temporary surface to faciliate cross-tile updates.
-    nsRefPtr<gfxASurface> mUpdateSurface;
+    // A temporary draw target to faciliate cross-tile updates.
+    RefPtr<gfx::DrawTarget> mUpdateDrawTarget;
     // The region of update requested
     nsIntRegion mUpdateRegion;
     TextureState mTextureState;
     TextureImage::ImageFormat mImageFormat;
 };
 
 /**
  * Creates a TextureImage of the basic implementation, can be useful in cases
--- a/gfx/gl/TextureImageEGL.cpp
+++ b/gfx/gl/TextureImageEGL.cpp
@@ -10,77 +10,74 @@
 #include "gfxPlatform.h"
 #include "gfx2DGlue.h"
 #include "mozilla/gfx/Types.h"
 
 namespace mozilla {
 namespace gl {
 
 static GLenum
-GLFormatForImage(gfxImageFormat aFormat)
+GLFormatForImage(gfx::SurfaceFormat aFormat)
 {
     switch (aFormat) {
-    case gfxImageFormat::ARGB32:
-    case gfxImageFormat::RGB24:
-        // Thebes only supports RGBX, not packed RGB.
+    case gfx::SurfaceFormat::B8G8R8A8:
+    case gfx::SurfaceFormat::B8G8R8X8:
         return LOCAL_GL_RGBA;
-    case gfxImageFormat::RGB16_565:
+    case gfx::SurfaceFormat::R5G6B5:
         return LOCAL_GL_RGB;
-    case gfxImageFormat::A8:
+    case gfx::SurfaceFormat::A8:
         return LOCAL_GL_LUMINANCE;
     default:
-        NS_WARNING("Unknown GL format for Image format");
+        NS_WARNING("Unknown GL format for Surface format");
     }
     return 0;
 }
 
 static GLenum
-GLTypeForImage(gfxImageFormat aFormat)
+GLTypeForImage(gfx::SurfaceFormat aFormat)
 {
     switch (aFormat) {
-    case gfxImageFormat::ARGB32:
-    case gfxImageFormat::RGB24:
-    case gfxImageFormat::A8:
+    case gfx::SurfaceFormat::B8G8R8A8:
+    case gfx::SurfaceFormat::B8G8R8X8:
+    case gfx::SurfaceFormat::A8:
         return LOCAL_GL_UNSIGNED_BYTE;
-    case gfxImageFormat::RGB16_565:
+    case gfx::SurfaceFormat::R5G6B5:
         return LOCAL_GL_UNSIGNED_SHORT_5_6_5;
     default:
-        NS_WARNING("Unknown GL format for Image format");
+        NS_WARNING("Unknown GL format for Surface 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)
+    , mUpdateFormat(gfx::ImageFormatToSurfaceFormat(aImageFormat))
     , mEGLImage(nullptr)
     , mTexture(aTexture)
     , mSurface(nullptr)
     , mConfig(nullptr)
     , mTextureState(aTextureState)
     , mBound(false)
 {
-    if (mUpdateFormat == gfxImageFormat::Unknown) {
-        mUpdateFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType());
+    if (mUpdateFormat == gfx::SurfaceFormat::UNKNOWN) {
+        mUpdateFormat = gfx::ImageFormatToSurfaceFormat(
+                gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType()));
     }
 
-    if (mUpdateFormat == gfxImageFormat::RGB16_565) {
+    if (mUpdateFormat == gfx::SurfaceFormat::R5G6B5) {
         mTextureFormat = gfx::SurfaceFormat::R8G8B8X8;
-    } else if (mUpdateFormat == gfxImageFormat::RGB24) {
-        // RGB24 means really RGBX for Thebes, which means we have to
-        // use the right shader and ignore the uninitialized alpha
-        // value.
+    } else if (mUpdateFormat == gfx::SurfaceFormat::B8G8R8X8) {
         mTextureFormat = gfx::SurfaceFormat::B8G8R8X8;
     } else {
         mTextureFormat = gfx::SurfaceFormat::B8G8R8A8;
     }
 }
 
 TextureImageEGL::~TextureImageEGL()
 {
@@ -109,66 +106,60 @@ TextureImageEGL::GetUpdateRegion(nsIntRe
 
     // 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*
+gfx::DrawTarget*
 TextureImageEGL::BeginUpdate(nsIntRegion& aRegion)
 {
-    NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
+    NS_ASSERTION(!mUpdateDrawTarget, "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), gfx::ThebesIntSize(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);
+    mUpdateDrawTarget = gfx::Factory::CreateDrawTarget(gfx::BackendType::CAIRO,
+                                                       gfx::IntSize(mUpdateRect.width, mUpdateRect.height),
+                                                       mUpdateFormat);
 
-    mUpdateSurface->SetDeviceOffset(gfxPoint(-mUpdateRect.x, -mUpdateRect.y));
-
-    return mUpdateSurface;
+    return mUpdateDrawTarget;
 }
 
 void
 TextureImageEGL::EndUpdate()
 {
-    NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
+    NS_ASSERTION(!!mUpdateDrawTarget, "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));
+    RefPtr<gfx::SourceSurface> updateSurface = nullptr;
+    RefPtr<gfx::DataSourceSurface> uploadImage = nullptr;
+    gfx::IntSize updateSize(mUpdateRect.width, mUpdateRect.height);
 
-    nsRefPtr<gfxImageSurface> uploadImage = nullptr;
-    gfxIntSize updateSize(mUpdateRect.width, mUpdateRect.height);
+    NS_ASSERTION(mUpdateDrawTarget->GetSize() == updateSize,
+                  "Upload image is the wrong size!");
 
-    NS_ASSERTION(mUpdateSurface->GetType() == gfxSurfaceType::Image &&
-                  mUpdateSurface->GetSize() == updateSize,
-                  "Upload image isn't an image surface when one is expected, or is wrong size!");
-
-    uploadImage = static_cast<gfxImageSurface*>(mUpdateSurface.get());
+    updateSurface = mUpdateDrawTarget->Snapshot();
+    uploadImage = updateSurface->GetDataSurface();
 
     if (!uploadImage) {
         return;
     }
 
     mGLContext->MakeCurrent();
     mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
 
@@ -178,32 +169,32 @@ TextureImageEGL::EndUpdate()
                       "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());
+                                GLFormatForImage(uploadImage->GetFormat()),
+                                GLTypeForImage(uploadImage->GetFormat()),
+                                uploadImage->GetData());
     } else {
         mGLContext->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
                                     0,
                                     mUpdateRect.x,
                                     mUpdateRect.y,
                                     mUpdateRect.width,
                                     mUpdateRect.height,
-                                    GLFormatForImage(uploadImage->Format()),
-                                    GLTypeForImage(uploadImage->Format()),
-                                    uploadImage->Data());
+                                    GLFormatForImage(uploadImage->GetFormat()),
+                                    GLTypeForImage(uploadImage->GetFormat()),
+                                    uploadImage->GetData());
     }
 
-    mUpdateSurface = nullptr;
+    mUpdateDrawTarget = nullptr;
     mTextureState = Valid;
     return;         // mTexture is bound
 }
 
 bool
 TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom /* = gfx::IntPoint(0,0) */)
 {
     nsIntRect bounds = aRegion.GetBounds();
@@ -240,17 +231,17 @@ TextureImageEGL::BindTexture(GLenum aTex
     mGLContext->fActiveTexture(aTextureUnit);
     mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
     mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
 }
 
 void
 TextureImageEGL::Resize(const gfx::IntSize& aSize)
 {
-    NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
+    NS_ASSERTION(!mUpdateDrawTarget, "Resize() while in update?");
 
     if (mSize == aSize && mTextureState != Created)
         return;
 
     mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
 
     mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
                             0,
--- a/gfx/gl/TextureImageEGL.h
+++ b/gfx/gl/TextureImageEGL.h
@@ -23,34 +23,34 @@ public:
                     Flags aFlags = TextureImage::NoFlags,
                     TextureState aTextureState = Created,
                     TextureImage::ImageFormat aImageFormat = gfxImageFormat::Unknown);
 
     virtual ~TextureImageEGL();
 
     virtual void GetUpdateRegion(nsIntRegion& aForRegion);
 
-    virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
+    virtual gfx::DrawTarget* BeginUpdate(nsIntRegion& aRegion);
 
     virtual void EndUpdate();
 
     virtual bool DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom = gfx::IntPoint(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 bool InUpdate() const { return !!mUpdateDrawTarget; }
 
     virtual void Resize(const gfx::IntSize& aSize);
 
     bool BindTexImage();
 
     bool ReleaseTexImage();
 
     virtual bool CreateEGLSurface(gfxASurface* aSurface)
@@ -61,18 +61,18 @@ public:
     virtual void DestroyEGLSurface(void);
 
 protected:
     typedef gfxImageFormat ImageFormat;
 
     GLContext* mGLContext;
 
     nsIntRect mUpdateRect;
-    ImageFormat mUpdateFormat;
-    nsRefPtr<gfxASurface> mUpdateSurface;
+    gfx::SurfaceFormat mUpdateFormat;
+    RefPtr<gfx::DrawTarget> mUpdateDrawTarget;
     EGLImage mEGLImage;
     GLuint mTexture;
     EGLSurface mSurface;
     EGLConfig mConfig;
     TextureState mTextureState;
 
     bool mBound;
 };