Bug 1288618 - Part 8: Add Compositor API to create a TextureSource from a layers::Image. r=nical
☠☠ backed out by 84ee142476f5 ☠ ☠
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 15 Sep 2016 23:17:59 +1200
changeset 355346 da04776fc1bd56ae127e9c04069bf62090e2f41c
parent 355345 30e2b2eea845c8c2772743c97ac4ceda529aab2d
child 355347 7ac458ce1e64a34ff9ab6a98badf74920166a1ed
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1288618
milestone51.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 1288618 - Part 8: Add Compositor API to create a TextureSource from a layers::Image. r=nical
gfx/layers/Compositor.cpp
gfx/layers/Compositor.h
gfx/layers/d3d11/CompositorD3D11.cpp
gfx/layers/d3d11/CompositorD3D11.h
gfx/layers/d3d9/CompositorD3D9.cpp
gfx/layers/d3d9/CompositorD3D9.h
--- a/gfx/layers/Compositor.cpp
+++ b/gfx/layers/Compositor.cpp
@@ -114,16 +114,31 @@ Compositor::FlushPendingNotifyNotUsed()
 /* static */ void
 Compositor::AssertOnCompositorThread()
 {
   MOZ_ASSERT(!CompositorThreadHolder::Loop() ||
              CompositorThreadHolder::Loop() == MessageLoop::current(),
              "Can only call this from the compositor thread!");
 }
 
