Bug 1299435 - part 2 - fix Moz2d for Skia m55 update. r=mchang
authorLee Salzman <lsalzman@mozilla.com>
Mon, 24 Oct 2016 22:40:59 -0400
changeset 319232 305afd8b36421f1b62384263857ca5624cdf9ba8
parent 319231 f997223b1815b694a83a42062a52a8919a089394
child 319233 62b54f38b6f3d6c9c338c9505f2091979ae08625
push id83111
push userlsalzman@mozilla.com
push dateTue, 25 Oct 2016 02:42:49 +0000
treeherdermozilla-inbound@a90c5c087244 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmchang
bugs1299435
milestone52.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 1299435 - part 2 - fix Moz2d for Skia m55 update. r=mchang MozReview-Commit-ID: 8jRzOaS5vqy
gfx/2d/DrawTargetSkia.cpp
gfx/2d/DrawTargetSkia.h
gfx/2d/Factory.cpp
gfx/2d/HelpersSkia.h
gfx/2d/RefPtrSkia.h
gfx/2d/ScaledFontBase.cpp
gfx/2d/ScaledFontWin.h
gfx/2d/SourceSurfaceSkia.cpp
gfx/2d/SourceSurfaceSkia.h
gfx/2d/image_operations.cpp
gfx/2d/moz.build
gfx/gl/SkiaGLGlue.cpp
gfx/gl/SkiaGLGlue.h
gfx/layers/composite/PaintCounter.cpp
gfx/layers/composite/PaintCounter.h
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -14,27 +14,30 @@
 #include "mozilla/ArrayUtils.h"
 
 #include "skia/include/core/SkSurface.h"
 #include "skia/include/core/SkTypeface.h"
 #include "skia/include/effects/SkGradientShader.h"
 #include "skia/include/core/SkColorFilter.h"
 #include "skia/include/effects/SkBlurImageFilter.h"
 #include "skia/include/effects/SkLayerRasterizer.h"
+#include "skia/src/core/SkSpecialImage.h"
 #include "Blur.h"
 #include "Logging.h"
 #include "Tools.h"
 #include "DataSurfaceHelpers.h"
 #include <algorithm>
 
 #ifdef USE_SKIA_GPU
 #include "GLDefs.h"
 #include "skia/include/gpu/SkGr.h"
 #include "skia/include/gpu/GrContext.h"
+#include "skia/include/gpu/GrDrawContext.h"
 #include "skia/include/gpu/gl/GrGLInterface.h"
+#include "skia/src/image/SkImage_Gpu.h"
 #endif
 
 #ifdef MOZ_WIDGET_COCOA
 #include "BorrowedContext.h"
 #include <ApplicationServices/ApplicationServices.h>
 #include "mozilla/Vector.h"
 #include "ScaledFontMac.h"
 #include "CGTextDrawing.h"
@@ -89,23 +92,23 @@ public:
 
   std::vector<SkColor> mColors;
   std::vector<SkScalar> mPositions;
   int mCount;
   ExtendMode mExtendMode;
 };
 
 /**
- * When constructing a temporary SkBitmap via GetBitmapForSurface, we may also
+ * When constructing a temporary SkImage via GetSkImageForSurface, we may also
  * have to construct a temporary DataSourceSurface, which must live as long as
- * the SkBitmap. We attach this temporary surface to the bitmap's pixelref, so
+ * the SkImage. We attach this temporary surface to the image's pixelref, so
  * that it can be released once the pixelref is freed.
  */
 static void
-ReleaseTemporarySurface(void* aPixels, void* aContext)
+ReleaseTemporarySurface(const void* aPixels, void* aContext)
 {
   DataSourceSurface* surf = static_cast<DataSourceSurface*>(aContext);
   if (surf) {
     surf->Release();
   }
 }
 
 #ifdef IS_BIG_ENDIAN
@@ -203,47 +206,46 @@ VerifyRGBXCorners(uint8_t* aData, const 
                            << int(aData[offset+3]);
     }
   }
 
   return true;
 }
 #endif
 
-static SkBitmap
-GetBitmapForSurface(SourceSurface* aSurface)
+static sk_sp<SkImage>
+GetSkImageForSurface(SourceSurface* aSurface)
 {
-  SkBitmap bitmap;
-
   if (!aSurface) {
-    gfxDebug() << "Creating empty Skia bitmap from null SourceSurface";
-    return bitmap;
+    gfxDebug() << "Creating null Skia image from null SourceSurface";
+    return nullptr;
   }
 
   if (aSurface->GetType() == SurfaceType::SKIA) {
-    bitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
-    return bitmap;
+    return static_cast<SourceSurfaceSkia*>(aSurface)->GetImage();
   }
 
   DataSourceSurface* surf = aSurface->GetDataSurface().take();
   if (!surf) {
-    gfxWarning() << "Failed getting DataSourceSurface for Skia bitmap";
-    return bitmap;
+    gfxWarning() << "Failed getting DataSourceSurface for Skia image";
+    return nullptr;
   }
 
-  if (!bitmap.installPixels(MakeSkiaImageInfo(surf->GetSize(), surf->GetFormat()),
-                            surf->GetData(), surf->Stride(), nullptr,
-                            ReleaseTemporarySurface, surf)) {
-    gfxDebug() << "Failed installing pixels on Skia bitmap for temporary surface";
+  SkPixmap pixmap(MakeSkiaImageInfo(surf->GetSize(), surf->GetFormat()),
+                  surf->GetData(), surf->Stride());
+  sk_sp<SkImage> image = SkImage::MakeFromRaster(pixmap, ReleaseTemporarySurface, surf);
+  if (!image) {
+    ReleaseTemporarySurface(nullptr, surf);
+    gfxDebug() << "Failed making Skia raster image for temporary surface";
   }
 
   // Skia doesn't support RGBX surfaces so ensure that the alpha value is opaque white.
   MOZ_ASSERT(VerifyRGBXCorners(surf->GetData(), surf->GetSize(),
                                surf->Stride(), surf->GetFormat()));
-  return bitmap;
+  return image;
 }
 
 DrawTargetSkia::DrawTargetSkia()
   : mSnapshot(nullptr)
 #ifdef MOZ_WIDGET_COCOA
   , mCG(nullptr)
   , mColorSpace(nullptr)
   , mCanvasData(nullptr)
@@ -268,19 +270,29 @@ DrawTargetSkia::~DrawTargetSkia()
 }
 
 already_AddRefed<SourceSurface>
 DrawTargetSkia::Snapshot()
 {
   RefPtr<SourceSurfaceSkia> snapshot = mSnapshot;
   if (!snapshot) {
     snapshot = new SourceSurfaceSkia();
+    sk_sp<SkImage> image;
+    // If the surface is raster, making a snapshot may trigger a pixel copy.
+    // Instead, try to directly make a raster image referencing the surface pixels.
+    SkPixmap pixmap;
+    if (mSurface->peekPixels(&pixmap)) {
+      image = SkImage::MakeFromRaster(pixmap, nullptr, nullptr);
+    } else {
+      image = mSurface->makeImageSnapshot(SkBudgeted::kNo);
+    }
+    if (!snapshot->InitFromImage(image, mFormat, this)) {
+      return nullptr;
+    }
     mSnapshot = snapshot;
-    if (!snapshot->InitFromCanvas(mCanvas.get(), mFormat, this))
-      return nullptr;
   }
 
   return snapshot.forget();
 }
 
 bool
 DrawTargetSkia::LockBits(uint8_t** aData, IntSize* aSize,
                          int32_t* aStride, SurfaceFormat* aFormat,
@@ -319,16 +331,91 @@ DrawTargetSkia::LockBits(uint8_t** aData
 }
 
 void
 DrawTargetSkia::ReleaseBits(uint8_t* aData)
 {
 }
 
 static void
+ReleaseImage(const void* aPixels, void* aContext)
+{
+  SkImage* image = static_cast<SkImage*>(aContext);
+  SkSafeUnref(image);
+}
+
+static sk_sp<SkImage>
+ExtractSubset(sk_sp<SkImage> aImage, const IntRect& aRect)
+{
+  SkIRect subsetRect = IntRectToSkIRect(aRect);
+  if (aImage->bounds() == subsetRect) {
+    return aImage;
+  }
+  // makeSubset is slow, so prefer to use SkPixmap::extractSubset where possible.
+  SkPixmap pixmap, subsetPixmap;
+  if (aImage->peekPixels(&pixmap) &&
+      pixmap.extractSubset(&subsetPixmap, subsetRect)) {
+    // Release the original image reference so only the subset image keeps it alive.
+    return SkImage::MakeFromRaster(subsetPixmap, ReleaseImage, aImage.release());
+  }
+  return aImage->makeSubset(subsetRect);
+}
+
+static inline bool
+SkImageIsMask(const sk_sp<SkImage>& aImage)
+{
+  SkPixmap pixmap;
+  if (aImage->peekPixels(&pixmap)) {
+    return pixmap.colorType() == kAlpha_8_SkColorType;
+#ifdef USE_SKIA_GPU
+  } else if (GrTexture* tex = aImage->getTexture()) {
+    return GrPixelConfigIsAlphaOnly(tex->config());
+#endif
+  } else {
+    return false;
+  }
+}
+
+static bool
+ExtractAlphaBitmap(sk_sp<SkImage> aImage, SkBitmap* aResultBitmap)
+{
+  SkImageInfo info = SkImageInfo::MakeA8(aImage->width(), aImage->height());
+  SkBitmap bitmap;
+  if (!bitmap.tryAllocPixels(info, SkAlign4(info.minRowBytes())) ||
+      !aImage->readPixels(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes(), 0, 0)) {
+    gfxWarning() << "Failed reading alpha pixels for Skia bitmap";
+    return false;
+  }
+
+  *aResultBitmap = bitmap;
+  return true;
+}
+
+static sk_sp<SkImage>
+ExtractAlphaForSurface(SourceSurface* aSurface)
+{
+  sk_sp<SkImage> image = GetSkImageForSurface(aSurface);
+  if (!image) {
+    return nullptr;
+  }
+  if (SkImageIsMask(image)) {
+    return image;
+  }
+
+  SkBitmap bitmap;
+  if (!ExtractAlphaBitmap(image, &bitmap)) {
+    return nullptr;
+  }
+
+  // Mark the bitmap immutable so that it will be shared rather than copied.
+  bitmap.setImmutable();
+  return SkImage::MakeFromBitmap(bitmap);
+}
+
+static void
 SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, Float aAlpha = 1.0, Point aOffset = Point(0, 0))
 {
   switch (aPattern.GetType()) {
     case PatternType::COLOR: {
       Color color = static_cast<const ColorPattern&>(aPattern).mColor;
       aPaint.setColor(ColorToSkColor(color, aAlpha));
       break;
     }
@@ -381,33 +468,36 @@ SetPaintPattern(SkPaint& aPaint, const P
                                                                        stops->mCount,
                                                                        mode, 0, &mat);
         aPaint.setShader(shader);
       }
       break;
     }
     case PatternType::SURFACE: {
       const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
-      SkBitmap bitmap = GetBitmapForSurface(pat.mSurface);
+      sk_sp<SkImage> image = GetSkImageForSurface(pat.mSurface);
 
       SkMatrix mat;
       GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
       mat.postTranslate(SkFloatToScalar(aOffset.x), SkFloatToScalar(aOffset.y));
 
       if (!pat.mSamplingRect.IsEmpty()) {
-        SkIRect rect = IntRectToSkIRect(pat.mSamplingRect);
-        bitmap.extractSubset(&bitmap, rect);
-        mat.preTranslate(rect.x(), rect.y());
+        image = ExtractSubset(image, pat.mSamplingRect);
+        mat.preTranslate(pat.mSamplingRect.x, pat.mSamplingRect.y);
       }
 
       SkShader::TileMode xTileMode = ExtendModeToTileMode(pat.mExtendMode, Axis::X_AXIS);
       SkShader::TileMode yTileMode = ExtendModeToTileMode(pat.mExtendMode, Axis::Y_AXIS);
 
-      sk_sp<SkShader> shader = SkShader::MakeBitmapShader(bitmap, xTileMode, yTileMode, &mat);
-      aPaint.setShader(shader);
+      if (image) {
+        aPaint.setShader(image->makeShader(xTileMode, yTileMode, &mat));
+      } else {
+        aPaint.setColor(SK_ColorTRANSPARENT);
+      }
+
       if (pat.mSamplingFilter == SamplingFilter::POINT) {
         aPaint.setFilterQuality(kNone_SkFilterQuality);
       }
       break;
     }
   }
 }
 
