Bug 962786 - Convert nsDragService to use Moz2D. r=roc
authorMatt Woodrow <mwoodrow@mozilla.com>
Wed, 29 Jan 2014 13:10:33 +1300
changeset 182947 975cc687b0e32e9b9b65bbc4447a895920d11fc4
parent 182946 c1a6fdd3fa0159ac1a62a83eb1abd07af703e49c
child 182948 70c7b1b1cc181e37ab1329df8a5ec84c67b50952
push id462
push userraliiev@mozilla.com
push dateTue, 22 Apr 2014 00:22:30 +0000
treeherdermozilla-release@ac5db8c74ac0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs962786
milestone29.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 962786 - Convert nsDragService to use Moz2D. r=roc * * * Bug 962786 - Bustage fix on a CLOSED TREE
layout/base/nsIPresShell.h
layout/base/nsPresShell.cpp
layout/base/nsPresShell.h
widget/cocoa/nsDragService.mm
widget/gtk/nsDragService.cpp
widget/gtk/nsDragService.h
widget/gtk/nsImageToPixbuf.cpp
widget/gtk/nsImageToPixbuf.h
widget/windows/nsDragService.cpp
widget/xpwidgets/nsBaseDragService.cpp
widget/xpwidgets/nsBaseDragService.h
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -98,19 +98,23 @@ namespace mozilla {
 class Selection;
 
 namespace dom {
 class Element;
 class Touch;
 class ShadowRoot;
 } // namespace dom
 
-namespace layers{
+namespace layers {
 class LayerManager;
 } // namespace layers
+
+namespace gfx {
+class SourceSurface;
+} // namespace gfx
 } // namespace mozilla
 
 // Flags to pass to SetCapturingContent
 //
 // when assigning capture, ignore whether capture is allowed or not
 #define CAPTURE_IGNOREALLOWED 1
 // true if events should be targeted at the capturing content or its children
 #define CAPTURE_RETARGETTOELEMENT 2
@@ -123,21 +127,20 @@ typedef struct CapturingContentInfo {
   // capture should only be allowed during a mousedown event
   bool mAllowed;
   bool mPointerLock;
   bool mRetargetToElement;
   bool mPreventDrag;
   nsIContent* mContent;
 } CapturingContentInfo;
 
-
-// db8d5e1e-6392-4ec1-9a29-18ee2ec0889b
+//bccc1c01-5123-4f49-9572-c0bf506b6418
 #define NS_IPRESSHELL_IID \
-{ 0xdb8d5e1e, 0x6392, 0x4ec1, \
-  {0x9a, 0x29, 0x18, 0xee, 0x2e, 0xc0, 0x88, 0x9b}}
+{ 0xbccc1c01, 0x5123, 0x4f49, \
+  {0x95, 0x72, 0xc0, 0xbf, 0x50, 0x6b, 0x64, 0x18}}
 
 // debug VerifyReflow flags
 #define VERIFY_REFLOW_ON                    0x01
 #define VERIFY_REFLOW_NOISY                 0x02
 #define VERIFY_REFLOW_ALL                   0x04
 #define VERIFY_REFLOW_DUMP_COMMANDS         0x08
 #define VERIFY_REFLOW_NOISY_RC              0x10
 #define VERIFY_REFLOW_REALLY_NOISY_RC       0x20
@@ -173,16 +176,17 @@ public:
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIPresShell_base, NS_IPRESSHELL_IID)
 
 class nsIPresShell : public nsIPresShell_base
 {
 protected:
   typedef mozilla::layers::LayerManager LayerManager;
+  typedef mozilla::gfx::SourceSurface SourceSurface;
 
   enum eRenderFlag {
     STATE_IGNORING_VIEWPORT_SCROLLING = 0x1,
     STATE_DRAWWINDOW_NOT_FLUSHING = 0x2
   };
   typedef uint8_t RenderFlags; // for storing the above flags
 
 public:
@@ -1026,39 +1030,41 @@ public:
                                               gfxContext* aRenderedContext) = 0;
 
   /**
    * Renders a node aNode to a surface and returns it. The aRegion may be used
    * to clip the rendering. This region is measured in CSS pixels from the
    * edge of the presshell area. The aPoint, aScreenRect and aSurface
    * arguments function in a similar manner as RenderSelection.
    */
-  virtual already_AddRefed<gfxASurface> RenderNode(nsIDOMNode* aNode,
-                                                   nsIntRegion* aRegion,
-                                                   nsIntPoint& aPoint,
-                                                   nsIntRect* aScreenRect) = 0;
+  virtual mozilla::TemporaryRef<SourceSurface>
+  RenderNode(nsIDOMNode* aNode,
+             nsIntRegion* aRegion,
+             nsIntPoint& aPoint,
+             nsIntRect* aScreenRect) = 0;
 
   /**
    * Renders a selection to a surface and returns it. This method is primarily
    * intended to create the drag feedback when dragging a selection.
    *
    * aScreenRect will be filled in with the bounding rectangle of the
    * selection area on screen.
    *
    * If the area of the selection is large, the image will be scaled down.
    * The argument aPoint is used in this case as a reference point when
    * determining the new screen rectangle after scaling. Typically, this
    * will be the mouse position, so that the screen rectangle is positioned
    * such that the mouse is over the same point in the scaled image as in
    * the original. When scaling does not occur, the mouse point isn't used
    * as the position can be determined from the displayed frames.
    */