+already_AddRefed<TextureSource>
+Compositor::CreateTextureSourceForImage(Image* aImage)
+{
+  RefPtr<gfx::SourceSurface> src = aImage->GetAsSourceSurface();
+  if (!src) {
+    return nullptr;
+  }
+  RefPtr<gfx::DataSourceSurface> data = src->GetDataSurface();
+  if (!data) {
+    return nullptr;
+  }
+  RefPtr<DataTextureSource> result = CreateDataTextureSourceAround(data);
+  return result.forget();
+}
+
 bool
 Compositor::ShouldDrawDiagnostics(DiagnosticFlags aFlags)
 {
   if ((aFlags & DiagnosticFlags::TILE) && !(mDiagnosticTypes & DiagnosticTypes::TILE_BORDERS)) {
     return false;
   }
   if ((aFlags & DiagnosticFlags::BIGIMAGE) &&
       !(mDiagnosticTypes & DiagnosticTypes::BIGIMAGE_BORDERS)) {
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -198,16 +198,23 @@ public:
   virtual already_AddRefed<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) = 0;
 
   virtual already_AddRefed<DataTextureSource>
   CreateDataTextureSourceAround(gfx::DataSourceSurface* aSurface) { return nullptr; }
 
   virtual already_AddRefed<DataTextureSource>
   CreateDataTextureSourceAroundYCbCr(TextureHost* aTexture) { return nullptr; }
 
+  /**
+   * Used for OOP video decoding. This should go away when we switch to
+   * using PTexture (bug 1302918). DO NOT USE THIS FOR ANYTHING ELSE.
+   */
+  virtual already_AddRefed<TextureSource>
+  CreateTextureSourceForImage(Image* aImage);
+
   virtual bool Initialize(nsCString* const out_failureReason) = 0;
   virtual void Destroy();
   bool IsDestroyed() const { return mIsDestroyed; }
 
   virtual void DetachWidget() { mWidget = nullptr; }
 
   /**
    * Return true if the effect type is supported.
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -22,16 +22,19 @@
 #include "mozilla/gfx/StackArray.h"
 #include "mozilla/Services.h"
 #include "mozilla/widget/WinCompositorWidget.h"
 
 #include "mozilla/EnumeratedArray.h"
 #include "mozilla/Telemetry.h"
 #include "BlendShaderConstants.h"
 
+#include "D3D11ShareHandleImage.h"
+#include "D3D9SurfaceImage.h"
+
 #include <dxgi1_2.h>
 
 namespace mozilla {
 
 using namespace gfx;
 
 namespace layers {
 
@@ -442,16 +445,73 @@ CanUsePartialPresents(ID3D11Device* aDev
 already_AddRefed<DataTextureSource>
 CompositorD3D11::CreateDataTextureSource(TextureFlags aFlags)
 {
   RefPtr<DataTextureSource> result = new DataTextureSourceD3D11(gfx::SurfaceFormat::UNKNOWN,
                                                                 this, aFlags);
   return result.forget();
 }
 
+already_AddRefed<TextureSource>
+CompositorD3D11::CreateTextureSourceForImage(Image* aImage)
+{
+  if (aImage->GetFormat() == ImageFormat::D3D11_SHARE_HANDLE_TEXTURE) {
+    D3D11ShareHandleImage* image = static_cast<D3D11ShareHandleImage*>(aImage);
+
+    RefPtr<ID3D11Texture2D> tex = image->GetTexture();
+    RefPtr<ID3D11Device> device;
+    tex->GetDevice(getter_AddRefs(device));
+
+    HRESULT hr;
+    if (device != GetDevice()) {
+      RefPtr<IDXGIResource> resource;
+      tex->QueryInterface((IDXGIResource**)getter_AddRefs(resource));
+      if (!resource) {
+        return nullptr;
+      }
+      HANDLE sharedHandle;
+      hr = resource->GetSharedHandle(&sharedHandle);
+      if (FAILED(hr)) {
+        return nullptr;
+      }
+
+      tex = nullptr;
+      hr = GetDevice()->OpenSharedResource(sharedHandle,
+                                           __uuidof(ID3D11Texture2D),
+                                           (void**)(ID3D11Texture2D**)getter_AddRefs(tex));
+      if (FAILED(hr)) {
+        return nullptr;
+      }
+    }
+    RefPtr<TextureSource> source = new DataTextureSourceD3D11(SurfaceFormat::B8G8R8X8,
+                                                              this,
+                                                              tex);
+    return source.forget();
+  } else if (aImage->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) {
+    D3D9SurfaceImage* image = static_cast<D3D9SurfaceImage*>(aImage);
+
+    HANDLE handle = image->GetShareHandle();
+
+    RefPtr<ID3D11Texture2D> texture;
+    HRESULT hr = GetDevice()->OpenSharedResource(handle,
+                                                 __uuidof(ID3D11Texture2D),
+                                                 (void**)(ID3D11Texture2D**)getter_AddRefs(texture));
+    if (FAILED(hr)) {
+      NS_WARNING("Failed to open shared texture");
+      return nullptr;
+    }
+
+    RefPtr<TextureSource> source = new DataTextureSourceD3D11(SurfaceFormat::B8G8R8X8,
+                                                              this,
+                                                              texture);
+    return source.forget();
+  }
+  return Compositor::CreateTextureSourceForImage(aImage);
+}
+
 TextureFactoryIdentifier
 CompositorD3D11::GetTextureFactoryIdentifier()
 {
   TextureFactoryIdentifier ident;
   ident.mMaxTextureSize = GetMaxTextureSize();
   ident.mParentProcessId = XRE_GetProcessType();
   ident.mParentBackend = LayersBackend::LAYERS_D3D11;
   ident.mSyncHandle = mAttachments->mSyncHandle;
--- a/gfx/layers/d3d11/CompositorD3D11.h
+++ b/gfx/layers/d3d11/CompositorD3D11.h
@@ -50,16 +50,19 @@ public:
   virtual bool Initialize(nsCString* const out_failureReason) override;
 
   virtual TextureFactoryIdentifier
     GetTextureFactoryIdentifier() override;
 
   virtual already_AddRefed<DataTextureSource>
     CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override;
 
+  virtual already_AddRefed<TextureSource>
+    CreateTextureSourceForImage(Image* aImage) override;
+
   virtual bool CanUseCanvasLayerForSize(const gfx::IntSize& aSize) override;
   virtual int32_t GetMaxTextureSize() const final;
 
   virtual void MakeCurrent(MakeCurrentFlags aFlags = 0)  override {}
 
   virtual already_AddRefed<CompositingRenderTarget>
     CreateRenderTarget(const gfx::IntRect &aRect,
                        SurfaceInitMode aInit) override;
--- a/gfx/layers/d3d9/CompositorD3D9.cpp
+++ b/gfx/layers/d3d9/CompositorD3D9.cpp
@@ -13,16 +13,17 @@
 #include "nsWindowsHelpers.h"
 #include "Nv3DVUtils.h"
 #include "gfxFailure.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "gfxPrefs.h"
 #include "gfxCrashReporterUtils.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/widget/WinCompositorWidget.h"
+#include "D3D9SurfaceImage.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 
 CompositorD3D9::CompositorD3D9(CompositorBridgeParent* aParent, widget::CompositorWidget* aWidget)
   : Compositor(aWidget, aParent)
@@ -197,16 +198,43 @@ CompositorD3D9::CreateRenderTargetFromSo
 {
   RefPtr<IDirect3DTexture9> texture = CreateTexture(aRect, aSource, aSourcePoint);
 
   return MakeAndAddRef<CompositingRenderTargetD3D9>(texture,
                                                     INIT_MODE_NONE,
                                                     aRect);
 }
 
+already_AddRefed<TextureSource>
+CompositorD3D9::CreateTextureSourceForImage(Image* aImage)
+{
+  if (aImage->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) {
+    D3D9SurfaceImage* image = static_cast<D3D9SurfaceImage*>(aImage);
+
+    HANDLE handle = image->GetShareHandle();
+
+    RefPtr<IDirect3DTexture9> texture;
+    HRESULT hr = device()->CreateTexture(aImage->GetSize().width, aImage->GetSize().height, 1,
+                                         D3DUSAGE_RENDERTARGET,
+                                         D3DFMT_A8R8G8B8,
+                                         D3DPOOL_DEFAULT,
+                                         getter_AddRefs(texture),
+                                         (HANDLE*)&handle);
+    if (FAILED(hr)) {
+      NS_WARNING("Failed to open shared texture");
+      return nullptr;
+    }
+
+    RefPtr<TextureSource> source =
+      new DataTextureSourceD3D9(SurfaceFormat::B8G8R8A8, aImage->GetSize(), this, texture);
+    return source.forget();
+  }
+  return Compositor::CreateTextureSourceForImage(aImage);
+}
+
 void
 CompositorD3D9::SetRenderTarget(CompositingRenderTarget *aRenderTarget)
 {
   MOZ_ASSERT(aRenderTarget && mDeviceManager);
   RefPtr<CompositingRenderTargetD3D9> oldRT = mCurrentRT;
   mCurrentRT = static_cast<CompositingRenderTargetD3D9*>(aRenderTarget);
   mCurrentRT->BindRenderTarget(device());
   PrepareViewport(mCurrentRT->GetSize());
--- a/gfx/layers/d3d9/CompositorD3D9.h
+++ b/gfx/layers/d3d9/CompositorD3D9.h
@@ -40,16 +40,19 @@ public:
     CreateRenderTarget(const gfx::IntRect &aRect,
                        SurfaceInitMode aInit) override;
 
   virtual already_AddRefed<CompositingRenderTarget>
     CreateRenderTargetFromSource(const gfx::IntRect &aRect,
                                  const CompositingRenderTarget *aSource,
                                  const gfx::IntPoint &aSourcePoint) override;
 
+  virtual already_AddRefed<TextureSource>
+    CreateTextureSourceForImage(Image* aImage) override;
+
   virtual void SetRenderTarget(CompositingRenderTarget *aSurface) override;
   virtual CompositingRenderTarget* GetCurrentRenderTarget() const override
   {
     return mCurrentRT;
   }
 
   virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) override {}