Bug 1331938 - Part 1. Add SourceSurfaceVolatileData, a volatile data backed DataSourceSurface. r=nical
authorAndrew Osmond <aosmond@mozilla.com>
Wed, 18 Jan 2017 08:38:02 -0500
changeset 468833 faa107ec149b0517fe2d54d5e1724dbaa25732e8
parent 468832 60b3df69c5a9e204c9da031e6b515c9b9b8cc391
child 468834 20978572be888eff89432a173cca7458b0fe2ae2
push id43551
push userbmo:kgilbert@mozilla.com
push dateTue, 31 Jan 2017 23:27:06 +0000
reviewersnical
bugs1331938
milestone54.0a1
Bug 1331938 - Part 1. Add SourceSurfaceVolatileData, a volatile data backed DataSourceSurface. r=nical
gfx/2d/2D.h
gfx/layers/SourceSurfaceVolatileData.cpp
gfx/layers/SourceSurfaceVolatileData.h
gfx/layers/moz.build
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -490,16 +490,34 @@ public:
   }
 
   /**
    * Returns a DataSourceSurface with the same data as this one, but
    * guaranteed to have surface->GetType() == SurfaceType::DATA.
    */
   virtual already_AddRefed<DataSourceSurface> GetDataSurface() override;
 
+  /**
+   * Add the size of the underlying data buffer to the aggregate.
+   */
+  virtual void AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
+                                      size_t& aHeapSizeOut,
+                                      size_t& aNonHeapSizeOut) const
+  {
+  }
+
+  /**
+   * Returns whether or not the data was allocated on the heap. This should
+   * be used to determine if the memory needs to be cleared to 0.
+   */
+  virtual bool OnHeap() const
+  {
+    return true;
+  }
+
 protected:
   bool mIsMapped;
 };
 
 /** This is an abstract object that accepts path segments. */
 class PathSink : public RefCounted<PathSink>
 {
 public:
new file mode 100644
--- /dev/null
+++ b/gfx/layers/SourceSurfaceVolatileData.cpp
@@ -0,0 +1,52 @@
+/* -*- 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 "SourceSurfaceVolatileData.h"
+
+#include "gfxAlphaRecovery.h"
+#include "mozilla/Likely.h"
+#include "mozilla/Types.h" // for decltype
+
+namespace mozilla {
+namespace gfx {
+
+bool
+SourceSurfaceVolatileData::Init(const IntSize &aSize,
+                                int32_t aStride,
+                                SurfaceFormat aFormat)
+{
+  mSize = aSize;
+  mStride = aStride;
+  mFormat = aFormat;
+
+  size_t alignment = size_t(1) << gfxAlphaRecovery::GoodAlignmentLog2();
+  mVBuf = new VolatileBuffer();
+  if (MOZ_UNLIKELY(!mVBuf->Init(aStride * aSize.height, alignment))) {
+    mVBuf = nullptr;
+    return false;
+  }
+
+  return true;
+}
+
+void
+SourceSurfaceVolatileData::GuaranteePersistance()
+{
+  MOZ_ASSERT_UNREACHABLE("Should use SourceSurfaceRawData wrapper!");
+}
+
+void
+SourceSurfaceVolatileData::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
+                                                  size_t& aHeapSizeOut,
+                                                  size_t& aNonHeapSizeOut) const
+{
+  if (mVBuf) {
+    aHeapSizeOut += mVBuf->HeapSizeOfExcludingThis(aMallocSizeOf);
+    aNonHeapSizeOut += mVBuf->NonHeapSizeOfExcludingThis();
+  }
+}
+
+} // namespace gfx
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/SourceSurfaceVolatileData.h
@@ -0,0 +1,108 @@
+/* -*- 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_SOURCESURFACEVOLATILEDATA_H_
+#define MOZILLA_GFX_SOURCESURFACEVOLATILEDATA_H_
+
+#include "mozilla/gfx/2D.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/VolatileBuffer.h"
+
+namespace mozilla {
+namespace gfx {
+
+/**
+ * This class is used to wrap volatile data buffers used for source surfaces.
+ * The Map and Unmap semantics are used to guarantee that the volatile data
+ * buffer is not freed by the operating system while the surface is in active
+ * use. If GetData is expected to return a non-null value without a
+ * corresponding Map call (and verification of the result), the surface data
+ * should be wrapped in a temporary SourceSurfaceRawData with a ScopedMap
+ * closure.
+ */
+class SourceSurfaceVolatileData : public DataSourceSurface
+{
+public:
+  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceVolatileData, override)
+
+  SourceSurfaceVolatileData()
+    : mMutex("SourceSurfaceVolatileData")
+    , mStride(0)
+    , mMapCount(0)
+    , mFormat(SurfaceFormat::UNKNOWN)
+  {
+  }
+
+  bool Init(const IntSize &aSize,
+            int32_t aStride,
+            SurfaceFormat aFormat);
+
+  uint8_t *GetData() override { return mVBufPtr; }
+  int32_t Stride() override { return mStride; }
+
+  SurfaceType GetType() const override { return SurfaceType::DATA; }
+  IntSize GetSize() const override { return mSize; }
+  SurfaceFormat GetFormat() const override { return mFormat; }
+
+  void GuaranteePersistance() override;
+
+  void AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
+                              size_t& aHeapSizeOut,
+                              size_t& aNonHeapSizeOut) const override;
+
+  bool OnHeap() const override
+  {
+    return mVBuf->OnHeap();
+  }
+
+  // Althought Map (and Moz2D in general) isn't normally threadsafe,
+  // we want to allow it for SourceSurfaceVolatileData since it should
+  // always be fine (for reading at least).
+  //
+  // This is the same as the base class implementation except using
+  // mMapCount instead of mIsMapped since that breaks for multithread.
+  bool Map(MapType, MappedSurface *aMappedSurface) override
+  {
+    MutexAutoLock lock(mMutex);
+    if (mMapCount == 0) {
+      mVBufPtr = mVBuf;
+    }
+    if (mVBufPtr.WasBufferPurged()) {
+      return false;
+    }
+    aMappedSurface->mData = mVBufPtr;
+    aMappedSurface->mStride = mStride;
+    ++mMapCount;
+    return true;
+  }
+
+  void Unmap() override
+  {
+    MutexAutoLock lock(mMutex);
+    MOZ_ASSERT(mMapCount > 0);
+    if (--mMapCount == 0) {
+      mVBufPtr = nullptr;
+    }
+  }
+
+private:
+  ~SourceSurfaceVolatileData() override
+  {
+    MOZ_ASSERT(mMapCount == 0);
+  }
+
+  Mutex mMutex;
+  int32_t mStride;
+  int32_t mMapCount;
+  IntSize mSize;
+  RefPtr<VolatileBuffer> mVBuf;
+  VolatileBufferPtr<uint8_t> mVBufPtr;
+  SurfaceFormat mFormat;
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif /* MOZILLA_GFX_SOURCESURFACEVOLATILEDATA_H_ */
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -196,16 +196,17 @@ EXPORTS.mozilla.layers += [
     'opengl/CompositingRenderTargetOGL.h',
     'opengl/CompositorOGL.h',
     'opengl/MacIOSurfaceTextureClientOGL.h',
     'opengl/MacIOSurfaceTextureHostOGL.h',
     'opengl/TextureClientOGL.h',
     'opengl/TextureHostOGL.h',
     'PersistentBufferProvider.h',
     'RenderTrace.h',
+    'SourceSurfaceVolatileData.h',
     'TextureWrapperImage.h',
     'TransactionIdAllocator.h',
 ]
 
 if CONFIG['MOZ_X11']:
     EXPORTS.mozilla.layers += [
         'basic/TextureClientX11.h',
         'basic/X11TextureSourceBasic.h',
@@ -368,16 +369,17 @@ UNIFIED_SOURCES += [
     'opengl/TextureClientOGL.cpp',
     'opengl/TextureHostOGL.cpp',
     'opengl/TexturePoolOGL.cpp',
     'protobuf/LayerScopePacket.pb.cc',
     'ReadbackProcessor.cpp',
     'RenderTrace.cpp',
     'RotatedBuffer.cpp',
     'ShareableCanvasLayer.cpp',
+    'SourceSurfaceVolatileData.cpp',
     'TextureWrapperImage.cpp',
 ]
 
 SOURCES += [
     'basic/BasicImageLayer.cpp',
     'ImageContainer.cpp',
     'Layers.cpp',
     'LayerTreeInvalidation.cpp',