Bug 959123 - Implement CairoImage::GetAsSourceSurface. r=nical
authorAli Akhtarzada <ali@comoyo.com>
Fri, 17 Jan 2014 11:22:09 -0500
changeset 164081 8c9e9d8c4c758156ae52609c25ed8090687db4a8
parent 164080 4230d328b65f25ca7398a9da4b2ff345e0600d6d
child 164082 3eb0b43bae64aab7a57a58c5f4612652a6d4d535
push id26026
push userphilringnalda@gmail.com
push dateSat, 18 Jan 2014 23:17:27 +0000
treeherdermozilla-central@61fd0f987cf2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs959123
milestone29.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 959123 - Implement CairoImage::GetAsSourceSurface. r=nical Deprecate CairoImage::Data::mSurface and add an mSourceSurface. Also change all the callers of CairoImage::SetData to set the SourceSurface as well. Also change scope of CairoImage::mSource to private
content/media/webrtc/MediaEngineTabVideoSource.cpp
dom/plugins/ipc/PluginInstanceParent.cpp
gfx/layers/ImageContainer.h
gfx/layers/d3d10/ImageLayerD3D10.cpp
gfx/layers/d3d9/ImageLayerD3D9.cpp
image/src/RasterImage.cpp
layout/base/FrameLayerBuilder.cpp
media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
--- a/content/media/webrtc/MediaEngineTabVideoSource.cpp
+++ b/content/media/webrtc/MediaEngineTabVideoSource.cpp
@@ -252,18 +252,19 @@ MediaEngineTabVideoSource::Draw() {
   gfxPoint pt(0, 0);
   context->Translate(pt);
   context->Scale(scale * size.width / srcW, scale * size.height / srcH);
   rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
 
   NS_ENSURE_SUCCESS_VOID(rv);
 
   layers::CairoImage::Data cairoData;
-  cairoData.mSurface = surf;
+  cairoData.mDeprecatedSurface = surf;
   cairoData.mSize = size;
+  cairoData.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surf);
 
   nsRefPtr<layers::CairoImage> image = new layers::CairoImage();
 
   image->SetData(cairoData);
 
   MonitorAutoLock mon(mMonitor);
   mImage = image;
 }
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -638,18 +638,19 @@ PluginInstanceParent::RecvShow(const NPR
         surface->MarkDirty(ur);
 
         ImageContainer *container = GetImageContainer();
         ImageFormat format = CAIRO_SURFACE;
         nsRefPtr<Image> image = container->CreateImage(&format, 1);
         NS_ASSERTION(image->GetFormat() == CAIRO_SURFACE, "Wrong format?");
         CairoImage* cairoImage = static_cast<CairoImage*>(image.get());
         CairoImage::Data cairoData;
-        cairoData.mSurface = surface;
+        cairoData.mDeprecatedSurface = surface;
         cairoData.mSize = surface->GetSize().ToIntSize();
+        cairoData.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surface);
         cairoImage->SetData(cairoData);
 
         container->SetCurrentImage(cairoImage);
     }
     else if (mImageContainer) {
         mImageContainer->SetCurrentImage(nullptr);
     }
 
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -36,16 +36,19 @@
  * or released off the main thread. We can ensure that we never AddRef
  * a gfxASurface off the main thread, but we might want to Release due
  * to an Image being destroyed off the main thread.
  *
  * We use nsCountedRef<nsMainThreadSurfaceRef> to reference the
  * gfxASurface. When AddRefing, we assert that we're on the main thread.
  * When Releasing, if we're not on the main thread, we post an event to
  * the main thread to do the actual release.
+ *
+ * This should be removed after after Image::DeprecatedGetAsSurface is
+ * removed. It is replaced by nsMainThreadSourceSurfaceRef
  */
 class nsMainThreadSurfaceRef;
 
 template <>
 class nsAutoRefTraits<nsMainThreadSurfaceRef> {
 public:
   typedef gfxASurface* RawRef;
 
@@ -75,16 +78,59 @@ public:
   static void AddRef(RawRef aRawRef)
   {
     NS_ASSERTION(NS_IsMainThread(),
                  "Can only add a reference on the main thread");
     aRawRef->AddRef();
   }
 };
 
