Implemented D3D11 offscreen texture share handle support.
Chrome uses this to for composited rendering. Currently Chrome uses a BGRA texture format
for surface sharing, so we must create our offscreen textures this way.
See EGL_ANGLE_query_surface_pointer, EGL_ANGLE_surface_d3d_texture_2d_share_handle,
EGL_ANGLE_d3d_share_handle_client_buffer.
TRAC #22410
Signed-off-by: Geoff Lang
Signed-off-by: Daniel Koch
Author: Jamie Madill
git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1772 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index 95a3fc4..de1ea82 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -41,6 +41,7 @@
{
static const DXGI_FORMAT RenderTargetFormats[] =
{
+ DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM
};
@@ -1892,11 +1893,10 @@
bool Renderer11::getShareHandleSupport() const
{
- // TODO
- // UNIMPLEMENTED();
-
+ // We only currently support share handles with BGRA surfaces, because
+ // chrome needs BGRA. Once chrome fixes this, we should always support them.
// PIX doesn't seem to support using share handles, so disable them.
- return false && !gl::perfActive();
+ return getBGRATextureSupport() && !gl::perfActive();
}
bool Renderer11::getDerivativeInstructionSupport() const
diff --git a/src/libGLESv2/renderer/SwapChain11.cpp b/src/libGLESv2/renderer/SwapChain11.cpp
index 5087626..f3faae4 100644
--- a/src/libGLESv2/renderer/SwapChain11.cpp
+++ b/src/libGLESv2/renderer/SwapChain11.cpp
@@ -40,6 +40,7 @@
mPassThroughPS = NULL;
mWidth = -1;
mHeight = -1;
+ mAppCreatedShareHandle = mShareHandle != NULL;
}
SwapChain11::~SwapChain11()
@@ -127,8 +128,10 @@
mPassThroughPS = NULL;
}
- if (mWindow)
+ if (!mAppCreatedShareHandle)
+ {
mShareHandle = NULL;
+ }
}
EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
@@ -190,44 +193,107 @@
mDepthStencilDSView = NULL;
}
- HANDLE *pShareHandle = NULL;
- if (!mWindow && mRenderer->getShareHandleSupport())
+ // If the app passed in a share handle, open the resource
+ // See EGL_ANGLE_d3d_share_handle_client_buffer
+ if (mAppCreatedShareHandle)
{
- pShareHandle = &mShareHandle;
- }
+ ID3D11Resource *tempResource11;
+ HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);
- D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
- offscreenTextureDesc.Width = backbufferWidth;
- offscreenTextureDesc.Height = backbufferHeight;
- offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
- offscreenTextureDesc.MipLevels = 1;
- offscreenTextureDesc.ArraySize = 1;
- offscreenTextureDesc.SampleDesc.Count = 1;
- offscreenTextureDesc.SampleDesc.Quality = 0;
- offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
- offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
- offscreenTextureDesc.CPUAccessFlags = 0;
- offscreenTextureDesc.MiscFlags = 0; // D3D11_RESOURCE_MISC_SHARED
-
- HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
- d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture");
-
- if (FAILED(result))
- {
- ERR("Could not create offscreen texture: %08lX", result);
- release();
-
- if (isDeviceLostError(result))
+ if (FAILED(result))
{
- return EGL_CONTEXT_LOST;
+ ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
+ release();
+ return EGL_BAD_PARAMETER;
}
- else
+
+ result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
+ tempResource11->Release();
+
+ if (FAILED(result))
{
- return EGL_BAD_ALLOC;
+ ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
+ release();
+ return EGL_BAD_PARAMETER;
+ }
+
+ // Validate offscreen texture parameters
+ D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
+ mOffscreenTexture->GetDesc(&offscreenTextureDesc);
+
+ if (offscreenTextureDesc.Width != (UINT)backbufferWidth
+ || offscreenTextureDesc.Height != (UINT)backbufferHeight
+ || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat)
+ || offscreenTextureDesc.MipLevels != 1
+ || offscreenTextureDesc.ArraySize != 1)
+ {
+ ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
+ release();
+ return EGL_BAD_PARAMETER;
+ }
+ }
+ else
+ {
+ const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport();
+
+ D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
+ offscreenTextureDesc.Width = backbufferWidth;
+ offscreenTextureDesc.Height = backbufferHeight;
+ offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
+ offscreenTextureDesc.MipLevels = 1;
+ offscreenTextureDesc.ArraySize = 1;
+ offscreenTextureDesc.SampleDesc.Count = 1;
+ offscreenTextureDesc.SampleDesc.Quality = 0;
+ offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
+ offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+ offscreenTextureDesc.CPUAccessFlags = 0;
+ offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0;
+
+ HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
+
+ if (FAILED(result))
+ {
+ ERR("Could not create offscreen texture: %08lX", result);
+ release();
+
+ if (isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+
+ d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture");
+
+ // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
+ if (useSharedResource)
+ {
+ IDXGIResource *offscreenTextureResource = NULL;
+ result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
+
+ // Fall back to no share handle on failure
+ if (FAILED(result))
+ {
+ ERR("Could not query offscreen texture resource: %08lX", result);
+ }
+ else
+ {
+ result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
+
+ if (FAILED(result))
+ {
+ mShareHandle = NULL;
+ ERR("Could not get offscreen texture shared handle: %08lX", result);
+ }
+ }
}
}
- result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView);
+ HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView);
+
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target");
diff --git a/src/libGLESv2/renderer/SwapChain11.h b/src/libGLESv2/renderer/SwapChain11.h
index 8dce2f2..acdc535 100644
--- a/src/libGLESv2/renderer/SwapChain11.h
+++ b/src/libGLESv2/renderer/SwapChain11.h
@@ -47,6 +47,7 @@
Renderer11 *mRenderer;
EGLint mHeight;
EGLint mWidth;
+ bool mAppCreatedShareHandle;
IDXGISwapChain *mSwapChain;
diff --git a/src/libGLESv2/renderer/renderer11_utils.cpp b/src/libGLESv2/renderer/renderer11_utils.cpp
index 6bbf66c..2247e50 100644
--- a/src/libGLESv2/renderer/renderer11_utils.cpp
+++ b/src/libGLESv2/renderer/renderer11_utils.cpp
@@ -217,6 +217,7 @@
switch (format)
{
case DXGI_FORMAT_R8G8B8A8_UNORM: return GL_RGBA8_OES;
+ case DXGI_FORMAT_B8G8R8A8_UNORM: return GL_BGRA8_EXT;
default:
UNREACHABLE();
}
@@ -240,6 +241,8 @@
{
switch (format)
{
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ return GL_BGRA8_EXT;
case DXGI_FORMAT_R8G8B8A8_UNORM:
return GL_RGBA8_OES;
case DXGI_FORMAT_D24_UNORM_S8_UINT:
@@ -307,6 +310,8 @@
case GL_RGB565:
case GL_RGB8_OES:
return DXGI_FORMAT_R8G8B8A8_UNORM;
+ case GL_BGRA8_EXT:
+ return DXGI_FORMAT_B8G8R8A8_UNORM;
case GL_DEPTH_COMPONENT16:
case GL_STENCIL_INDEX8:
case GL_DEPTH24_STENCIL8_OES:
diff --git a/src/libGLESv2/utilities.cpp b/src/libGLESv2/utilities.cpp
index 2a3ea73..d3af91e 100644
--- a/src/libGLESv2/utilities.cpp
+++ b/src/libGLESv2/utilities.cpp
@@ -533,6 +533,8 @@
case GL_STENCIL_INDEX8:
case GL_DEPTH24_STENCIL8_OES:
return false;
+ case GL_BGRA8_EXT:
+ return true;
default:
UNIMPLEMENTED();
}