Commit 6b2ea3fe by Geoff Lang Committed by Commit Bot

Support D3D texture share handles in the OpenGL backend on Windows.

BUG=angleproject:1144 Change-Id: Ideb0ed306ae8417f53b813745ced43002d028126 Reviewed-on: https://chromium-review.googlesource.com/461271Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent 9ec79391
...@@ -21,21 +21,18 @@ namespace rx ...@@ -21,21 +21,18 @@ namespace rx
namespace namespace
{ {
egl::Error GetD3DTextureInfo(EGLClientBuffer clientBuffer, egl::Error GetD3D11TextureInfo(EGLenum buftype,
size_t *width, ID3D11Texture2D *texture11,
size_t *height, size_t *width,
IUnknown **object, size_t *height,
IUnknown **device) IUnknown **object,
IUnknown **device)
{ {
IUnknown *buffer = static_cast<IUnknown *>(clientBuffer); D3D11_TEXTURE2D_DESC textureDesc;
texture11->GetDesc(&textureDesc);
IDirect3DTexture9 *texture9 = nullptr; if (buftype == EGL_D3D_TEXTURE_ANGLE)
ID3D11Texture2D *texture11 = nullptr;
if (SUCCEEDED(buffer->QueryInterface<ID3D11Texture2D>(&texture11)))
{ {
D3D11_TEXTURE2D_DESC textureDesc;
texture11->GetDesc(&textureDesc);
// From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer. // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
switch (textureDesc.Format) switch (textureDesc.Format)
{ {
...@@ -52,55 +49,63 @@ egl::Error GetD3DTextureInfo(EGLClientBuffer clientBuffer, ...@@ -52,55 +49,63 @@ egl::Error GetD3DTextureInfo(EGLClientBuffer clientBuffer,
return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.", return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
textureDesc.Format); textureDesc.Format);
} }
}
ID3D11Device *d3d11Device = nullptr; ID3D11Device *d3d11Device = nullptr;
texture11->GetDevice(&d3d11Device); texture11->GetDevice(&d3d11Device);
if (d3d11Device == nullptr) if (d3d11Device == nullptr)
{ {
SafeRelease(texture11); SafeRelease(texture11);
return egl::Error(EGL_BAD_PARAMETER, return egl::Error(EGL_BAD_PARAMETER,
"Could not query the D3D11 device from the client buffer."); "Could not query the D3D11 device from the client buffer.");
} }
if (width)
{
*width = textureDesc.Width;
}
if (height)
{
*height = textureDesc.Height;
}
if (device) if (width)
{ {
*device = d3d11Device; *width = textureDesc.Width;
} }
else if (height)
{ {
SafeRelease(d3d11Device); *height = textureDesc.Height;
} }
if (object) if (device)
{ {
*object = texture11; *device = d3d11Device;
} }
else else
{ {
SafeRelease(texture11); SafeRelease(d3d11Device);
} }
return egl::Error(EGL_SUCCESS); if (object)
{
*object = texture11;
} }
else if (SUCCEEDED(buffer->QueryInterface<IDirect3DTexture9>(&texture9))) else
{ {
D3DSURFACE_DESC surfaceDesc; SafeRelease(texture11);
if (FAILED(texture9->GetLevelDesc(0, &surfaceDesc))) }
{
SafeRelease(texture9);
return egl::Error(EGL_BAD_PARAMETER,
"Could not query description of the D3D9 surface.");
}
return egl::Error(EGL_SUCCESS);
}
egl::Error GetD3D9TextureInfo(EGLenum buftype,
IDirect3DTexture9 *texture9,
size_t *width,
size_t *height,
IUnknown **object,
IUnknown **device)
{
D3DSURFACE_DESC surfaceDesc;
if (FAILED(texture9->GetLevelDesc(0, &surfaceDesc)))
{
SafeRelease(texture9);
return egl::Error(EGL_BAD_PARAMETER, "Could not query description of the D3D9 surface.");
}
if (buftype == EGL_D3D_TEXTURE_ANGLE)
{
// From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer. // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
switch (surfaceDesc.Format) switch (surfaceDesc.Format)
{ {
...@@ -115,49 +120,93 @@ egl::Error GetD3DTextureInfo(EGLClientBuffer clientBuffer, ...@@ -115,49 +120,93 @@ egl::Error GetD3DTextureInfo(EGLClientBuffer clientBuffer,
return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.", return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
surfaceDesc.Format); surfaceDesc.Format);
} }
}
if (width) if (width)
{ {
*width = surfaceDesc.Width; *width = surfaceDesc.Width;
} }
if (height) if (height)
{ {
*height = surfaceDesc.Height; *height = surfaceDesc.Height;
} }
IDirect3DDevice9 *d3d9Device = nullptr; IDirect3DDevice9 *d3d9Device = nullptr;
HRESULT result = texture9->GetDevice(&d3d9Device); HRESULT result = texture9->GetDevice(&d3d9Device);
if (FAILED(result)) if (FAILED(result))
{ {
SafeRelease(texture9); SafeRelease(texture9);
return egl::Error(EGL_BAD_PARAMETER, return egl::Error(EGL_BAD_PARAMETER,
"Could not query the D3D9 device from the client buffer."); "Could not query the D3D9 device from the client buffer.");
} }
if (device)
{
*device = d3d9Device;
}
else
{
SafeRelease(d3d9Device);
}
if (object)
{
*object = texture9;
}
else
{
SafeRelease(texture9);
}
if (device) return egl::Error(EGL_SUCCESS);
}
egl::Error GetD3DTextureInfo(EGLenum buftype,
EGLClientBuffer clientBuffer,
ID3D11Device *d3d11Device,
size_t *width,
size_t *height,
IUnknown **object,
IUnknown **device)
{
if (buftype == EGL_D3D_TEXTURE_ANGLE)
{
IUnknown *buffer = static_cast<IUnknown *>(clientBuffer);
ID3D11Texture2D *texture11 = nullptr;
IDirect3DTexture9 *texture9 = nullptr;
if (SUCCEEDED(buffer->QueryInterface<ID3D11Texture2D>(&texture11)))
{ {
*device = d3d9Device; return GetD3D11TextureInfo(buftype, texture11, width, height, object, device);
} }
else else if (SUCCEEDED(buffer->QueryInterface<IDirect3DTexture9>(&texture9)))
{ {
SafeRelease(d3d9Device); return GetD3D9TextureInfo(buftype, texture9, width, height, object, device);
} }
else
if (object)
{ {
*object = texture9; return egl::Error(EGL_BAD_PARAMETER,
"Provided buffer is not a IDirect3DTexture9 or ID3D11Texture2D.");
} }
else }
else if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
{
ASSERT(d3d11Device);
HANDLE shareHandle = static_cast<HANDLE>(clientBuffer);
ID3D11Texture2D *texture11 = nullptr;
HRESULT result = d3d11Device->OpenSharedResource(shareHandle, __uuidof(ID3D11Texture2D),
reinterpret_cast<void **>(&texture11));
if (FAILED(result))
{ {
SafeRelease(texture9); return egl::Error(EGL_BAD_PARAMETER, "Failed to open share handle, result: 0x%X.",
result);
} }
return egl::Error(EGL_SUCCESS); return GetD3D11TextureInfo(buftype, texture11, width, height, object, device);
} }
else else
{ {
return egl::Error(EGL_BAD_PARAMETER, UNREACHABLE();
"Provided buffer is not a IDirect3DTexture9 or ID3D11Texture2D."); return egl::Error(EGL_BAD_DISPLAY, "Unknown buftype for D3DTextureSurfaceWGL.");
} }
} }
...@@ -165,15 +214,19 @@ egl::Error GetD3DTextureInfo(EGLClientBuffer clientBuffer, ...@@ -165,15 +214,19 @@ egl::Error GetD3DTextureInfo(EGLClientBuffer clientBuffer,
D3DTextureSurfaceWGL::D3DTextureSurfaceWGL(const egl::SurfaceState &state, D3DTextureSurfaceWGL::D3DTextureSurfaceWGL(const egl::SurfaceState &state,
RendererGL *renderer, RendererGL *renderer,
EGLenum buftype,
EGLClientBuffer clientBuffer, EGLClientBuffer clientBuffer,
DisplayWGL *display, DisplayWGL *display,
HGLRC wglContext, HGLRC wglContext,
HDC deviceContext, HDC deviceContext,
ID3D11Device *displayD3D11Device,
const FunctionsGL *functionsGL, const FunctionsGL *functionsGL,
const FunctionsWGL *functionsWGL) const FunctionsWGL *functionsWGL)
: SurfaceGL(state, renderer), : SurfaceGL(state, renderer),
mBuftype(buftype),
mClientBuffer(clientBuffer), mClientBuffer(clientBuffer),
mRenderer(renderer), mRenderer(renderer),
mDisplayD3D11Device(displayD3D11Device),
mDisplay(display), mDisplay(display),
mStateManager(renderer->getStateManager()), mStateManager(renderer->getStateManager()),
mWorkarounds(renderer->getWorkarounds()), mWorkarounds(renderer->getWorkarounds()),
...@@ -185,6 +238,7 @@ D3DTextureSurfaceWGL::D3DTextureSurfaceWGL(const egl::SurfaceState &state, ...@@ -185,6 +238,7 @@ D3DTextureSurfaceWGL::D3DTextureSurfaceWGL(const egl::SurfaceState &state,
mHeight(0), mHeight(0),
mDeviceHandle(nullptr), mDeviceHandle(nullptr),
mObject(nullptr), mObject(nullptr),
mKeyedMutex(nullptr),
mBoundObjectTextureHandle(nullptr), mBoundObjectTextureHandle(nullptr),
mBoundObjectRenderbufferHandle(nullptr), mBoundObjectRenderbufferHandle(nullptr),
mRenderbufferID(0), mRenderbufferID(0),
...@@ -197,6 +251,7 @@ D3DTextureSurfaceWGL::~D3DTextureSurfaceWGL() ...@@ -197,6 +251,7 @@ D3DTextureSurfaceWGL::~D3DTextureSurfaceWGL()
ASSERT(mBoundObjectTextureHandle == nullptr); ASSERT(mBoundObjectTextureHandle == nullptr);
SafeRelease(mObject); SafeRelease(mObject);
SafeRelease(mKeyedMutex);
if (mDeviceHandle) if (mDeviceHandle)
{ {
...@@ -221,15 +276,22 @@ D3DTextureSurfaceWGL::~D3DTextureSurfaceWGL() ...@@ -221,15 +276,22 @@ D3DTextureSurfaceWGL::~D3DTextureSurfaceWGL()
} }
} }
egl::Error D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(EGLClientBuffer clientBuffer) egl::Error D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(EGLenum buftype,
EGLClientBuffer clientBuffer,
ID3D11Device *d3d11Device)
{ {
return GetD3DTextureInfo(clientBuffer, nullptr, nullptr, nullptr, nullptr); return GetD3DTextureInfo(buftype, clientBuffer, d3d11Device, nullptr, nullptr, nullptr,
nullptr);
} }
egl::Error D3DTextureSurfaceWGL::initialize(const DisplayImpl *displayImpl) egl::Error D3DTextureSurfaceWGL::initialize(const DisplayImpl *displayImpl)
{ {
IUnknown *device = nullptr; IUnknown *device = nullptr;
ANGLE_TRY(GetD3DTextureInfo(mClientBuffer, &mWidth, &mHeight, &mObject, &device)); ANGLE_TRY(GetD3DTextureInfo(mBuftype, mClientBuffer, mDisplayD3D11Device, &mWidth, &mHeight,
&mObject, &device));
// Grab the keyed mutex, if one exists
mObject->QueryInterface(&mKeyedMutex);
ASSERT(device != nullptr); ASSERT(device != nullptr);
egl::Error error = mDisplay->registerD3DDevice(device, &mDeviceHandle); egl::Error error = mDisplay->registerD3DDevice(device, &mDeviceHandle);
...@@ -300,7 +362,20 @@ egl::Error D3DTextureSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, ...@@ -300,7 +362,20 @@ egl::Error D3DTextureSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width,
egl::Error D3DTextureSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value) egl::Error D3DTextureSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
{ {
UNIMPLEMENTED(); switch (attribute)
{
case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
*value = (mBuftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE) ? mClientBuffer : nullptr;
break;
case EGL_DXGI_KEYED_MUTEX_ANGLE:
*value = mKeyedMutex;
break;
default:
UNREACHABLE();
}
return egl::Error(EGL_SUCCESS); return egl::Error(EGL_SUCCESS);
} }
......
...@@ -27,15 +27,19 @@ class D3DTextureSurfaceWGL : public SurfaceGL ...@@ -27,15 +27,19 @@ class D3DTextureSurfaceWGL : public SurfaceGL
public: public:
D3DTextureSurfaceWGL(const egl::SurfaceState &state, D3DTextureSurfaceWGL(const egl::SurfaceState &state,
RendererGL *renderer, RendererGL *renderer,
EGLenum buftype,
EGLClientBuffer clientBuffer, EGLClientBuffer clientBuffer,
DisplayWGL *display, DisplayWGL *display,
HGLRC wglContext, HGLRC wglContext,
HDC deviceContext, HDC deviceContext,
ID3D11Device *displayD3D11Device,
const FunctionsGL *functionsGL, const FunctionsGL *functionsGL,
const FunctionsWGL *functionsWGL); const FunctionsWGL *functionsWGL);
~D3DTextureSurfaceWGL() override; ~D3DTextureSurfaceWGL() override;
static egl::Error ValidateD3DTextureClientBuffer(EGLClientBuffer clientBuffer); static egl::Error ValidateD3DTextureClientBuffer(EGLenum buftype,
EGLClientBuffer clientBuffer,
ID3D11Device *d3d11Device);
egl::Error initialize(const DisplayImpl *displayImpl) override; egl::Error initialize(const DisplayImpl *displayImpl) override;
egl::Error makeCurrent() override; egl::Error makeCurrent() override;
...@@ -57,10 +61,13 @@ class D3DTextureSurfaceWGL : public SurfaceGL ...@@ -57,10 +61,13 @@ class D3DTextureSurfaceWGL : public SurfaceGL
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override; FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override;
private: private:
EGLenum mBuftype;
EGLClientBuffer mClientBuffer; EGLClientBuffer mClientBuffer;
RendererGL *mRenderer; RendererGL *mRenderer;
ID3D11Device *mDisplayD3D11Device;
DisplayWGL *mDisplay; DisplayWGL *mDisplay;
StateManagerGL *mStateManager; StateManagerGL *mStateManager;
const WorkaroundsGL &mWorkarounds; const WorkaroundsGL &mWorkarounds;
...@@ -75,6 +82,7 @@ class D3DTextureSurfaceWGL : public SurfaceGL ...@@ -75,6 +82,7 @@ class D3DTextureSurfaceWGL : public SurfaceGL
HANDLE mDeviceHandle; HANDLE mDeviceHandle;
IUnknown *mObject; IUnknown *mObject;
IDXGIKeyedMutex *mKeyedMutex;
HANDLE mBoundObjectTextureHandle; HANDLE mBoundObjectTextureHandle;
HANDLE mBoundObjectRenderbufferHandle; HANDLE mBoundObjectRenderbufferHandle;
......
...@@ -375,7 +375,7 @@ egl::Error DisplayWGL::initialize(egl::Display *display) ...@@ -375,7 +375,7 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
mUseDXGISwapChains = false; mUseDXGISwapChains = false;
} }
if (mUseDXGISwapChains) if (mFunctionsWGL->hasExtension("WGL_NV_DX_interop2"))
{ {
egl::Error error = initializeD3DDevice(); egl::Error error = initializeD3DDevice();
if (error.isError()) if (error.isError())
...@@ -383,6 +383,11 @@ egl::Error DisplayWGL::initialize(egl::Display *display) ...@@ -383,6 +383,11 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
return error; return error;
} }
} }
else if (mUseDXGISwapChains)
{
// Want to use DXGI swap chains but WGL_NV_DX_interop2 is not present, fail initialization
return egl::Error(EGL_NOT_INITIALIZED, "WGL_NV_DX_interop2 is required but not present.");
}
return DisplayGL::initialize(display); return DisplayGL::initialize(display);
} }
...@@ -465,9 +470,8 @@ SurfaceImpl *DisplayWGL::createPbufferFromClientBuffer(const egl::SurfaceState & ...@@ -465,9 +470,8 @@ SurfaceImpl *DisplayWGL::createPbufferFromClientBuffer(const egl::SurfaceState &
EGLClientBuffer clientBuffer, EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const egl::AttributeMap &attribs)
{ {
ASSERT(buftype == EGL_D3D_TEXTURE_ANGLE); return new D3DTextureSurfaceWGL(state, getRenderer(), buftype, clientBuffer, this, mWGLContext,
return new D3DTextureSurfaceWGL(state, getRenderer(), clientBuffer, this, mWGLContext, mDeviceContext, mD3D11Device, mFunctionsGL, mFunctionsWGL);
mDeviceContext, mFunctionsGL, mFunctionsWGL);
} }
SurfaceImpl *DisplayWGL::createPixmapSurface(const egl::SurfaceState &state, SurfaceImpl *DisplayWGL::createPixmapSurface(const egl::SurfaceState &state,
...@@ -588,7 +592,9 @@ egl::Error DisplayWGL::validateClientBuffer(const egl::Config *configuration, ...@@ -588,7 +592,9 @@ egl::Error DisplayWGL::validateClientBuffer(const egl::Config *configuration,
switch (buftype) switch (buftype)
{ {
case EGL_D3D_TEXTURE_ANGLE: case EGL_D3D_TEXTURE_ANGLE:
return D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(clientBuffer); case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
return D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(buftype, clientBuffer,
mD3D11Device);
default: default:
return DisplayGL::validateClientBuffer(configuration, buftype, clientBuffer, attribs); return DisplayGL::validateClientBuffer(configuration, buftype, clientBuffer, attribs);
...@@ -659,7 +665,11 @@ void DisplayWGL::generateExtensions(egl::DisplayExtensions *outExtensions) const ...@@ -659,7 +665,11 @@ void DisplayWGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
outExtensions->createContextRobustness = mHasRobustness; outExtensions->createContextRobustness = mHasRobustness;
outExtensions->d3dTextureClientBuffer = mFunctionsWGL->hasExtension("WGL_NV_DX_interop2"); outExtensions->d3dTextureClientBuffer = mD3D11Device != nullptr;
outExtensions->d3dShareHandleClientBuffer = mD3D11Device != nullptr;
outExtensions->surfaceD3DTexture2DShareHandle = true;
outExtensions->querySurfacePointer = true;
outExtensions->keyedMutex = true;
// Contexts are virtualized so textures can be shared globally // Contexts are virtualized so textures can be shared globally
outExtensions->displayTextureShareGroup = true; outExtensions->displayTextureShareGroup = true;
......
...@@ -134,7 +134,7 @@ egl::Error PbufferSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EG ...@@ -134,7 +134,7 @@ egl::Error PbufferSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EG
egl::Error PbufferSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value) egl::Error PbufferSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
{ {
UNIMPLEMENTED(); *value = nullptr;
return egl::Error(EGL_SUCCESS); return egl::Error(EGL_SUCCESS);
} }
......
...@@ -119,7 +119,7 @@ egl::Error WindowSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGL ...@@ -119,7 +119,7 @@ egl::Error WindowSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGL
egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value) egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
{ {
UNIMPLEMENTED(); *value = nullptr;
return egl::Error(EGL_SUCCESS); return egl::Error(EGL_SUCCESS);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment