d2d1: Support shared bitmaps created from dxgi surface.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2016-10-10 17:12:39 +03:00 committed by Alexandre Julliard
parent a85f11c2e6
commit 31b162b37d
4 changed files with 137 additions and 8 deletions

View file

@ -296,22 +296,32 @@ 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;
if (IsEqualGUID(iid, &IID_ID2D1Bitmap))
{
struct d2d_bitmap *src_impl = unsafe_impl_from_ID2D1Bitmap(data);
D2D1_BITMAP_PROPERTIES d;
ID3D10Device *device;
HRESULT hr = S_OK;
ID2D1RenderTarget_GetFactory(render_target, &factory);
if (src_impl->factory != factory)
return D2DERR_WRONG_FACTORY;
{
hr = D2DERR_WRONG_FACTORY;
goto failed;
}
ID3D10ShaderResourceView_GetDevice(src_impl->view, &device);
ID3D10Device_Release(device);
if (device != target_device)
return D2DERR_UNSUPPORTED_OPERATION;
{
hr = D2DERR_UNSUPPORTED_OPERATION;
goto failed;
}
if (!desc)
{
@ -325,15 +335,90 @@ HRESULT d2d_bitmap_create_shared(ID2D1Factory *factory, ID3D10Device *target_dev
{
WARN("Tried to create bitmap with unsupported format {%#x / %#x}.\n",
desc->pixelFormat.format, desc->pixelFormat.alphaMode);
return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
hr = D2DERR_UNSUPPORTED_PIXEL_FORMAT;
goto failed;
}
if (!(*bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**bitmap))))
return E_OUTOFMEMORY;
{
hr = E_OUTOFMEMORY;
goto failed;
}
d2d_bitmap_init(*bitmap, factory, src_impl->view, src_impl->pixel_size, desc);
TRACE("Created bitmap %p.\n", *bitmap);
failed:
ID2D1Factory_Release(factory);
return hr;
}
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;
ID3D10Device *device;
HRESULT hr;
if (FAILED(IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
{
WARN("Failed to get d3d resource from dxgi surface.\n");
return E_FAIL;
}
ID3D10Resource_GetDevice(resource, &device);
ID3D10Device_Release(device);
if (device != target_device)
{
ID3D10Resource_Release(resource);
return D2DERR_UNSUPPORTED_OPERATION;
}
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;
}
if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
{
WARN("Failed to get surface desc, hr %#x.\n", hr);
ID3D10ShaderResourceView_Release(view);
return hr;
}
pixel_size.width = surface_desc.Width;
pixel_size.height = surface_desc.Height;
ID2D1RenderTarget_GetFactory(render_target, &factory);
d2d_bitmap_init(*bitmap, factory, view, pixel_size, &d);
ID3D10ShaderResourceView_Release(view);
ID2D1Factory_Release(factory);
TRACE("Created bitmap %p.\n", *bitmap);
return S_OK;
}

View file

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

View file

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

View file

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