-  virtual already_AddRefed<gfxASurface> RenderSelection(nsISelection* aSelection,
-                                                        nsIntPoint& aPoint,
-                                                        nsIntRect* aScreenRect) = 0;
+  virtual mozilla::TemporaryRef<SourceSurface>
+  RenderSelection(nsISelection* aSelection,
+                  nsIntPoint& aPoint,
+                  nsIntRect* aScreenRect) = 0;
 
   void AddWeakFrameInternal(nsWeakFrame* aWeakFrame);
   virtual void AddWeakFrameExternal(nsWeakFrame* aWeakFrame);
 
   void AddWeakFrame(nsWeakFrame* aWeakFrame)
   {
 #ifdef MOZILLA_INTERNAL_API
     AddWeakFrameInternal(aWeakFrame);
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -160,28 +160,30 @@
 #include "nsIScreenManager.h"
 #include "nsPlaceholderFrame.h"
 #include "nsTransitionManager.h"
 #include "ChildIterator.h"
 #include "RestyleManager.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDragSession.h"
 #include "nsIFrameInlines.h"
+#include "mozilla/gfx/2D.h"
 
 #ifdef ANDROID
 #include "nsIDocShellTreeOwner.h"
 #endif
 
 #define ANCHOR_SCROLL_FLAGS \
   (nsIPresShell::SCROLL_OVERFLOW_HIDDEN | nsIPresShell::SCROLL_NO_PARENT_FRAMES)
 
 using namespace mozilla;
 using namespace mozilla::css;
 using namespace mozilla::dom;
 using namespace mozilla::layers;
+using namespace mozilla::gfx;
 
 CapturingContentInfo nsIPresShell::gCaptureInfo =
   { false /* mAllowed */, false /* mPointerLock */, false /* mRetargetToElement */,
     false /* mPreventDrag */, nullptr /* mContent */ };
 nsIContent* nsIPresShell::gKeyDownTarget;
 nsRefPtrHashtable<nsUint32HashKey, dom::Touch>* nsIPresShell::gCaptureTouchList;
 bool nsIPresShell::gPreventMouseEvents = false;
 
@@ -4841,17 +4843,17 @@ PresShell::CreateRangePaintInfo(nsIDOMRa
   // to all be offset from the same point
   info->mRootOffset = ancestorFrame->GetOffsetTo(rootFrame);
   rangeRect.MoveBy(info->mRootOffset);
   aSurfaceRect.UnionRect(aSurfaceRect, rangeRect);
 
   return info;
 }
 
-already_AddRefed<gfxASurface>
+TemporaryRef<SourceSurface>
 PresShell::PaintRangePaintInfo(nsTArray<nsAutoPtr<RangePaintInfo> >* aItems,
                                nsISelection* aSelection,
                                nsIntRegion* aRegion,
                                nsRect aArea,
                                nsIntPoint& aPoint,
                                nsIntRect* aScreenRect)
 {
   nsPresContext* pc = GetPresContext();
@@ -4910,18 +4912,24 @@ PresShell::PaintRangePaintInfo(nsTArray<
   }
 
   // clear the image
   gfxContext context(surface);
   context.SetOperator(gfxContext::OPERATOR_CLEAR);
   context.Rectangle(gfxRect(0, 0, pixelArea.width, pixelArea.height));
   context.Fill();
 
+
+  RefPtr<DrawTarget> dt =
+    gfxPlatform::GetPlatform()->
+      CreateDrawTargetForSurface(surface, gfx::IntSize(pixelArea.width, pixelArea.height));
+
+  nsRefPtr<gfxContext> ctx = new gfxContext(dt);
   nsRefPtr<nsRenderingContext> rc = new nsRenderingContext();
-  rc->Init(deviceContext, surface);
+  rc->Init(deviceContext, ctx);
 
   if (aRegion) {
     // Convert aRegion from CSS pixels to dev pixels
     nsIntRegion region =
       aRegion->ToAppUnits(nsPresContext::AppUnitsPerCSSPixel())
         .ToOutsidePixels(pc->AppUnitsPerDevPixel());
     rc->SetClip(region);
   }
@@ -4959,20 +4967,20 @@ PresShell::PaintRangePaintInfo(nsTArray<
     rangeInfo->mList.ComputeVisibilityForRoot(&rangeInfo->mBuilder, &visible);
     rangeInfo->mList.PaintRoot(&rangeInfo->mBuilder, rc, nsDisplayList::PAINT_DEFAULT);
     aArea.MoveBy(rangeInfo->mRootOffset.x, rangeInfo->mRootOffset.y);
   }
 
   // restore the old selection display state
   frameSelection->SetDisplaySelection(oldDisplaySelection);
 
-  return surface.forget();
-}
-
-already_AddRefed<gfxASurface>
+  return dt->Snapshot();
+}
+
+TemporaryRef<SourceSurface>
 PresShell::RenderNode(nsIDOMNode* aNode,
                       nsIntRegion* aRegion,
                       nsIntPoint& aPoint,
                       nsIntRect* aScreenRect)
 {
   // area will hold the size of the surface needed to draw the node, measured
   // from the root frame.
   nsRect area;
@@ -5008,17 +5016,17 @@ PresShell::RenderNode(nsIDOMNode* aNode,
     aRegion->MoveBy(-pc->AppUnitsToDevPixels(area.x),
                     -pc->AppUnitsToDevPixels(area.y));
   }
 
   return PaintRangePaintInfo(&rangeItems, nullptr, aRegion, area, aPoint,
                              aScreenRect);
 }
 
