Bug 997551 - Avoid copying data in GetSourceSurfaceForSurface whenever possible. r=Bas
authorMatt Woodrow <mwoodrow@mozilla.com>
Fri, 25 Apr 2014 15:31:53 +1200
changeset 200070 7eba5b89f831b0205ad16c018ecc383c50b6a41d
parent 200069 d9a6a378349a840f72466549292c7dbf43b228bf
child 200071 d6a1810f209276176ef79068cc8e23ea29d6e145
push id486
push userasasaki@mozilla.com
push dateMon, 14 Jul 2014 18:39:42 +0000
treeherdermozilla-release@d33428174ff1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas
bugs997551
milestone31.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 997551 - Avoid copying data in GetSourceSurfaceForSurface whenever possible. r=Bas
gfx/2d/DrawTargetD2D.cpp
gfx/2d/DrawTargetD2D1.cpp
gfx/thebes/gfxPlatform.cpp
--- a/gfx/2d/DrawTargetD2D.cpp
+++ b/gfx/2d/DrawTargetD2D.cpp
@@ -1217,17 +1217,17 @@ DrawTargetD2D::OptimizeSourceSurface(Sou
   }
 
   RefPtr<SourceSurfaceD2D> newSurf = new SourceSurfaceD2D();
   bool success = newSurf->InitFromData(map.mData, data->GetSize(), map.mStride, data->GetFormat(), mRT);
 
   data->Unmap();
 
   if (!success) {
-    return nullptr;
+    return data;
   }
   return newSurf;
 }
 
 TemporaryRef<SourceSurface>
 DrawTargetD2D::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
 {
   if (aSurface.mType != NativeSurfaceType::D3D10_TEXTURE) {
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -938,17 +938,17 @@ DrawTargetD2D1::OptimizeSourceSurface(So
   RefPtr<ID2D1Bitmap1> bitmap;
   HRESULT hr = mDC->CreateBitmap(D2DIntSize(data->GetSize()), map.mData, map.mStride,
                                  D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_NONE, D2DPixelFormat(data->GetFormat())),
                                  byRef(bitmap));
 
   data->Unmap();
 
   if (!bitmap) {
-    return nullptr;
+    return data;
   }
 
   return new SourceSurfaceD2D1(bitmap.get(), mDC, data->GetFormat(), data->GetSize());
 }
 
 void
 DrawTargetD2D1::PushD2DLayer(ID2D1DeviceContext *aDC, ID2D1Geometry *aGeometry, const D2D1_MATRIX_3X2_F &aTransform)
 {
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -749,86 +749,36 @@ gfxPlatform::GetSourceSurfaceForSurface(
       // keeping it creates a cycle.
       return srcBuffer;
     }
   }
 
   if (!srcBuffer) {
     nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
 
-    RefPtr<DataSourceSurface> copy;
-    if (!imgSurface) {
-      copy = CopySurface(aSurface);
+    RefPtr<DataSourceSurface> dataSurf;
 
-      if (!copy) {
-        return nullptr;
-      }
-
-      DataSourceSurface::MappedSurface map;
-      DebugOnly<bool> result = copy->Map(DataSourceSurface::WRITE, &map);
-      MOZ_ASSERT(result, "Should always succeed mapping raw data surfaces!");
-
-      imgSurface = new gfxImageSurface(map.mData, aSurface->GetSize(), map.mStride,
-                                       SurfaceFormatToImageFormat(copy->GetFormat()));
+    if (imgSurface) {
+      dataSurf = GetWrappedDataSourceSurface(aSurface);
+    } else {
+      dataSurf = CopySurface(aSurface);
     }
 
-    gfxImageFormat cairoFormat = imgSurface->Format();
-    switch(cairoFormat) {
-      case gfxImageFormat::ARGB32:
-        format = SurfaceFormat::B8G8R8A8;
-        break;
-      case gfxImageFormat::RGB24:
-        format = SurfaceFormat::B8G8R8X8;
-        break;
-      case gfxImageFormat::A8:
-        format = SurfaceFormat::A8;
-        break;
-      case gfxImageFormat::RGB16_565:
-        format = SurfaceFormat::R5G6B5;
-        break;
-      default:
-        NS_RUNTIMEABORT("Invalid surface format!");
-    }
-
-    IntSize size = IntSize(imgSurface->GetSize().width, imgSurface->GetSize().height);
-    srcBuffer = aTarget->CreateSourceSurfaceFromData(imgSurface->Data(),
-                                                     size,
-                                                     imgSurface->Stride(),
-                                                     format);
-
-    if (copy) {
-      copy->Unmap();
-    }
-
-    if (!srcBuffer) {
-      // If we had to make a copy, then just return that. Otherwise aSurface
-      // must have supported GetAsImageSurface, so we can just wrap that data.
-      if (copy) {
-        srcBuffer = copy;
-      } else {
-        return GetWrappedDataSourceSurface(aSurface);
-      }
-    }
-
-    if (!srcBuffer) {
+    if (!dataSurf) {
       return nullptr;
     }
 
-#if MOZ_TREE_CAIRO
-    cairo_surface_t *nullSurf =
-    cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
-    cairo_surface_set_user_data(nullSurf,
-                                &kSourceSurface,
-                                imgSurface,
-                                nullptr);
-    cairo_surface_attach_snapshot(imgSurface->CairoSurface(), nullSurf, SourceSnapshotDetached);
-    cairo_surface_destroy(nullSurf);
-#else
-    cairo_surface_set_mime_data(imgSurface->CairoSurface(), "mozilla/magic", (const unsigned char*) "data", 4, SourceSnapshotDetached, imgSurface.get());
-#endif
+    srcBuffer = aTarget->OptimizeSourceSurface(dataSurf);
+
+    if (imgSurface && srcBuffer == dataSurf) {
+      // Our wrapping surface will hold a reference to its image surface. We cause
+      // a reference cycle if we add it to the cache. And caching it is pretty
+      // pointless since we'll just wrap it again next use.
+     return srcBuffer;
+    }
   }
 
   // Add user data to aSurface so we can cache lookups in the future.
   SourceSurfaceUserData *srcSurfUD = new SourceSurfaceUserData;
   srcSurfUD->mBackendType = aTarget->GetType();
   srcSurfUD->mSrcSurface = srcBuffer;
   aSurface->SetData(&kSourceSurface, srcSurfUD, SourceBufferDestroy);