For React Native
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/d2d1/tests/d2d1.c | 335 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 332 insertions(+), 3 deletions(-)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 2b894695c98..54b856f2c56 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,129 @@ 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) _check_bitmap_subresource_surface(__LINE__, a, b, c, d, e, f) +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) +{ + unsigned int usage = 0, bind_flags = 0, cpu_access_flags = 0, misc_flags = 0; + static const D2D1_COLOR_F red_colour_f = {1.0f, 0.0f, 0.0f, 1.0f}; + static const DWORD red_colour = 0xffff0000; + D3D10_TEXTURE2D_DESC texture_desc; + IDXGIResource1 *parent_resource2; + ID3D10Texture2D *parent_texture; + DXGI_SURFACE_DESC surface_desc; + D2D1_BITMAP_OPTIONS options; + struct resource_readback rb; + IDXGISurface2 *surface2; + D2D1_SIZE_U pixel_size; + UINT subresource_index; + ID2D1Bitmap1 *bitmap1; + IDXGISurface *surface; + IDXGIObject *object; + DWORD colour; + 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 (texture_desc.BindFlags & D3D10_BIND_RENDER_TARGET) + { + ID2D1DeviceContext_BeginDraw(ctx->context); + ID2D1DeviceContext_SetTarget(ctx->context, (ID2D1Image *)bitmap); + ID2D1DeviceContext_Clear(ctx->context, &red_colour_f); + hr = ID2D1DeviceContext_EndDraw(ctx->context, NULL, NULL); + ok(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(compare_colour(colour, red_colour, 1), + "Got unexpected colour %#lx, expected %#lx.\n", colour, red_colour); + release_resource_readback(&rb); + } + + 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 +14294,43 @@ 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 resource_type; /* 0 -> ID3D10Buffer, 1~3 -> ID3D10Texture1/2/3D */ + unsigned int width; + unsigned int height; + 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[] = + { + {0, 512, 1, 1, 1, D3D10_BIND_RENDER_TARGET, 0, D3D10_USAGE_DEFAULT, 0, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW}, + {1, 512, 1, 1, 1, D3D10_BIND_RENDER_TARGET, 0, D3D10_USAGE_DEFAULT, 0, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW}, + {1, 512, 1, 2, 2, D3D10_BIND_RENDER_TARGET, 0, D3D10_USAGE_DEFAULT, 0, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW}, + {2, 512, 512, 1, 1, D3D10_BIND_RENDER_TARGET, 0, D3D10_USAGE_DEFAULT, 0, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW}, + {2, 512, 512, 2, 2, D3D10_BIND_RENDER_TARGET, 0, D3D10_USAGE_DEFAULT, 0, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW}, + {2, 512, 512, 1, 1, D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE, 0, D3D10_USAGE_DEFAULT, 0, D2D1_BITMAP_OPTIONS_TARGET}, + {2, 512, 512, 2, 2, D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE, 0, D3D10_USAGE_DEFAULT, 0, D2D1_BITMAP_OPTIONS_TARGET}, + {2, 512, 512, 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}, + {2, 512, 512, 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}, + {2, 512, 512, 1, 1, 0, 0, D3D10_USAGE_STAGING, D3D10_CPU_ACCESS_READ, D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ}, + {2, 512, 512, 2, 2, 0, 0, D3D10_USAGE_STAGING, D3D10_CPU_ACCESS_READ, D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ}, + {3, 512, 512, 1, 1, D3D10_BIND_RENDER_TARGET, 0, D3D10_USAGE_DEFAULT, 0, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW}, + }; + unsigned int i, j, subresource_count; D2D1_BITMAP_PROPERTIES1 bitmap_desc; struct d2d1_test_context ctx; + BOOL expect_parent_surface; + ID3D10Device *d3d_device; + 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 +14371,159 @@ 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); + + /* ID3D10Buffer */ + if (subresource_tests[i].resource_type == 0) + { + D3D10_BUFFER_DESC buffer_desc; + ID3D10Buffer *buffer; + + buffer_desc.ByteWidth = subresource_tests[i].width; + buffer_desc.Usage = subresource_tests[i].usage; + buffer_desc.BindFlags = subresource_tests[i].bind_flags; + buffer_desc.CPUAccessFlags = subresource_tests[i].cpu_access_flags; + buffer_desc.MiscFlags = subresource_tests[i].misc_flags; + hr = ID3D10Device_CreateBuffer(d3d_device, &buffer_desc, NULL, &buffer); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID3D10Buffer_QueryInterface(buffer, &IID_IDXGIResource1, (void **)&resource); + ID3D10Buffer_Release(buffer); + } + /* ID3D10Texture1D */ + else if (subresource_tests[i].resource_type == 1) + { + D3D10_TEXTURE1D_DESC texture_desc; + ID3D10Texture1D *texture; + + texture_desc.Width = subresource_tests[i].width; + 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.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_CreateTexture1D(d3d_device, &texture_desc, NULL, &texture); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID3D10Texture1D_QueryInterface(texture, &IID_IDXGIResource1, (void **)&resource); + ID3D10Texture1D_Release(texture); + } + /* ID3D10Texture2D */ + else if (subresource_tests[i].resource_type == 2) + { + D3D10_TEXTURE2D_DESC texture_desc; + ID3D10Texture2D *texture; + + texture_desc.Width = subresource_tests[i].width; + texture_desc.Height = subresource_tests[i].height; + 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); + } + /* ID3D10Texture3D */ + else if (subresource_tests[i].resource_type == 3) + { + D3D10_TEXTURE3D_DESC texture_desc; + ID3D10Texture3D *texture; + + texture_desc.Width = subresource_tests[i].width; + texture_desc.Height = subresource_tests[i].height; + texture_desc.Depth = subresource_tests[i].array_size; + texture_desc.MipLevels = subresource_tests[i].mip_levels; + texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + 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_CreateTexture3D(d3d_device, &texture_desc, NULL, &texture); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID3D10Texture3D_QueryInterface(texture, &IID_IDXGIResource1, (void **)&resource); + ID3D10Texture3D_Release(texture); + } + else + { + ok(0, "Unexpected resource type %u.\n", subresource_tests[i].resource_type); + winetest_pop_context(); + continue; + } + + 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); + /* Only accepts surface from 2d texture */ + if (subresource_tests[i].resource_type == 2) + { + 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); + ID2D1Bitmap_Release(bitmap2); + } + } + else + { + todo_wine + ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr); + } + + hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, + (IDXGISurface *)surface2, &bitmap_desc, &bitmap); + /* Only accepts surface from 2d texture */ + if (subresource_tests[i].resource_type == 2) + { + 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); + ID2D1Bitmap1_Release(bitmap); + } + } + else + { + todo_wine + ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr); + } + + 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 | 224 ++++++++++++++++++++++++++++++++--- dlls/d2d1/d2d1_private.h | 3 + dlls/d2d1/dc_render_target.c | 3 +- dlls/d2d1/device.c | 14 ++- dlls/d2d1/tests/d2d1.c | 22 +--- 5 files changed, 228 insertions(+), 38 deletions(-)
diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c index e5048611519..ccc785039ce 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); ID3D11DeviceContext_Release(context); ID3D11Device_Release(device);
@@ -172,9 +172,9 @@ 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, dst_point ? dst_point->x : 0, dst_point ? dst_point->y : 0, + 0, src_bitmap->resource, src_bitmap->subresource_idx, src_rect ? &box : NULL); ID3D11DeviceContext_Release(context); ID3D11Device_Release(device);
@@ -211,7 +211,8 @@ 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, + dst_rect ? &box : NULL, src_data, pitch, 0); ID3D11DeviceContext_Release(context); ID3D11Device_Release(device);
@@ -279,8 +280,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, + map_type, 0, &mapped_resource))) { bitmap->mapped_resource = mapped_resource; } @@ -363,8 +364,161 @@ 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 = 0; + + 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 bool d2d_resource_need_view_desc(ID3D11Resource *resource) +{ + IDXGISurface *surface; + HRESULT hr; + + /* IDXGISurface is not available if the resource has multiple mipmap levels or array */ + hr = ID3D11Resource_QueryInterface(resource, &IID_IDXGISurface, (void **)&surface); + if (SUCCEEDED(hr)) + { + IDXGISurface_Release(surface); + return FALSE; + } + else + { + return TRUE; + } +} + +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; + if (texture_desc.ArraySize > 1) + { + 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; + } + } + else + { + if (texture_desc.SampleDesc.Count == 1) + { + srv_desc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srv_desc->Texture2D.MostDetailedMip = subresource_idx; + srv_desc->Texture2D.MipLevels = 1; + } + else + { + srv_desc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS; + } + } +} + 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 +527,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 +535,42 @@ 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 (d2d_resource_need_view_desc(resource)) + { + 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))) + if (d2d_resource_need_view_desc(resource)) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; + + d2d_resource_get_srv_desc(resource, subresource_idx, &srv_desc); + hr = ID3D11Device_CreateShaderResourceView(d3d_device, resource, &srv_desc, &bitmap->srv); + } + else + { + hr = ID3D11Device_CreateShaderResourceView(d3d_device, resource, NULL, &bitmap->srv); + } + + if (FAILED(hr)) WARN("Failed to create SRV, hr %#lx.\n", hr); } ID3D11Device_Release(d3d_device); @@ -487,7 +666,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, 0, size, desc); TRACE("Created bitmap %p.\n", *bitmap); } ID3D11Texture2D_Release(texture); @@ -501,7 +680,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 +755,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 = 0; + 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 +830,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..512ca00df86 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)) { diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 54b856f2c56..1b726c32ad3 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -14481,18 +14481,13 @@ static void test_bitmap_create(BOOL d3d11) /* Only accepts surface from 2d texture */ if (subresource_tests[i].resource_type == 2) { - 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); - ID2D1Bitmap_Release(bitmap2); - } + check_bitmap_subresource_surface(&ctx, bitmap2, resource, (IDXGISurface *)surface2, + expect_parent_surface, subresource_tests[i].options); + ID2D1Bitmap_Release(bitmap2); } else { - todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr); }
@@ -14501,18 +14496,13 @@ static void test_bitmap_create(BOOL d3d11) /* Only accepts surface from 2d texture */ if (subresource_tests[i].resource_type == 2) { - 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); - ID2D1Bitmap1_Release(bitmap); - } + check_bitmap_subresource_surface(&ctx, (ID2D1Bitmap *)bitmap, resource, + (IDXGISurface *)surface2, expect_parent_surface, subresource_tests[i].options); + ID2D1Bitmap1_Release(bitmap); } else { - todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr); }
Nikolay Sivov (@nsivov) commented about dlls/d2d1/bitmap.c:
srv_desc->Texture2DMSArray.ArraySize = 1;
}
- }
- else
- {
if (texture_desc.SampleDesc.Count == 1)
{
srv_desc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srv_desc->Texture2D.MostDetailedMip = subresource_idx;
srv_desc->Texture2D.MipLevels = 1;
}
else
{
srv_desc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
}
- }
Which one of those are actually used by React Native? I'd rather we keep it as simple as possible. I'm especially unsure about MS case, if it supposed to work at all.
Nikolay Sivov (@nsivov) commented about dlls/d2d1/bitmap.c:
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 (d2d_resource_need_view_desc(resource))
We could use ~0u for subresource index to indicate whole resource, this will make this check unnecessary.
Nikolay Sivov (@nsivov) commented about dlls/d2d1/tests/d2d1.c:
{ D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE }, { D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ }, };
- static const struct
- {
unsigned int resource_type; /* 0 -> ID3D10Buffer, 1~3 -> ID3D10Texture1/2/3D */
Let's test what application is actually using. Is that a 2DArray?
Nikolay Sivov (@nsivov) commented about dlls/d2d1/tests/d2d1.c:
hr = ID3D10Device_CreateTexture3D(d3d_device, &texture_desc, NULL, &texture);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = ID3D10Texture3D_QueryInterface(texture, &IID_IDXGIResource1, (void **)&resource);
ID3D10Texture3D_Release(texture);
}
else
{
ok(0, "Unexpected resource type %u.\n", subresource_tests[i].resource_type);
winetest_pop_context();
continue;
}
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++)
{
Checking every subresource seems unnecessary. I think it's enough to have tests for count>1 and index=1. Case for count==1 is the same as our existing tests, right?
Important thing this isn't testing is using such bitmaps for rendering. If 2DArray should work, we should have a test for e.g. 3 elements initialized to different color, and used with DrawBitmap(). This would be a short test.