-already_AddRefed<gfxASurface>
+TemporaryRef<SourceSurface>
 PresShell::RenderSelection(nsISelection* aSelection,
                            nsIntPoint& aPoint,
                            nsIntRect* aScreenRect)
 {
   // area will hold the size of the surface needed to draw the selection,
   // measured from the root frame.
   nsRect area;
   nsTArray<nsAutoPtr<RangePaintInfo> > rangeItems;
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -157,24 +157,26 @@ public:
   virtual void Freeze() MOZ_OVERRIDE;
   virtual void Thaw() MOZ_OVERRIDE;
   virtual void FireOrClearDelayedEvents(bool aFireEvents) MOZ_OVERRIDE;
 
   virtual NS_HIDDEN_(nsresult) RenderDocument(const nsRect& aRect, uint32_t aFlags,
                                               nscolor aBackgroundColor,
                                               gfxContext* aThebesContext) MOZ_OVERRIDE;
 
-  virtual already_AddRefed<gfxASurface> RenderNode(nsIDOMNode* aNode,
-                                                   nsIntRegion* aRegion,
-                                                   nsIntPoint& aPoint,
-                                                   nsIntRect* aScreenRect) MOZ_OVERRIDE;
+  virtual mozilla::TemporaryRef<SourceSurface>
+  RenderNode(nsIDOMNode* aNode,
+             nsIntRegion* aRegion,
+             nsIntPoint& aPoint,
+             nsIntRect* aScreenRect) MOZ_OVERRIDE;
 
-  virtual already_AddRefed<gfxASurface> RenderSelection(nsISelection* aSelection,
-                                                        nsIntPoint& aPoint,
-                                                        nsIntRect* aScreenRect) MOZ_OVERRIDE;
+  virtual mozilla::TemporaryRef<SourceSurface>
+  RenderSelection(nsISelection* aSelection,
+                  nsIntPoint& aPoint,
+                  nsIntRect* aScreenRect) MOZ_OVERRIDE;
 
   virtual already_AddRefed<nsPIDOMWindow> GetRootWindow() MOZ_OVERRIDE;
 
   virtual LayerManager* GetLayerManager() MOZ_OVERRIDE;
 
   virtual void SetIgnoreViewportScrolling(bool aIgnore) MOZ_OVERRIDE;
 
   virtual void SetDisplayPort(const nsRect& aDisplayPort);
@@ -499,17 +501,17 @@ protected:
    *
    * aSelection - selection being painted, if any
    * aRegion - clip region, if any
    * aArea - area that the surface occupies, relative to the root frame
    * aPoint - reference point, typically the mouse position
    * aScreenRect - [out] set to the area of the screen the painted area should
    *               be displayed at
    */
-  already_AddRefed<gfxASurface>
+  mozilla::TemporaryRef<SourceSurface>
   PaintRangePaintInfo(nsTArray<nsAutoPtr<RangePaintInfo> >* aItems,
                       nsISelection* aSelection,
                       nsIntRegion* aRegion,
                       nsRect aArea,
                       nsIntPoint& aPoint,
                       nsIntRect* aScreenRect);
 
   /**
--- a/widget/cocoa/nsDragService.mm
+++ b/widget/cocoa/nsDragService.mm
@@ -25,16 +25,21 @@
 #include "nsIIOService.h"
 #include "nsNetUtil.h"
 #include "nsIDocument.h"
 #include "nsIContent.h"
 #include "nsView.h"
 #include "gfxASurface.h"
 #include "gfxContext.h"
 #include "nsCocoaUtils.h"
+#include "mozilla/gfx/2D.h"
+#include "gfxPlatform.h"
+
+using namespace mozilla;
+using namespace mozilla::gfx;
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* sCocoaLog;
 #endif
 
 extern void EnsureLogInitialized();
 
 extern NSPasteboard* globalDragPboard;
@@ -136,22 +141,22 @@ nsDragService::ConstructDragImage(nsIDOM
   NSPoint screenPoint =
     [[gLastDragView window] convertBaseToScreen:
       [gLastDragMouseDownEvent locationInWindow]];
   // Y coordinates are bottom to top, so reverse this
   screenPoint.y = nsCocoaUtils::FlippedScreenY(screenPoint.y);
 
   CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(gLastDragView);
 
-  nsRefPtr<gfxASurface> surface;
+  RefPtr<SourceSurface> surface;
   nsPresContext* pc;
   nsresult rv = DrawDrag(aDOMNode, aRegion,
                          NSToIntRound(screenPoint.x),
                          NSToIntRound(screenPoint.y),
-                         aDragRect, getter_AddRefs(surface), &pc);
+                         aDragRect, &surface, &pc);
   if (!aDragRect->width || !aDragRect->height) {
     // just use some suitable defaults
     int32_t size = nsCocoaUtils::CocoaPointsToDevPixels(20, scaleFactor);
     aDragRect->SetRect(nsCocoaUtils::CocoaPointsToDevPixels(screenPoint.x, scaleFactor),
                        nsCocoaUtils::CocoaPointsToDevPixels(screenPoint.y, scaleFactor),
                        size, size);
   }
 
@@ -161,23 +166,25 @@ nsDragService::ConstructDragImage(nsIDOM
   uint32_t width = aDragRect->width;
   uint32_t height = aDragRect->height;
 
   nsRefPtr<gfxImageSurface> imgSurface = new gfxImageSurface(
     gfxIntSize(width, height), gfxImageFormat::ARGB32);
   if (!imgSurface)
     return nil;
 
-  nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
-  if (!context)
+  RefPtr<DrawTarget> dt =
+    gfxPlatform::GetPlatform()->
+      CreateDrawTargetForSurface(imgSurface, IntSize(width, height));
+  if (!dt)
     return nil;
 
-  context->SetOperator(gfxContext::OPERATOR_SOURCE);
-  context->SetSource(surface);
-  context->Paint();
+  dt->FillRect(gfx::Rect(0, 0, width, height),
+               SurfacePattern(surface, ExtendMode::CLAMP),
+               DrawOptions(1.0f, CompositionOp::OP_SOURCE));
 
   uint32_t* imageData = (uint32_t*)imgSurface->Data();
   int32_t stride = imgSurface->Stride();
 
   NSBitmapImageRep* imageRep =
     [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
                                             pixelsWide:width
                                             pixelsHigh:height
--- a/widget/gtk/nsDragService.cpp
+++ b/widget/gtk/nsDragService.cpp
@@ -31,16 +31,21 @@
 #include "nsImageToPixbuf.h"
 #include "nsPresContext.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsISelection.h"
 #include "nsViewManager.h"
 #include "nsIFrame.h"
 #include "nsGtkUtils.h"
+#include "mozilla/gfx/2D.h"
+#include "gfxPlatform.h"
+
+using namespace mozilla;
+using namespace mozilla::gfx;
 
 // This sets how opaque the drag image is
 #define DRAG_IMAGE_ALPHA_LEVEL 0.5
 
 // These values are copied from GtkDragResult (rather than using GtkDragResult
 // directly) so that this code can be compiled against versions of GTK+ that
 // do not have GtkDragResult.
 // GtkDragResult is available from GTK+ version 2.12.
@@ -385,21 +390,21 @@ nsDragService::InvokeDragSession(nsIDOMN
     }
 
     gtk_target_list_unref(sourceList);
 
     return rv;
 }
 
 bool
-nsDragService::SetAlphaPixmap(gfxASurface *aSurface,
-                                 GdkDragContext *aContext,
-                                 int32_t aXOffset,
-                                 int32_t aYOffset,
-                                 const nsIntRect& dragRect)
+nsDragService::SetAlphaPixmap(SourceSurface *aSurface,
+                              GdkDragContext *aContext,
+                              int32_t aXOffset,
+                              int32_t aYOffset,
+                              const nsIntRect& dragRect)
 {
 #if (MOZ_WIDGET_GTK == 2)
     GdkScreen* screen = gtk_widget_get_screen(mHiddenWidget);
 
     // Transparent drag icons need, like a lot of transparency-related things,
     // a compositing X window manager
     if (!gdk_screen_is_composited(screen))
       return false;
@@ -417,26 +422,31 @@ nsDragService::SetAlphaPixmap(gfxASurfac
 
     // Make a gfxXlibSurface wrapped around the pixmap to render on
     nsRefPtr<gfxASurface> xPixmapSurface =
          nsWindow::GetSurfaceForGdkDrawable(GDK_DRAWABLE(pixmap),
                                             dragRect.Size());
     if (!xPixmapSurface)
       return false;
 
-    nsRefPtr<gfxContext> xPixmapCtx = new gfxContext(xPixmapSurface);
+    RefPtr<DrawTarget> dt =
+    gfxPlatform::GetPlatform()->
+      CreateDrawTargetForSurface(xPixmapSurface, IntSize(dragRect.width, dragRect.height));
+    if (!dt)
+      return false;
 
     // Clear it...
-    xPixmapCtx->SetOperator(gfxContext::OPERATOR_CLEAR);
-    xPixmapCtx->Paint();
+    dt->ClearRect(Rect(0, 0, dragRect.width, dragRect.height));
 
     // ...and paint the drag image with translucency
-    xPixmapCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
-    xPixmapCtx->SetSource(aSurface);
-    xPixmapCtx->Paint(DRAG_IMAGE_ALPHA_LEVEL);
+    dt->DrawSurface(aSurface,
+                    Rect(0, 0, dragRect.width, dragRect.height),
+                    Rect(0, 0, dragRect.width, dragRect.height),
+                    DrawSurfaceOptions(),
+                    DrawOptions(DRAG_IMAGE_ALPHA_LEVEL, CompositionOp::OP_SOURCE));
 
     // The drag transaction addrefs the pixmap, so we can just unref it from us here
     gtk_drag_set_icon_pixmap(aContext, alphaColormap, pixmap, nullptr,
                              aXOffset, aYOffset);
     g_object_unref(pixmap);
     return true;
 #else
     // TODO GTK3
@@ -1560,19 +1570,19 @@ nsDragService::SourceDataGet(GtkWidget  
 
 void nsDragService::SetDragIcon(GdkDragContext* aContext)
 {
     if (!mHasImage && !mSelection)
         return;
 
     nsIntRect dragRect;
     nsPresContext* pc;
-    nsRefPtr<gfxASurface> surface;
+    RefPtr<SourceSurface> surface;
     DrawDrag(mSourceNode, mSourceRegion, mScreenX, mScreenY,
-             &dragRect, getter_AddRefs(surface), &pc);
+             &dragRect, &surface, &pc);
     if (!pc)
         return;
 
     int32_t sx = mScreenX, sy = mScreenY;
     ConvertToUnscaledDevPixels(pc, &sx, &sy);
 
     int32_t offsetX = sx - dragRect.x;
     int32_t offsetY = sy - dragRect.y;
@@ -1592,17 +1602,17 @@ void nsDragService::SetDragIcon(GdkDragC
                     gtk_drag_set_icon_widget(aContext, gtkWidget, offsetX, offsetY);
                 }
             }
         }
     }
     else if (surface) {
         if (!SetAlphaPixmap(surface, aContext, offsetX, offsetY, dragRect)) {
             GdkPixbuf* dragPixbuf =
-              nsImageToPixbuf::SurfaceToPixbuf(surface, dragRect.width, dragRect.height);
+              nsImageToPixbuf::SourceSurfaceToPixbuf(surface, dragRect.width, dragRect.height);
             if (dragPixbuf) {
                 gtk_drag_set_icon_pixbuf(aContext, dragPixbuf, offsetX, offsetY);
                 g_object_unref(dragPixbuf);
             }
         }
     }
 }
 
--- a/widget/gtk/nsDragService.h
+++ b/widget/gtk/nsDragService.h
@@ -9,16 +9,22 @@
 
 #include "nsBaseDragService.h"
 #include "nsIObserver.h"
 #include "nsAutoRef.h"
 #include <gtk/gtk.h>
 
 class nsWindow;
 
+namespace mozilla {
+namespace gfx {
+class SourceSurface;
+}
+}
+
 #ifndef HAVE_NSGOBJECTREFTRAITS
 #define HAVE_NSGOBJECTREFTRAITS
 template <class T>
 class nsGObjectRefTraits : public nsPointerRefTraits<T> {
 public:
     static void Release(T *aPtr) { g_object_unref(aPtr); }
     static void AddRef(T *aPtr) { g_object_ref(aPtr); }
 };
@@ -178,21 +184,21 @@ private:
 
     nsCOMPtr<nsIScriptableRegion> mSourceRegion;
 
     // get a list of the sources in gtk's format
     GtkTargetList *GetSourceList(void);
 
     // attempts to create a semi-transparent drag image. Returns TRUE if
     // successful, FALSE if not
-    bool SetAlphaPixmap(gfxASurface     *aPixbuf,
-                          GdkDragContext  *aContext,
-                          int32_t          aXOffset,
-                          int32_t          aYOffset,
-                          const nsIntRect &dragRect);
+    bool SetAlphaPixmap(SourceSurface *aPixbuf,
+                        GdkDragContext  *aContext,
+                        int32_t          aXOffset,
+                        int32_t          aYOffset,
+                        const nsIntRect &dragRect);
 
     gboolean Schedule(DragTask aTask, nsWindow *aWindow,
                       GdkDragContext *aDragContext,
                       nsIntPoint aWindowPoint, guint aTime);
 
     // Callback for g_idle_add_full() to run mScheduledTask.
     static gboolean TaskDispatchCallback(gpointer data);
     gboolean RunScheduledTask();
--- a/widget/gtk/nsImageToPixbuf.cpp
+++ b/widget/gtk/nsImageToPixbuf.cpp
@@ -124,42 +124,8 @@ nsImageToPixbuf::SourceSurfaceToPixbuf(S
         }
     }
 
     dataSurface->Unmap();
 
     return pixbuf;
 }
 
-GdkPixbuf*
-nsImageToPixbuf::SurfaceToPixbuf(gfxASurface* aSurface, int32_t aWidth, int32_t aHeight)
-{
-    if (aSurface->CairoStatus()) {
-        NS_ERROR("invalid surface");
-        return nullptr;
-    }
-
-    nsRefPtr<gfxImageSurface> imgSurface;
-    if (aSurface->GetType() == gfxSurfaceType::Image) {
-        imgSurface = static_cast<gfxImageSurface*>
-                                (static_cast<gfxASurface*>(aSurface));
-    } else {
-        imgSurface = new gfxImageSurface(gfxIntSize(aWidth, aHeight),
-					 gfxImageFormat::ARGB32);
-                                       
-        if (!imgSurface)
-            return nullptr;
-
-        nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
-        if (!context)
-            return nullptr;
-
-        context->SetOperator(gfxContext::OPERATOR_SOURCE);
-        context->SetSource(aSurface);
-        context->Paint();
-    }
-
-    RefPtr<SourceSurface> surface =
-        gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
-                                                               imgSurface);
-
-    return SourceSurfaceToPixbuf(surface, aWidth, aHeight);
-}
--- a/widget/gtk/nsImageToPixbuf.h
+++ b/widget/gtk/nsImageToPixbuf.h
@@ -28,18 +28,16 @@ class nsImageToPixbuf MOZ_FINAL : public
 
         // Friendlier version of ConvertImageToPixbuf for callers inside of
         // widget
         /**
          * The return value of all these, if not null, should be
          * released as needed by the caller using g_object_unref.
          */
         static GdkPixbuf* ImageToPixbuf(imgIContainer * aImage);
-        static GdkPixbuf* SurfaceToPixbuf(gfxASurface* aSurface,
-                                          int32_t aWidth, int32_t aHeight);
         static GdkPixbuf* SourceSurfaceToPixbuf(SourceSurface* aSurface,
                                                 int32_t aWidth,
                                                 int32_t aHeight);
 
     private:
         ~nsImageToPixbuf() {}
 };
 