+/**
+ * Same purpose as nsMainThreadSurfaceRef byt holds a gfx::SourceSurface instead.
+ * The specialization of nsMainThreadSurfaceRef should be removed after
+ * Image::DeprecatedGetAsSurface is removed
+ */
+class nsMainThreadSourceSurfaceRef;
+
+template <>
+class nsAutoRefTraits<nsMainThreadSourceSurfaceRef> {
+public:
+  typedef mozilla::gfx::SourceSurface* RawRef;
+
+  /**
+   * The XPCOM event that will do the actual release on the main thread.
+   */
+  class SurfaceReleaser : public nsRunnable {
+  public:
+    SurfaceReleaser(RawRef aRef) : mRef(aRef) {}
+    NS_IMETHOD Run() {
+      mRef->Release();
+      return NS_OK;
+    }
+    RawRef mRef;
+  };
+
+  static RawRef Void() { return nullptr; }
+  static void Release(RawRef aRawRef)
+  {
+    if (NS_IsMainThread()) {
+      aRawRef->Release();
+      return;
+    }
+    nsCOMPtr<nsIRunnable> runnable = new SurfaceReleaser(aRawRef);
+    NS_DispatchToMainThread(runnable);
+  }
+  static void AddRef(RawRef aRawRef)
+  {
+    NS_ASSERTION(NS_IsMainThread(),
+                 "Can only add a reference on the main thread");
+    aRawRef->AddRef();
+  }
+};
+
 #endif
 
 #ifdef XP_WIN
 struct ID3D10Texture2D;
 struct ID3D10Device;
 struct ID3D10ShaderResourceView;
 #endif
 
@@ -872,44 +918,59 @@ protected:
 /**
  * Currently, the data in a CairoImage surface is treated as being in the
  * device output color space. This class is very simple as all backends
  * have to know about how to deal with drawing a cairo image.
  */
 class CairoImage : public Image {
 public:
   struct Data {
-    gfxASurface* mSurface;
+    gfxASurface* mDeprecatedSurface;
     gfx::IntSize mSize;
+
+    // mSourceSurface wraps mDeprrecatedSurface's data, therefore it should not
+    // outlive mDeprecatedSurface
+    RefPtr<gfx::SourceSurface> mSourceSurface;
   };
 
   /**
    * This can only be called on the main thread. It may add a reference
    * to the surface (which will eventually be released on the main thread).
    * The surface must not be modified after this call!!!
    */
   void SetData(const Data& aData)
   {
-    mSurface = aData.mSurface;
+    mDeprecatedSurface = aData.mDeprecatedSurface;
     mSize = aData.mSize;
+    mSourceSurface = aData.mSourceSurface;
   }
 
+  virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface()
+  {
+    return mSourceSurface.get();
+  }
 
   virtual already_AddRefed<gfxASurface> DeprecatedGetAsSurface()
   {
-    nsRefPtr<gfxASurface> surface = mSurface.get();
+    nsRefPtr<gfxASurface> surface = mDeprecatedSurface.get();
     return surface.forget();
   }
 
   gfx::IntSize GetSize() { return mSize; }
 
   CairoImage() : Image(nullptr, CAIRO_SURFACE) {}
 
-  nsCountedRef<nsMainThreadSurfaceRef> mSurface;
+private:
+
+  nsCountedRef<nsMainThreadSurfaceRef> mDeprecatedSurface;
   gfx::IntSize mSize;
+
+  // mSourceSurface wraps mDeprrecatedSurface's data, therefore it should not
+  // outlive mDeprecatedSurface
+  nsCountedRef<nsMainThreadSourceSurfaceRef> mSourceSurface;
 };
 
 class RemoteBitmapImage : public Image {
 public:
   RemoteBitmapImage() : Image(nullptr, REMOTE_IMAGE_BITMAP) {}
 
   already_AddRefed<gfxASurface> DeprecatedGetAsSurface();
 
--- a/gfx/layers/d3d10/ImageLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ImageLayerD3D10.cpp
@@ -122,31 +122,32 @@ ImageLayerD3D10::GetImageSRView(Image* a
 
     remoteImage->GetD3D10TextureBackendData(device());
 
     aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
   } else if (aImage->GetFormat() == ImageFormat::CAIRO_SURFACE) {
     CairoImage *cairoImage =
       static_cast<CairoImage*>(aImage);
 
-    if (!cairoImage->mSurface) {
+    nsRefPtr<gfxASurface> surf = cairoImage->DeprecatedGetAsSurface();
+    if (!surf) {
       return nullptr;
     }
 
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D10)) {
       nsAutoPtr<TextureD3D10BackendData> dat(new TextureD3D10BackendData());
-      dat->mTexture = SurfaceToTexture(device(), cairoImage->mSurface, cairoImage->mSize);
+      dat->mTexture = SurfaceToTexture(device(), surf, cairoImage->GetSize());
 
       if (dat->mTexture) {
         device()->CreateShaderResourceView(dat->mTexture, nullptr, getter_AddRefs(dat->mSRView));
         aImage->SetBackendData(mozilla::layers::LAYERS_D3D10, dat.forget());
       }
     }
 
-    aHasAlpha = cairoImage->mSurface->GetContentType() == GFX_CONTENT_COLOR_ALPHA;
+    aHasAlpha = surf->GetContentType() == GFX_CONTENT_COLOR_ALPHA;
   } else if (aImage->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) {
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D10)) {
       // Use resource sharing to open the D3D9 texture as a D3D10 texture,
       HRESULT hr;
       D3D9SurfaceImage* d3dImage = reinterpret_cast<D3D9SurfaceImage*>(aImage);
       nsRefPtr<ID3D10Texture2D> texture;
       hr = device()->OpenSharedResource(d3dImage->GetShareHandle(),
                                         IID_ID3D10Texture2D,
@@ -207,24 +208,24 @@ ImageLayerD3D10::RenderLayer()
   }
 
   IntSize size = image->GetSize();
 
   SetEffectTransformAndOpacity();
 
   ID3D10EffectTechnique *technique;
   nsRefPtr<IDXGIKeyedMutex> keyedMutex;
+  nsRefPtr<gfxASurface> surf = image->DeprecatedGetAsSurface();
 
   if (image->GetFormat() == ImageFormat::CAIRO_SURFACE ||
       image->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP ||
       image->GetFormat() == ImageFormat::REMOTE_IMAGE_DXGI_TEXTURE ||
       image->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) {
     NS_ASSERTION(image->GetFormat() != ImageFormat::CAIRO_SURFACE ||
-                 !static_cast<CairoImage*>(image)->mSurface ||
-                 static_cast<CairoImage*>(image)->mSurface->GetContentType() != GFX_CONTENT_ALPHA,
+                 !surf || surf->GetContentType() != GFX_CONTENT_ALPHA,
                  "Image layer has alpha image");
     bool hasAlpha = false;
 
     nsRefPtr<ID3D10ShaderResourceView> srView = GetImageSRView(image, hasAlpha, getter_AddRefs(keyedMutex));
     if (!srView) {
       return;
     }
 
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -339,29 +339,30 @@ ImageLayerD3D9::GetTexture(Image *aImage
       }
     }
 
     aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
   } else if (aImage->GetFormat() == CAIRO_SURFACE) {
     CairoImage *cairoImage =
       static_cast<CairoImage*>(aImage);
 
-    if (!cairoImage->mSurface) {
+    nsRefPtr<gfxASurface> surf = cairoImage->DeprecatedGetAsSurface();
+    if (!surf) {
       return nullptr;
     }
 
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D9)) {
       nsAutoPtr<TextureD3D9BackendData> dat(new TextureD3D9BackendData());
-      dat->mTexture = SurfaceToTexture(device(), cairoImage->mSurface, cairoImage->mSize);
+      dat->mTexture = SurfaceToTexture(device(), surf, cairoImage->GetSize());
       if (dat->mTexture) {
         aImage->SetBackendData(mozilla::layers::LAYERS_D3D9, dat.forget());
       }
     }
 