@@ -448,17 +538,17 @@ struct AutoPaintSetup {
   {
     if (mNeedsRestore) {
       mCanvas->restore();
     }
   }
 
   void Init(SkCanvas *aCanvas, const DrawOptions& aOptions, const Rect* aMaskBounds, bool aForceGroup)
   {
-    mPaint.setXfermodeMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
+    mPaint.setBlendMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
     mCanvas = aCanvas;
 
     //TODO: Can we set greyscale somehow?
     if (aOptions.mAntialiasMode != AntialiasMode::NONE) {
       mPaint.setAntiAlias(true);
     } else {
       mPaint.setAntiAlias(false);
     }
@@ -466,19 +556,19 @@ struct AutoPaintSetup {
     bool needsGroup = aForceGroup ||
                       (!IsOperatorBoundByMask(aOptions.mCompositionOp) &&
                        (!aMaskBounds || !aMaskBounds->Contains(GetClipBounds(aCanvas))));
 
     // TODO: We could skip the temporary for operator_source and just
     // clear the clip rect. The other operators would be harder
     // but could be worth it to skip pushing a group.
     if (needsGroup) {
-      mPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
+      mPaint.setBlendMode(SkBlendMode::kSrcOver);
       SkPaint temp;
-      temp.setXfermodeMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
+      temp.setBlendMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
       temp.setAlpha(ColorFloatToByte(aOptions.mAlpha));
       //TODO: Get a rect here
       mCanvas->saveLayer(nullptr, &temp);
       mNeedsRestore = true;
     } else {
       mPaint.setAlpha(ColorFloatToByte(aOptions.mAlpha));
       mAlpha = aOptions.mAlpha;
     }
@@ -506,32 +596,32 @@ DrawTargetSkia::DrawSurface(SourceSurfac
                             const DrawOptions &aOptions)
 {
   if (aSource.IsEmpty()) {
     return;
   }
 
   MarkChanged();
 
-  SkBitmap bitmap = GetBitmapForSurface(aSurface);
-  if (bitmap.empty()) {
+  sk_sp<SkImage> image = GetSkImageForSurface(aSurface);
+  if (!image) {
     return;
   }
 
   SkRect destRect = RectToSkRect(aDest);
   SkRect sourceRect = RectToSkRect(aSource);
-  bool forceGroup = bitmap.colorType() == kAlpha_8_SkColorType &&
+  bool forceGroup = SkImageIsMask(image) &&
                     aOptions.mCompositionOp != CompositionOp::OP_OVER;
 
   AutoPaintSetup paint(mCanvas.get(), aOptions, &aDest, forceGroup);
   if (aSurfOptions.mSamplingFilter == SamplingFilter::POINT) {
     paint.mPaint.setFilterQuality(kNone_SkFilterQuality);
   }
 
-  mCanvas->drawBitmapRect(bitmap, sourceRect, destRect, &paint.mPaint);
+  mCanvas->drawImageRect(image, sourceRect, destRect, &paint.mPaint);
 }
 
 DrawTargetType
 DrawTargetSkia::GetType() const
 {
 #ifdef USE_SKIA_GPU
   if (mGrContext) {
     return DrawTargetType::HARDWARE_RASTER;
@@ -559,43 +649,43 @@ DrawTargetSkia::DrawSurfaceWithShadow(So
                                       CompositionOp aOperator)
 {
   if (aSurface->GetSize().IsEmpty()) {
     return;
   }
 
   MarkChanged();
 
-  SkBitmap bitmap = GetBitmapForSurface(aSurface);
-  if (bitmap.empty()) {
+  sk_sp<SkImage> image = GetSkImageForSurface(aSurface);
+  if (!image) {
     return;
   }
 
   mCanvas->save();
   mCanvas->resetMatrix();
 
   SkPaint paint;
-  paint.setXfermodeMode(GfxOpToSkiaOp(aOperator));
+  paint.setBlendMode(GfxOpToSkiaOp(aOperator));
 
   // bug 1201272
   // We can't use the SkDropShadowImageFilter here because it applies the xfer
   // mode first to render the bitmap to a temporary layer, and then implicitly
   // uses src-over to composite the resulting shadow.
   // The canvas spec, however, states that the composite op must be used to
   // composite the resulting shadow, so we must instead use a SkBlurImageFilter
   // to blur the image ourselves.
 
   SkPaint shadowPaint;
-  shadowPaint.setXfermodeMode(GfxOpToSkiaOp(aOperator));
+  shadowPaint.setBlendMode(GfxOpToSkiaOp(aOperator));
 
   auto shadowDest = IntPoint::Round(aDest + aOffset);
 
   SkBitmap blurMask;
   if (!UsingSkiaGPU() &&
-      bitmap.extractAlpha(&blurMask)) {
+      ExtractAlphaBitmap(image, &blurMask)) {
     // Prefer using our own box blur instead of Skia's when we're
     // not using the GPU. It currently performs much better than
     // SkBlurImageFilter or SkBlurMaskFilter on the CPU.
     AlphaBoxBlur blur(Rect(0, 0, blurMask.width(), blurMask.height()),
                       int32_t(blurMask.rowBytes()),
                       aSigma, aSigma);
     blurMask.lockPixels();
     blur.Blur(reinterpret_cast<uint8_t*>(blurMask.getPixels()));
@@ -603,27 +693,27 @@ DrawTargetSkia::DrawSurfaceWithShadow(So
     blurMask.notifyPixelsChanged();
 
     shadowPaint.setColor(ColorToSkColor(aColor, 1.0f));
 
     mCanvas->drawBitmap(blurMask, shadowDest.x, shadowDest.y, &shadowPaint);
   } else {
     sk_sp<SkImageFilter> blurFilter(SkBlurImageFilter::Make(aSigma, aSigma, nullptr));
     sk_sp<SkColorFilter> colorFilter(
-      SkColorFilter::MakeModeFilter(ColorToSkColor(aColor, 1.0f), SkXfermode::kSrcIn_Mode));
+      SkColorFilter::MakeModeFilter(ColorToSkColor(aColor, 1.0f), SkBlendMode::kSrcIn));
 
     shadowPaint.setImageFilter(blurFilter);
     shadowPaint.setColorFilter(colorFilter);
 
-    mCanvas->drawBitmap(bitmap, shadowDest.x, shadowDest.y, &shadowPaint);
+    mCanvas->drawImage(image, shadowDest.x, shadowDest.y, &shadowPaint);
   }
 
   // Composite the original image after the shadow
   auto dest = IntPoint::Round(aDest);
-  mCanvas->drawBitmap(bitmap, dest.x, dest.y, &paint);
+  mCanvas->drawImage(image, dest.x, dest.y, &paint);
 
   mCanvas->restore();
 }
 
 void
 DrawTargetSkia::FillRect(const Rect &aRect,
                          const Pattern &aPattern,
                          const DrawOptions &aOptions)
@@ -771,28 +861,28 @@ DrawTargetSkia::ShouldLCDRenderText(Font
   return (aAntialiasMode == AntialiasMode::SUBPIXEL);
 }
 
 #ifdef MOZ_WIDGET_COCOA
 class CGClipApply : public SkCanvas::ClipVisitor {
 public:
   explicit CGClipApply(CGContextRef aCGContext)
     : mCG(aCGContext) {}
-  void clipRect(const SkRect& aRect, SkRegion::Op op, bool antialias) override {
+  void clipRect(const SkRect& aRect, SkCanvas::ClipOp op, bool antialias) override {
     CGRect rect = CGRectMake(aRect.x(), aRect.y(), aRect.width(), aRect.height());
     CGContextClipToRect(mCG, rect);
   }
 
-  void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) override {
+  void clipRRect(const SkRRect& rrect, SkCanvas::ClipOp op, bool antialias) override {
     SkPath path;
     path.addRRect(rrect);
     clipPath(path, op, antialias);
   }
 
-  void clipPath(const SkPath& aPath, SkRegion::Op, bool antialias) override {
+  void clipPath(const SkPath& aPath, SkCanvas::ClipOp, bool antialias) override {
     SkPath::Iter iter(aPath, true);
     SkPoint source[4];
     SkPath::Verb verb;
     RefPtr<PathBuilderCG> pathBuilder =
         new PathBuilderCG(GetFillRule(aPath.getFillType()));
 
     while ((verb = iter.next(source)) != SkPath::kDone_Verb) {
       switch (verb) {
@@ -931,17 +1021,17 @@ GfxMatrixToCGAffineTransform(const Matri
  * 3) The letter P right side up at (0, -20) due to the first flip
  * 4) The letter P right side up at (0, 80) due to the translation
  *
  * tl;dr - CGRects assume origin is bottom left, DrawTarget rects assume top left.
  */
 static bool
 SetupCGContext(DrawTargetSkia* aDT,
                CGContextRef aCGContext,
-               RefPtrSkia<SkCanvas> aCanvas)
+               sk_sp<SkCanvas> aCanvas)
 {
   // DrawTarget expects the origin to be at the top left, but CG
   // expects it to be at the bottom left. Transform to set the origin to
   // the top left. Have to set this before we do anything else.
   // This is transform (1) up top
   CGContextTranslateCTM(aCGContext, 0, aDT->GetSize().height);
 
   // Transform (2) from the comments.
@@ -1224,17 +1314,17 @@ DrawTargetSkia::FillGlyphs(ScaledFont *a
   AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
   AntialiasMode aaMode = aFont->GetDefaultAAMode();
   if (aOptions.mAntialiasMode != AntialiasMode::DEFAULT) {
     aaMode = aOptions.mAntialiasMode;
   }
   bool aaEnabled = aaMode != AntialiasMode::NONE;
 
   paint.mPaint.setAntiAlias(aaEnabled);
-  paint.mPaint.setTypeface(typeface);
+  paint.mPaint.setTypeface(sk_ref_sp(typeface));
   paint.mPaint.setTextSize(SkFloatToScalar(skiaFont->mSize));
   paint.mPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
 
   bool shouldLCDRenderText = ShouldLCDRenderText(aFont->GetType(), aaMode);
   paint.mPaint.setLCDRenderText(shouldLCDRenderText);
 
   bool useSubpixelText = true;
 
@@ -1332,24 +1422,23 @@ void
 DrawTargetSkia::MaskSurface(const Pattern &aSource,
                             SourceSurface *aMask,
                             Point aOffset,
                             const DrawOptions &aOptions)
 {
   MarkChanged();
   AutoPaintSetup paint(mCanvas.get(), aOptions, aSource, nullptr, -aOffset);
 
-  SkBitmap bitmap = GetBitmapForSurface(aMask);
-  if (bitmap.colorType() != kAlpha_8_SkColorType &&
-      !bitmap.extractAlpha(&bitmap)) {
+  sk_sp<SkImage> alphaMask = ExtractAlphaForSurface(aMask);
+  if (!alphaMask) {
     gfxDebug() << *this << ": MaskSurface() failed to extract alpha for mask";
     return;
   }
 
-  mCanvas->drawBitmap(bitmap, aOffset.x, aOffset.y, &paint.mPaint);
+  mCanvas->drawImage(alphaMask, aOffset.x, aOffset.y, &paint.mPaint);
 }
 
 bool
 DrawTarget::Draw3DTransformedSurface(SourceSurface* aSurface, const Matrix4x4& aMatrix)
 {
   // Composite the 3D transform with the DT's transform.
   Matrix4x4 fullMat = aMatrix * Matrix4x4::From2D(mTransform);
   if (fullMat.IsSingular()) {
@@ -1362,53 +1451,52 @@ DrawTarget::Draw3DTransformedSurface(Sou
                                      Rect(Point(0, 0), Size(GetSize()))));
   if (xformBounds.IsEmpty()) {
     return true;
   }
   // Offset the matrix by the transformed origin.
   fullMat.PostTranslate(-xformBounds.x, -xformBounds.y, 0);
 
   // Read in the source data.
-  SkBitmap srcBitmap = GetBitmapForSurface(aSurface);
-  if (srcBitmap.empty()) {
+  sk_sp<SkImage> srcImage = GetSkImageForSurface(aSurface);
+  if (!srcImage) {
     return true;
   }
 
   // Set up an intermediate destination surface only the size of the transformed bounds.
   // Try to pass through the source's format unmodified in both the BGRA and ARGB cases.
   RefPtr<DataSourceSurface> dstSurf =
     Factory::CreateDataSourceSurface(xformBounds.Size(),
-                                     srcBitmap.alphaType() == kPremul_SkAlphaType ?
+                                     !srcImage->isOpaque() ?
                                        aSurface->GetFormat() : SurfaceFormat::A8R8G8B8_UINT32,
                                      true);
   if (!dstSurf) {
     return false;
   }
-  SkAutoTUnref<SkCanvas> dstCanvas(
+  sk_sp<SkCanvas> dstCanvas(
     SkCanvas::NewRasterDirect(
       SkImageInfo::Make(xformBounds.width, xformBounds.height,
-                        srcBitmap.alphaType() == kPremul_SkAlphaType ?
-                          srcBitmap.colorType() : kBGRA_8888_SkColorType,
+                        GfxFormatToSkiaColorType(dstSurf->GetFormat()),
                         kPremul_SkAlphaType),
       dstSurf->GetData(), dstSurf->Stride()));
   if (!dstCanvas) {
     return false;
   }
 
   // Do the transform.
   SkPaint paint;
   paint.setAntiAlias(true);
   paint.setFilterQuality(kLow_SkFilterQuality);
-  paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+  paint.setBlendMode(SkBlendMode::kSrc);
 
   SkMatrix xform;
   GfxMatrixToSkiaMatrix(fullMat, xform);
   dstCanvas->setMatrix(xform);
 
-  dstCanvas->drawBitmap(srcBitmap, 0, 0, &paint);
+  dstCanvas->drawImage(srcImage, 0, 0, &paint);
   dstCanvas->flush();
 
   // Temporarily reset the DT's transform, since it has already been composed above.
   Matrix origTransform = mTransform;
   SetTransform(Matrix());
 
   // Draw the transformed surface within the transformed bounds.
   DrawSurface(dstSurf, Rect(xformBounds), Rect(Point(0, 0), Size(xformBounds.Size())));
@@ -1422,32 +1510,32 @@ bool
 DrawTargetSkia::Draw3DTransformedSurface(SourceSurface* aSurface, const Matrix4x4& aMatrix)
 {
   if (aMatrix.IsSingular()) {
     return false;
   }
 
   MarkChanged();
 
-  SkBitmap bitmap = GetBitmapForSurface(aSurface);
-  if (bitmap.empty()) {
+  sk_sp<SkImage> image = GetSkImageForSurface(aSurface);
+  if (!image) {
     return true;
   }
 
   mCanvas->save();
 
   SkPaint paint;
   paint.setAntiAlias(true);
   paint.setFilterQuality(kLow_SkFilterQuality);
 
   SkMatrix xform;
   GfxMatrixToSkiaMatrix(aMatrix, xform);
   mCanvas->concat(xform);
 
-  mCanvas->drawBitmap(bitmap, 0, 0, &paint);
+  mCanvas->drawImage(image, 0, 0, &paint);
 
   mCanvas->restore();
 
   return true;
 }
 
 already_AddRefed<SourceSurface>
 DrawTargetSkia::CreateSourceSurfaceFromData(unsigned char *aData,
@@ -1494,47 +1582,43 @@ DrawTargetSkia::UsingSkiaGPU() const
   return false;
 #endif
 }
 
 #ifdef USE_SKIA_GPU
 already_AddRefed<SourceSurface>
 DrawTargetSkia::OptimizeGPUSourceSurface(SourceSurface *aSurface) const
 {
-  // Check if the underlying SkBitmap already has an associated GrTexture.
-  if (aSurface->GetType() == SurfaceType::SKIA &&
-      static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap().getTexture()) {
+  // Check if the underlying SkImage already has an associated GrTexture.
+  sk_sp<SkImage> image = GetSkImageForSurface(aSurface);
+  if (!image || image->isTextureBacked()) {
     RefPtr<SourceSurface> surface(aSurface);
     return surface.forget();
   }
 
-  SkBitmap bitmap = GetBitmapForSurface(aSurface);
-
-  // Upload the SkBitmap to a GrTexture otherwise.
-  SkAutoTUnref<GrTexture> texture(
-      GrRefCachedBitmapTexture(mGrContext.get(), bitmap, GrTextureParams::ClampBilerp()));
-
+  // Upload the SkImage to a GrTexture otherwise.
+  sk_sp<SkImage> texture = image->makeTextureImage(mGrContext.get());
   if (texture) {
-    // Create a new SourceSurfaceSkia whose SkBitmap contains the GrTexture.
+    // Create a new SourceSurfaceSkia whose SkImage contains the GrTexture.
     RefPtr<SourceSurfaceSkia> surface = new SourceSurfaceSkia();
-    if (surface->InitFromGrTexture(texture, aSurface->GetSize(), aSurface->GetFormat())) {
+    if (surface->InitFromImage(texture, aSurface->GetFormat())) {
       return surface.forget();
     }
   }
 
   // The data was too big to fit in a GrTexture.
   if (aSurface->GetType() == SurfaceType::SKIA) {
     // It is already a Skia source surface, so just reuse it as-is.
     RefPtr<SourceSurface> surface(aSurface);
     return surface.forget();
   }
 
   // Wrap it in a Skia source surface so that can do tiled uploads on-demand.
   RefPtr<SourceSurfaceSkia> surface = new SourceSurfaceSkia();
-  surface->InitFromBitmap(bitmap);
+  surface->InitFromImage(image);
   return surface.forget();
 }
 #endif
 
 already_AddRefed<SourceSurface>
 DrawTargetSkia::OptimizeSourceSurfaceForUnknownAlpha(SourceSurface *aSurface) const
 {
 #ifdef USE_SKIA_GPU
@@ -1595,83 +1679,83 @@ DrawTargetSkia::CreateSourceSurfaceFromN
     texDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
     texDesc.fConfig = GfxFormatToGrConfig(aSurface.mFormat);
 
     GrGLTextureInfo texInfo;
     texInfo.fTarget = LOCAL_GL_TEXTURE_2D;
     texInfo.fID = (GrGLuint)(uintptr_t)aSurface.mSurface;
     texDesc.fTextureHandle = reinterpret_cast<GrBackendObject>(&texInfo);
 
-    SkAutoTUnref<GrTexture> texture(mGrContext->textureProvider()->wrapBackendTexture(texDesc, kAdopt_GrWrapOwnership));
-
+    sk_sp<SkImage> texture =
+      SkImage::MakeFromAdoptedTexture(mGrContext.get(), texDesc,
+                                      GfxFormatToSkiaAlphaType(aSurface.mFormat));
     RefPtr<SourceSurfaceSkia> newSurf = new SourceSurfaceSkia();
-    if (newSurf->InitFromGrTexture(texture, aSurface.mSize, aSurface.mFormat)) {
+    if (texture && newSurf->InitFromImage(texture, aSurface.mFormat)) {
       return newSurf.forget();
     }
     return nullptr;
   }
 #endif
 
   return nullptr;
 }
 
 void
 DrawTargetSkia::CopySurface(SourceSurface *aSurface,
                             const IntRect& aSourceRect,
                             const IntPoint &aDestination)
 {
   MarkChanged();
 
-  SkBitmap bitmap = GetBitmapForSurface(aSurface);
-  if (bitmap.empty()) {
+  sk_sp<SkImage> image = GetSkImageForSurface(aSurface);
+  if (!image) {
     return;
   }
 
   mCanvas->save();
   mCanvas->setMatrix(SkMatrix::MakeTrans(SkIntToScalar(aDestination.x), SkIntToScalar(aDestination.y)));
-  mCanvas->clipRect(SkRect::MakeIWH(aSourceRect.width, aSourceRect.height), SkRegion::kReplace_Op);
+  mCanvas->clipRect(SkRect::MakeIWH(aSourceRect.width, aSourceRect.height), kReplace_SkClipOp);
 
   SkPaint paint;
-  if (!bitmap.isOpaque()) {
+  if (!image->isOpaque()) {
     // Keep the xfermode as SOURCE_OVER for opaque bitmaps
     // http://code.google.com/p/skia/issues/detail?id=628
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
   }
-  // drawBitmap with A8 bitmaps ends up doing a mask operation
+  // drawImage with A8 images ends up doing a mask operation
   // so we need to clear before
-  if (bitmap.colorType() == kAlpha_8_SkColorType) {
+  if (SkImageIsMask(image)) {
     mCanvas->clear(SK_ColorTRANSPARENT);
   }
-  mCanvas->drawBitmap(bitmap, -SkIntToScalar(aSourceRect.x), -SkIntToScalar(aSourceRect.y), &paint);
+  mCanvas->drawImage(image, -SkIntToScalar(aSourceRect.x), -SkIntToScalar(aSourceRect.y), &paint);
   mCanvas->restore();
 }
 
 bool
 DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat)
 {
   if (size_t(std::max(aSize.width, aSize.height)) > GetMaxSurfaceSize()) {
     return false;
   }
 
   // we need to have surfaces that have a stride aligned to 4 for interop with cairo
-  int stride = (BytesPerPixel(aFormat)*aSize.width + (4-1)) & -4;
-
-  SkBitmap bitmap;
-  bitmap.setInfo(MakeSkiaImageInfo(aSize, aFormat), stride);
-  if (!bitmap.tryAllocPixels()) {
+  SkImageInfo info = MakeSkiaImageInfo(aSize, aFormat);
+  size_t stride = SkAlign4(info.minRowBytes());
+  mSurface = SkSurface::MakeRaster(info, stride, nullptr);
+  if (!mSurface) {
     return false;
   }
 
-  SkColor clearColor = (aFormat == SurfaceFormat::B8G8R8X8) ? SK_ColorBLACK : SK_ColorTRANSPARENT;
-  bitmap.eraseColor(clearColor);
+  mSize = aSize;
+  mFormat = aFormat;
+  mCanvas = sk_ref_sp(mSurface->getCanvas());
 
-  mCanvas.adopt(new SkCanvas(bitmap));
-  mSize = aSize;
-
-  mFormat = aFormat;
+  if (info.isOpaque()) {
+    mCanvas->clear(SK_ColorBLACK);
+  }
   return true;
 }
 
 #ifdef USE_SKIA_GPU
 /** Indicating a DT should be cached means that space will be reserved in Skia's cache
  * for the render target at creation time, with any unused resources exceeding the cache
  * limits being purged. When the DT is freed, it will then be guaranteed to be kept around
  * for subsequent allocations until it gets incidentally purged.
@@ -1699,73 +1783,67 @@ DrawTargetSkia::InitWithGrContext(GrCont
   MOZ_ASSERT(aGrContext, "null GrContext");
 
   if (size_t(std::max(aSize.width, aSize.height)) > GetMaxSurfaceSize()) {
     return false;
   }
 
   // Create a GPU rendertarget/texture using the supplied GrContext.
   // NewRenderTarget also implicitly clears the underlying texture on creation.
-  sk_sp<SkSurface> gpuSurface =
+  mSurface =
     SkSurface::MakeRenderTarget(aGrContext,
                                 SkBudgeted(aCached),
                                 MakeSkiaImageInfo(aSize, aFormat));
-  if (!gpuSurface) {
+  if (!mSurface) {
     return false;
   }
 
-  mGrContext = aGrContext;
+  mGrContext = sk_ref_sp(aGrContext);
   mSize = aSize;
   mFormat = aFormat;
-
-  mCanvas = gpuSurface->getCanvas();
-
+  mCanvas = sk_ref_sp(mSurface->getCanvas());
   return true;
 }
 
 #endif
 
-void
+bool
 DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat, bool aUninitialized)
 {
   MOZ_ASSERT((aFormat != SurfaceFormat::B8G8R8X8) ||
               aUninitialized || VerifyRGBXFormat(aData, aSize, aStride, aFormat));
 
-  SkBitmap bitmap;
-  bitmap.setInfo(MakeSkiaImageInfo(aSize, aFormat), aStride);
-  bitmap.setPixels(aData);
-
-  mCanvas.adopt(new SkCanvas(bitmap));
+  mSurface = SkSurface::MakeRasterDirect(MakeSkiaImageInfo(aSize, aFormat), aData, aStride);
+  if (!mSurface) {
+    return false;
+  }
 
   mSize = aSize;
   mFormat = aFormat;
+  mCanvas = sk_ref_sp(mSurface->getCanvas());
+  return true;
 }
 
 void
 DrawTargetSkia::SetTransform(const Matrix& aTransform)
 {
   SkMatrix mat;
   GfxMatrixToSkiaMatrix(aTransform, mat);
   mCanvas->setMatrix(mat);
   mTransform = aTransform;
 }
 
 void*
 DrawTargetSkia::GetNativeSurface(NativeSurfaceType aType)
 {
 #ifdef USE_SKIA_GPU
   if (aType == NativeSurfaceType::OPENGL_TEXTURE) {
-    // Get the current texture backing the GPU device.
-    // Beware - this texture is only guaranteed to valid after a draw target flush.
-    GrRenderTarget* rt = mCanvas->getDevice()->accessRenderTarget();
-    if (rt) {
-      GrTexture* tex = rt->asTexture();
-      if (tex) {
-        return (void*)(uintptr_t)reinterpret_cast<GrGLTextureInfo *>(tex->getTextureHandle())->fID;
-      }
+    GrBackendObject handle = mSurface->getTextureHandle(SkSurface::kFlushRead_BackendHandleAccess);
+    if (handle) {
+      return (void*)(uintptr_t)reinterpret_cast<GrGLTextureInfo *>(handle)->fID;
     }
   }
 #endif
   return nullptr;
 }
 
 
 already_AddRefed<PathBuilder>
@@ -1774,78 +1852,78 @@ DrawTargetSkia::CreatePathBuilder(FillRu
   return MakeAndAddRef<PathBuilderSkia>(aFillRule);
 }
 
 void
 DrawTargetSkia::ClearRect(const Rect &aRect)
 {
   MarkChanged();
   mCanvas->save();
-  mCanvas->clipRect(RectToSkRect(aRect), SkRegion::kIntersect_Op, true);
+  mCanvas->clipRect(RectToSkRect(aRect), kIntersect_SkClipOp, true);
   SkColor clearColor = (mFormat == SurfaceFormat::B8G8R8X8) ? SK_ColorBLACK : SK_ColorTRANSPARENT;
   mCanvas->clear(clearColor);
   mCanvas->restore();
 }
 
 void
 DrawTargetSkia::PushClip(const Path *aPath)
 {
   if (aPath->GetBackendType() != BackendType::SKIA) {
     return;
   }
 
   const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath);
   mCanvas->save();
-  mCanvas->clipPath(skiaPath->GetPath(), SkRegion::kIntersect_Op, true);
+  mCanvas->clipPath(skiaPath->GetPath(), kIntersect_SkClipOp, true);
 }
 
 void
 DrawTargetSkia::PushDeviceSpaceClipRects(const IntRect* aRects, uint32_t aCount)
 {
   // Build a region by unioning all the rects together.
   SkRegion region;
   for (uint32_t i = 0; i < aCount; i++) {
     region.op(IntRectToSkIRect(aRects[i]), SkRegion::kUnion_Op);
   }
 
   // Clip with the resulting region. clipRegion does not transform
   // this region by the current transform, unlike the other SkCanvas
   // clip methods, so it is just passed through in device-space.
   mCanvas->save();
-  mCanvas->clipRegion(region, SkRegion::kIntersect_Op);
+  mCanvas->clipRegion(region, kIntersect_SkClipOp);
 }
 
 void
 DrawTargetSkia::PushClipRect(const Rect& aRect)
 {
   SkRect rect = RectToSkRect(aRect);
 
   mCanvas->save();
-  mCanvas->clipRect(rect, SkRegion::kIntersect_Op, true);
+  mCanvas->clipRect(rect, kIntersect_SkClipOp, true);
 }
 
 void
 DrawTargetSkia::PopClip()
 {
   mCanvas->restore();
 }
 
 // Image filter that just passes the source through to the result unmodified.
 class CopyLayerImageFilter : public SkImageFilter
 {
 public:
   CopyLayerImageFilter()
-    : SkImageFilter(0, nullptr)
+    : SkImageFilter(nullptr, 0, nullptr)
   {}
 
-  virtual bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&,
-                                       SkBitmap* result, SkIPoint* offset) const override {
-    *result = src;
+  virtual sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source,
+                                              const Context& ctx,
+                                              SkIPoint* offset) const override {
     offset->set(0, 0);
-    return true;
+    return sk_ref_sp(source);
   }
 
   SK_TO_STRING_OVERRIDE()
   SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(CopyLayerImageFilter)
 };
 
 sk_sp<SkFlattenable>
 CopyLayerImageFilter::CreateProc(SkReadBuffer& buffer)
@@ -1873,17 +1951,17 @@ DrawTargetSkia::PushLayer(bool aOpaque, 
   SkPaint paint;
 
   // If we have a mask, set the opacity to 0 so that SkCanvas::restore skips
   // implicitly drawing the layer so that we can properly mask it in PopLayer.
   paint.setAlpha(aMask ? 0 : ColorFloatToByte(aOpacity));
 
   SkRect bounds = IntRectToSkRect(aBounds);
 
-  SkAutoTUnref<SkImageFilter> backdrop(aCopyBackground ? new CopyLayerImageFilter : nullptr);
+  sk_sp<SkImageFilter> backdrop(aCopyBackground ? new CopyLayerImageFilter : nullptr);
 
   SkCanvas::SaveLayerRec saveRec(aBounds.IsEmpty() ? nullptr : &bounds,
                                  &paint,
                                  backdrop.get(),
                                  aOpaque ? SkCanvas::kIsOpaque_SaveLayerFlag : 0);
 
   mCanvas->saveLayer(saveRec);
 
@@ -1899,22 +1977,36 @@ void
 DrawTargetSkia::PopLayer()
 {
   MarkChanged();
 
   MOZ_ASSERT(mPushedLayers.size());
   const PushedLayer& layer = mPushedLayers.back();
 
   if (layer.mMask) {
-    // If we have a mask, take a reference to the layer's bitmap device so that
+    // If we have a mask, take a reference to the top layer's device so that
     // we can mask it ourselves. This assumes we forced SkCanvas::restore to
     // skip implicitly drawing the layer.
-    SkAutoTUnref<SkBaseDevice> layerDevice(SkSafeRef(mCanvas->getTopDevice()));
+    sk_sp<SkBaseDevice> layerDevice = sk_ref_sp(mCanvas->getTopDevice());
     SkIRect layerBounds = layerDevice->getGlobalBounds();
-    SkBitmap layerBitmap = layerDevice->accessBitmap(false);
+    sk_sp<SkImage> layerImage;
+    SkPixmap layerPixmap;
+    if (layerDevice->peekPixels(&layerPixmap)) {
+      layerImage = SkImage::MakeFromRaster(layerPixmap, nullptr, nullptr);
+#ifdef USE_SKIA_GPU
+    } else if (GrDrawContext* drawCtx = mCanvas->internal_private_accessTopLayerDrawContext()) {
+      drawCtx->prepareForExternalIO();
+      if (GrTexture* tex = drawCtx->accessRenderTarget()->asTexture()) {
+        layerImage = sk_make_sp<SkImage_Gpu>(layerBounds.width(), layerBounds.height(),
+                                             kNeedNewImageUniqueID,
+                                             layerDevice->imageInfo().alphaType(),
+                                             tex, nullptr, SkBudgeted::kNo);
+      }
+#endif
+    }
 
     // Restore the background with the layer's device left alive.
     mCanvas->restore();
 
     SkPaint paint;
     paint.setAlpha(ColorFloatToByte(layer.mOpacity));
 
     SkMatrix maskMat, layerMat;
@@ -1924,36 +2016,36 @@ DrawTargetSkia::PopLayer()
     maskMat.postConcat(mCanvas->getTotalMatrix());
     if (!maskMat.invert(&layerMat)) {
       gfxDebug() << *this << ": PopLayer() failed to invert mask transform";
     } else {
       // The layer should not be affected by the current canvas transform,
       // even though the mask is. So first we use the inverse of the transform
       // affecting the mask, then add back on the layer's origin.
       layerMat.preTranslate(layerBounds.x(), layerBounds.y());
-      sk_sp<SkShader> shader = SkShader::MakeBitmapShader(layerBitmap,
-                                                          SkShader::kClamp_TileMode,
-                                                          SkShader::kClamp_TileMode,
-                                                          &layerMat);
-      paint.setShader(shader);
 
-      SkBitmap mask = GetBitmapForSurface(layer.mMask);
-      if (mask.colorType() != kAlpha_8_SkColorType &&
-          !mask.extractAlpha(&mask)) {
+      if (layerImage) {
+        paint.setShader(layerImage->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &layerMat));
+      } else {
+        paint.setColor(SK_ColorTRANSPARENT);
+      }
+
+      sk_sp<SkImage> alphaMask = ExtractAlphaForSurface(layer.mMask);
+      if (!alphaMask) {
         gfxDebug() << *this << ": PopLayer() failed to extract alpha for mask";
       } else {
         mCanvas->save();
 
         // The layer may be smaller than the canvas size, so make sure drawing is
         // clipped to within the bounds of the layer.
         mCanvas->resetMatrix();
         mCanvas->clipRect(SkRect::Make(layerBounds));
 
         mCanvas->setMatrix(maskMat);
-        mCanvas->drawBitmap(mask, 0, 0, &paint);
+        mCanvas->drawImage(alphaMask, 0, 0, &paint);
 
         mCanvas->restore();
       }
     }
   } else {
     mCanvas->restore();
   }
 
@@ -1987,16 +2079,19 @@ DrawTargetSkia::CreateFilter(FilterType 
 }
 
 void
 DrawTargetSkia::MarkChanged()
 {
   if (mSnapshot) {
     mSnapshot->DrawTargetWillChange();
     mSnapshot = nullptr;
+
+    // Handle copying of any image snapshots bound to the surface.
+    mSurface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode);
   }
 }
 
 void
 DrawTargetSkia::SnapshotDestroyed()
 {
   mSnapshot = nullptr;
 }
--- a/gfx/2d/DrawTargetSkia.h
+++ b/gfx/2d/DrawTargetSkia.h
@@ -2,16 +2,17 @@
  * 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 _MOZILLA_GFX_SOURCESURFACESKIA_H
 #define _MOZILLA_GFX_SOURCESURFACESKIA_H
 
 #include "skia/include/core/SkCanvas.h"
+#include "skia/include/core/SkSurface.h"
 
 #include "2D.h"
 #include "HelpersSkia.h"
 #include "Rect.h"
 #include "PathSkia.h"
 #include <sstream>
 #include <vector>
 
@@ -125,17 +126,17 @@ public:
   virtual already_AddRefed<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override;
   virtual already_AddRefed<GradientStops> CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const override;
   virtual already_AddRefed<FilterNode> CreateFilter(FilterType aType) override;
   virtual void SetTransform(const Matrix &aTransform) override;
   virtual void *GetNativeSurface(NativeSurfaceType aType) override;
   virtual void DetachAllSnapshots() override { MarkChanged(); }
 
   bool Init(const IntSize &aSize, SurfaceFormat aFormat);
-  void Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat, bool aUninitialized = false);
+  bool Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat, bool aUninitialized = false);
 
 #ifdef USE_SKIA_GPU
   bool InitWithGrContext(GrContext* aGrContext,
                          const IntSize &aSize,
                          SurfaceFormat aFormat,
                          bool aCached);
   virtual bool
     InitWithGrContext(GrContext* aGrContext,
@@ -185,21 +186,22 @@ private:
     bool mOpaque;
     Float mOpacity;
     RefPtr<SourceSurface> mMask;
     Matrix mMaskTransform;
   };
   std::vector<PushedLayer> mPushedLayers;
 
 #ifdef USE_SKIA_GPU
-  RefPtrSkia<GrContext> mGrContext;
+  sk_sp<GrContext> mGrContext;
 #endif
 
   IntSize mSize;
-  RefPtrSkia<SkCanvas> mCanvas;
+  sk_sp<SkSurface> mSurface;
+  sk_sp<SkCanvas> mCanvas;
   SourceSurfaceSkia* mSnapshot;
 
 #ifdef MOZ_WIDGET_COCOA
   CGContextRef mCG;
   CGColorSpaceRef mColorSpace;
   uint8_t* mCanvasData;
   IntSize mCGSize;
 #endif
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -377,18 +377,19 @@ Factory::CreateDrawTargetForData(Backend
   RefPtr<DrawTarget> retVal;
 
   switch (aBackend) {
 #ifdef USE_SKIA
   case BackendType::SKIA:
     {
       RefPtr<DrawTargetSkia> newTarget;
       newTarget = new DrawTargetSkia();
-      newTarget->Init(aData, aSize, aStride, aFormat, aUninitialized);
-      retVal = newTarget;
+      if (newTarget->Init(aData, aSize, aStride, aFormat, aUninitialized)) {
+        retVal = newTarget;
+      }
       break;
     }
 #endif
 #ifdef USE_CAIRO
   case BackendType::CAIRO:
     {
       RefPtr<DrawTargetCairo> newTarget;
       newTarget = new DrawTargetCairo();
--- a/gfx/2d/HelpersSkia.h
+++ b/gfx/2d/HelpersSkia.h
@@ -10,17 +10,16 @@
 #include "skia/include/core/SkCanvas.h"
 #include "skia/include/effects/SkDashPathEffect.h"
 #include "skia/include/core/SkShader.h"
 #ifdef USE_SKIA_GPU
 #include "skia/include/gpu/GrTypes.h"
 #endif
 #include "mozilla/Assertions.h"
 #include <vector>
-#include "RefPtrSkia.h"
 #include "nsDebug.h"
 
 namespace mozilla {
 namespace gfx {
 
 static inline SkColorType
 GfxFormatToSkiaColorType(SurfaceFormat format)
 {
@@ -182,75 +181,75 @@ StrokeOptionsToPaint(SkPaint& aPaint, co
                                                       SkFloatToScalar(aOptions.mDashOffset));
     aPaint.setPathEffect(dash);
   }
 
   aPaint.setStyle(SkPaint::kStroke_Style);
   return true;
 }
 
-static inline SkXfermode::Mode
+static inline SkBlendMode
 GfxOpToSkiaOp(CompositionOp op)
 {
   switch (op)
   {
     case CompositionOp::OP_OVER:
-      return SkXfermode::kSrcOver_Mode;
+      return SkBlendMode::kSrcOver;
     case CompositionOp::OP_ADD:
-      return SkXfermode::kPlus_Mode;
+      return SkBlendMode::kPlus;
     case CompositionOp::OP_ATOP:
-      return SkXfermode::kSrcATop_Mode;
+      return SkBlendMode::kSrcATop;
     case CompositionOp::OP_OUT:
-      return SkXfermode::kSrcOut_Mode;
+      return SkBlendMode::kSrcOut;
     case CompositionOp::OP_IN:
-      return SkXfermode::kSrcIn_Mode;
+      return SkBlendMode::kSrcIn;
     case CompositionOp::OP_SOURCE:
-      return SkXfermode::kSrc_Mode;
+      return SkBlendMode::kSrc;
     case CompositionOp::OP_DEST_IN:
-      return SkXfermode::kDstIn_Mode;
+      return SkBlendMode::kDstIn;
     case CompositionOp::OP_DEST_OUT:
-      return SkXfermode::kDstOut_Mode;
+      return SkBlendMode::kDstOut;
     case CompositionOp::OP_DEST_OVER:
-      return SkXfermode::kDstOver_Mode;
+      return SkBlendMode::kDstOver;
     case CompositionOp::OP_DEST_ATOP:
-      return SkXfermode::kDstATop_Mode;
+      return SkBlendMode::kDstATop;
     case CompositionOp::OP_XOR:
-      return SkXfermode::kXor_Mode;
+      return SkBlendMode::kXor;
     case CompositionOp::OP_MULTIPLY:
-      return SkXfermode::kMultiply_Mode;
+      return SkBlendMode::kMultiply;
     case CompositionOp::OP_SCREEN:
-      return SkXfermode::kScreen_Mode;
+      return SkBlendMode::kScreen;
     case CompositionOp::OP_OVERLAY:
-      return SkXfermode::kOverlay_Mode;
+      return SkBlendMode::kOverlay;
     case CompositionOp::OP_DARKEN:
-      return SkXfermode::kDarken_Mode;
+      return SkBlendMode::kDarken;
     case CompositionOp::OP_LIGHTEN:
-      return SkXfermode::kLighten_Mode;
+      return SkBlendMode::kLighten;
     case CompositionOp::OP_COLOR_DODGE:
-      return SkXfermode::kColorDodge_Mode;
+      return SkBlendMode::kColorDodge;
     case CompositionOp::OP_COLOR_BURN:
-      return SkXfermode::kColorBurn_Mode;
+      return SkBlendMode::kColorBurn;
     case CompositionOp::OP_HARD_LIGHT:
-      return SkXfermode::kHardLight_Mode;
+      return SkBlendMode::kHardLight;
     case CompositionOp::OP_SOFT_LIGHT:
-      return SkXfermode::kSoftLight_Mode;
+      return SkBlendMode::kSoftLight;
     case CompositionOp::OP_DIFFERENCE:
-      return SkXfermode::kDifference_Mode;
+      return SkBlendMode::kDifference;
     case CompositionOp::OP_EXCLUSION:
-      return SkXfermode::kExclusion_Mode;
+      return SkBlendMode::kExclusion;
     case CompositionOp::OP_HUE:
-      return SkXfermode::kHue_Mode;
+      return SkBlendMode::kHue;
     case CompositionOp::OP_SATURATION:
-      return SkXfermode::kSaturation_Mode;
+      return SkBlendMode::kSaturation;
     case CompositionOp::OP_COLOR:
-      return SkXfermode::kColor_Mode;
+      return SkBlendMode::kColor;
     case CompositionOp::OP_LUMINOSITY:
-      return SkXfermode::kLuminosity_Mode;
+      return SkBlendMode::kLuminosity;
     default:
-      return SkXfermode::kSrcOver_Mode;
+      return SkBlendMode::kSrcOver;
   }
 }
 
 /* There's quite a bit of inconsistency about
  * whether float colors should be rounded with .5f.
  * We choose to do it to match cairo which also
  * happens to match the Direct3D specs */
 static inline U8CPU ColorFloatToByte(Float color)
deleted file mode 100644
--- a/gfx/2d/RefPtrSkia.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*- 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/. */
-
-#ifndef MOZILLA_GFX_REFPTRSKIA_H_
-#define MOZILLA_GFX_REFPTRSKIA_H_
-
-namespace mozilla {
-namespace gfx {
-
-// The following class was imported from Skia, which is under the
-// following licence:
-//
-// Copyright (c) 2011 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-template <typename T> class RefPtrSkia {
-public:
-  RefPtrSkia() : fObj(NULL) {}
-  explicit RefPtrSkia(T* obj) : fObj(obj) { SkSafeRef(fObj); }
-  RefPtrSkia(const RefPtrSkia& o) : fObj(o.fObj) { SkSafeRef(fObj); }
-  ~RefPtrSkia() { SkSafeUnref(fObj); }
-
-  RefPtrSkia& operator=(const RefPtrSkia& rp) {
-    SkRefCnt_SafeAssign(fObj, rp.fObj);
-    return *this;
-  }
-  RefPtrSkia& operator=(T* obj) {
-    SkRefCnt_SafeAssign(fObj, obj);
-    return *this;
-  }
-
-  T* get() const { return fObj; }
-  T& operator*() const { return *fObj; }
-  T* operator->() const { return fObj; }
-
-  RefPtrSkia& adopt(T* obj) {
-    SkSafeUnref(fObj);
-    fObj = obj;
-    return *this;
-  }
-
-  typedef T* RefPtrSkia::*unspecified_bool_type;
-  operator unspecified_bool_type() const {
-    return fObj ? &RefPtrSkia::fObj : NULL;
-  }
-
-private:
-  T* fObj;
-};
-
-// End of code imported from Skia.
-
-} // namespace gfx
-} // namespace mozilla
-
-#endif /* MOZILLA_GFX_REFPTRSKIA_H_ */
--- a/gfx/2d/ScaledFontBase.cpp
+++ b/gfx/2d/ScaledFontBase.cpp
@@ -75,17 +75,17 @@ ScaledFontBase::PopulateCairoScaledFont(
 #ifdef USE_SKIA
 SkPath
 ScaledFontBase::GetSkiaPathForGlyphs(const GlyphBuffer &aBuffer)
 {
   SkTypeface *typeFace = GetSkTypeface();
   MOZ_ASSERT(typeFace);
 
   SkPaint paint;
-  paint.setTypeface(typeFace);
+  paint.setTypeface(sk_ref_sp(typeFace));
   paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
   paint.setTextSize(SkFloatToScalar(mSize));
 
   std::vector<uint16_t> indices;
   std::vector<SkPoint> offsets;
   indices.resize(aBuffer.mNumGlyphs);
   offsets.resize(aBuffer.mNumGlyphs);
 
--- a/gfx/2d/ScaledFontWin.h
+++ b/gfx/2d/ScaledFontWin.h
@@ -2,16 +2,17 @@
  * 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 MOZILLA_GFX_SCALEDFONTWIN_H_
 #define MOZILLA_GFX_SCALEDFONTWIN_H_
 
 #include "ScaledFontBase.h"
+#include <windows.h>
 
 namespace mozilla {
 namespace gfx {
 
 class ScaledFontWin : public ScaledFontBase
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontWin)
--- a/gfx/2d/SourceSurfaceSkia.cpp
+++ b/gfx/2d/SourceSurfaceSkia.cpp
@@ -1,37 +1,32 @@
 /* -*- 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 "Logging.h"
 #include "SourceSurfaceSkia.h"
-#include "skia/include/core/SkBitmap.h"
-#include "skia/include/core/SkDevice.h"
 #include "HelpersSkia.h"
 #include "DrawTargetSkia.h"
 #include "DataSurfaceHelpers.h"
-
-#ifdef USE_SKIA_GPU
-#include "skia/include/gpu/SkGrPixelRef.h"
-#endif
+#include "skia/include/core/SkData.h"
+#include "mozilla/CheckedInt.h"
 
 namespace mozilla {
 namespace gfx {
 
 SourceSurfaceSkia::SourceSurfaceSkia()
-  : mDrawTarget(nullptr), mLocked(false)
+  : mDrawTarget(nullptr)
 {
 }
 
 SourceSurfaceSkia::~SourceSurfaceSkia()
 {
-  MaybeUnlock();
   if (mDrawTarget) {
     mDrawTarget->SnapshotDestroyed();
     mDrawTarget = nullptr;
   }
 }
 
 IntSize
 SourceSurfaceSkia::GetSize() const
@@ -41,115 +36,118 @@ SourceSurfaceSkia::GetSize() const
 
 SurfaceFormat
 SourceSurfaceSkia::GetFormat() const
 {
   return mFormat;
 }
 
 bool
-SourceSurfaceSkia::InitFromCanvas(SkCanvas* aCanvas,
-                                  SurfaceFormat aFormat,
-                                  DrawTargetSkia* aOwner)
-{
-  mBitmap = aCanvas->getDevice()->accessBitmap(false);
-
-  mFormat = aFormat;
-
-  mSize = IntSize(mBitmap.width(), mBitmap.height());
-  mStride = mBitmap.rowBytes();
-  mDrawTarget = aOwner;
-
-  return true;
-}
-
-bool
 SourceSurfaceSkia::InitFromData(unsigned char* aData,
                                 const IntSize &aSize,
                                 int32_t aStride,
                                 SurfaceFormat aFormat)
 {
-  SkBitmap temp;
-  temp.setInfo(MakeSkiaImageInfo(aSize, aFormat), aStride);
-  temp.setPixels(aData);
-
-  if (!temp.copyTo(&mBitmap)) {
+  SkPixmap pixmap(MakeSkiaImageInfo(aSize, aFormat), aData, aStride);
+  mImage = SkImage::MakeRasterCopy(pixmap);
+  if (!mImage) {
     return false;
   }
 
   mSize = aSize;
   mFormat = aFormat;
-  mStride = mBitmap.rowBytes();
+  mStride = aStride;
   return true;
 }
 
-void
-SourceSurfaceSkia::InitFromBitmap(const SkBitmap& aBitmap)
+bool
+SourceSurfaceSkia::InitFromImage(sk_sp<SkImage> aImage,
+                                 SurfaceFormat aFormat,
+                                 DrawTargetSkia* aOwner)
 {
-  mBitmap = aBitmap;
+  if (!aImage) {
+    return false;
+  }
+
+  mSize = IntSize(aImage->width(), aImage->height());
 
-  mSize = IntSize(mBitmap.width(), mBitmap.height());
-  mFormat = SkiaColorTypeToGfxFormat(mBitmap.colorType(), mBitmap.alphaType());
-  mStride = mBitmap.rowBytes();
-}
-
-#ifdef USE_SKIA_GPU
-bool
-SourceSurfaceSkia::InitFromGrTexture(GrTexture* aTexture,
-                                     const IntSize &aSize,
-                                     SurfaceFormat aFormat)
-{
-  if (!aTexture) {
+  // For the raster image case, we want to use the format and stride
+  // information that the underlying raster image is using, which is
+  // reliable.
+  // For the GPU case (for which peekPixels is false), we can't easily
+  // figure this information out. It is better to report the originally
+  // intended format and stride that we will convert to if this GPU
+  // image is ever read back into a raster image.
+  SkPixmap pixmap;
+  if (aImage->peekPixels(&pixmap)) {
+    mFormat =
+      aFormat != SurfaceFormat::UNKNOWN ?
+        aFormat :
+        SkiaColorTypeToGfxFormat(pixmap.colorType(), pixmap.alphaType());
+    mStride = pixmap.rowBytes();
+  } else if (aFormat != SurfaceFormat::UNKNOWN) {
+    mFormat = aFormat;
+    SkImageInfo info = MakeSkiaImageInfo(mSize, mFormat);
+    mStride = SkAlign4(info.minRowBytes());
+  } else {
     return false;
   }
 
-  // Create a GPU pixelref wrapping the texture.
-  SkImageInfo imgInfo = MakeSkiaImageInfo(aSize, aFormat);
-  mBitmap.setInfo(imgInfo);
-  mBitmap.setPixelRef(new SkGrPixelRef(imgInfo, aTexture))->unref();
+  mImage = aImage;
 
-  mSize = aSize;
-  mFormat = aFormat;
-  mStride = mBitmap.rowBytes();
+  if (aOwner) {
+    mDrawTarget = aOwner;
+  }
+
   return true;
 }
-#endif
 
-unsigned char*
+uint8_t*
 SourceSurfaceSkia::GetData()
 {
-  if (!mLocked) {
-    mBitmap.lockPixels();
-    mLocked = true;
+#ifdef USE_SKIA_GPU
+  if (mImage->isTextureBacked()) {
+    sk_sp<SkImage> raster;
+    CheckedInt<size_t> size = mStride;
+    size *= mSize.height;
+    if (size.isValid()) {
+      if (sk_sp<SkData> data = SkData::MakeUninitialized(size.value())) {
+        SkImageInfo info = MakeSkiaImageInfo(mSize, mFormat);
+        if (mImage->readPixels(info, data->writable_data(), mStride, 0, 0, SkImage::kDisallow_CachingHint)) {
+          raster = SkImage::MakeRasterData(info, data, mStride);
+        }
+      }
+    }
+    if (!raster) {
+      gfxCriticalError() << "Failed making Skia raster image for GPU surface";
+    }
+    mImage = raster;
   }
-
-  unsigned char *pixels = (unsigned char *)mBitmap.getPixels();
-  return pixels;
+#endif
+  SkPixmap pixmap;
+  if (!mImage->peekPixels(&pixmap)) {
+    gfxCriticalError() << "Failed accessing pixels for Skia raster image";
+  }
+  return reinterpret_cast<uint8_t*>(pixmap.writable_addr());
 }
 
 void
 SourceSurfaceSkia::DrawTargetWillChange()
 {
   if (mDrawTarget) {
-    MaybeUnlock();
-
-    mDrawTarget = nullptr;
-
-    // First try a deep copy to avoid a readback from the GPU.
-    // If that fails, try the CPU copy.
-    if (!mBitmap.deepCopyTo(&mBitmap) &&
-        !mBitmap.copyTo(&mBitmap)) {
-      mBitmap.reset();
+    // Raster snapshots do not use Skia's internal copy-on-write mechanism,
+    // so we need to do an explicit copy here.
+    // GPU snapshots, for which peekPixels is false, will already be dealt
+    // with automatically via the internal copy-on-write mechanism, so we
+    // don't need to do anything for them here.
+    SkPixmap pixmap;
+    if (mImage->peekPixels(&pixmap)) {
+      mImage = SkImage::MakeRasterCopy(pixmap);
+      if (!mImage) {
+        gfxCriticalError() << "Failed copying Skia raster snapshot";
+      }
     }
-  }
-}
-
-void
-SourceSurfaceSkia::MaybeUnlock()
-{
-  if (mLocked) {
-    mBitmap.unlockPixels();
-    mLocked = false;
+    mDrawTarget = nullptr;
   }
 }
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/2d/SourceSurfaceSkia.h
+++ b/gfx/2d/SourceSurfaceSkia.h
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_SOURCESURFACESKIA_H_
 #define MOZILLA_GFX_SOURCESURFACESKIA_H_
 
 #include "2D.h"
 #include <vector>
 #include "skia/include/core/SkCanvas.h"
-#include "skia/include/core/SkBitmap.h"
+#include "skia/include/core/SkImage.h"
 
 namespace mozilla {
 
 namespace gfx {
 
 class DrawTargetSkia;
 
 class SourceSurfaceSkia : public DataSourceSurface
@@ -23,53 +23,39 @@ public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceSkia)
   SourceSurfaceSkia();
   ~SourceSurfaceSkia();
 
   virtual SurfaceType GetType() const { return SurfaceType::SKIA; }
   virtual IntSize GetSize() const;
   virtual SurfaceFormat GetFormat() const;
 
-  SkBitmap& GetBitmap() { return mBitmap; }
+  sk_sp<SkImage>& GetImage() { return mImage; }
 
   bool InitFromData(unsigned char* aData,
                     const IntSize &aSize,
                     int32_t aStride,
                     SurfaceFormat aFormat);
 
-  bool InitFromCanvas(SkCanvas* aCanvas,
-                      SurfaceFormat aFormat,
-                      DrawTargetSkia* aOwner);
-
-  void InitFromBitmap(const SkBitmap& aBitmap);
+  bool InitFromImage(sk_sp<SkImage> aImage,
+                     SurfaceFormat aFormat = SurfaceFormat::UNKNOWN,
+                     DrawTargetSkia* aOwner = nullptr);
 
-#ifdef USE_SKIA_GPU
-  /**
-   * NOTE: While wrapping a Texture for SkiaGL, the texture *must* be created
-   *       with the same GLcontext of DrawTargetSkia
-   */
-  bool InitFromGrTexture(GrTexture* aTexture,
-                         const IntSize &aSize,
-                         SurfaceFormat aFormat);
-#endif
-
-  virtual unsigned char *GetData();
+  virtual uint8_t* GetData();
 
   virtual int32_t Stride() { return mStride; }
 
 private:
   friend class DrawTargetSkia;
 
   void DrawTargetWillChange();
-  void MaybeUnlock();
 
-  SkBitmap mBitmap;
+  sk_sp<SkImage> mImage;
   SurfaceFormat mFormat;
   IntSize mSize;
   int32_t mStride;
   RefPtr<DrawTargetSkia> mDrawTarget;
-  bool mLocked;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_SOURCESURFACESKIA_H_ */
--- a/gfx/2d/image_operations.cpp
+++ b/gfx/2d/image_operations.cpp
@@ -34,17 +34,17 @@
 
 #include "image_operations.h"
 
 #include "base/stack_container.h"
 #include "convolver.h"
 #include "skia/include/core/SkColorPriv.h"
 #include "skia/include/core/SkBitmap.h"
 #include "skia/include/core/SkRect.h"
-#include "skia/include/core/SkFontHost.h"
+#include "skia/include/core/SkFontLCDConfig.h"
 
 namespace skia {
 
 namespace resize {
 
 // TODO(egouriou): Take advantage of periods in the convolution.
 // Practical resizing filters are periodic outside of the border area.
 // For Lanczos, a scaling by a (reduced) factor of p/q (q pixels in the
@@ -200,31 +200,31 @@ SkBitmap ImageOperations::Resize(const S
                        dest_pixels);
 }
 
 // static
 SkBitmap ImageOperations::ResizeSubpixel(const SkBitmap& source,
                                          int dest_width, int dest_height,
                                          const SkIRect& dest_subset) {
   // Currently only works on Linux/BSD because these are the only platforms
-  // where SkFontHost::GetSubpixelOrder is defined.
+  // where SkFontLCDConfig::GetSubpixelOrder is defined.
 #if defined(XP_UNIX)
   // Understand the display.
-  const SkFontHost::LCDOrder order = SkFontHost::GetSubpixelOrder();
-  const SkFontHost::LCDOrientation orientation =
-      SkFontHost::GetSubpixelOrientation();
+  const SkFontLCDConfig::LCDOrder order = SkFontLCDConfig::GetSubpixelOrder();
+  const SkFontLCDConfig::LCDOrientation orientation =
+      SkFontLCDConfig::GetSubpixelOrientation();
 
   // Decide on which dimension, if any, to deploy subpixel rendering.
   int w = 1;
   int h = 1;
   switch (orientation) {
-    case SkFontHost::kHorizontal_LCDOrientation:
+    case SkFontLCDConfig::kHorizontal_LCDOrientation:
       w = dest_width < source.width() ? 3 : 1;
       break;
-    case SkFontHost::kVertical_LCDOrientation:
+    case SkFontLCDConfig::kVertical_LCDOrientation:
       h = dest_height < source.height() ? 3 : 1;
       break;
   }
 
   // Resize the image.
   const int width = dest_width * w;
   const int height = dest_height * h;
   SkIRect subset = { dest_subset.fLeft, dest_subset.fTop,
@@ -255,49 +255,49 @@ SkBitmap ImageOperations::ResizeSubpixel
   uint32_t* src_row = img.getAddr32(0, 0);
   uint32_t* dst_row = result.getAddr32(0, 0);
   for (int y = 0; y < dest_subset.height(); y++) {
     uint32_t* src = src_row;
     uint32_t* dst = dst_row;
     for (int x = 0; x < dest_subset.width(); x++, src += w, dst++) {
       uint8_t r = 0, g = 0, b = 0, a = 0;
       switch (order) {
-        case SkFontHost::kRGB_LCDOrder:
+        case SkFontLCDConfig::kRGB_LCDOrder:
           switch (orientation) {
-            case SkFontHost::kHorizontal_LCDOrientation:
+            case SkFontLCDConfig::kHorizontal_LCDOrientation:
               r = SkGetPackedR32(src[0]);
               g = SkGetPackedG32(src[1]);
               b = SkGetPackedB32(src[2]);
               a = SkGetPackedA32(src[1]);
               break;
-            case SkFontHost::kVertical_LCDOrientation:
+            case SkFontLCDConfig::kVertical_LCDOrientation:
               r = SkGetPackedR32(src[0 * row_words]);
               g = SkGetPackedG32(src[1 * row_words]);
               b = SkGetPackedB32(src[2 * row_words]);
               a = SkGetPackedA32(src[1 * row_words]);
               break;
           }
           break;
-        case SkFontHost::kBGR_LCDOrder:
+        case SkFontLCDConfig::kBGR_LCDOrder:
           switch (orientation) {
-            case SkFontHost::kHorizontal_LCDOrientation:
+            case SkFontLCDConfig::kHorizontal_LCDOrientation:
               b = SkGetPackedB32(src[0]);
               g = SkGetPackedG32(src[1]);
               r = SkGetPackedR32(src[2]);
               a = SkGetPackedA32(src[1]);
               break;
-            case SkFontHost::kVertical_LCDOrientation:
+            case SkFontLCDConfig::kVertical_LCDOrientation:
               b = SkGetPackedB32(src[0 * row_words]);
               g = SkGetPackedG32(src[1 * row_words]);
               r = SkGetPackedR32(src[2 * row_words]);
               a = SkGetPackedA32(src[1 * row_words]);
               break;
           }
           break;
-        case SkFontHost::kNONE_LCDOrder:
+        case SkFontLCDConfig::kNONE_LCDOrder:
           break;
       }
       // Premultiplied alpha is very fragile.
       a = a > r ? a : r;
       a = a > g ? a : g;
       a = a > b ? a : b;
       *dst = SkPackARGB32(a, r, g, b);
     }
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -106,17 +106,16 @@ if CONFIG['MOZ_ENABLE_SKIA']:
     ]
     if CONFIG['CLANG_CXX']:
         # Suppress warnings from Skia header files.
         SOURCES['DrawTargetSkia.cpp'].flags += ['-Wno-implicit-fallthrough']
         SOURCES['PathSkia.cpp'].flags += ['-Wno-implicit-fallthrough']
         SOURCES['SourceSurfaceSkia.cpp'].flags += ['-Wno-implicit-fallthrough']
     EXPORTS.mozilla.gfx += [
         'HelpersSkia.h',
-        'RefPtrSkia.h',
     ]
 
 # Are we targeting x86 or x64?  If so, build SSE2 files.
 if CONFIG['INTEL_ARCHITECTURE']:
     SOURCES += [
         'BlurSSE2.cpp',
         'FilterProcessingSSE2.cpp',
         'ImageScalingSSE2.cpp',
@@ -212,8 +211,20 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('and
     DEFINES['MOZ_ENABLE_FREETYPE'] = True
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk'):
     CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
 
 LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
+
+if CONFIG['MOZ_ENABLE_SKIA']:
+    LOCAL_INCLUDES += [
+        '/gfx/skia/skia/include/private',
+        '/gfx/skia/skia/src/core',
+        '/gfx/skia/skia/src/image',
+    ]
+if CONFIG['MOZ_ENABLE_SKIA_GPU']:
+    LOCAL_INCLUDES += [
+        '/gfx/skia/skia/src/gpu',
+    ]
+
--- a/gfx/gl/SkiaGLGlue.cpp
+++ b/gfx/gl/SkiaGLGlue.cpp
@@ -191,16 +191,17 @@ static GrGLInterface* CreateGrGLInterfac
     i->fFunctions.fDeleteRenderbuffers = WrapGL(context, &GLContext::fDeleteRenderbuffers);
     i->fFunctions.fDeleteShader = WrapGL(context, &GLContext::fDeleteShader);
     i->fFunctions.fDeleteTextures = WrapGL(context, &GLContext::fDeleteTextures);
     i->fFunctions.fDepthMask = WrapGL(context, &GLContext::fDepthMask);
     i->fFunctions.fDisable = WrapGL(context, &GLContext::fDisable);
     i->fFunctions.fDisableVertexAttribArray = WrapGL(context, &GLContext::fDisableVertexAttribArray);
     i->fFunctions.fDrawArrays = WrapGL(context, &GLContext::fDrawArrays);
     i->fFunctions.fDrawElements = WrapGL(context, &GLContext::fDrawElements);
+    i->fFunctions.fDrawRangeElements = WrapGL(context, &GLContext::fDrawRangeElements);
     i->fFunctions.fEnable = WrapGL(context, &GLContext::fEnable);
     i->fFunctions.fEnableVertexAttribArray = WrapGL(context, &GLContext::fEnableVertexAttribArray);
     i->fFunctions.fFinish = WrapGL(context, &GLContext::fFinish);
     i->fFunctions.fFlush = WrapGL(context, &GLContext::fFlush);
     i->fFunctions.fFramebufferRenderbuffer = WrapGL(context, &GLContext::fFramebufferRenderbuffer);
     i->fFunctions.fFramebufferTexture2D = WrapGL(context, &GLContext::fFramebufferTexture2D);
     i->fFunctions.fFrontFace = WrapGL(context, &GLContext::fFrontFace);
     i->fFunctions.fGenBuffers = WrapGL(context, &GLContext::fGenBuffers);
@@ -300,18 +301,18 @@ static GrGLInterface* CreateGrGLInterfac
     i->fFunctions.fDrawBuffers = WrapGL(context, &GLContext::fDrawBuffers);
 
     return i;
 }
 
 SkiaGLGlue::SkiaGLGlue(GLContext* context)
     : mGLContext(context)
 {
-    mGrGLInterface.adopt(CreateGrGLInterfaceFromGLContext(mGLContext));
-    mGrContext.adopt(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)mGrGLInterface.get()));
+    mGrGLInterface.reset(CreateGrGLInterfaceFromGLContext(mGLContext));
+    mGrContext.reset(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)mGrGLInterface.get()));
 }
 
 SkiaGLGlue::~SkiaGLGlue()
 {
     /*
      * These members have inter-dependencies, but do not keep each other alive, so
      * destruction order is very important here: mGrContext uses mGrGLInterface, and
      * through it, uses mGLContext
--- a/gfx/gl/SkiaGLGlue.h
+++ b/gfx/gl/SkiaGLGlue.h
@@ -3,17 +3,17 @@
 * 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 SKIA_GL_GLUE_H_
 #define SKIA_GL_GLUE_H_
 
 #ifdef USE_SKIA_GPU
 
-#include "mozilla/gfx/RefPtrSkia.h"
+#include "skia/include/core/SkRefCnt.h"
 #include "mozilla/RefPtr.h"
 
 struct GrGLInterface;
 class GrContext;
 
 namespace mozilla {
 namespace gl {
 
@@ -27,18 +27,18 @@ public:
   GLContext* GetGLContext() const { return mGLContext.get(); }
   GrContext* GetGrContext() const { return mGrContext.get(); }
 
 protected:
   virtual ~SkiaGLGlue();
 
 private:
   RefPtr<GLContext> mGLContext;
-  gfx::RefPtrSkia<GrGLInterface> mGrGLInterface;
-  gfx::RefPtrSkia<GrContext> mGrContext;
+  sk_sp<GrGLInterface> mGrGLInterface;
+  sk_sp<GrContext> mGrContext;
 };
 
 } // namespace gl
 } // namespace mozilla
 
 #else // USE_SKIA_GPU
 
 class GrContext;
--- a/gfx/layers/composite/PaintCounter.cpp
+++ b/gfx/layers/composite/PaintCounter.cpp
@@ -7,41 +7,37 @@
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/gfx/Types.h"          // for Color, SurfaceFormat
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/Effects.h"     // for Effect, EffectChain, etc
 #include "mozilla/TimeStamp.h"          // for TimeStamp, TimeDuration
 #include "mozilla/Sprintf.h"
 
-#include "SkColor.h"
 #include "mozilla/gfx/HelpersSkia.h"
-#include "skia/include/core/SkBitmapDevice.h"
 #include "PaintCounter.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 
 // Positioned below the chrome UI
 IntRect PaintCounter::mRect = IntRect(0, 175, 300, 60);
 
 PaintCounter::PaintCounter()
 {
   mFormat = SurfaceFormat::B8G8R8A8;
   mSurface = Factory::CreateDataSourceSurface(mRect.Size(), mFormat);
   mStride = mSurface->Stride();
 
-  SkBitmap bitmap;
-  bitmap.setInfo(MakeSkiaImageInfo(mRect.Size(), mFormat), mStride);
-  bitmap.setPixels(mSurface->GetData());
-  bitmap.eraseColor(SK_ColorWHITE);
-
-  mCanvas.adopt(new SkCanvas(bitmap));
+  mCanvas.reset(
+    SkCanvas::NewRasterDirect(MakeSkiaImageInfo(mRect.Size(), mFormat),
+                              mSurface->GetData(), mStride));
+  mCanvas->clear(SK_ColorWHITE);
 }
 
 PaintCounter::~PaintCounter()
 {
   mSurface = nullptr;
   mTextureSource = nullptr;
   mTexturedEffect = nullptr;
 }
--- a/gfx/layers/composite/PaintCounter.h
+++ b/gfx/layers/composite/PaintCounter.h
@@ -5,17 +5,16 @@
 
 #ifndef mozilla_layers_PaintCounter_h_
 #define mozilla_layers_PaintCounter_h_
 
 #include <map>                          // for std::map
 #include "mozilla/RefPtr.h"             // for already_AddRefed, RefCounted
 #include "mozilla/TimeStamp.h"          // for TimeStamp, TimeDuration
 #include "skia/include/core/SkCanvas.h"
-#include "mozilla/gfx/HelpersSkia.h"
 
 namespace mozilla {
 namespace layers {
 
 class Compositor;
 
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
@@ -29,17 +28,17 @@ public:
   PaintCounter();
   void Draw(Compositor* aCompositor, TimeDuration aPaintTime, TimeDuration aCompositeTime);
   static IntRect GetPaintRect() { return PaintCounter::mRect; }
 
 private:
   virtual ~PaintCounter();
 
   SurfaceFormat mFormat;
-  RefPtrSkia<SkCanvas> mCanvas;
+  sk_sp<SkCanvas> mCanvas;
   IntSize mSize;
   int mStride;
 
   RefPtr<DataSourceSurface> mSurface;
   RefPtr<DataTextureSource> mTextureSource;
   RefPtr<TexturedEffect> mTexturedEffect;
   static IntRect mRect;
 };