Bug 1288618 - Part 8: Add Compositor API to create a TextureSource from a layers::Image. r?nical draft
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 15 Sep 2016 14:24:23 +1200
changeset 413861 d29c09fa35b5a76e335ceec167a8106f289cbe02
parent 413860 3b5ecfc317e8af0b5a4061191dfcb867afb351e1
child 413862 8af89c48cbd71fae0ed8c5e3a0c55c18325419a9
push id29543
push usermwoodrow@mozilla.com
push dateThu, 15 Sep 2016 02:36:28 +0000
reviewersnical
bugs1288618
milestone51.0a1
Bug 1288618 - Part 8: Add Compositor API to create a TextureSource from a layers::Image. r?nical MozReview-Commit-ID: 6lupK1Umn5S
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,19 @@ 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; }
 
+  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 {}