Bug 1288618 - Part 8: Add Compositor API to create a TextureSource from a layers::Image. r?nical
MozReview-Commit-ID: 6lupK1Umn5S
--- 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 {}