--- a/widget/windows/nsDragService.cpp
+++ b/widget/windows/nsDragService.cpp
@@ -35,16 +35,20 @@
 #include "nsCRT.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsUnicharUtils.h"
 #include "gfxASurface.h"
 #include "gfxContext.h"
 #include "nsRect.h"
 #include "nsMathUtils.h"
 #include "gfxWindowsPlatform.h"
+#include "mozilla/gfx/2D.h"
+
+using namespace mozilla;
+using namespace mozilla::gfx;
 
 //-------------------------------------------------------------------------
 //
 // DragService constructor
 //
 //-------------------------------------------------------------------------
 nsDragService::nsDragService()
   : mDataObject(nullptr), mSentLocalDropEvent(false)
@@ -70,44 +74,52 @@ nsDragService::CreateDragImage(nsIDOMNod
     return false;
 
   memset(psdi, 0, sizeof(SHDRAGIMAGE));
   if (!aDOMNode) 
     return false;
 
   // Prepare the drag image
   nsIntRect dragRect;
-  nsRefPtr<gfxASurface> surface;
+  RefPtr<SourceSurface> surface;
   nsPresContext* pc;
   DrawDrag(aDOMNode, aRegion,
            mScreenX, mScreenY,
-           &dragRect, getter_AddRefs(surface), &pc);
+           &dragRect, &surface, &pc);
   if (!surface)
     return false;
 
   uint32_t bmWidth = dragRect.width, bmHeight = dragRect.height;
 
   if (bmWidth == 0 || bmHeight == 0)
     return false;
 
   psdi->crColorKey = CLR_NONE;
 
