For React Native
-- v3: d2d1: Support creating bitmap from DXGI subresource surface. d2d1/tests: Test creating bitmap from DXGI subresource surface.
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/d2d1/tests/d2d1.c | 300 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 297 insertions(+), 3 deletions(-)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 2b894695c98..279b4d9e865 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -25,6 +25,7 @@ #include "d2d1_3.h" #include "d2d1effectauthor.h" #include "d3d11.h" +#include "dxgi1_2.h" #include "wincrypt.h" #include "wine/test.h" #include "initguid.h" @@ -643,12 +644,21 @@ static void get_d3d10_surface_readback(IDXGISurface *surface, struct resource_re D3D10_MAPPED_TEXTURE2D map_desc; DXGI_SURFACE_DESC surface_desc; ID3D10Resource *src_resource; + UINT subresource_idx = 0; + IDXGISurface2 *surface2; ID3D10Device *device; HRESULT hr;
hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&device); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&src_resource); + if (hr == E_NOINTERFACE) + { + hr = IDXGISurface_QueryInterface(surface, &IID_IDXGISurface2, (void **)&surface2); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = IDXGISurface2_GetResource(surface2, &IID_ID3D10Resource, (void **)&src_resource, &subresource_idx); + IDXGISurface2_Release(surface2); + } ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = IDXGISurface_GetDesc(surface, &surface_desc); @@ -669,7 +679,8 @@ static void get_d3d10_surface_readback(IDXGISurface *surface, struct resource_re rb->width = texture_desc.Width; rb->height = texture_desc.Height;
- ID3D10Device_CopyResource(device, rb->u.d3d10_resource, src_resource); + ID3D10Device_CopySubresourceRegion(device, rb->u.d3d10_resource, 0, 0, 0, 0, src_resource, + subresource_idx, NULL); ID3D10Resource_Release(src_resource); ID3D10Device_Release(device);
@@ -687,12 +698,21 @@ static void get_d3d11_surface_readback(IDXGISurface *surface, struct resource_re DXGI_SURFACE_DESC surface_desc; ID3D11Resource *src_resource; ID3D11DeviceContext *context; + UINT subresource_idx = 0; + IDXGISurface2 *surface2; ID3D11Device *device; HRESULT hr;
hr = IDXGISurface_GetDevice(surface, &IID_ID3D11Device, (void **)&device); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); hr = IDXGISurface_QueryInterface(surface, &IID_ID3D11Resource, (void **)&src_resource); + if (hr == E_NOINTERFACE) + { + hr = IDXGISurface_QueryInterface(surface, &IID_IDXGISurface2, (void **)&surface2); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = IDXGISurface2_GetResource(surface2, &IID_ID3D11Resource, (void **)&src_resource, &subresource_idx); + IDXGISurface2_Release(surface2); + } ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = IDXGISurface_GetDesc(surface, &surface_desc); @@ -714,7 +734,8 @@ static void get_d3d11_surface_readback(IDXGISurface *surface, struct resource_re rb->height = texture_desc.Height;
ID3D11Device_GetImmediateContext(device, &context); - ID3D11DeviceContext_CopyResource(context, rb->u.d3d11_resource, src_resource); + ID3D11DeviceContext_CopySubresourceRegion(context, rb->u.d3d11_resource, 0, 0, 0, 0, + src_resource, subresource_idx, NULL); ID3D11Resource_Release(src_resource); ID3D11Device_Release(device);
@@ -1416,6 +1437,185 @@ static void check_bitmap_surface_(unsigned int line, ID2D1Bitmap *bitmap, BOOL h ID2D1Bitmap1_Release(bitmap1); }
+#define check_bitmap_subresource_surface(a, b, c, d, e, f, g) _check_bitmap_subresource_surface(__LINE__, a, b, c, d, e, f, g) +static void _check_bitmap_subresource_surface(unsigned int line, struct d2d1_test_context *ctx, + ID2D1Bitmap *bitmap, IDXGIResource1 *parent_resource, IDXGISurface *subresource_surface, + BOOL expect_parent_surface, DWORD expect_options, BOOL succeed_draw) +{ + static const D2D1_COLOR_F test_colours_f[] = + { + {1.0f, 0.0f, 0.0f, 1.0f}, + {0.0f, 1.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f, 1.0f}, + {1.0f, 0.0f, 1.0f, 1.0f}, + }; + static const DWORD test_colours[] = + { + 0xffff0000, + 0xff00ff00, + 0xff0000ff, + 0xffff00ff, + }; + unsigned int usage = 0, bind_flags = 0, cpu_access_flags = 0, misc_flags = 0; + IDXGISurface *surface, *target_surface; + D2D1_BITMAP_PROPERTIES1 bitmap_desc; + D3D10_TEXTURE2D_DESC texture_desc; + IDXGIResource1 *parent_resource2; + ID3D10Texture2D *parent_texture; + DXGI_SURFACE_DESC surface_desc; + DWORD colour, expected_colour; + D2D1_BITMAP_OPTIONS options; + ID2D1Bitmap1 *target_bitmap; + struct resource_readback rb; + IDXGISurface2 *surface2; + D2D1_SIZE_U pixel_size; + UINT subresource_index; + ID2D1Bitmap1 *bitmap1; + IDXGIObject *object; + D2D1_SIZE_U size; + HRESULT hr; + + hr = ID2D1Bitmap_QueryInterface(bitmap, &IID_ID2D1Bitmap1, (void **)&bitmap1); + ok_(__FILE__, line)(hr == S_OK, "Failed to get bitmap, hr %#lx.\n", hr); + + options = ID2D1Bitmap1_GetOptions(bitmap1); + ok_(__FILE__, line)(options == expect_options, "Got unexpected bitmap options %#x, expected %#lx.\n", + options, expect_options); + + surface = (void *)0xdeadbeef; + hr = ID2D1Bitmap1_GetSurface(bitmap1, &surface); + ok_(__FILE__, line)(hr == S_OK, "Failed to get bitmap surface, hr %#lx.\n", hr); + ok_(__FILE__, line)(!!surface, "Expected surface instance.\n"); + hr = IDXGISurface_QueryInterface(surface, &IID_IDXGISurface2, (void **)&surface2); + ok_(__FILE__, line)(hr == S_OK, "Failed to get surface pointer, hr %#lx.\n", hr); + if (expect_parent_surface) + { + hr = IDXGISurface_QueryInterface(surface, &IID_IDXGIObject, (void **)&object); + ok_(__FILE__, line)(hr == S_OK, "Failed to get object pointer, hr %#lx.\n", hr); + ok_(__FILE__, line)(object == (IDXGIObject *)parent_resource, + "Expected the parent surface being used as the bitmap surface.\n"); + IDXGIObject_Release(object); + check_interface_(line, surface, &IID_ID3D10Texture2D, TRUE); + check_interface_(line, surface, &IID_ID3D11Texture2D, TRUE); + } + else + { + hr = IDXGISurface2_GetResource(surface2, &IID_IDXGIResource1, (void **)&parent_resource2, + &subresource_index); + ok_(__FILE__, line)(hr == S_OK, "Failed to get parent texture pointer, hr %#lx.\n", hr); + ok_(__FILE__, line)(surface != subresource_surface, + "Expected the surface is not the same one used for creating the bitmap.\n"); + ok_(__FILE__, line)(parent_resource2 == parent_resource, + "Expected the bitmap surface is subresource surface of the parent surface.\n"); + IDXGIResource1_Release(parent_resource2); + check_interface_(line, surface, &IID_ID3D10Texture2D, FALSE); + check_interface_(line, surface, &IID_ID3D11Texture2D, FALSE); + } + + hr = IDXGISurface2_GetResource(surface2, &IID_ID3D10Texture2D, (void **)&parent_texture, + &subresource_index); + ok_(__FILE__, line)(hr == S_OK, "Failed to get parent texture pointer, hr %#lx.\n", hr); + ID3D10Texture2D_GetDesc(parent_texture, &texture_desc); + + if (options & D2D1_BITMAP_OPTIONS_TARGET) + bind_flags |= D3D10_BIND_RENDER_TARGET; + if (!(options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW)) + bind_flags |= D3D10_BIND_SHADER_RESOURCE; + if (options & D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE) + misc_flags |= D3D10_RESOURCE_MISC_GDI_COMPATIBLE; + if (options & D2D1_BITMAP_OPTIONS_CPU_READ) + { + usage |= D3D11_USAGE_STAGING; + cpu_access_flags |= D3D11_CPU_ACCESS_READ; + } + + ok_(__FILE__, line)(texture_desc.Usage == usage, "Unexpected usage %#x for bitmap options %#x.\n", + texture_desc.Usage, options); + ok_(__FILE__, line)(texture_desc.BindFlags == bind_flags, + "Unexpected bind flags %#x for bitmap options %#x.\n", texture_desc.BindFlags, options); + ok_(__FILE__, line)(texture_desc.CPUAccessFlags == cpu_access_flags, + "Unexpected cpu access flags %#x for bitmap options %#x.\n", + texture_desc.CPUAccessFlags, options); + ok_(__FILE__, line)(texture_desc.MiscFlags == misc_flags, + "Unexpected misc flags %#x for bitmap options %#x.\n", texture_desc.MiscFlags, options); + + pixel_size = ID2D1Bitmap_GetPixelSize(bitmap); + if (!pixel_size.width || !pixel_size.height) + pixel_size.width = pixel_size.height = 1; + + hr = IDXGISurface2_GetDesc(surface2, &surface_desc); + ok_(__FILE__, line)(hr == S_OK, "Failed to get surface description, hr %#lx.\n", hr); + ok_(__FILE__, line)(surface_desc.Width == pixel_size.width, "Got width %u, expected %u.\n", + surface_desc.Width, pixel_size.width); + ok_(__FILE__, line)(surface_desc.Height == pixel_size.height, "Got height %u, expected %u.\n", + surface_desc.Height, pixel_size.height); + + /* Test drawing with the bitmap created from subresource surface */ + if (options & D2D1_BITMAP_OPTIONS_TARGET) + { + /* Test bitmap as rendering destination */ + ID2D1DeviceContext_BeginDraw(ctx->context); + ID2D1DeviceContext_SetTarget(ctx->context, (ID2D1Image *)bitmap); + ID2D1DeviceContext_Clear(ctx->context, &test_colours_f[subresource_index]); + ID2D1DeviceContext_SetTarget(ctx->context, NULL); + hr = ID2D1DeviceContext_EndDraw(ctx->context, NULL, NULL); + ok_(__FILE__, line)(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + if ((rb.d3d11 = ctx->d3d11)) + get_d3d11_surface_readback(surface, &rb); + else + get_d3d10_surface_readback(surface, &rb); + colour = get_readback_colour(&rb, 0, 0); + + ok_(__FILE__, line)(compare_colour(colour, test_colours[subresource_index], 1), + "Got unexpected colour %#lx, expected %#lx.\n", colour, test_colours[subresource_index]); + release_resource_readback(&rb); + + /* Test bitmap as rendering source */ + if (!(options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW)) + { + set_size_u(&size, pixel_size.width, pixel_size.height); + bitmap_desc.dpiX = 96.0f; + bitmap_desc.dpiY = 96.0f; + bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; + bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE; + bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET; + bitmap_desc.colorContext = NULL; + hr = ID2D1DeviceContext_CreateBitmap(ctx->context, size, NULL, 0, &bitmap_desc, &target_bitmap); + ok_(__FILE__, line)(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1Bitmap1_GetSurface(target_bitmap, &target_surface); + ok_(__FILE__, line)(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + ID2D1DeviceContext_BeginDraw(ctx->context); + ID2D1DeviceContext_SetTarget(ctx->context, (ID2D1Image *)target_bitmap); + ID2D1DeviceContext_DrawBitmap(ctx->context, bitmap, NULL, 1.0f, + D2D1_INTERPOLATION_MODE_LINEAR, NULL, NULL); + hr = ID2D1DeviceContext_EndDraw(ctx->context, NULL, NULL); + ok_(__FILE__, line)(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + if ((rb.d3d11 = ctx->d3d11)) + get_d3d11_surface_readback(target_surface, &rb); + else + get_d3d10_surface_readback(target_surface, &rb); + colour = get_readback_colour(&rb, 0, 0); + + expected_colour = succeed_draw ? test_colours[subresource_index] : 0; + todo_wine_if(!succeed_draw) + ok_(__FILE__, line)(compare_colour(colour, expected_colour, 1), + "Got unexpected colour %#lx, expected %#lx.\n", colour, expected_colour); + release_resource_readback(&rb); + + IDXGISurface_Release(target_surface); + ID2D1Bitmap1_Release(target_bitmap); + } + } + + ID3D10Texture2D_Release(parent_texture); + IDXGISurface2_Release(surface2); + IDXGISurface_Release(surface); + ID2D1Bitmap1_Release(bitmap1); +} + static inline struct geometry_sink *impl_from_ID2D1SimplifiedGeometrySink(ID2D1SimplifiedGeometrySink *iface) { return CONTAINING_RECORD(iface, struct geometry_sink, ID2D1SimplifiedGeometrySink_iface); @@ -14150,11 +14350,38 @@ static void test_bitmap_create(BOOL d3d11) { D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE }, { D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ }, }; + static const struct + { + unsigned int mip_levels; + unsigned int array_size; + unsigned int bind_flags; + unsigned int misc_flags; + unsigned int usage; + unsigned int cpu_access_flags; + unsigned int options; + } subresource_tests[] = + { + {1, 1, D3D10_BIND_RENDER_TARGET, 0, D3D10_USAGE_DEFAULT, 0, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW}, + {2, 2, D3D10_BIND_RENDER_TARGET, 0, D3D10_USAGE_DEFAULT, 0, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW}, + {1, 1, D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE, 0, D3D10_USAGE_DEFAULT, 0, D2D1_BITMAP_OPTIONS_TARGET}, + {2, 2, D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE, 0, D3D10_USAGE_DEFAULT, 0, D2D1_BITMAP_OPTIONS_TARGET}, + {1, 1, D3D10_BIND_RENDER_TARGET, D3D10_RESOURCE_MISC_GDI_COMPATIBLE, D3D10_USAGE_DEFAULT, 0 , D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE}, + {1, 2, D3D10_BIND_RENDER_TARGET, D3D10_RESOURCE_MISC_GDI_COMPATIBLE, D3D10_USAGE_DEFAULT, 0 , D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE}, + {1, 1, 0, 0, D3D10_USAGE_STAGING, D3D10_CPU_ACCESS_READ, D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ}, + {2, 2, 0, 0, D3D10_USAGE_STAGING, D3D10_CPU_ACCESS_READ, D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ}, + }; + unsigned int i, j, subresource_count; D2D1_BITMAP_PROPERTIES1 bitmap_desc; + D3D10_TEXTURE2D_DESC texture_desc; struct d2d1_test_context ctx; + BOOL expect_parent_surface; + ID3D10Device *d3d_device; + ID3D10Texture2D *texture; + IDXGIResource1 *resource; + IDXGISurface2 *surface2; + ID2D1Bitmap *bitmap2; ID2D1Bitmap1 *bitmap; D2D1_SIZE_U size; - unsigned int i; HRESULT hr;
if (!init_test_context(&ctx, d3d11)) @@ -14195,6 +14422,73 @@ static void test_bitmap_create(BOOL d3d11) winetest_pop_context(); }
+ /* Subresource surface */ + hr = IDXGIDevice_QueryInterface(ctx.device, &IID_ID3D10Device, (void **)&d3d_device); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + for (i = 0; i < ARRAY_SIZE(subresource_tests); i++) + { + winetest_push_context("Test %u", i); + + texture_desc.Width = 512; + texture_desc.Height = 512; + texture_desc.MipLevels = subresource_tests[i].mip_levels; + texture_desc.ArraySize = subresource_tests[i].array_size; + texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.Usage = subresource_tests[i].usage; + texture_desc.BindFlags = subresource_tests[i].bind_flags; + texture_desc.CPUAccessFlags = subresource_tests[i].cpu_access_flags; + texture_desc.MiscFlags = subresource_tests[i].misc_flags; + hr = ID3D10Device_CreateTexture2D(d3d_device, &texture_desc, NULL, &texture); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID3D10Texture2D_QueryInterface(texture, &IID_IDXGIResource1, (void **)&resource); + ID3D10Texture2D_Release(texture); + + subresource_count = subresource_tests[i].mip_levels * subresource_tests[i].array_size; + expect_parent_surface = subresource_count == 1; + for (j = 0; j < subresource_count; j++) + { + winetest_push_context("Subtest %u", j); + + hr = IDXGIResource1_CreateSubresourceSurface(resource, j, &surface2); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + memset(&bitmap_desc, 0, sizeof(bitmap_desc)); + bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; + bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE; + bitmap_desc.bitmapOptions = subresource_tests[i].options; + hr = ID2D1DeviceContext_CreateSharedBitmap(ctx.context, &IID_IDXGISurface2, surface2, + (const D2D1_BITMAP_PROPERTIES *)&bitmap_desc, &bitmap2); + todo_wine + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + check_bitmap_subresource_surface(&ctx, bitmap2, resource, (IDXGISurface *)surface2, + expect_parent_surface, subresource_tests[i].options, TRUE); + ID2D1Bitmap_Release(bitmap2); + } + + hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, + (IDXGISurface *)surface2, &bitmap_desc, &bitmap); + todo_wine + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + check_bitmap_subresource_surface(&ctx, (ID2D1Bitmap *)bitmap, resource, + (IDXGISurface *)surface2, expect_parent_surface, subresource_tests[i].options, FALSE); + ID2D1Bitmap1_Release(bitmap); + } + + IDXGISurface2_Release(surface2); + winetest_pop_context(); + } + IDXGIResource1_Release(resource); + winetest_pop_context(); + } + + ID3D10Device_Release(d3d_device); release_test_context(&ctx); }
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/d2d1/bitmap.c | 206 +++++++++++++++++++++++++++++++---- dlls/d2d1/d2d1_private.h | 3 + dlls/d2d1/dc_render_target.c | 3 +- dlls/d2d1/device.c | 22 +++- dlls/d2d1/tests/d2d1.c | 20 +--- 5 files changed, 214 insertions(+), 40 deletions(-)
diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c index e5048611519..047be8879eb 100644 --- a/dlls/d2d1/bitmap.c +++ b/dlls/d2d1/bitmap.c @@ -36,7 +36,7 @@ static HRESULT d2d_bitmap_unmap(struct d2d_bitmap *bitmap)
ID3D11Resource_GetDevice(bitmap->resource, &device); ID3D11Device_GetImmediateContext(device, &context); - ID3D11DeviceContext_Unmap(context, bitmap->resource, 0); + ID3D11DeviceContext_Unmap(context, bitmap->resource, bitmap->subresource_idx == ~0u ? 0 : bitmap->subresource_idx); ID3D11DeviceContext_Release(context); ID3D11Device_Release(device);
@@ -172,9 +172,11 @@ static HRESULT STDMETHODCALLTYPE d2d_bitmap_CopyFromBitmap(ID2D1Bitmap1 *iface,
ID3D11Resource_GetDevice(dst_bitmap->resource, &device); ID3D11Device_GetImmediateContext(device, &context); - ID3D11DeviceContext_CopySubresourceRegion(context, dst_bitmap->resource, 0, - dst_point ? dst_point->x : 0, dst_point ? dst_point->y : 0, 0, - src_bitmap->resource, 0, src_rect ? &box : NULL); + ID3D11DeviceContext_CopySubresourceRegion(context, dst_bitmap->resource, + dst_bitmap->subresource_idx == ~0u ? 0 : dst_bitmap->subresource_idx, + dst_point ? dst_point->x : 0, dst_point ? dst_point->y : 0, + 0, src_bitmap->resource, src_bitmap->subresource_idx == ~0u ? 0 : src_bitmap->subresource_idx, + src_rect ? &box : NULL); ID3D11DeviceContext_Release(context); ID3D11Device_Release(device);
@@ -211,7 +213,9 @@ static HRESULT STDMETHODCALLTYPE d2d_bitmap_CopyFromMemory(ID2D1Bitmap1 *iface,
ID3D11Resource_GetDevice(bitmap->resource, &device); ID3D11Device_GetImmediateContext(device, &context); - ID3D11DeviceContext_UpdateSubresource(context, bitmap->resource, 0, dst_rect ? &box : NULL, src_data, pitch, 0); + ID3D11DeviceContext_UpdateSubresource(context, bitmap->resource, + bitmap->subresource_idx == ~0u ? 0 : bitmap->subresource_idx, dst_rect ? &box : NULL, + src_data, pitch, 0); ID3D11DeviceContext_Release(context); ID3D11Device_Release(device);
@@ -279,8 +283,8 @@ static HRESULT STDMETHODCALLTYPE d2d_bitmap_Map(ID2D1Bitmap1 *iface, D2D1_MAP_OP
ID3D11Resource_GetDevice(bitmap->resource, &device); ID3D11Device_GetImmediateContext(device, &context); - if (SUCCEEDED(hr = ID3D11DeviceContext_Map(context, bitmap->resource, 0, map_type, - 0, &mapped_resource))) + if (SUCCEEDED(hr = ID3D11DeviceContext_Map(context, bitmap->resource, + bitmap->subresource_idx == ~0u ? 0 : bitmap->subresource_idx, map_type, 0, &mapped_resource))) { bitmap->mapped_resource = mapped_resource; } @@ -363,8 +367,149 @@ static BOOL format_supported(const D2D1_PIXEL_FORMAT *format) return FALSE; }
+HRESULT d2d_get_surface_from_resource(ID3D11Resource *resource, UINT subresource_idx, + REFIID surface_iid, void **surface) +{ + IDXGIResource1 *resource1; + IDXGISurface2 *surface2; + HRESULT hr; + + if (SUCCEEDED(ID3D11Resource_QueryInterface(resource, surface_iid, surface))) + return S_OK; + + /* Resource has multiple mipmap levels or array. Query for the subresource surface instead */ + if (FAILED(hr = ID3D11Resource_QueryInterface(resource, &IID_IDXGIResource1, (void **)&resource1))) + return hr; + + if (FAILED(hr = IDXGIResource1_CreateSubresourceSurface(resource1, subresource_idx, &surface2))) + { + IDXGIResource1_Release(resource1); + return hr; + } + + hr = IDXGISurface2_QueryInterface(surface2, surface_iid, surface); + IDXGISurface2_Release(surface2); + IDXGIResource1_Release(resource1); + return hr; +} + +HRESULT d2d_get_resource_from_surface(IDXGISurface *surface, REFIID resource_iid, + UINT *subresource_idx, void **resource) +{ + IDXGISurface2 *surface2; + UINT index; + HRESULT hr; + + if (subresource_idx) + *subresource_idx = ~0u; + + if (SUCCEEDED(IDXGISurface_QueryInterface(surface, resource_iid, resource))) + return S_OK; + + /* Get the parent resource if the surface is a subresource surface */ + if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_IDXGISurface2, (void **)&surface2))) + return hr; + + hr = IDXGISurface2_GetResource(surface2, resource_iid, resource, &index); + if (SUCCEEDED(hr) && subresource_idx) + *subresource_idx = index; + IDXGISurface2_Release(surface2); + return hr; +} + +static void d2d_resource_get_rtv_desc(ID3D11Resource *resource, UINT subresource_idx, + D3D11_RENDER_TARGET_VIEW_DESC *rtv_desc) +{ + D3D11_TEXTURE2D_DESC texture_desc; + ID3D11Texture2D *texture; + + ID3D11Resource_QueryInterface(resource, &IID_ID3D11Texture2D, (void **)&texture); + ID3D11Texture2D_GetDesc(texture, &texture_desc); + ID3D11Texture2D_Release(texture); + + rtv_desc->Format = texture_desc.Format; + if (texture_desc.ArraySize > 1) + { + if (texture_desc.SampleDesc.Count == 1) + { + rtv_desc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtv_desc->Texture2DArray.MipSlice = subresource_idx % texture_desc.MipLevels; + rtv_desc->Texture2DArray.FirstArraySlice = subresource_idx / texture_desc.MipLevels; + rtv_desc->Texture2DArray.ArraySize = 1; + } + else + { + rtv_desc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY; + rtv_desc->Texture2DMSArray.FirstArraySlice = subresource_idx; + rtv_desc->Texture2DMSArray.ArraySize = 1; + } + } + else + { + if (texture_desc.SampleDesc.Count == 1) + { + rtv_desc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtv_desc->Texture2D.MipSlice = subresource_idx; + } + else + { + rtv_desc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; + } + } +} + +static void d2d_resource_get_srv_desc(ID3D11Resource *resource, UINT subresource_idx, + D3D11_SHADER_RESOURCE_VIEW_DESC *srv_desc) +{ + D3D11_TEXTURE2D_DESC texture_desc; + ID3D11Texture2D *texture; + + ID3D11Resource_QueryInterface(resource, &IID_ID3D11Texture2D, (void **)&texture); + ID3D11Texture2D_GetDesc(texture, &texture_desc); + ID3D11Texture2D_Release(texture); + + srv_desc->Format = texture_desc.Format; + + /* Always use 2d texture array view dimension even if it's not a 2d texture array. See shape_ps_code. */ + if (subresource_idx == ~0u) + { + if (texture_desc.SampleDesc.Count == 1) + { + srv_desc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srv_desc->Texture2DArray.MostDetailedMip = 0; + srv_desc->Texture2DArray.FirstArraySlice = 0; + srv_desc->Texture2DArray.MipLevels = texture_desc.MipLevels; + srv_desc->Texture2DArray.ArraySize = texture_desc.ArraySize; + } + else + { + srv_desc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY; + srv_desc->Texture2DMSArray.FirstArraySlice = 0; + srv_desc->Texture2DMSArray.ArraySize = texture_desc.ArraySize; + } + } + else + { + if (texture_desc.SampleDesc.Count == 1) + { + srv_desc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srv_desc->Texture2DArray.MostDetailedMip = subresource_idx % texture_desc.MipLevels; + srv_desc->Texture2DArray.FirstArraySlice = subresource_idx / texture_desc.MipLevels; + srv_desc->Texture2DArray.MipLevels = 1; + srv_desc->Texture2DArray.ArraySize = 1; + } + else + { + srv_desc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY; + srv_desc->Texture2DMSArray.FirstArraySlice = subresource_idx; + srv_desc->Texture2DMSArray.ArraySize = 1; + } + } +} + static void d2d_bitmap_init(struct d2d_bitmap *bitmap, struct d2d_device_context *context, - ID3D11Resource *resource, D2D1_SIZE_U size, const D2D1_BITMAP_PROPERTIES1 *desc) + ID3D11Resource *resource, UINT subresource_idx, D2D1_SIZE_U size, + const D2D1_BITMAP_PROPERTIES1 *desc) { ID3D11Device *d3d_device; HRESULT hr; @@ -373,6 +518,7 @@ static void d2d_bitmap_init(struct d2d_bitmap *bitmap, struct d2d_device_context bitmap->refcount = 1; ID2D1Factory_AddRef(bitmap->factory = context->factory); ID3D11Resource_AddRef(bitmap->resource = resource); + bitmap->subresource_idx = subresource_idx; bitmap->pixel_size = size; bitmap->format = desc->pixelFormat; bitmap->dpi_x = desc->dpiX; @@ -380,18 +526,33 @@ static void d2d_bitmap_init(struct d2d_bitmap *bitmap, struct d2d_device_context bitmap->options = desc->bitmapOptions;
if (d2d_device_context_is_dxgi_target(context)) - ID3D11Resource_QueryInterface(resource, &IID_IDXGISurface, (void **)&bitmap->surface); + d2d_get_surface_from_resource(resource, subresource_idx, &IID_IDXGISurface, (void **)&bitmap->surface);
ID3D11Resource_GetDevice(resource, &d3d_device); if (bitmap->options & D2D1_BITMAP_OPTIONS_TARGET) { - if (FAILED(hr = ID3D11Device_CreateRenderTargetView(d3d_device, resource, NULL, &bitmap->rtv))) + if (subresource_idx != ~0u) + { + D3D11_RENDER_TARGET_VIEW_DESC rtv_desc; + + d2d_resource_get_rtv_desc(resource, subresource_idx, &rtv_desc); + hr = ID3D11Device_CreateRenderTargetView(d3d_device, resource, &rtv_desc, &bitmap->rtv); + } + else + { + hr = ID3D11Device_CreateRenderTargetView(d3d_device, resource, NULL, &bitmap->rtv); + } + + if (FAILED(hr)) WARN("Failed to create RTV, hr %#lx.\n", hr); }
if (!(bitmap->options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW)) { - if (FAILED(hr = ID3D11Device_CreateShaderResourceView(d3d_device, resource, NULL, &bitmap->srv))) + D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; + + d2d_resource_get_srv_desc(resource, subresource_idx, &srv_desc); + if (FAILED(hr = ID3D11Device_CreateShaderResourceView(d3d_device, resource, &srv_desc, &bitmap->srv))) WARN("Failed to create SRV, hr %#lx.\n", hr); } ID3D11Device_Release(d3d_device); @@ -487,7 +648,7 @@ HRESULT d2d_bitmap_create(struct d2d_device_context *context, D2D1_SIZE_U size,
if ((*bitmap = calloc(1, sizeof(**bitmap)))) { - d2d_bitmap_init(*bitmap, context, (ID3D11Resource *)texture, size, desc); + d2d_bitmap_init(*bitmap, context, (ID3D11Resource *)texture, ~0u, size, desc); TRACE("Created bitmap %p.\n", *bitmap); } ID3D11Texture2D_Release(texture); @@ -501,7 +662,7 @@ unsigned int d2d_get_bitmap_options_for_surface(IDXGISurface *surface) unsigned int options = 0; ID3D11Texture2D *texture;
- if (FAILED(IDXGISurface_QueryInterface(surface, &IID_ID3D11Texture2D, (void **)&texture))) + if (FAILED(d2d_get_resource_from_surface(surface, &IID_ID3D11Texture2D, NULL, (void **)&texture))) return 0;
ID3D11Texture2D_GetDesc(texture, &desc); @@ -576,27 +737,34 @@ HRESULT d2d_bitmap_create_shared(struct d2d_device_context *context, REFIID iid, goto failed; }
- d2d_bitmap_init(*bitmap, context, src_impl->resource, src_impl->pixel_size, desc); + d2d_bitmap_init(*bitmap, context, src_impl->resource, src_impl->subresource_idx, + src_impl->pixel_size, desc); TRACE("Created bitmap %p.\n", *bitmap);
failed: return hr; }
- if (IsEqualGUID(iid, &IID_IDXGISurface) || IsEqualGUID(iid, &IID_IDXGISurface1)) + if (IsEqualGUID(iid, &IID_IDXGISurface) || IsEqualGUID(iid, &IID_IDXGISurface1) + || IsEqualGUID(iid, &IID_IDXGISurface2)) { DXGI_SURFACE_DESC surface_desc; IDXGISurface *surface = data; + UINT subresource_idx = ~0u; + ID3D11Texture2D *texture; ID3D11Resource *resource; D2D1_SIZE_U pixel_size; ID3D11Device *device; HRESULT hr;
- if (FAILED(IDXGISurface_QueryInterface(surface, &IID_ID3D11Resource, (void **)&resource))) + if (FAILED(hr = d2d_get_resource_from_surface(surface, &IID_ID3D11Texture2D, &subresource_idx, + (void **)&texture))) { - WARN("Failed to get d3d resource from dxgi surface.\n"); - return E_FAIL; + WARN("Surface is not from a 2D texture, hr %#lx.\n", hr); + return hr; } + ID3D11Texture2D_QueryInterface(texture, &IID_ID3D11Resource, (void **)&resource); + ID3D11Texture2D_Release(texture);
ID3D11Resource_GetDevice(resource, &device); ID3D11Device_Release(device); @@ -644,7 +812,7 @@ HRESULT d2d_bitmap_create_shared(struct d2d_device_context *context, REFIID iid, pixel_size.width = surface_desc.Width; pixel_size.height = surface_desc.Height;
- d2d_bitmap_init(*bitmap, context, resource, pixel_size, &d); + d2d_bitmap_init(*bitmap, context, resource, subresource_idx, pixel_size, &d); ID3D11Resource_Release(resource); TRACE("Created bitmap %p.\n", *bitmap);
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index 46999eaa272..ca0c6a1333b 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -430,6 +430,7 @@ struct d2d_bitmap ID3D11RenderTargetView *rtv; IDXGISurface *surface; ID3D11Resource *resource; + UINT subresource_idx; D3D11_MAPPED_SUBRESOURCE mapped_resource; D2D1_SIZE_U pixel_size; D2D1_PIXEL_FORMAT format; @@ -446,6 +447,8 @@ HRESULT d2d_bitmap_create_from_wic_bitmap(struct d2d_device_context *context, IW const D2D1_BITMAP_PROPERTIES1 *desc, struct d2d_bitmap **bitmap); unsigned int d2d_get_bitmap_options_for_surface(IDXGISurface *surface); struct d2d_bitmap *unsafe_impl_from_ID2D1Bitmap(ID2D1Bitmap *iface); +HRESULT d2d_get_surface_from_resource(ID3D11Resource *resource, UINT subresource_idx, REFIID surface_iid, void **surface); +HRESULT d2d_get_resource_from_surface(IDXGISurface *surface, REFIID resource_iid, UINT *subresource_idx, void **resource);
struct d2d_state_block { diff --git a/dlls/d2d1/dc_render_target.c b/dlls/d2d1/dc_render_target.c index b09b77ff788..d8028b016ac 100644 --- a/dlls/d2d1/dc_render_target.c +++ b/dlls/d2d1/dc_render_target.c @@ -751,7 +751,8 @@ static HRESULT STDMETHODCALLTYPE d2d_dc_render_target_BindDC(ID2D1DCRenderTarget }
bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap); - ID3D11Resource_QueryInterface(bitmap_impl->resource, &IID_IDXGISurface1, (void **)&dxgi_surface); + d2d_get_surface_from_resource(bitmap_impl->resource, bitmap_impl->subresource_idx, + &IID_IDXGISurface1, (void **)&dxgi_surface);
ID2D1DeviceContext_SetTarget(context, (ID2D1Image *)bitmap); ID2D1Bitmap_Release(bitmap); diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index 59e93bfac38..f1472fa7c9f 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -418,7 +418,8 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSharedBitmap(ID2D1Devi if (desc) { memcpy(&bitmap_desc, desc, sizeof(*desc)); - if (IsEqualIID(iid, &IID_IDXGISurface) || IsEqualIID(iid, &IID_IDXGISurface1)) + if (IsEqualIID(iid, &IID_IDXGISurface) || IsEqualIID(iid, &IID_IDXGISurface1) + || IsEqualIID(iid, &IID_IDXGISurface2)) bitmap_desc.bitmapOptions = d2d_get_bitmap_options_for_surface(data); else bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; @@ -2204,10 +2205,18 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface( D2D1_BITMAP_PROPERTIES1 bitmap_desc; unsigned int surface_options; struct d2d_bitmap *object; + ID3D11Texture2D *texture; HRESULT hr;
TRACE("iface %p, surface %p, desc %p, bitmap %p.\n", iface, surface, desc, bitmap);
+ if (FAILED(hr = d2d_get_resource_from_surface(surface, &IID_ID3D11Texture2D, NULL, (void **)&texture))) + { + WARN("Surface is not from a 2D texture, hr %#lx.\n", hr); + return hr; + } + ID3D11Texture2D_Release(texture); + surface_options = d2d_get_bitmap_options_for_surface(surface);
if (desc) @@ -3460,7 +3469,8 @@ static HRESULT d2d_gdi_interop_get_surface(struct d2d_device_context *context, I return D2DERR_TARGET_NOT_GDI_COMPATIBLE;
ID3D11RenderTargetView_GetResource(context->target.bitmap->rtv, &resource); - hr = ID3D11Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface); + hr = d2d_get_surface_from_resource(resource, context->target.bitmap->subresource_idx, + &IID_IDXGISurface1, (void **)surface); ID3D11Resource_Release(resource); if (FAILED(hr)) { @@ -3815,7 +3825,7 @@ static const char shape_ps_code[] = "} colour_brush, opacity_brush;\n" "\n" "SamplerState s0, s1;\n" - "Texture2D t0, t1;\n" + "Texture2DArray t0, t1;\n" "Buffer<float4> b0, b1;\n" "\n" "struct input\n" @@ -3904,7 +3914,7 @@ static const char shape_ps_code[] = " return sample_gradient(gradient, stop_count, l / t);\n" "}\n" "\n" - "float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)\n" + "float4 brush_bitmap(struct brush brush, Texture2DArray t, SamplerState s, float2 position)\n" "{\n" " float3 transform[2];\n" " bool ignore_alpha;\n" @@ -3917,13 +3927,13 @@ static const char shape_ps_code[] = "\n" " texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;\n" " texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;\n" - " colour = t.Sample(s, texcoord);\n" + " colour = t.Sample(s, float3(texcoord, 0.0));\n" " if (ignore_alpha)\n" " colour.a = 1.0;\n" " return colour;\n" "}\n" "\n" - "float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)\n" + "float4 sample_brush(struct brush brush, Texture2DArray t, SamplerState s, Buffer<float4> b, float2 position)\n" "{\n" " if (brush.type == BRUSH_TYPE_SOLID)\n" " return brush.data[0] * brush.opacity;\n" diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 279b4d9e865..3693f07c796 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -14461,25 +14461,17 @@ static void test_bitmap_create(BOOL d3d11) bitmap_desc.bitmapOptions = subresource_tests[i].options; hr = ID2D1DeviceContext_CreateSharedBitmap(ctx.context, &IID_IDXGISurface2, surface2, (const D2D1_BITMAP_PROPERTIES *)&bitmap_desc, &bitmap2); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - check_bitmap_subresource_surface(&ctx, bitmap2, resource, (IDXGISurface *)surface2, - expect_parent_surface, subresource_tests[i].options, TRUE); - ID2D1Bitmap_Release(bitmap2); - } + check_bitmap_subresource_surface(&ctx, bitmap2, resource, (IDXGISurface *)surface2, + expect_parent_surface, subresource_tests[i].options, TRUE); + ID2D1Bitmap_Release(bitmap2);
hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, (IDXGISurface *)surface2, &bitmap_desc, &bitmap); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - check_bitmap_subresource_surface(&ctx, (ID2D1Bitmap *)bitmap, resource, - (IDXGISurface *)surface2, expect_parent_surface, subresource_tests[i].options, FALSE); - ID2D1Bitmap1_Release(bitmap); - } + check_bitmap_subresource_surface(&ctx, (ID2D1Bitmap *)bitmap, resource, + (IDXGISurface *)surface2, expect_parent_surface, subresource_tests[i].options, FALSE); + ID2D1Bitmap1_Release(bitmap);
IDXGISurface2_Release(surface2); winetest_pop_context();