Bug 1303094 - avoid OOM crashes in SourceSurfaceSkia::DrawTargetWillChange. r=mchang
authorLee Salzman <lsalzman@mozilla.com>
Thu, 23 Feb 2017 14:40:59 -0500 (2017-02-23)
changeset 344527 c69c880f88628541bc812cf730ed6607c7a83aa0
parent 344526 391047948db40495f68c43421bb7263d10680b97
child 344528 3a585de719c2d165c5f8f9e888b87cf058380f23
push id87382
push userlsalzman@mozilla.com
push dateThu, 23 Feb 2017 19:42:17 +0000 (2017-02-23)
treeherdermozilla-inbound@c69c880f8862 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmchang
bugs1303094
milestone54.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 1303094 - avoid OOM crashes in SourceSurfaceSkia::DrawTargetWillChange. r=mchang MozReview-Commit-ID: 236vebw7ftU
gfx/2d/SourceSurfaceSkia.cpp
--- a/gfx/2d/SourceSurfaceSkia.cpp
+++ b/gfx/2d/SourceSurfaceSkia.cpp
@@ -36,39 +36,50 @@ SourceSurfaceSkia::GetSize() const
 
 SurfaceFormat
 SourceSurfaceSkia::GetFormat() const
 {
   return mFormat;
 }
 
 static sk_sp<SkData>
-MakeSkData(unsigned char* aData, const IntSize& aSize, int32_t aStride)
+MakeSkData(void* aData, int32_t aHeight, size_t aStride)
 {
   CheckedInt<size_t> size = aStride;
-  size *= aSize.height;
+  size *= aHeight;
   if (size.isValid()) {
     void* mem = sk_malloc_flags(size.value(), 0);
     if (mem) {
       if (aData) {
         memcpy(mem, aData, size.value());
       }
       return SkData::MakeFromMalloc(mem, size.value());
     }
   }
   return nullptr;
 }
 
+static sk_sp<SkImage>
+ReadSkImage(const sk_sp<SkImage>& aImage, const SkImageInfo& aInfo, size_t aStride)
+{
+  if (sk_sp<SkData> data = MakeSkData(nullptr, aInfo.height(), aStride)) {
+    if (aImage->readPixels(aInfo, data->writable_data(), aStride, 0, 0, SkImage::kDisallow_CachingHint)) {
+      return SkImage::MakeRasterData(aInfo, data, aStride);
+    }
+  }
+  return nullptr;
+}
+
 bool
 SourceSurfaceSkia::InitFromData(unsigned char* aData,
                                 const IntSize &aSize,
                                 int32_t aStride,
                                 SurfaceFormat aFormat)
 {
-  sk_sp<SkData> data = MakeSkData(aData, aSize, aStride);
+  sk_sp<SkData> data = MakeSkData(aData, aSize.height, aStride);
   if (!data) {
     return false;
   }
 
   SkImageInfo info = MakeSkiaImageInfo(aSize, aFormat);
   mImage = SkImage::MakeRasterData(info, data, aStride);
   if (!mImage) {
     return false;
@@ -120,26 +131,22 @@ SourceSurfaceSkia::InitFromImage(const s
   }
 
   return true;
 }
 
 uint8_t*
 SourceSurfaceSkia::GetData()
 {
+  if (!mImage) {
+    return nullptr;
+  }
 #ifdef USE_SKIA_GPU
   if (mImage->isTextureBacked()) {
-    sk_sp<SkImage> raster;
-    if (sk_sp<SkData> data = MakeSkData(nullptr, mSize, mStride)) {
-      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) {
+    if (sk_sp<SkImage> raster = ReadSkImage(mImage, MakeSkiaImageInfo(mSize, mFormat), mStride)) {
       mImage = raster;
     } else {
       gfxCriticalError() << "Failed making Skia raster image for GPU surface";
     }
   }
 #endif
   SkPixmap pixmap;
   if (!mImage->peekPixels(&pixmap)) {
@@ -154,17 +161,17 @@ SourceSurfaceSkia::DrawTargetWillChange(
   if (mDrawTarget) {
     // 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);
+      mImage = ReadSkImage(mImage, pixmap.info(), pixmap.rowBytes());
       if (!mImage) {
         gfxCriticalError() << "Failed copying Skia raster snapshot";
       }
     }
     mDrawTarget = nullptr;
   }
 }