+  RefPtr<DataSourceSurface> data = surface->GetDataSurface();
+  DataSourceSurface::MappedSurface map;
+  if (!data->Map(DataSourceSurface::READ, &map)) {
+    return false;
+  }
+
   nsRefPtr<gfxImageSurface> imgSurface = new gfxImageSurface(
     gfxIntSize(bmWidth, bmHeight), 
     gfxImageFormat::ARGB32);
   if (!imgSurface)
     return false;
 
-  nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
-  if (!context)
+  RefPtr<DrawTarget> dt =
+    gfxPlatform::GetPlatform()->
+      CreateDrawTargetForSurface(imgSurface, IntSize(bmWidth, bmHeight));
+  if (!dt)
     return false;
 
-  context->SetOperator(gfxContext::OPERATOR_SOURCE);
-  context->SetSource(surface);
-  context->Paint();
+  dt->FillRect(Rect(0, 0, bmWidth, bmHeight),
+               SurfacePattern(surface, ExtendMode::CLAMP),
+               DrawOptions(1.0f, CompositionOp::OP_SOURCE));
 
   BITMAPV5HEADER bmih;
   memset((void*)&bmih, 0, sizeof(BITMAPV5HEADER));
   bmih.bV5Size        = sizeof(BITMAPV5HEADER);
   bmih.bV5Width       = bmWidth;
   bmih.bV5Height      = -(int32_t)bmHeight; // flip vertical
   bmih.bV5Planes      = 1;
   bmih.bV5BitCount    = 32;
