[PATCH 3/5] d2d1: Implement d2d_d3d_render_target_CreateSharedBitmap().

Henri Verbeet hverbeet at codeweavers.com
Tue Aug 4 01:53:27 CDT 2015


---
 dlls/d2d1/bitmap.c          | 108 +++++++++++++++++++++---------
 dlls/d2d1/d2d1_private.h    |   4 +-
 dlls/d2d1/render_target.c   |  25 +++++--
 dlls/d2d1/tests/Makefile.in |   2 +-
 dlls/d2d1/tests/d2d1.c      | 155 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 259 insertions(+), 35 deletions(-)

diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c
index 2627501..b3348c6 100644
--- a/dlls/d2d1/bitmap.c
+++ b/dlls/d2d1/bitmap.c
@@ -163,15 +163,9 @@ static const struct ID2D1BitmapVtbl d2d_bitmap_vtbl =
     d2d_bitmap_CopyFromMemory,
 };
 
-HRESULT d2d_bitmap_init(struct d2d_bitmap *bitmap, struct d2d_d3d_render_target *render_target,
-        D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc)
+static BOOL format_supported(const D2D1_PIXEL_FORMAT *format)
 {
-    D3D10_SUBRESOURCE_DATA resource_data;
-    D3D10_TEXTURE2D_DESC texture_desc;
-    ID3D10Texture2D *texture;
-    BOOL supported = FALSE;
     unsigned int i;
-    HRESULT hr;
 
     static const D2D1_PIXEL_FORMAT supported_formats[] =
     {
@@ -196,27 +190,49 @@ HRESULT d2d_bitmap_init(struct d2d_bitmap *bitmap, struct d2d_d3d_render_target
 
     for (i = 0; i < sizeof(supported_formats) / sizeof(*supported_formats); ++i)
     {
-        if (supported_formats[i].format == desc->pixelFormat.format
-                && supported_formats[i].alphaMode == desc->pixelFormat.alphaMode)
-        {
-            supported = TRUE;
-            break;
-        }
+        if (supported_formats[i].format == format->format
+                && supported_formats[i].alphaMode == format->alphaMode)
+            return TRUE;
     }
 
-    if (!supported)
+    return FALSE;
+}
+
+static void d2d_bitmap_init(struct d2d_bitmap *bitmap, ID2D1Factory *factory,
+        ID3D10ShaderResourceView *view, D2D1_SIZE_U size, const D2D1_BITMAP_PROPERTIES *desc)
+{
+    bitmap->ID2D1Bitmap_iface.lpVtbl = &d2d_bitmap_vtbl;
+    bitmap->refcount = 1;
+    ID2D1Factory_AddRef(bitmap->factory = factory);
+    ID3D10ShaderResourceView_AddRef(bitmap->view = view);
+    bitmap->pixel_size = size;
+    bitmap->format = desc->pixelFormat;
+    bitmap->dpi_x = desc->dpiX;
+    bitmap->dpi_y = desc->dpiY;
+
+    if (bitmap->dpi_x == 0.0f && bitmap->dpi_y == 0.0f)
+    {
+        bitmap->dpi_x = 96.0f;
+        bitmap->dpi_y = 96.0f;
+    }
+}
+
+HRESULT d2d_bitmap_init_memory(struct d2d_bitmap *bitmap, struct d2d_d3d_render_target *render_target,
+        D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc)
+{
+    D3D10_SUBRESOURCE_DATA resource_data;
+    D3D10_TEXTURE2D_DESC texture_desc;
+    ID3D10ShaderResourceView *view;
+    ID3D10Texture2D *texture;
+    HRESULT hr;
+
+    if (!format_supported(&desc->pixelFormat))
     {
         WARN("Tried to create bitmap with unsupported format {%#x / %#x}.\n",
                 desc->pixelFormat.format, desc->pixelFormat.alphaMode);
         return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
     }
 
-    FIXME("Ignoring bitmap properties.\n");
-
-    bitmap->ID2D1Bitmap_iface.lpVtbl = &d2d_bitmap_vtbl;
-    bitmap->refcount = 1;
-    ID2D1Factory_AddRef(bitmap->factory = render_target->factory);
-
     texture_desc.Width = size.width;
     texture_desc.Height = size.height;
     texture_desc.MipLevels = 1;
@@ -239,7 +255,7 @@ HRESULT d2d_bitmap_init(struct d2d_bitmap *bitmap, struct d2d_d3d_render_target
         return hr;
     }
 
-    hr = ID3D10Device_CreateShaderResourceView(render_target->device, (ID3D10Resource *)texture, NULL, &bitmap->view);
+    hr = ID3D10Device_CreateShaderResourceView(render_target->device, (ID3D10Resource *)texture, NULL, &view);
     ID3D10Texture2D_Release(texture);
     if (FAILED(hr))
     {
@@ -247,18 +263,52 @@ HRESULT d2d_bitmap_init(struct d2d_bitmap *bitmap, struct d2d_d3d_render_target
         return hr;
     }
 
-    bitmap->pixel_size = size;
-    bitmap->format = desc->pixelFormat;
-    bitmap->dpi_x = desc->dpiX;
-    bitmap->dpi_y = desc->dpiY;
+    d2d_bitmap_init(bitmap, render_target->factory, view, size, desc);
+    ID3D10ShaderResourceView_Release(view);
 
-    if (bitmap->dpi_x == 0.0f && bitmap->dpi_y == 0.0f)
+    return S_OK;
+}
+
+HRESULT d2d_bitmap_init_shared(struct d2d_bitmap *bitmap, struct d2d_d3d_render_target *render_target,
+        REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc)
+{
+    if (IsEqualGUID(iid, &IID_ID2D1Bitmap))
     {
-        bitmap->dpi_x = 96.0f;
-        bitmap->dpi_y = 96.0f;
+        struct d2d_bitmap *src_impl = unsafe_impl_from_ID2D1Bitmap(data);
+        D2D1_BITMAP_PROPERTIES d;
+        ID3D10Device *device;
+
+        if (src_impl->factory != render_target->factory)
+            return D2DERR_WRONG_FACTORY;
+
+        ID3D10ShaderResourceView_GetDevice(src_impl->view, &device);
+        ID3D10Device_Release(device);
+        if (device != render_target->device)
+            return D2DERR_UNSUPPORTED_OPERATION;
+
+        if (!desc)
+        {
+            d.pixelFormat = src_impl->format;
+            d.dpiX = src_impl->dpi_x;
+            d.dpiY = src_impl->dpi_y;
+            desc = &d;
+        }
+
+        if (!format_supported(&desc->pixelFormat))
+        {
+            WARN("Tried to create bitmap with unsupported format {%#x / %#x}.\n",
+                    desc->pixelFormat.format, desc->pixelFormat.alphaMode);
+            return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
+        }
+
+        d2d_bitmap_init(bitmap, render_target->factory, src_impl->view, src_impl->pixel_size, desc);
+
+        return S_OK;
     }
 
-    return S_OK;
+    WARN("Unhandled interface %s.\n", debugstr_guid(iid));
+
+    return E_INVALIDARG;
 }
 
 struct d2d_bitmap *unsafe_impl_from_ID2D1Bitmap(ID2D1Bitmap *iface)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 08e0b3f..6553eeb 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -196,8 +196,10 @@ struct d2d_bitmap
     float dpi_y;
 };
 
-HRESULT d2d_bitmap_init(struct d2d_bitmap *bitmap, struct d2d_d3d_render_target *render_target,
+HRESULT d2d_bitmap_init_memory(struct d2d_bitmap *bitmap, struct d2d_d3d_render_target *render_target,
         D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc) DECLSPEC_HIDDEN;
+HRESULT d2d_bitmap_init_shared(struct d2d_bitmap *bitmap, struct d2d_d3d_render_target *render_target,
+        REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc) DECLSPEC_HIDDEN;
 struct d2d_bitmap *unsafe_impl_from_ID2D1Bitmap(ID2D1Bitmap *iface) DECLSPEC_HIDDEN;
 
 struct d2d_state_block
diff --git a/dlls/d2d1/render_target.c b/dlls/d2d1/render_target.c
index 99cb7c8..df9a898 100644
--- a/dlls/d2d1/render_target.c
+++ b/dlls/d2d1/render_target.c
@@ -284,7 +284,7 @@ static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderT
     if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
         return E_OUTOFMEMORY;
 
-    if (FAILED(hr = d2d_bitmap_init(object, render_target, size, src_data, pitch, desc)))
+    if (FAILED(hr = d2d_bitmap_init_memory(object, render_target, size, src_data, pitch, desc)))
     {
         WARN("Failed to initialize bitmap, hr %#x.\n", hr);
         HeapFree(GetProcessHeap(), 0, object);
@@ -406,10 +406,27 @@ static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap
 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
         REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
 {
-    FIXME("iface %p, iid %s, data %p, desc %p, bitmap %p stub!\n",
-        iface, debugstr_guid(iid), data, desc, bitmap);
+    struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
+    struct d2d_bitmap *object;
+    HRESULT hr;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
+            iface, debugstr_guid(iid), data, desc, bitmap);
+
+    if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
+        return E_OUTOFMEMORY;
+
+    if (FAILED(hr = d2d_bitmap_init_shared(object, render_target, iid, data, desc)))
+    {
+        WARN("Failed to initialize bitmap, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created bitmap %p.\n", object);
+    *bitmap = &object->ID2D1Bitmap_iface;
+
+    return S_OK;
 }
 
 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
diff --git a/dlls/d2d1/tests/Makefile.in b/dlls/d2d1/tests/Makefile.in
index 83406c1..28b741f 100644
--- a/dlls/d2d1/tests/Makefile.in
+++ b/dlls/d2d1/tests/Makefile.in
@@ -1,5 +1,5 @@
 TESTDLL   = d2d1.dll
-IMPORTS   = d2d1 d3d10_1 dwrite dxguid uuid user32 advapi32
+IMPORTS   = d2d1 d3d10_1 dwrite dxguid uuid user32 advapi32 ole32
 
 C_SRCS = \
 	d2d1.c
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index a0c9b11..739e2fb 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -23,6 +23,7 @@
 #include "wine/test.h"
 #include "initguid.h"
 #include "dwrite.h"
+#include "wincodec.h"
 
 struct figure
 {
@@ -1844,6 +1845,159 @@ static void test_alpha_mode(void)
     DestroyWindow(window);
 }
 
+static void test_shared_bitmap(void)
+{
+    IDXGISwapChain *swapchain1, *swapchain2;
+    IWICBitmap *wic_bitmap1, *wic_bitmap2;
+    D2D1_RENDER_TARGET_PROPERTIES desc;
+    D2D1_BITMAP_PROPERTIES bitmap_desc;
+    IDXGISurface *surface1, *surface2;
+    ID2D1Factory *factory1, *factory2;
+    ID3D10Device1 *device1, *device2;
+    IWICImagingFactory *wic_factory;
+    ID2D1Bitmap *bitmap1, *bitmap2;
+    ID2D1RenderTarget *rt1, *rt2;
+    D2D1_SIZE_U size = {4, 4};
+    HWND window1, window2;
+    HRESULT hr;
+
+    if (!(device1 = create_device()))
+    {
+        skip("Failed to create device, skipping tests.\n");
+        return;
+    }
+
+    window1 = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+            0, 0, 640, 480, NULL, NULL, NULL, NULL);
+    window2 = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+            0, 0, 640, 480, NULL, NULL, NULL, NULL);
+    swapchain1 = create_swapchain(device1, window1, TRUE);
+    swapchain2 = create_swapchain(device1, window2, TRUE);
+    hr = IDXGISwapChain_GetBuffer(swapchain1, 0, &IID_IDXGISurface, (void **)&surface1);
+    ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
+    hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
+    ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
+
+    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+    hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
+            &IID_IWICImagingFactory, (void **)&wic_factory);
+    ok(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
+    hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
+            &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap1);
+    ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
+    hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
+            &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap2);
+    ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
+    IWICImagingFactory_Release(wic_factory);
+
+    desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
+    desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
+    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;
+
+    bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
+    bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
+    bitmap_desc.dpiX = 96.0f;
+    bitmap_desc.dpiY = 96.0f;
+
+    hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory1);
+    ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
+    hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
+    ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
+
+    /* DXGI surface render targets with the same device and factory. */
+    hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface1, &desc, &rt1);
+    ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
+    hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
+    ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
+
+    hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
+    ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
+    hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
+    ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
+    ID2D1Bitmap_Release(bitmap2);
+    hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IUnknown, bitmap1, NULL, &bitmap2);
+    ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
+    ID2D1RenderTarget_Release(rt2);
+
+    /* DXGI surface render targets with the same device but different factories. */
+    hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
+    ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
+    hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
+    ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
+    ID2D1RenderTarget_Release(rt2);
+
+    /* DXGI surface render targets with different devices but the same factory. */
+    IDXGISurface_Release(surface2);
+    IDXGISwapChain_Release(swapchain2);
+    device2 = create_device();
+    ok(!!device2, "Failed to create device.\n");
+    swapchain2 = create_swapchain(device2, window2, TRUE);
+    hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
+    ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
+
+    hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
+    ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
+    hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
+    ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
+    ID2D1RenderTarget_Release(rt2);
+
+    /* DXGI surface render targets with different devices and different factories. */
+    hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
+    ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
+    hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
+    ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
+    ID2D1RenderTarget_Release(rt2);
+
+    /* DXGI surface render target and WIC bitmap render target, same factory. */
+    hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
+    ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
+    hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
+    ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
+    ID2D1RenderTarget_Release(rt2);
+
+    /* WIC bitmap render targets on different D2D factories. */
+    ID2D1Bitmap_Release(bitmap1);
+    ID2D1RenderTarget_Release(rt1);
+    hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap1, &desc, &rt1);
+    ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
+    hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
+    ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
+
+    hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory2, wic_bitmap2, &desc, &rt2);
+    ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
+    hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
+    ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
+    ID2D1RenderTarget_Release(rt2);
+
+    /* WIC bitmap render targets on the same D2D factory. */
+    hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
+    ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
+    hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
+    ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
+    ID2D1Bitmap_Release(bitmap2);
+    ID2D1RenderTarget_Release(rt2);
+
+    ID2D1Bitmap_Release(bitmap1);
+    ID2D1RenderTarget_Release(rt1);
+    ID2D1Factory_Release(factory2);
+    ID2D1Factory_Release(factory1);
+    IWICBitmap_Release(wic_bitmap2);
+    IWICBitmap_Release(wic_bitmap1);
+    IDXGISurface_Release(surface2);
+    IDXGISurface_Release(surface1);
+    IDXGISwapChain_Release(swapchain2);
+    IDXGISwapChain_Release(swapchain1);
+    ID3D10Device1_Release(device2);
+    ID3D10Device1_Release(device1);
+    DestroyWindow(window2);
+    DestroyWindow(window1);
+    CoUninitialize();
+}
+
 START_TEST(d2d1)
 {
     test_clip();
@@ -1853,4 +2007,5 @@ START_TEST(d2d1)
     test_path_geometry();
     test_bitmap_formats();
     test_alpha_mode();
+    test_shared_bitmap();
 }
-- 
2.1.4




More information about the wine-patches mailing list