Bug 1265598: Deal with the possibility of a write map failing. r=kaku r=milan
authorBas Schouten <bschouten@mozilla.com>
Thu, 28 Apr 2016 13:22:32 +0000
changeset 319768 89b02b6959ee93a58c033c158005668bdb46773b
parent 319767 dade9df33a9fabf3977f749244c6c3def0a9e755
child 319769 d88619681bc2aa68a2c4008422ba3f02992af0c8
push id9671
push userraliiev@mozilla.com
push dateMon, 06 Jun 2016 20:27:52 +0000
treeherdermozilla-aurora@cea65ca3d0bd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskaku, milan
bugs1265598
milestone49.0a1
Bug 1265598: Deal with the possibility of a write map failing. r=kaku r=milan MozReview-Commit-ID: KLrlKf6Silc
dom/canvas/ImageBitmap.cpp
gfx/2d/SourceSurfaceD2D1.cpp
--- a/dom/canvas/ImageBitmap.cpp
+++ b/dom/canvas/ImageBitmap.cpp
@@ -480,22 +480,37 @@ ImageBitmap::PrepareForDrawTarget(gfx::D
 
   // Pre-multiply alpha here.
   // Apply pre-multiply alpha only if mIsPremultipliedAlpha is false.
   if (!mIsPremultipliedAlpha) {
     MOZ_ASSERT(mSurface->GetFormat() == SurfaceFormat::R8G8B8A8 ||
                mSurface->GetFormat() == SurfaceFormat::B8G8R8A8 ||
                mSurface->GetFormat() == SurfaceFormat::A8R8G8B8);
 
-    RefPtr<DataSourceSurface> dataSourceSurface = mSurface->GetDataSurface();
-    MOZ_ASSERT(dataSourceSurface);
+    RefPtr<DataSourceSurface> dstSurface = mSurface->GetDataSurface();
+    MOZ_ASSERT(dstSurface);
+
+    RefPtr<DataSourceSurface> srcSurface;
+    DataSourceSurface::MappedSurface srcMap;
+    DataSourceSurface::MappedSurface dstMap;
 
-    DataSourceSurface::ScopedMap map(dataSourceSurface, DataSourceSurface::READ_WRITE);
-    if (NS_WARN_IF(!map.IsMapped())) {
-      return nullptr;
+    if (!dstSurface->Map(DataSourceSurface::MapType::READ_WRITE, &dstMap)) {
+      srcSurface = dstSurface;
+      if (!srcSurface->Map(DataSourceSurface::READ, &srcMap)) {
+        gfxCriticalError() << "Failed to map source surface for premultiplying alpha.";
+        return nullptr;
+      }
+
+      dstSurface = Factory::CreateDataSourceSurface(srcSurface->GetSize(), srcSurface->GetFormat());
+
+      if (!dstSurface || !dstSurface->Map(DataSourceSurface::MapType::WRITE, &dstMap)) {
+        gfxCriticalError() << "Failed to map destination surface for premultiplying alpha.";
+        srcSurface->Unmap();
+        return nullptr;
+      }
     }
 
     uint8_t rIndex = 0;
     uint8_t gIndex = 0;
     uint8_t bIndex = 0;
     uint8_t aIndex = 0;
 
     if (mSurface->GetFormat() == SurfaceFormat::R8G8B8A8) {
@@ -510,34 +525,41 @@ ImageBitmap::PrepareForDrawTarget(gfx::D
       aIndex = 3;
     } else if (mSurface->GetFormat() == SurfaceFormat::A8R8G8B8) {
       rIndex = 1;
       gIndex = 2;
       bIndex = 3;
       aIndex = 0;
     }
 
-    for (int i = 0; i < dataSourceSurface->GetSize().height; ++i) {
-      uint8_t* bufferPtr = map.GetData() + map.GetStride() * i;
-      for (int i = 0; i < dataSourceSurface->GetSize().width; ++i) {
-        uint8_t r = *(bufferPtr+rIndex);
-        uint8_t g = *(bufferPtr+gIndex);
-        uint8_t b = *(bufferPtr+bIndex);
-        uint8_t a = *(bufferPtr+aIndex);
+    for (int i = 0; i < dstSurface->GetSize().height; ++i) {
+      uint8_t* bufferPtr = dstMap.mData + dstMap.mStride * i;
+      uint8_t* srcBufferPtr = srcSurface ? srcMap.mData + srcMap.mStride * i : bufferPtr;
+      for (int i = 0; i < dstSurface->GetSize().width; ++i) {
+        uint8_t r = *(srcBufferPtr+rIndex);
+        uint8_t g = *(srcBufferPtr+gIndex);
+        uint8_t b = *(srcBufferPtr+bIndex);
+        uint8_t a = *(srcBufferPtr+aIndex);
 
         *(bufferPtr+rIndex) = gfxUtils::sPremultiplyTable[a * 256 + r];
         *(bufferPtr+gIndex) = gfxUtils::sPremultiplyTable[a * 256 + g];
         *(bufferPtr+bIndex) = gfxUtils::sPremultiplyTable[a * 256 + b];
         *(bufferPtr+aIndex) = a;
 
         bufferPtr += 4;
+        srcBufferPtr += 4;
       }
     }
 
-    mSurface = dataSourceSurface;
+    dstSurface->Unmap();
+    if (srcSurface) {
+      srcSurface->Unmap();
+    }
+
+    mSurface = dstSurface;
   }
 
   // Replace our surface with one optimized for the target we're about to draw
   // to, under the assumption it'll likely be drawn again to that target.
   // This call should be a no-op for already-optimized surfaces
   mSurface = target->OptimizeSourceSurface(mSurface);
 
   RefPtr<gfx::SourceSurface> surface(mSurface);
--- a/gfx/2d/SourceSurfaceD2D1.cpp
+++ b/gfx/2d/SourceSurfaceD2D1.cpp
@@ -184,17 +184,17 @@ DataSourceSurfaceD2D1::Map(MapType aMapT
   // DataSourceSurfaces used with the new Map API should not be used with GetData!!
   MOZ_ASSERT(!mMapped);
   MOZ_ASSERT(!mIsMapped);
 
   D2D1_MAP_OPTIONS options;
   if (aMapType == MapType::READ) {
     options = D2D1_MAP_OPTIONS_READ;
   } else {
-    gfxDevCrash(LogReason::D2D1NoWriteMap) << "No support for Write maps on D2D1 DataSourceSurfaces yet!";
+    gfxWarning() << "Attempt to map D2D1 DrawTarget for writing.";
     return false;
   }
 
   D2D1_MAPPED_RECT map;
   if (FAILED(mBitmap->Map(D2D1_MAP_OPTIONS_READ, &map))) {
     gfxCriticalError() << "Failed to map bitmap (M).";
     return false;
   }