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