Bug 1072501: Unmap file mapping on source surface destruction. r=jrmuizel
☠☠ backed out by d11cceb2f732 ☠ ☠
authorBas Schouten <bschouten@mozilla.com>
Tue, 01 Dec 2015 16:41:08 +0100
changeset 297673 975af6bc574f57965594fe21fab64861212417e9
parent 297672 aad9086f8efdb9b6b049234c13c0c0fd261a8c79
child 297674 68a913a7d737eec7f06cfffdd8bdcc83a9864a09
push id8824
push userraliiev@mozilla.com
push dateMon, 14 Dec 2015 20:18:56 +0000
treeherdermozilla-aurora@e2031358e2a6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1072501
milestone45.0a1
Bug 1072501: Unmap file mapping on source surface destruction. r=jrmuizel
gfx/layers/TextureDIB.cpp
gfx/layers/TextureDIB.h
gfx/layers/client/TextureClient.cpp
--- a/gfx/layers/TextureDIB.cpp
+++ b/gfx/layers/TextureDIB.cpp
@@ -23,16 +23,18 @@ class MemoryDIBTextureData : public DIBT
 public:
   virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
 
   virtual TextureData*
   CreateSimilar(ISurfaceAllocator* aAllocator,
                 TextureFlags aFlags = TextureFlags::DEFAULT,
                 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
 
+  virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
+
   static
   DIBTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat);
 
   virtual void Deallocate(ISurfaceAllocator* aAllocator) override
   {
     mSurface = nullptr;
   }
 
@@ -58,16 +60,18 @@ class ShmemDIBTextureData : public DIBTe
 public:
   virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
 
   virtual TextureData*
   CreateSimilar(ISurfaceAllocator* aAllocator,
                 TextureFlags aFlags = TextureFlags::DEFAULT,
                 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
 
+  virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
+
   static
   DIBTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                          ISurfaceAllocator* aAllocator);
 
   void DeallocateData()
   {
     if (mSurface) {
       ::DeleteObject(mBitmap);
@@ -110,41 +114,16 @@ public:
 };
 
 already_AddRefed<gfx::DrawTarget>
 DIBTextureData::BorrowDrawTarget()
 {
   return gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mSurface, mSize);
 }
 
