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/libEGL/Config.cpp b/src/libEGL/Config.cpp
index 2e90b32..5488cb6 100644
--- a/src/libEGL/Config.cpp
+++ b/src/libEGL/Config.cpp
@@ -59,6 +59,14 @@
         mAlphaSize = 0;
         mBindToTextureRGB = true;
         break;
+      case GL_BGRA8_EXT:
+        mBufferSize = 32;
+        mRedSize = 8;
+        mGreenSize = 8;
+        mBlueSize = 8;
+        mAlphaSize = 8;
+        mBindToTextureRGBA = true;
+        break;
       default:
         UNREACHABLE();   // Other formats should not be valid
     }
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();
     }