Bug 1504699 - Part 4. Add method to SharedSurfacesChild to cast to a shared surface. r=nical
authorAndrew Osmond <aosmond@mozilla.com>
Mon, 01 Oct 2018 14:47:17 -0400
changeset 503960 0c50877a2132bc8bcbcdee8ddb8dce13913c1c80
parent 503959 0871bc2a309c9df65ff41d27b6615e51201cad0d
child 503961 a687664414491ef27cbca5060c83443814fb0693
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1504699
milestone65.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 1504699 - Part 4. Add method to SharedSurfacesChild to cast to a shared surface. r=nical Differential Revision: https://phabricator.services.mozilla.com/D10900
gfx/2d/2D.h
gfx/2d/Types.h
gfx/layers/ipc/SharedSurfacesChild.cpp
gfx/layers/ipc/SharedSurfacesChild.h
image/imgFrame.cpp
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -398,17 +398,18 @@ public:
 
   /**
    * This function will return true if the surface type matches that of a
    * DataSourceSurface and if GetDataSurface will return the same object.
    */
   bool IsDataSourceSurface() const {
     SurfaceType type = GetType();
     return type == SurfaceType::DATA ||
-           type == SurfaceType::DATA_SHARED;
+           type == SurfaceType::DATA_SHARED ||
+           type == SurfaceType::DATA_RECYCLING_SHARED;
   }
 
   /**
    * This function will get a DataSourceSurface for this surface, a
    * DataSourceSurface's data can be accessed directly.
    */
   virtual already_AddRefed<DataSourceSurface> GetDataSurface() = 0;
 
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -28,17 +28,18 @@ enum class SurfaceType : int8_t {
   COREGRAPHICS_IMAGE, /* Surface wrapping a CoreGraphics Image */
   COREGRAPHICS_CGCONTEXT, /* Surface wrapping a CG context */
   SKIA, /* Surface wrapping a Skia bitmap */
   DUAL_DT, /* Snapshot of a dual drawtarget */
   D2D1_1_IMAGE, /* A D2D 1.1 ID2D1Image SourceSurface */
   RECORDING, /* Surface used for recording */
   TILED, /* Surface from a tiled DrawTarget */
   DATA_SHARED, /* Data surface using shared memory */
-  CAPTURE /* Data from a DrawTargetCapture */
+  CAPTURE, /* Data from a DrawTargetCapture */
+  DATA_RECYCLING_SHARED /* Data surface using shared memory */
 };
 
 enum class SurfaceFormat : int8_t {
   // The following values are named to reflect layout of colors in memory, from
   // lowest byte to highest byte. The 32-bit value layout depends on machine
   // endianness.
   //               in-memory            32-bit LE value   32-bit BE value
   B8G8R8A8,     // [BB, GG, RR, AA]     0xAARRGGBB        0xBBGGRRAA
--- a/gfx/layers/ipc/SharedSurfacesChild.cpp
+++ b/gfx/layers/ipc/SharedSurfacesChild.cpp
@@ -3,16 +3,17 @@
 /* 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 "SharedSurfacesChild.h"
 #include "SharedSurfacesParent.h"
 #include "CompositorManagerChild.h"
 #include "mozilla/gfx/gfxVars.h"
+#include "mozilla/image/RecyclingSourceSurface.h"
 #include "mozilla/layers/SourceSurfaceSharedData.h"
 #include "mozilla/layers/WebRenderBridgeChild.h"
 #include "mozilla/layers/WebRenderLayerManager.h"
 #include "mozilla/SystemGroup.h"        // for SystemGroup
 
 namespace mozilla {
 namespace layers {
 
@@ -151,16 +152,34 @@ SharedSurfacesChild::SharedUserData::Upd
     ImageKeyData data(aManager, key);
     mKeys.AppendElement(std::move(data));
     aResources.AddExternalImage(mId, key);
   }
 
   return key;
 }
 
+/* static */ SourceSurfaceSharedData*
+SharedSurfacesChild::AsSourceSurfaceSharedData(SourceSurface* aSurface)
+{
+  MOZ_ASSERT(aSurface);
+  switch (aSurface->GetType()) {
+    case SurfaceType::DATA_SHARED:
+      return static_cast<SourceSurfaceSharedData*>(aSurface);
+    case SurfaceType::DATA_RECYCLING_SHARED: {
+      auto recycleSurface =
+        static_cast<image::RecyclingSourceSurface*>(aSurface);
+      auto childSurface = recycleSurface->GetChildSurface();
+      return static_cast<SourceSurfaceSharedData*>(childSurface);
+    }
+    default:
+      return nullptr;
+  }
+}
+
 /* static */ void
 SharedSurfacesChild::DestroySharedUserData(void* aClosure)
 {
   MOZ_ASSERT(aClosure);
   auto data = static_cast<SharedUserData*>(aClosure);
   delete data;
 }
 
@@ -333,44 +352,44 @@ SharedSurfacesChild::Share(ImageContaine
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   RefPtr<gfx::SourceSurface> surface = images[0].mImage->GetAsSourceSurface();
   if (!surface) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
-  if (surface->GetType() != SurfaceType::DATA_SHARED) {
+  auto sharedSurface = AsSourceSurfaceSharedData(surface);
+  if (!sharedSurface) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
-  auto sharedSurface = static_cast<SourceSurfaceSharedData*>(surface.get());
   SharedSurfacesAnimation* anim = aContainer->GetSharedSurfacesAnimation();
   if (anim) {
     return anim->UpdateKey(surface, sharedSurface, aManager, aResources, aKey);
   }
 
   return Share(sharedSurface, aManager, aResources, aKey);
 }
 
 /* static */ nsresult
 SharedSurfacesChild::Share(SourceSurface* aSurface,
                            wr::ExternalImageId& aId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aSurface);
 
-  if (aSurface->GetType() != SurfaceType::DATA_SHARED) {
+  auto sharedSurface = AsSourceSurfaceSharedData(aSurface);
+  if (!sharedSurface) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // The external image ID does not change with the invalidation counter. The
   // caller of this should be aware of the invalidations of the surface through
   // another mechanism (e.g. imgRequestProxy listener notifications).
-  auto sharedSurface = static_cast<SourceSurfaceSharedData*>(aSurface);
   SharedUserData* data = nullptr;
   nsresult rv = ShareInternal(sharedSurface, &data);
   if (NS_SUCCEEDED(rv)) {
     MOZ_ASSERT(data);
     aId = data->Id();
   }
 
   return rv;
@@ -438,26 +457,26 @@ SharedSurfacesChild::UpdateAnimation(Ima
                                      const IntRect& aDirtyRect)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aContainer);
   MOZ_ASSERT(!aContainer->IsAsync());
   MOZ_ASSERT(aSurface);
 
   // If we aren't using shared surfaces, then is nothing to do.
-  if (aSurface->GetType() != SurfaceType::DATA_SHARED) {
+  auto sharedSurface = SharedSurfacesChild::AsSourceSurfaceSharedData(aSurface);
+  if (!sharedSurface) {
     MOZ_ASSERT(!aContainer->GetSharedSurfacesAnimation());
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   SharedSurfacesAnimation* anim =
     aContainer->EnsureSharedSurfacesAnimation();
   MOZ_ASSERT(anim);
 
-  auto sharedSurface = static_cast<SourceSurfaceSharedData*>(aSurface);
   return anim->SetCurrentFrame(aSurface, sharedSurface, aDirtyRect);
 }
 
 nsresult
 SharedSurfacesAnimation::SetCurrentFrame(SourceSurface* aParentSurface,
                                          SourceSurfaceSharedData* aSurface,
                                          const gfx::IntRect& aDirtyRect)
 {
--- a/gfx/layers/ipc/SharedSurfacesChild.h
+++ b/gfx/layers/ipc/SharedSurfacesChild.h
@@ -75,16 +75,23 @@ public:
 
   /**
    * Get the external ID, if any, bound to the shared surface. Used for memory
    * reporting purposes.
    */
   static Maybe<wr::ExternalImageId>
   GetExternalId(const gfx::SourceSurfaceSharedData* aSurface);
 
+  /**
+   * Get the surface (or its underlying surface) as a SourceSurfaceSharedData
+   * pointer, if valid.
+   */
+  static gfx::SourceSurfaceSharedData*
+  AsSourceSurfaceSharedData(gfx::SourceSurface* aSurface);
+
   static nsresult UpdateAnimation(ImageContainer* aContainer,
                                   gfx::SourceSurface* aSurface,
                                   const gfx::IntRect& aDirtyRect);
 
 private:
   SharedSurfacesChild() = delete;
   ~SharedSurfacesChild() = delete;
 
--- a/image/imgFrame.cpp
+++ b/image/imgFrame.cpp
@@ -930,17 +930,18 @@ imgFrame::FinalizeSurface()
 }
 
 void
 imgFrame::FinalizeSurfaceInternal()
 {
   mMonitor.AssertCurrentThreadOwns();
 
   // Not all images will have mRawSurface to finalize (i.e. paletted images).
-  if (!mRawSurface || mRawSurface->GetType() != SurfaceType::DATA_SHARED) {
+  if (mShouldRecycle || !mRawSurface ||
+      mRawSurface->GetType() != SurfaceType::DATA_SHARED) {
     return;
   }
 
   auto sharedSurf = static_cast<SourceSurfaceSharedData*>(mRawSurface.get());
   sharedSurf->Finalize();
 }
 
 already_AddRefed<SourceSurface>
@@ -1075,16 +1076,20 @@ imgFrame::AddSizeOfExcludingThis(MallocS
 
 RecyclingSourceSurface::RecyclingSourceSurface(imgFrame* aParent, DataSourceSurface* aSurface)
   : mParent(aParent)
   , mSurface(aSurface)
   , mType(SurfaceType::DATA)
 {
   mParent->mMonitor.AssertCurrentThreadOwns();
   ++mParent->mRecycleLockCount;
+
+  if (aSurface->GetType() == SurfaceType::DATA_SHARED) {
+    mType = SurfaceType::DATA_RECYCLING_SHARED;
+  }
 }
 
 RecyclingSourceSurface::~RecyclingSourceSurface()
 {
   MonitorAutoLock lock(mParent->mMonitor);
   MOZ_ASSERT(mParent->mRecycleLockCount > 0);
   if (--mParent->mRecycleLockCount == 0) {
     mParent->mMonitor.NotifyAll();