-bool
-DIBTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
-{
-  RefPtr<gfxImageSurface> imgSurf = mSurface->GetAsImageSurface();
-
-  RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
-
-  if (!srcSurf) {
-    gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
-    return false;
-  }
-
-  DataSourceSurface::MappedSurface sourceMap;
-  srcSurf->Map(DataSourceSurface::READ, &sourceMap);
-
-  for (int y = 0; y < srcSurf->GetSize().height; y++) {
-    memcpy(imgSurf->Data() + imgSurf->Stride() * y,
-           sourceMap.mData + sourceMap.mStride * y,
-           srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
-  }
-
-  srcSurf->Unmap();
-  return true;
-}
-
 DIBTextureData*
 DIBTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                        ISurfaceAllocator* aAllocator)
 {
   if (!aAllocator) {
     return nullptr;
   }
   if (aFormat == gfx::SurfaceFormat::UNKNOWN) {
@@ -187,28 +166,96 @@ MemoryDIBTextureData::Create(gfx::IntSiz
   if (!surface || surface->CairoStatus()) {
     NS_WARNING("Could not create DIB surface");
     return nullptr;
   }
 
   return new MemoryDIBTextureData(aSize, aFormat, surface);
 }
 
+bool
+MemoryDIBTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
+{
+  RefPtr<gfxImageSurface> imgSurf = mSurface->GetAsImageSurface();
+
+  RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
+
+  if (!srcSurf) {
+    gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
+    return false;
+  }
+
+  DataSourceSurface::MappedSurface sourceMap;
+  if (!srcSurf->Map(gfx::DataSourceSurface::READ, &sourceMap)) {
+    gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
+    return false;
+  }
+
+  for (int y = 0; y < srcSurf->GetSize().height; y++) {
+    memcpy(imgSurf->Data() + imgSurf->Stride() * y,
+           sourceMap.mData + sourceMap.mStride * y,
+           srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
+  }
+
+  srcSurf->Unmap();
+  return true;
+}
+
 TextureData*
 ShmemDIBTextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
                                    TextureFlags aFlags,
                                    TextureAllocationFlags aAllocFlags) const
 {
   if (!aAllocator) {
     return nullptr;
   }
   return ShmemDIBTextureData::Create(mSize, mFormat, aAllocator);
 }
 
 bool
+ShmemDIBTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
+{
+
+  RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
+
+  if (!srcSurf) {
+    gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
+    return false;
+  }
+
+  DataSourceSurface::MappedSurface sourceMap;
+  if (!srcSurf->Map(gfx::DataSourceSurface::READ, &sourceMap)) {
+    gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
+    return false;
+  }
+
+  GdiFlush();
+
+  uint32_t stride = mSize.width * BytesPerPixel(mFormat);
+  uint8_t* data = (uint8_t*)::MapViewOfFile(mFileMapping, FILE_MAP_WRITE, 0, 0, stride * mSize.height);
+
+  if (!data) {
+    gfxCriticalError() << "Failed to map view of file for UpdateFromSurface.";
+    srcSurf->Unmap();
+    return false;
+  }
+
+  for (int y = 0; y < srcSurf->GetSize().height; y++) {
+    memcpy(data + stride * y,
+           sourceMap.mData + sourceMap.mStride * y,
+           srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
+  }
+
+  ::UnmapViewOfFile(data);
+
+  srcSurf->Unmap();
+  return true;
+}
+
+bool
 ShmemDIBTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
 {
   if (GetFormat() == gfx::SurfaceFormat::UNKNOWN) {
     return false;
   }
 
   ::GdiFlush();
   aOutDescriptor = SurfaceDescriptorFileMapping((WindowsHandle)mHostHandle, mFormat, mSize);
@@ -225,20 +272,19 @@ ShmemDIBTextureData::Create(gfx::IntSize
   HANDLE fileMapping = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, mapSize, NULL);
 
   if (!fileMapping) {
     gfxCriticalError() << "Failed to create memory file mapping for " << mapSize << " bytes.";
     return nullptr;
   }
 
   uint8_t* data = (uint8_t*)::MapViewOfFile(fileMapping, FILE_MAP_WRITE | FILE_MAP_READ,
-                                            0, 0, aSize.width * aSize.height
-                                                  * BytesPerPixel(aFormat));
+                                            0, 0, mapSize);
 
-  memset(data, 0x80, aSize.width * aSize.height * BytesPerPixel(aFormat));
+  memset(data, 0x80, mapSize);
 
   ::UnmapViewOfFile(fileMapping);
 
   BITMAPV4HEADER header;
   memset(&header, 0, sizeof(BITMAPV4HEADER));
   header.bV4Size          = sizeof(BITMAPV4HEADER);
   header.bV4Width         = aSize.width;
   header.bV4Height        = -LONG(aSize.height); // top-to-buttom DIB
@@ -387,16 +433,24 @@ TextureHostFileMapping::TextureHostFileM
 {
 }
 
 TextureHostFileMapping::~TextureHostFileMapping()
 {
   ::CloseHandle(mFileMapping);
 }
 
+UserDataKey kFileMappingKey;
+
+static void UnmapFileData(void* aData)
+{
+  MOZ_ASSERT(aData);
+  ::UnmapViewOfFile(aData);
+}
+
 void
 TextureHostFileMapping::UpdatedInternal(const nsIntRegion* aRegion)
 {
   if (!mCompositor) {
     // This can happen if we send textures to a compositable that isn't yet
     // attached to a layer.
     return;
   }
@@ -405,20 +459,20 @@ TextureHostFileMapping::UpdatedInternal(
     mTextureSource = mCompositor->CreateDataTextureSource(mFlags);
   }
 
   uint8_t* data = (uint8_t*)::MapViewOfFile(mFileMapping, FILE_MAP_READ, 0, 0, mSize.width * mSize.height * BytesPerPixel(mFormat));
 
   if (data) {
     RefPtr<DataSourceSurface> surf = Factory::CreateWrappingDataSourceSurface(data, mSize.width * BytesPerPixel(mFormat), mSize, mFormat);
 
+    surf->AddUserData(&kFileMappingKey, data, UnmapFileData);
+
     if (!mTextureSource->Update(surf, const_cast<nsIntRegion*>(aRegion))) {
       mTextureSource = nullptr;
     }
   } else {
     mTextureSource = nullptr;
   }
-
-  ::UnmapViewOfFile(data);
 }
 
 }
 }
--- a/gfx/layers/TextureDIB.h
+++ b/gfx/layers/TextureDIB.h
@@ -25,18 +25,16 @@ public:
   virtual gfx::IntSize GetSize() const override { return mSize; }
 
   virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
 
   virtual bool SupportsMoz2D() const override { return true; }
 
   virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
 
-  virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
-
   virtual bool HasInternalBuffer() const override { return true; }
 
   static
   DIBTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                          ISurfaceAllocator* aAllocator);
 
 protected:
   DIBTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -727,17 +727,16 @@ TextureClient::CreateForDrawing(Composit
       aSize.width <= maxTextureSize &&
       aSize.height <= maxTextureSize &&
       NS_IsMainThread() &&
       gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
     data = D3D9TextureData::Create(aSize, aFormat, aAllocFlags);
   }
 
   if (!data && aFormat == SurfaceFormat::B8G8R8X8 &&
-      aAllocator->IsSameProcess() &&
       moz2DBackend == gfx::BackendType::CAIRO &&
       NS_IsMainThread()) {
     data = DIBTextureData::Create(aSize, aFormat, aAllocator);
   }
 #endif
 
 #ifdef MOZ_X11
   gfxSurfaceType type =