[v2 PATCH] d2d1: Support shared bitmaps created from dxgi surface

Nikolay Sivov nsivov at codeweavers.com
Sat Oct 8 12:18:00 CDT 2016


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---

v2: fixed test crash on vista

 dlls/d2d1/bitmap.c        | 60 +++++++++++++++++++++++++++++++++++++++++++++--
 dlls/d2d1/d2d1_private.h  |  2 +-
 dlls/d2d1/render_target.c |  2 +-
 dlls/d2d1/tests/d2d1.c    | 44 ++++++++++++++++++++++++++++++++++
 4 files changed, 104 insertions(+), 4 deletions(-)

diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c
index b2f2ad7..012d19d 100644
--- a/dlls/d2d1/bitmap.c
+++ b/dlls/d2d1/bitmap.c
@@ -296,13 +296,18 @@ HRESULT d2d_bitmap_create(ID2D1Factory *factory, ID3D10Device *device, D2D1_SIZE
     return *bitmap ? S_OK : E_OUTOFMEMORY;
 }
 
-HRESULT d2d_bitmap_create_shared(ID2D1Factory *factory, ID3D10Device *target_device,
+HRESULT d2d_bitmap_create_shared(ID2D1RenderTarget *render_target, ID3D10Device *target_device,
         REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, struct d2d_bitmap **bitmap)
 {
+    D2D1_BITMAP_PROPERTIES d;
+    ID2D1Factory *factory;
+
+    ID2D1RenderTarget_GetFactory(render_target, &factory);
+    ID2D1Factory_Release(factory);
+
     if (IsEqualGUID(iid, &IID_ID2D1Bitmap))
     {
         struct d2d_bitmap *src_impl = unsafe_impl_from_ID2D1Bitmap(data);
-        D2D1_BITMAP_PROPERTIES d;
         ID3D10Device *device;
 
         if (src_impl->factory != factory)
@@ -336,6 +341,57 @@ HRESULT d2d_bitmap_create_shared(ID2D1Factory *factory, ID3D10Device *target_dev
 
         return S_OK;
     }
+    else if (IsEqualGUID(iid, &IID_IDXGISurface) || IsEqualGUID(iid, &IID_IDXGISurface1))
+    {
+        ID3D10ShaderResourceView *view;
+        DXGI_SURFACE_DESC surface_desc;
+        IDXGISurface *surface = data;
+        ID3D10Resource *resource;
+        D2D1_SIZE_U pixel_size;
+        HRESULT hr;
+
+        if (FAILED(IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
+        {
+            WARN("Failed to get d3d resource from dxgi surface.\n");
+            return E_FAIL;
+        }
+
+        hr = ID3D10Device_CreateShaderResourceView(target_device, resource, NULL, &view);
+        ID3D10Resource_Release(resource);
+        if (FAILED(hr))
+        {
+            WARN("Failed to create shader resource view, hr %#x.\n", hr);
+            return hr;
+        }
+
+        if (!(*bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**bitmap))))
+        {
+            ID3D10ShaderResourceView_Release(view);
+            return E_OUTOFMEMORY;
+        }
+
+        d = *desc;
+        if (d.dpiX == 0.0f || d.dpiY == 0.0f)
+        {
+            float dpi_x, dpi_y;
+
+            ID2D1RenderTarget_GetDpi(render_target, &dpi_x, &dpi_y);
+            if (d.dpiX == 0.0f)
+                d.dpiX = dpi_x;
+            if (d.dpiY == 0.0f)
+                d.dpiY = dpi_y;
+        }
+
+        IDXGISurface_GetDesc(surface, &surface_desc);
+        pixel_size.width = surface_desc.Width;
+        pixel_size.height = surface_desc.Height;
+
+        d2d_bitmap_init(*bitmap, factory, view, pixel_size, &d);
+        ID3D10ShaderResourceView_Release(view);
+        TRACE("Created bitmap %p.\n", *bitmap);
+
+        return S_OK;
+    }
 
     WARN("Unhandled interface %s.\n", debugstr_guid(iid));
 
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 6cee5ef..c5c3a03 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -236,7 +236,7 @@ struct d2d_bitmap
 
 HRESULT d2d_bitmap_create(ID2D1Factory *factory, ID3D10Device *device, D2D1_SIZE_U size, const void *src_data,
         UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, struct d2d_bitmap **bitmap) DECLSPEC_HIDDEN;
-HRESULT d2d_bitmap_create_shared(ID2D1Factory *factory, ID3D10Device *device, REFIID iid, void *data,
+HRESULT d2d_bitmap_create_shared(ID2D1RenderTarget *render_target, ID3D10Device *device, REFIID iid, void *data,
         const D2D1_BITMAP_PROPERTIES *desc, struct d2d_bitmap **bitmap) DECLSPEC_HIDDEN;
 HRESULT d2d_bitmap_create_from_wic_bitmap(ID2D1Factory *factory, ID3D10Device *device, IWICBitmapSource *bitmap_source,
         const D2D1_BITMAP_PROPERTIES *desc, struct d2d_bitmap **bitmap) DECLSPEC_HIDDEN;
diff --git a/dlls/d2d1/render_target.c b/dlls/d2d1/render_target.c
index e9a971e..78000af 100644
--- a/dlls/d2d1/render_target.c
+++ b/dlls/d2d1/render_target.c
@@ -341,7 +341,7 @@ static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1R
     TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
             iface, debugstr_guid(iid), data, desc, bitmap);
 
-    if (SUCCEEDED(hr = d2d_bitmap_create_shared(render_target->factory, render_target->device, iid, data, desc, &object)))
+    if (SUCCEEDED(hr = d2d_bitmap_create_shared(iface, render_target->device, iid, data, desc, &object)))
         *bitmap = &object->ID2D1Bitmap_iface;
 
     return hr;
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index ba4be0c..38012ca 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -2046,8 +2046,10 @@ static void test_shared_bitmap(void)
     ID3D10Device1 *device1, *device2;
     IWICImagingFactory *wic_factory;
     ID2D1Bitmap *bitmap1, *bitmap2;
+    DXGI_SURFACE_DESC surface_desc;
     ID2D1RenderTarget *rt1, *rt2;
     D2D1_SIZE_U size = {4, 4};
+    IDXGISurface1 *surface3;
     HWND window1, window2;
     HRESULT hr;
 
@@ -2171,6 +2173,48 @@ static void test_shared_bitmap(void)
     ID2D1Bitmap_Release(bitmap2);
     ID2D1RenderTarget_Release(rt2);
 
+    /* Shared DXGI surface. */
+    desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
+    desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
+    desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
+    desc.dpiX = 0.0f;
+    desc.dpiY = 0.0f;
+    desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
+    desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
+
+    hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
+    ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
+
+    bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
+    bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
+    bitmap_desc.dpiX = 0.0f;
+    bitmap_desc.dpiY = 0.0f;
+
+    hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface, surface2, &bitmap_desc, &bitmap2);
+    ok(SUCCEEDED(hr) || broken(hr == E_INVALIDARG) /* vista */, "Failed to create bitmap, hr %#x.\n", hr);
+
+    if (SUCCEEDED(hr))
+    {
+        size = ID2D1Bitmap_GetPixelSize(bitmap2);
+        hr = IDXGISurface_GetDesc(surface2, &surface_desc);
+        ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
+        ok(size.width == surface_desc.Width && size.height == surface_desc.Height, "Got wrong bitmap size.\n");
+
+        ID2D1Bitmap_Release(bitmap2);
+
+        /* IDXGISurface1 is supported too. */
+        if (IDXGISurface_QueryInterface(surface2, &IID_IDXGISurface1, (void **)&surface3) == S_OK)
+        {
+            hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface1, surface3, &bitmap_desc, &bitmap2);
+            ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
+
+            ID2D1Bitmap_Release(bitmap2);
+            IDXGISurface1_Release(surface3);
+        }
+    }
+
+    ID2D1RenderTarget_Release(rt2);
+
     ID2D1Bitmap_Release(bitmap1);
     ID2D1RenderTarget_Release(rt1);
     ID2D1Factory_Release(factory2);
-- 
2.9.3




More information about the wine-patches mailing list