@@ -139,16 +151,18 @@ nsDragService::CreateDragImage(nsIDOMNod
       ConvertToUnscaledDevPixels(pc, &sx, &sy);
       psdi->ptOffset.x = sx - dragRect.x;
       psdi->ptOffset.y = sy - dragRect.y;
     }
 
     DeleteDC(hdcSrc);
   }
 
+  data->Unmap();
+
   return psdi->hbmpDragImage != nullptr;
 }
 
 //-------------------------------------------------------------------------
 NS_IMETHODIMP
 nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
                                  nsISupportsArray *anArrayTransferables,
                                  nsIScriptableRegion *aRegion,
--- a/widget/xpwidgets/nsBaseDragService.cpp
+++ b/widget/xpwidgets/nsBaseDragService.cpp
@@ -29,22 +29,24 @@
 #include "nsIImageLoadingContent.h"
 #include "imgIContainer.h"
 #include "imgIRequest.h"
 #include "nsRegion.h"
 #include "nsXULPopupManager.h"
 #include "nsMenuPopupFrame.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/gfx/2D.h"
 
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include <algorithm>
 
 using namespace mozilla;
+using namespace mozilla::gfx;
 
 #define DRAGIMAGES_PREF "nglayout.enable_drag_images"
 
 nsBaseDragService::nsBaseDragService()
   : mCanDrop(false), mOnlyChromeDrop(false), mDoingDrag(false),
     mHasImage(false), mUserCancelled(false),
     mDragAction(DRAGDROP_ACTION_NONE), mTargetSize(0,0),
     mImageX(0), mImageY(0), mScreenX(-1), mScreenY(-1), mSuppressLevel(0),
