[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