--- a/gfx/gl/SharedSurfaceD3D11Interop.cpp
+++ b/gfx/gl/SharedSurfaceD3D11Interop.cpp
@@ -107,298 +107,319 @@ while (!done) {
wglDXUnlockObjectsNVX(gl_handleD3D, 2, gl_handles);
<direct3d renders to the render targets and presents
the results on the screen>
}
*/
////////////////////////////////////////////////////////////////////////////////
-// DXGL Device
+// DXInterop2Device
-class DXGLDevice : public RefCounted<DXGLDevice>
+class DXInterop2Device : public RefCounted<DXInterop2Device>
{
public:
- MOZ_DECLARE_REFCOUNTED_TYPENAME(DXGLDevice)
+ MOZ_DECLARE_REFCOUNTED_TYPENAME(DXInterop2Device)
WGLLibrary* const mWGL;
const RefPtr<ID3D11Device> mD3D; // Only needed for lifetime guarantee.
- const HANDLE mDXGLDeviceHandle;
+ const HANDLE mInteropDevice;
+ GLContext* const mGL;
- static already_AddRefed<DXGLDevice> Open(WGLLibrary* wgl)
+ static already_AddRefed<DXInterop2Device> Open(WGLLibrary* wgl, GLContext* gl)
{
MOZ_ASSERT(wgl->HasDXInterop2());
- RefPtr<ID3D11Device> d3d = gfx::DeviceManagerD3D11::Get()->GetContentDevice();
+ const RefPtr<ID3D11Device> d3d = gfx::DeviceManagerD3D11::Get()->GetContentDevice();
if (!d3d) {
- NS_WARNING("Failed to create D3D11 device.");
+ gfxCriticalNote << "DXInterop2Device::Open: Failed to create D3D11 device.";
return nullptr;
}
- HANDLE dxglDeviceHandle = wgl->fDXOpenDevice(d3d);
- if (!dxglDeviceHandle) {
- NS_WARNING("Failed to open D3D device for use by WGL.");
+ if (!gl->MakeCurrent())
+ return nullptr;
+
+ const auto interopDevice = wgl->fDXOpenDevice(d3d);
+ if (!interopDevice) {
+ gfxCriticalNote << "DXInterop2Device::Open: DXOpenDevice failed.";
return nullptr;
}
- return MakeAndAddRef<DXGLDevice>(wgl, d3d, dxglDeviceHandle);
+ return MakeAndAddRef<DXInterop2Device>(wgl, d3d, interopDevice, gl);
}
- DXGLDevice(WGLLibrary* wgl, const RefPtr<ID3D11Device>& d3d, HANDLE dxglDeviceHandle)
+ DXInterop2Device(WGLLibrary* wgl, ID3D11Device* d3d, HANDLE interopDevice,
+ GLContext* gl)
: mWGL(wgl)
, mD3D(d3d)
- , mDXGLDeviceHandle(dxglDeviceHandle)
+ , mInteropDevice(interopDevice)
+ , mGL(gl)
{ }
- ~DXGLDevice() {
- if (!mWGL->fDXCloseDevice(mDXGLDeviceHandle)) {
- uint32_t error = GetLastError();
- const nsPrintfCString errorMessage("wglDXCloseDevice(0x%x) failed: "
- "GetLastError(): 0x%x\n",
- mDXGLDeviceHandle, error);
+ ~DXInterop2Device() {
+ const auto isCurrent = mGL->MakeCurrent();
+
+ if (mWGL->fDXCloseDevice(mInteropDevice))
+ return;
+
+ if (isCurrent) {
+ // That shouldn't have failed.
+ const uint32_t error = GetLastError();
+ const nsPrintfCString errorMessage("wglDXCloseDevice(0x%p) failed:"
+ " GetLastError(): %u\n",
+ mInteropDevice, error);
gfxCriticalError() << errorMessage.BeginReading();
- MOZ_CRASH("GFX: Problem closing DXGL device");
}
}
- HANDLE RegisterObject(void* dxObject, GLuint name, GLenum type, GLenum access) const {
- HANDLE ret = mWGL->fDXRegisterObject(mDXGLDeviceHandle, dxObject, name, type,
- access);
- if (!ret) {
- uint32_t error = GetLastError();
- const nsPrintfCString errorMessage("wglDXRegisterObject(0x%x, 0x%x, %u, 0x%x, 0x%x) failed:"
- " GetLastError(): 0x%x\n",
- mDXGLDeviceHandle, dxObject, name,
- type, access, error);
+ HANDLE RegisterObject(void* d3dObject, GLuint name, GLenum type,
+ GLenum access) const
+ {
+ if (!mGL->MakeCurrent())
+ return nullptr;
+
+ const auto ret = mWGL->fDXRegisterObject(mInteropDevice, d3dObject, name, type,
+ access);
+ if (ret)
+ return ret;
+
+ const uint32_t error = GetLastError();
+ const nsPrintfCString errorMessage("wglDXRegisterObject(0x%p, 0x%p, %u, 0x%04x,"
+ " 0x%04x) failed: GetLastError(): %u\n",
+ mInteropDevice, d3dObject, name, type, access,
+ error);
+ gfxCriticalNote << errorMessage.BeginReading();
+ return nullptr;
+ }
+
+ bool UnregisterObject(HANDLE lockHandle) const {
+ const auto isCurrent = mGL->MakeCurrent();
+
+ if (mWGL->fDXUnregisterObject(mInteropDevice, lockHandle))
+ return true;
+
+ if (!isCurrent) {
+ // That shouldn't have failed.
+ const uint32_t error = GetLastError();
+ const nsPrintfCString errorMessage("wglDXUnregisterObject(0x%p, 0x%p) failed:"
+ " GetLastError(): %u\n",
+ mInteropDevice, lockHandle, error);
gfxCriticalError() << errorMessage.BeginReading();
- MOZ_CRASH("GFX: Problem registering DXGL device");
}
- return ret;
+ return false;
}
- bool UnregisterObject(HANDLE hObject) const {
- bool ret = mWGL->fDXUnregisterObject(mDXGLDeviceHandle, hObject);
- if (!ret) {
- uint32_t error = GetLastError();
- const nsPrintfCString errorMessage("wglDXUnregisterObject(0x%x, 0x%x) failed: "
- "GetLastError(): 0x%x\n",
- mDXGLDeviceHandle, hObject, error);
- gfxCriticalError() << errorMessage.BeginReading();
- MOZ_CRASH("GFX: Problem unregistering DXGL device");
- }
- return ret;
+ bool LockObject(HANDLE lockHandle) const {
+ MOZ_ASSERT(mGL->IsCurrent());
+
+ if (mWGL->fDXLockObjects(mInteropDevice, 1, &lockHandle))
+ return true;
+
+ if (!mGL->MakeCurrent())
+ return false;
+
+ gfxCriticalNote << "wglDXLockObjects called without mGL being current."
+ << " Retrying after MakeCurrent.";
+
+ if (mWGL->fDXLockObjects(mInteropDevice, 1, &lockHandle))
+ return true;
+
+ const uint32_t error = GetLastError();
+ const nsPrintfCString errorMessage("wglDXLockObjects(0x%p, 1, {0x%p}) failed:"
+ " GetLastError(): %u\n",
+ mInteropDevice, lockHandle, error);
+ gfxCriticalError() << errorMessage.BeginReading();
+ return false;
}
- bool LockObject(HANDLE hObject) const {
- bool ret = mWGL->fDXLockObjects(mDXGLDeviceHandle, 1, &hObject);
- if (!ret) {
- uint32_t error = GetLastError();
- const nsPrintfCString errorMessage("wglDXLockObjects(0x%x, 1, {0x%x}) "
- "failed: GetLastError(): 0x%x\n",
- mDXGLDeviceHandle, hObject, error);
- gfxCriticalError() << errorMessage.BeginReading();
- MOZ_CRASH("GFX: Problem locking DXGL device");
- }
- return ret;
- }
+ bool UnlockObject(HANDLE lockHandle) const {
+ MOZ_ASSERT(mGL->IsCurrent());
+
+ if (mWGL->fDXUnlockObjects(mInteropDevice, 1, &lockHandle))
+ return true;
+
+ if (!mGL->MakeCurrent())
+ return false;
- bool UnlockObject(HANDLE hObject) const {
- bool ret = mWGL->fDXUnlockObjects(mDXGLDeviceHandle, 1, &hObject);
- if (!ret) {
- uint32_t error = GetLastError();
- const nsPrintfCString errorMessage("wglDXUnlockObjects(0x%x, 1, {0x%x}) "
- "failed: GetLastError(): 0x%x\n",
- mDXGLDeviceHandle, hObject, error);
- gfxCriticalError() << errorMessage.BeginReading();
- MOZ_CRASH("GFX: Problem unlocking DXGL device");
- }
- return ret;
+ gfxCriticalNote << "wglDXUnlockObjects called without mGL being current."
+ << " Retrying after MakeCurrent.";
+
+ if (mWGL->fDXUnlockObjects(mInteropDevice, 1, &lockHandle))
+ return true;
+
+ const uint32_t error = GetLastError();
+ const nsPrintfCString errorMessage("wglDXUnlockObjects(0x%p, 1, {0x%p}) failed:"
+ " GetLastError(): %u\n",
+ mInteropDevice, lockHandle, error);
+ gfxCriticalError() << errorMessage.BeginReading();
+ return false;
}
};
////////////////////////////////////////////////////////////////////////////////
// Shared Surface
/*static*/ UniquePtr<SharedSurface_D3D11Interop>
-SharedSurface_D3D11Interop::Create(const RefPtr<DXGLDevice>& dxgl,
+SharedSurface_D3D11Interop::Create(DXInterop2Device* interop,
GLContext* gl,
const gfx::IntSize& size,
bool hasAlpha)
{
- auto& d3d = *dxgl->mD3D;
+ const auto& d3d = interop->mD3D;
// Create a texture in case we need to readback.
DXGI_FORMAT format = hasAlpha ? DXGI_FORMAT_B8G8R8A8_UNORM
: DXGI_FORMAT_B8G8R8X8_UNORM;
CD3D11_TEXTURE2D_DESC desc(format, size.width, size.height, 1, 1);
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
- RefPtr<ID3D11Texture2D> textureD3D;
- HRESULT hr = d3d.CreateTexture2D(&desc, nullptr, getter_AddRefs(textureD3D));
+ RefPtr<ID3D11Texture2D> texD3D;
+ auto hr = d3d->CreateTexture2D(&desc, nullptr, getter_AddRefs(texD3D));
if (FAILED(hr)) {
NS_WARNING("Failed to create texture for CanvasLayer!");
return nullptr;
}
- RefPtr<IDXGIResource> textureDXGI;
- hr = textureD3D->QueryInterface(__uuidof(IDXGIResource), getter_AddRefs(textureDXGI));
+ RefPtr<IDXGIResource> texDXGI;
+ hr = texD3D->QueryInterface(__uuidof(IDXGIResource), getter_AddRefs(texDXGI));
if (FAILED(hr)) {
NS_WARNING("Failed to open texture for sharing!");
return nullptr;
}
- RefPtr<IDXGIKeyedMutex> keyedMutex;
- hr = textureD3D->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(keyedMutex));
- if (FAILED(hr)) {
- NS_WARNING("Failed to obtained keyed mutex from texture!");
+ HANDLE dxgiHandle;
+ texDXGI->GetSharedHandle(&dxgiHandle);
+
+ ////
+
+ if (!gl->MakeCurrent()) {
+ NS_WARNING("MakeCurrent failed.");
return nullptr;
}
- HANDLE sharedHandle;
- textureDXGI->GetSharedHandle(&sharedHandle);
-
- GLuint renderbufferGL = 0;
- gl->MakeCurrent();
- gl->fGenRenderbuffers(1, &renderbufferGL);
- HANDLE objectWGL = dxgl->RegisterObject(textureD3D, renderbufferGL,
- LOCAL_GL_RENDERBUFFER,
- LOCAL_WGL_ACCESS_WRITE_DISCARD_NV);
- if (!objectWGL) {
+ GLuint rbGL = 0;
+ gl->fGenRenderbuffers(1, &rbGL);
+ const auto lockHandle = interop->RegisterObject(texD3D, rbGL, LOCAL_GL_RENDERBUFFER,
+ LOCAL_WGL_ACCESS_WRITE_DISCARD_NV);
+ if (!lockHandle) {
NS_WARNING("Failed to register D3D object with WGL.");
+ gl->fDeleteRenderbuffers(1, &rbGL);
return nullptr;
}
+ ////
+
typedef SharedSurface_D3D11Interop ptrT;
- UniquePtr<ptrT> ret ( new ptrT(gl, size, hasAlpha, renderbufferGL, dxgl, objectWGL,
- textureD3D, sharedHandle, keyedMutex) );
+ UniquePtr<ptrT> ret ( new ptrT(gl, size, hasAlpha, rbGL, interop, lockHandle,
+ texD3D, dxgiHandle) );
return Move(ret);
}
SharedSurface_D3D11Interop::SharedSurface_D3D11Interop(GLContext* gl,
const gfx::IntSize& size,
- bool hasAlpha,
- GLuint renderbufferGL,
- const RefPtr<DXGLDevice>& dxgl,
- HANDLE objectWGL,
- const RefPtr<ID3D11Texture2D>& textureD3D,
- HANDLE sharedHandle,
- const RefPtr<IDXGIKeyedMutex>& keyedMutex)
+ bool hasAlpha, GLuint rbGL,
+ DXInterop2Device* interop,
+ HANDLE lockHandle,
+ ID3D11Texture2D* texD3D,
+ HANDLE dxgiHandle)
: SharedSurface(SharedSurfaceType::DXGLInterop2,
AttachmentType::GLRenderbuffer,
gl,
size,
hasAlpha,
true)
- , mProdRB(renderbufferGL)
- , mDXGL(dxgl)
- , mObjectWGL(objectWGL)
- , mTextureD3D(textureD3D)
+ , mProdRB(rbGL)
+ , mInterop(interop)
+ , mLockHandle(lockHandle)
+ , mTexD3D(texD3D)
+ , mDXGIHandle(dxgiHandle)
, mNeedsFinish(gfxPrefs::WebGLDXGLNeedsFinish())
- , mSharedHandle(sharedHandle)
- , mKeyedMutex(keyedMutex)
, mLockedForGL(false)
{ }
SharedSurface_D3D11Interop::~SharedSurface_D3D11Interop()
{
MOZ_ASSERT(!mLockedForGL);
- if (!mDXGL->UnregisterObject(mObjectWGL)) {
- NS_WARNING("Failed to release a DXGL object, possibly leaking it.");
- }
-
if (!mGL->MakeCurrent())
return;
- mGL->fDeleteRenderbuffers(1, &mProdRB);
+ if (!mInterop->UnregisterObject(mLockHandle)) {
+ NS_WARNING("Failed to release mLockHandle, possibly leaking it.");
+ }
- // mDXGL is closed when it runs out of refs.
+ mGL->fDeleteRenderbuffers(1, &mProdRB);
}
void
SharedSurface_D3D11Interop::ProducerAcquireImpl()
{
MOZ_ASSERT(!mLockedForGL);
- if (mKeyedMutex) {
- const uint64_t keyValue = 0;
- const DWORD timeoutMs = 10000;
- HRESULT hr = mKeyedMutex->AcquireSync(keyValue, timeoutMs);
- if (hr == WAIT_TIMEOUT) {
- // Doubt we should do this? Maybe Wait for ever?
- MOZ_CRASH("GFX: d3d11Interop timeout");
- }
- }
-
// Now we have the mutex, we can lock for GL.
- MOZ_ALWAYS_TRUE(mDXGL->LockObject(mObjectWGL));
+ MOZ_ALWAYS_TRUE( mInterop->LockObject(mLockHandle) );
mLockedForGL = true;
}
void
SharedSurface_D3D11Interop::ProducerReleaseImpl()
{
MOZ_ASSERT(mLockedForGL);
- mGL->fFlush();
- MOZ_ALWAYS_TRUE(mDXGL->UnlockObject(mObjectWGL));
+ if (mNeedsFinish) {
+ mGL->fFinish();
+ } else {
+ // We probably don't even need this.
+ mGL->fFlush();
+ }
+ MOZ_ALWAYS_TRUE( mInterop->UnlockObject(mLockHandle) );
mLockedForGL = false;
-
- // Now we have unlocked for GL, we can release to consumer.
- if (mKeyedMutex) {
- mKeyedMutex->ReleaseSync(0);
- }
-
- if (mNeedsFinish) {
- mGL->fFinish();
- }
}
bool
SharedSurface_D3D11Interop::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
{
- gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8
- : gfx::SurfaceFormat::B8G8R8X8;
- *out_descriptor = layers::SurfaceDescriptorD3D10(WindowsHandle(mSharedHandle), format,
+ const auto format = (mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8
+ : gfx::SurfaceFormat::B8G8R8X8);
+ *out_descriptor = layers::SurfaceDescriptorD3D10(WindowsHandle(mDXGIHandle), format,
mSize);
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////
// Factory
/*static*/ UniquePtr<SurfaceFactory_D3D11Interop>
SurfaceFactory_D3D11Interop::Create(GLContext* gl, const SurfaceCaps& caps,
- const RefPtr<layers::ClientIPCAllocator>& allocator,
+ layers::ClientIPCAllocator* allocator,
const layers::TextureFlags& flags)
{
WGLLibrary* wgl = &sWGLLib;
if (!wgl || !wgl->HasDXInterop2())
return nullptr;
- RefPtr<DXGLDevice> dxgl = DXGLDevice::Open(wgl);
- if (!dxgl) {
+ const RefPtr<DXInterop2Device> interop = DXInterop2Device::Open(wgl, gl);
+ if (!interop) {
NS_WARNING("Failed to open D3D device for use by WGL.");
return nullptr;
}
typedef SurfaceFactory_D3D11Interop ptrT;
- UniquePtr<ptrT> ret(new ptrT(gl, caps, allocator, flags, dxgl));
-
+ UniquePtr<ptrT> ret(new ptrT(gl, caps, allocator, flags, interop));
return Move(ret);
}
SurfaceFactory_D3D11Interop::SurfaceFactory_D3D11Interop(GLContext* gl,
const SurfaceCaps& caps,
- const RefPtr<layers::ClientIPCAllocator>& allocator,
+ layers::ClientIPCAllocator* allocator,
const layers::TextureFlags& flags,
- const RefPtr<DXGLDevice>& dxgl)
+ DXInterop2Device* interop)
: SurfaceFactory(SharedSurfaceType::DXGLInterop2, gl, caps, allocator, flags)
- , mDXGL(dxgl)
+ , mInterop(interop)
{ }
SurfaceFactory_D3D11Interop::~SurfaceFactory_D3D11Interop()
{ }
} // namespace gl
} // namespace mozilla
--- a/gfx/gl/SharedSurfaceD3D11Interop.h
+++ b/gfx/gl/SharedSurfaceD3D11Interop.h
@@ -4,104 +4,97 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef SHARED_SURFACE_D3D11_INTEROP_H_
#define SHARED_SURFACE_D3D11_INTEROP_H_
#include <windows.h>
#include "SharedSurface.h"
-struct ID3D11Device;
-struct ID3D11ShaderResourceView;
-
namespace mozilla {
namespace gl {
-class DXGLDevice;
+class DXInterop2Device;
class GLContext;
class WGLLibrary;
class SharedSurface_D3D11Interop
: public SharedSurface
{
public:
const GLuint mProdRB;
- const RefPtr<DXGLDevice> mDXGL;
- const HANDLE mObjectWGL;
- const HANDLE mSharedHandle;
- const RefPtr<ID3D11Texture2D> mTextureD3D;
+ const RefPtr<DXInterop2Device> mInterop;
+ const HANDLE mLockHandle;
+ const RefPtr<ID3D11Texture2D> mTexD3D;
+ const HANDLE mDXGIHandle;
const bool mNeedsFinish;
protected:
- RefPtr<IDXGIKeyedMutex> mKeyedMutex;
bool mLockedForGL;
public:
- static UniquePtr<SharedSurface_D3D11Interop> Create(const RefPtr<DXGLDevice>& dxgl,
+ static UniquePtr<SharedSurface_D3D11Interop> Create(DXInterop2Device* interop,
GLContext* gl,
const gfx::IntSize& size,
bool hasAlpha);
static SharedSurface_D3D11Interop* Cast(SharedSurface* surf) {
MOZ_ASSERT(surf->mType == SharedSurfaceType::DXGLInterop2);
-
return (SharedSurface_D3D11Interop*)surf;
}
protected:
SharedSurface_D3D11Interop(GLContext* gl,
const gfx::IntSize& size,
bool hasAlpha,
GLuint renderbufferGL,
- const RefPtr<DXGLDevice>& dxgl,
- HANDLE objectWGL,
- const RefPtr<ID3D11Texture2D>& textureD3D,
- HANDLE sharedHandle,
- const RefPtr<IDXGIKeyedMutex>& keyedMutex);
+ DXInterop2Device* interop,
+ HANDLE lockHandle,
+ ID3D11Texture2D* texD3D,
+ HANDLE dxgiHandle);
public:
- virtual ~SharedSurface_D3D11Interop();
+ virtual ~SharedSurface_D3D11Interop() override;
virtual void LockProdImpl() override { }
virtual void UnlockProdImpl() override { }
virtual void ProducerAcquireImpl() override;
virtual void ProducerReleaseImpl() override;
virtual GLuint ProdRenderbuffer() override {
return mProdRB;
}
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
};
-
class SurfaceFactory_D3D11Interop
: public SurfaceFactory
{
public:
- const RefPtr<DXGLDevice> mDXGL;
+ const RefPtr<DXInterop2Device> mInterop;
static UniquePtr<SurfaceFactory_D3D11Interop> Create(GLContext* gl,
const SurfaceCaps& caps,
- const RefPtr<layers::ClientIPCAllocator>& allocator,
+ layers::ClientIPCAllocator* allocator,
const layers::TextureFlags& flags);
protected:
SurfaceFactory_D3D11Interop(GLContext* gl, const SurfaceCaps& caps,
- const RefPtr<layers::ClientIPCAllocator>& allocator,
+ layers::ClientIPCAllocator* allocator,
const layers::TextureFlags& flags,
- const RefPtr<DXGLDevice>& dxgl);
+ DXInterop2Device* interop);
public:
- virtual ~SurfaceFactory_D3D11Interop();
+ virtual ~SurfaceFactory_D3D11Interop() override;
protected:
virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override {
bool hasAlpha = mReadCaps.alpha;
- return SharedSurface_D3D11Interop::Create(mDXGL, mGL, size, hasAlpha);
+ return SharedSurface_D3D11Interop::Create(mInterop, mGL, size, hasAlpha);
}
};
} /* namespace gl */
} /* namespace mozilla */
#endif /* SHARED_SURFACE_D3D11_INTEROP_H_ */