@@ -421,17 +423,17 @@ GetPresShellForContent(nsIDOMNode* aDOMN
   return nullptr;
 }
 
 nsresult
 nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode,
                             nsIScriptableRegion* aRegion,
                             int32_t aScreenX, int32_t aScreenY,
                             nsIntRect* aScreenDragRect,
-                            gfxASurface** aSurface,
+                            RefPtr<SourceSurface>* aSurface,
                             nsPresContext** aPresContext)
 {
   *aSurface = nullptr;
   *aPresContext = nullptr;
 
   // use a default size, in case of an error.
   aScreenDragRect->x = aScreenX - mImageX;
   aScreenDragRect->y = aScreenY - mImageY;
@@ -492,19 +494,17 @@ nsBaseDragService::DrawDrag(nsIDOMNode* 
     }
 
     return NS_OK;
   }
 
   // draw the image for selections
   if (mSelection) {
     nsIntPoint pnt(aScreenDragRect->x, aScreenDragRect->y);
-    nsRefPtr<gfxASurface> surface = presShell->RenderSelection(mSelection, pnt, aScreenDragRect);
-    *aSurface = surface;
-    NS_IF_ADDREF(*aSurface);
+    *aSurface = presShell->RenderSelection(mSelection, pnt, aScreenDragRect);
     return NS_OK;
   }
 
   // if a custom image was specified, check if it is an image node and draw
   // using the source rather than the displayed image. But if mImage isn't
   // an image or canvas, fall through to RenderNode below.
   if (mImage) {
     nsCOMPtr<nsICanvasElementExternal> canvas = do_QueryInterface(dragNode);
@@ -527,49 +527,45 @@ nsBaseDragService::DrawDrag(nsIDOMNode* 
 
     nsCOMPtr<nsIContent> content = do_QueryInterface(dragNode);
     nsIFrame* frame = content->GetPrimaryFrame();
     if (frame && frame->GetType() == nsGkAtoms::menuPopupFrame) {
       mDragPopup = content;
     }
   }
 
-  nsRefPtr<gfxASurface> surface;
   if (!mDragPopup) {
     // otherwise, just draw the node
     nsIntRegion clipRegion;
     if (aRegion) {
       aRegion->GetRegion(&clipRegion);
     }
 
     nsIntPoint pnt(aScreenDragRect->x, aScreenDragRect->y);
-    surface = presShell->RenderNode(dragNode, aRegion ? &clipRegion : nullptr,
-                                    pnt, aScreenDragRect);
+    *aSurface = presShell->RenderNode(dragNode, aRegion ? &clipRegion : nullptr,
+                                      pnt, aScreenDragRect);
   }
 
   // if an image was specified, reposition the drag rectangle to
   // the supplied offset in mImageX and mImageY.
   if (mImage) {
     aScreenDragRect->x = sx - mImageX;
     aScreenDragRect->y = sy - mImageY;
   }
 
-  *aSurface = surface;
-  NS_IF_ADDREF(*aSurface);
-
   return NS_OK;
 }
 
 nsresult
 nsBaseDragService::DrawDragForImage(nsPresContext* aPresContext,
                                     nsIImageLoadingContent* aImageLoader,
                                     nsICanvasElementExternal* aCanvas,
                                     int32_t aScreenX, int32_t aScreenY,
                                     nsIntRect* aScreenDragRect,
-                                    gfxASurface** aSurface)
+                                    RefPtr<SourceSurface>* aSurface)
 {
   nsCOMPtr<imgIContainer> imgContainer;
   if (aImageLoader) {
     nsCOMPtr<imgIRequest> imgRequest;
     nsresult rv = aImageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
                                           getter_AddRefs(imgRequest));
     NS_ENSURE_SUCCESS(rv, rv);
     if (!imgRequest)
@@ -615,41 +611,43 @@ nsBaseDragService::DrawDragForImage(nsPr
     destSize.height = NSToIntFloor(float(destSize.height) * scale);
 
     aScreenDragRect->x = NSToIntFloor(aScreenX - float(mImageX) * scale);
     aScreenDragRect->y = NSToIntFloor(aScreenY - float(mImageY) * scale);
     aScreenDragRect->width = destSize.width;
     aScreenDragRect->height = destSize.height;
   }
 
-  nsRefPtr<gfxASurface> surface =
-    gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(destSize.width, destSize.height),
-                                                       gfxContentType::COLOR_ALPHA);
-  if (!surface)
+  RefPtr<DrawTarget> dt =
+    gfxPlatform::GetPlatform()->
+      CreateOffscreenContentDrawTarget(IntSize(destSize.width, destSize.height),
+
+                                       SurfaceFormat::B8G8R8A8);
+  if (!dt)
     return NS_ERROR_FAILURE;
 
