d2d1: Implement d2d_d3d_render_target_CreateSharedBitmap().

This commit is contained in:
Henri Verbeet 2015-08-04 08:53:27 +02:00 committed by Alexandre Julliard
parent f0bf9e81fa
commit cd59e3db6c
5 changed files with 261 additions and 37 deletions

View File

@ -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,20 +263,54 @@ 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;
if (bitmap->dpi_x == 0.0f && bitmap->dpi_y == 0.0f)
{
bitmap->dpi_x = 96.0f;
bitmap->dpi_y = 96.0f;
}
d2d_bitmap_init(bitmap, render_target->factory, view, size, desc);
ID3D10ShaderResourceView_Release(view);
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))
{
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;
}
WARN("Unhandled interface %s.\n", debugstr_guid(iid));
return E_INVALIDARG;
}
struct d2d_bitmap *unsafe_impl_from_ID2D1Bitmap(ID2D1Bitmap *iface)
{
if (!iface)

View File

@ -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

View File

@ -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",
struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
struct d2d_bitmap *object;
HRESULT hr;
TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
iface, debugstr_guid(iid), data, desc, bitmap);
return E_NOTIMPL;
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,

View File

@ -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

View File

@ -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();
}