-    aHasAlpha = cairoImage->mSurface->GetContentType() == GFX_CONTENT_COLOR_ALPHA;
+    aHasAlpha = surf->GetContentType() == GFX_CONTENT_COLOR_ALPHA;
   } else if (aImage->GetFormat() == D3D9_RGB32_TEXTURE) {
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D9)) {
       // The texture in which the frame is stored belongs to DXVA's D3D9 device.
       // We need to open it on our device before we can use it.
       nsAutoPtr<TextureD3D9BackendData> backendData(new TextureD3D9BackendData());
       D3D9SurfaceImage* image = static_cast<D3D9SurfaceImage*>(aImage);
       backendData->mTexture = OpenSharedTexture(image->GetDesc(), image->GetShareHandle(), device());
       if (backendData->mTexture) {
@@ -408,19 +409,19 @@ ImageLayerD3D9::RenderLayer()
   SetShaderTransformAndOpacity();
 
   gfx::IntSize size = image->GetSize();
 
   if (image->GetFormat() == CAIRO_SURFACE ||
       image->GetFormat() == REMOTE_IMAGE_BITMAP ||
       image->GetFormat() == D3D9_RGB32_TEXTURE)
   {
+    nsRefPtr<gfxASurface> surf = image->DeprecatedGetAsSurface();
     NS_ASSERTION(image->GetFormat() != CAIRO_SURFACE ||
-                 !static_cast<CairoImage*>(image)->mSurface ||
-                 static_cast<CairoImage*>(image)->mSurface->GetContentType() != GFX_CONTENT_ALPHA,
+                 !surf || surf->GetContentType() != GFX_CONTENT_ALPHA,
                  "Image layer has alpha image");
 
     bool hasAlpha = false;
     nsRefPtr<IDirect3DTexture9> texture = GetTexture(image, hasAlpha);
 
     device()->SetVertexShaderConstantF(CBvLayerQuad,
                                        ShaderConstantRect(0,
                                                           0,
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -948,19 +948,20 @@ RasterImage::GetCurrentImage()
   nsRefPtr<gfxASurface> imageSurface = GetFrame(FRAME_CURRENT, FLAG_NONE);
   NS_ENSURE_TRUE(imageSurface, nullptr);
 
   if (!mImageContainer) {
     mImageContainer = LayerManager::CreateImageContainer();
   }
 
   CairoImage::Data cairoData;
-  cairoData.mSurface = imageSurface;
+  cairoData.mDeprecatedSurface = imageSurface;
   GetWidth(&cairoData.mSize.width);
   GetHeight(&cairoData.mSize.height);
+  cairoData.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, imageSurface);
 
   ImageFormat cairoFormat = CAIRO_SURFACE;
   nsRefPtr<layers::Image> image = mImageContainer->CreateImage(&cairoFormat, 1);
   NS_ASSERTION(image, "Failed to create Image");
 
   NS_ASSERTION(image->GetFormat() == cairoFormat, "Wrong format");
   static_cast<CairoImage*>(image.get())->SetData(cairoData);
 
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -3813,18 +3813,19 @@ ContainerState::SetupMaskLayer(Layer *aL
 
     // build the image and container
     container = aLayer->Manager()->CreateImageContainer();
     NS_ASSERTION(container, "Could not create image container for mask layer.");
     static const ImageFormat format = CAIRO_SURFACE;
     nsRefPtr<Image> image = container->CreateImage(&format, 1);
     NS_ASSERTION(image, "Could not create image container for mask layer.");
     CairoImage::Data data;
-    data.mSurface = surface;
+    data.mDeprecatedSurface = surface;
     data.mSize = surfaceSizeInt;
+    data.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surface);
     static_cast<CairoImage*>(image.get())->SetData(data);
     container->SetCurrentImageInTransaction(image);
 
     GetMaskLayerImageCache()->PutImage(newKey.forget(), container);
   }
 
   maskLayer->SetContainer(container);
 
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
@@ -35,16 +35,17 @@
 #include "transportflow.h"
 #include "transportlayer.h"
 #include "transportlayerdtls.h"
 #include "transportlayerice.h"
 #include "runnable_utils.h"
 #include "gfxImageSurface.h"
 #include "libyuv/convert.h"
 #include "mozilla/gfx/Point.h"
+#include "mozilla/gfx/Types.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 // Logging context
 MOZ_MTLOG_MODULE("mediapipeline")
 
 namespace mozilla {
@@ -956,37 +957,35 @@ void MediaPipelineTransmit::PipelineList
     int c_size = half_width * half_height;
     int buffer_size = size.width * size.height + 2 * c_size;
     uint8* yuv = (uint8*) malloc(buffer_size);
     if (!yuv)
       return;
 
     int cb_offset = size.width * size.height;
     int cr_offset = cb_offset + c_size;
-    nsRefPtr<gfxImageSurface> surf = rgb->mSurface->GetAsImageSurface();
+    RefPtr<gfx::SourceSurface> tempSurf = rgb->GetAsSourceSurface();
+    RefPtr<gfx::DataSourceSurface> surf = tempSurf->GetDataSurface();
 
-    switch (surf->Format()) {
-      case gfxImageFormatARGB32:
-      case gfxImageFormatRGB24:
-        libyuv::ARGBToI420(static_cast<uint8*>(surf->Data()), surf->Stride(),
+    switch (surf->GetFormat()) {
+      case gfx::SurfaceFormat::B8G8R8A8:
+      case gfx::SurfaceFormat::B8G8R8X8:
+        libyuv::ARGBToI420(static_cast<uint8*>(surf->GetData()), surf->Stride(),
                            yuv, size.width,
                            yuv + cb_offset, half_width,
                            yuv + cr_offset, half_width,
                            size.width, size.height);
         break;
-      case gfxImageFormatRGB16_565:
-        libyuv::RGB565ToI420(static_cast<uint8*>(surf->Data()), surf->Stride(),
+      case gfx::SurfaceFormat::R5G6B5:
+        libyuv::RGB565ToI420(static_cast<uint8*>(surf->GetData()), surf->Stride(),
                              yuv, size.width,
                              yuv + cb_offset, half_width,
                              yuv + cr_offset, half_width,
                              size.width, size.height);
         break;
-      case gfxImageFormatA1:
-      case gfxImageFormatA8:
-      case gfxImageFormatUnknown:
       default:
         MOZ_MTLOG(ML_ERROR, "Unsupported RGB video format");
         MOZ_ASSERT(PR_FALSE);
     }
     conduit->SendVideoFrame(yuv, buffer_size, size.width, size.height, mozilla::kVideoI420, 0);
   } else {
     MOZ_MTLOG(ML_ERROR, "Unsupported video format");
     MOZ_ASSERT(PR_FALSE);