-  nsRefPtr<gfxContext> ctx = new gfxContext(surface);
+  nsRefPtr<gfxContext> ctx = new gfxContext(dt);
   if (!ctx)
     return NS_ERROR_FAILURE;
 
-  *aSurface = surface;
-  NS_ADDREF(*aSurface);
-
+  nsresult result = NS_OK;
   if (aImageLoader) {
     gfxRect outRect(0, 0, destSize.width, destSize.height);
     gfxMatrix scale =
       gfxMatrix().Scale(srcSize.width/outRect.Width(), srcSize.height/outRect.Height());
     nsIntRect imgSize(0, 0, srcSize.width, srcSize.height);
     imgContainer->Draw(ctx, GraphicsFilter::FILTER_GOOD, scale, outRect, imgSize,
                        destSize, nullptr, imgIContainer::FRAME_CURRENT,
                        imgIContainer::FLAG_SYNC_DECODE);
-    return NS_OK;
   } else {
-    return aCanvas->RenderContextsExternal(ctx, GraphicsFilter::FILTER_GOOD);
+    result = aCanvas->RenderContextsExternal(ctx, GraphicsFilter::FILTER_GOOD);
   }
+
+  *aSurface = dt->Snapshot();
+  return result;
 }
 
 void
 nsBaseDragService::ConvertToUnscaledDevPixels(nsPresContext* aPresContext,
                                               int32_t* aScreenX, int32_t* aScreenY)
 {
   int32_t adj = aPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel();
   *aScreenX = nsPresContext::CSSPixelsToAppUnits(*aScreenX) / adj;
--- a/widget/xpwidgets/nsBaseDragService.h
+++ b/widget/xpwidgets/nsBaseDragService.h
@@ -8,38 +8,47 @@
 
 #include "nsIDragService.h"
 #include "nsIDragSession.h"
 #include "nsITransferable.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDataTransfer.h"
 #include "nsCOMPtr.h"
 #include "nsPoint.h"
+#include "mozilla/RefPtr.h"
 
 #include "gfxImageSurface.h"
 
 // translucency level for drag images
 #define DRAG_TRANSLUCENCY 0.65
 
 class nsIContent;
 class nsIDOMNode;
 class nsIFrame;
 class nsPresContext;
 class nsIImageLoadingContent;
 class nsICanvasElementExternal;
 
+namespace mozilla {
+namespace gfx {
+class SourceSurface;
+}
+}
+
 /**
  * XP DragService wrapper base class
  */
 
 class nsBaseDragService : public nsIDragService,
                           public nsIDragSession
 {
 
 public:
+  typedef mozilla::gfx::SourceSurface SourceSurface;
+
   nsBaseDragService();
   virtual ~nsBaseDragService();
 
   //nsISupports
   NS_DECL_ISUPPORTS
 
   //nsIDragSession and nsIDragService
   NS_DECL_NSIDRAGSERVICE
@@ -72,29 +81,29 @@ protected:
    *
    * aPresContext will be set to the nsPresContext used determined from
    * whichever of mImage or aDOMNode is used.
    */
   nsresult DrawDrag(nsIDOMNode* aDOMNode,
                     nsIScriptableRegion* aRegion,
                     int32_t aScreenX, int32_t aScreenY,
                     nsIntRect* aScreenDragRect,
-                    gfxASurface** aSurface,
+                    mozilla::RefPtr<SourceSurface>* aSurface,
                     nsPresContext **aPresContext);
 
   /**
    * Draw a drag image for an image node specified by aImageLoader or aCanvas.
    * This is called by DrawDrag.
    */
   nsresult DrawDragForImage(nsPresContext* aPresContext,
                             nsIImageLoadingContent* aImageLoader,
                             nsICanvasElementExternal* aCanvas,
                             int32_t aScreenX, int32_t aScreenY,
                             nsIntRect* aScreenDragRect,
-                            gfxASurface** aSurface);
+                            mozilla::RefPtr<SourceSurface>* aSurface);
 
   /**
    * Convert aScreenX and aScreenY from CSS pixels into unscaled device pixels.
    */
   void
   ConvertToUnscaledDevPixels(nsPresContext* aPresContext,
                              int32_t* aScreenX, int32_t* aScreenY);