Module: wine Branch: master Commit: 31b162b37d9b9338b168270fc37ed83cd23ffa85 URL: http://source.winehq.org/git/wine.git/?a=commit;h=31b162b37d9b9338b168270fc3...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Mon Oct 10 17:12:39 2016 +0300
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
---
dlls/d2d1/bitmap.c | 97 ++++++++++++++++++++++++++++++++++++++++++++--- dlls/d2d1/d2d1_private.h | 2 +- dlls/d2d1/render_target.c | 2 +- dlls/d2d1/tests/d2d1.c | 44 +++++++++++++++++++++ 4 files changed, 137 insertions(+), 8 deletions(-)
diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c index b2f2ad7..43904bb 100644 --- a/dlls/d2d1/bitmap.c +++ b/dlls/d2d1/bitmap.c @@ -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; }
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);