So that d2d_device_context_IsSupported() can know what type and usage a render target is created for.
-- v2: d2d1: Implement d2d_device_context_IsSupported(). d2d1: Save render target type and usage. d2d1/tests: Test d2d_device_context_IsSupported().
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/d2d1/tests/d2d1.c | 255 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 254 insertions(+), 1 deletion(-)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 665c3200e21..d19166d8c51 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -1307,6 +1307,7 @@ static void check_bitmap_surface_(unsigned int line, ID2D1Bitmap *bitmap, BOOL h ID3D10Texture2D *texture; D2D1_SIZE_U pixel_size; DWORD bind_flags = 0; + DWORD misc_flags = 0;
ok_(__FILE__, line)(hr == S_OK, "Failed to get bitmap surface, hr %#lx.\n", hr); ok_(__FILE__, line)(!!surface, "Expected surface instance.\n"); @@ -1323,10 +1324,14 @@ static void check_bitmap_surface_(unsigned int line, ID2D1Bitmap *bitmap, BOOL h 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; + ok_(__FILE__, line)(desc.BindFlags == bind_flags, "Unexpected bind flags %#x for bitmap options %#x.\n", desc.BindFlags, options); ok_(__FILE__, line)(!desc.CPUAccessFlags, "Unexpected cpu access flags %#x.\n", desc.CPUAccessFlags); - ok_(__FILE__, line)(!desc.MiscFlags, "Unexpected misc flags %#x.\n", desc.MiscFlags); + ok_(__FILE__, line)(desc.MiscFlags == misc_flags, "Unexpected misc flags %#x for bitmap options %#x.\n", + desc.MiscFlags, options);
pixel_size = ID2D1Bitmap_GetPixelSize(bitmap); if (!pixel_size.width || !pixel_size.height) @@ -13166,6 +13171,253 @@ static void test_bitmap_create(BOOL d3d11) release_test_context(&ctx); }
+static void test_target_is_supported(BOOL d3d11) +{ + static const DWORD levels[] = {D2D1_FEATURE_LEVEL_DEFAULT, D2D1_FEATURE_LEVEL_9, D2D1_FEATURE_LEVEL_10}; + D2D1_RENDER_TARGET_PROPERTIES desc, template_desc, test_desc; + D2D1_BITMAP_PROPERTIES1 bitmap_desc; + ID2D1DeviceContext *device_context; + IDXGISwapChain *swapchain; + ID2D1Factory *factory; + ID2D1RenderTarget *rt; + IDXGISurface *surface; + ID2D1Bitmap1 *bitmap; + IDXGIDevice *device; + unsigned int i, j; + D2D1_SIZE_U size; + BOOL supported; + HWND window; + HRESULT hr; + ULONG ref; + + if (!(device = create_device(d3d11))) + { + skip("Failed to create device, skipping tests.\n"); + return; + } + + window = create_window(); + ok(!!window, "Failed to create test window.\n"); + swapchain = create_swapchain(device, window, TRUE); + ok(!!swapchain, "Failed to create swapchain.\n"); + hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface); + ok(hr == S_OK, "Failed to get buffer, hr %#lx.\n", hr); + hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + template_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT; + template_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN; + template_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE; + template_desc.dpiX = 96.0f; + template_desc.dpiY = 96.0f; + template_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE; + template_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT; + + /* Test that SetTarget() with a bitmap of a different usage doesn't change the render target usage */ + hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &template_desc, &rt); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&device_context); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(device_context == (ID2D1DeviceContext *)rt, "Got unexpected interface pointer.\n"); + supported = ID2D1RenderTarget_IsSupported(rt, &template_desc); + todo_wine ok(supported, "Expected supported.\n"); + + test_desc = template_desc; + test_desc.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE; + supported = ID2D1RenderTarget_IsSupported(rt, &test_desc); + ok(!supported, "Expected unsupported.\n"); + + memset(&bitmap_desc, 0, sizeof(bitmap_desc)); + bitmap_desc.pixelFormat = ID2D1DeviceContext_GetPixelFormat(device_context); + bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE; + size.width = 4; + size.height = 4; + hr = ID2D1DeviceContext_CreateBitmap(device_context, size, NULL, 0, &bitmap_desc, &bitmap); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE); + ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap); + supported = ID2D1DeviceContext_IsSupported(device_context, &test_desc); + ok(!supported, "Expected unsupported.\n"); + + ID2D1Bitmap1_Release(bitmap); + ID2D1DeviceContext_Release(device_context); + ID2D1RenderTarget_Release(rt); + + /* Type */ + for (i = D2D1_RENDER_TARGET_TYPE_DEFAULT; i <= D2D1_RENDER_TARGET_TYPE_HARDWARE; ++i) + { + desc = template_desc; + desc.type = i; + hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt); + if (FAILED(hr)) + continue; + + for (j = D2D1_RENDER_TARGET_TYPE_DEFAULT; j <= D2D1_RENDER_TARGET_TYPE_HARDWARE; ++j) + { + winetest_push_context("type %u test %u", i, j); + + test_desc = template_desc; + test_desc.type = j; + supported = ID2D1RenderTarget_IsSupported(rt, &test_desc); + if (i == j || (i == D2D1_RENDER_TARGET_TYPE_DEFAULT && j == D2D1_RENDER_TARGET_TYPE_HARDWARE) + || (i == D2D1_RENDER_TARGET_TYPE_HARDWARE && j == D2D1_RENDER_TARGET_TYPE_DEFAULT)) + todo_wine ok(supported, "Expected supported.\n"); + else + ok(!supported, "Expected unsupported.\n"); + + winetest_pop_context(); + } + + ID2D1RenderTarget_Release(rt); + } + + /* Pixel DXGI format */ + for (i = DXGI_FORMAT_UNKNOWN; i <= DXGI_FORMAT_V408; ++i) + { + if (i > DXGI_FORMAT_B4G4R4A4_UNORM && i < DXGI_FORMAT_P208) + continue; + + desc = template_desc; + desc.pixelFormat.format = i; + hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt); + if (FAILED(hr)) + continue; + + for (j = DXGI_FORMAT_UNKNOWN; j <= DXGI_FORMAT_V408; ++j) + { + if (j > DXGI_FORMAT_B4G4R4A4_UNORM && j < DXGI_FORMAT_P208) + continue; + + winetest_push_context("format %#x test %#x", i, j); + + test_desc = template_desc; + test_desc.pixelFormat.format = j; + supported = ID2D1RenderTarget_IsSupported(rt, &test_desc); + if (i == j || (i == DXGI_FORMAT_UNKNOWN && j == DXGI_FORMAT_B8G8R8A8_UNORM) + || (i == DXGI_FORMAT_B8G8R8A8_UNORM && j == DXGI_FORMAT_UNKNOWN)) + todo_wine ok(supported, "Expected supported.\n"); + else + ok(!supported, "Expected unsupported.\n"); + + winetest_pop_context(); + } + + ID2D1RenderTarget_Release(rt); + } + + /* Pixel alpha mode */ + for (i = D2D1_ALPHA_MODE_UNKNOWN; i <= D2D1_ALPHA_MODE_IGNORE; ++i) + { + desc = template_desc; + desc.pixelFormat.alphaMode = i; + hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt); + if (FAILED(hr)) + continue; + + for (j = D2D1_ALPHA_MODE_UNKNOWN; j <= D2D1_ALPHA_MODE_IGNORE; ++j) + { + winetest_push_context("alpha %#x test %#x", i, j); + + test_desc = template_desc; + test_desc.pixelFormat.alphaMode = j; + supported = ID2D1RenderTarget_IsSupported(rt, &test_desc); + if (i == j || j == D2D1_ALPHA_MODE_UNKNOWN) + todo_wine ok(supported, "Expected supported.\n"); + else + ok(!supported, "Expected unsupported.\n"); + + winetest_pop_context(); + } + + ID2D1RenderTarget_Release(rt); + } + + /* DPI */ + for (i = 0; i <= 192; i += 96) + { + desc = template_desc; + desc.dpiX = i; + desc.dpiY = i; + hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt); + if (FAILED(hr)) + continue; + + for (j = 0; j <= 192; j += 96) + { + winetest_push_context("dpi %#x test %#x", i, j); + + test_desc = template_desc; + test_desc.dpiX = j; + test_desc.dpiY = j; + supported = ID2D1RenderTarget_IsSupported(rt, &test_desc); + todo_wine ok(supported, "Expected supported.\n"); + + winetest_pop_context(); + } + + ID2D1RenderTarget_Release(rt); + } + + /* Usage */ + for (i = D2D1_RENDER_TARGET_USAGE_NONE; i <= D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE; ++i) + { + desc = template_desc; + desc.usage = i; + hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt); + if (FAILED(hr)) + continue; + + for (j = D2D1_RENDER_TARGET_USAGE_NONE; j <= D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE; ++j) + { + winetest_push_context("usage %#x test %#x", i, j); + + test_desc = template_desc; + test_desc.usage = j; + supported = ID2D1RenderTarget_IsSupported(rt, &test_desc); + if (i == j || (i == D2D1_RENDER_TARGET_USAGE_FORCE_BITMAP_REMOTING + && j == D2D1_RENDER_TARGET_USAGE_NONE)) + todo_wine ok(supported, "Expected supported.\n"); + else + ok(!supported, "Expected unsupported.\n"); + + winetest_pop_context(); + } + + ID2D1RenderTarget_Release(rt); + } + + /* Min level */ + for (i = 0; i < ARRAY_SIZE(levels); ++i) + { + desc = template_desc; + desc.minLevel = levels[i]; + hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt); + if (FAILED(hr)) + continue; + + for (j = 0; j < ARRAY_SIZE(levels); ++j) + { + winetest_push_context("level %#lx test %#lx", levels[i], levels[j]); + + test_desc = template_desc; + test_desc.minLevel = levels[j]; + supported = ID2D1RenderTarget_IsSupported(rt, &test_desc); + todo_wine ok(supported, "Expected supported.\n"); + + winetest_pop_context(); + } + + ID2D1RenderTarget_Release(rt); + } + + ID2D1Factory_Release(factory); + IDXGISurface_Release(surface); + IDXGISwapChain_Release(swapchain); + DestroyWindow(window); + ref = IDXGIDevice_Release(device); + ok(!ref, "Device has %lu references left.\n", ref); +} + START_TEST(d2d1) { HMODULE d2d1_dll = GetModuleHandleA("d2d1.dll"); @@ -13250,6 +13502,7 @@ START_TEST(d2d1) queue_test(test_image_bounds); queue_test(test_bitmap_map); queue_test(test_bitmap_create); + queue_test(test_target_is_supported);
run_queued_tests(); }
From: Zhiyi Zhang zzhang@codeweavers.com
So that d2d_device_context_IsSupported() can know what type and usage a render target is created for. --- dlls/d2d1/device.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index 32519f662c9..b35e99acaf8 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -4448,6 +4448,8 @@ HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, return hr; }
+ object->desc.type = desc->type; + object->desc.usage = desc->usage; ID2D1DeviceContext1_SetDpi(&object->ID2D1DeviceContext1_iface, bitmap_desc.dpiX, bitmap_desc.dpiY);
if (surface)
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/d2d1/device.c | 26 ++++++++++++++++++++++++-- dlls/d2d1/tests/d2d1.c | 14 +++++++------- 2 files changed, 31 insertions(+), 9 deletions(-)
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index b35e99acaf8..fa3595d7f70 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -2013,9 +2013,31 @@ static UINT32 STDMETHODCALLTYPE d2d_device_context_GetMaximumBitmapSize(ID2D1Dev static BOOL STDMETHODCALLTYPE d2d_device_context_IsSupported(ID2D1DeviceContext1 *iface, const D2D1_RENDER_TARGET_PROPERTIES *desc) { - FIXME("iface %p, desc %p stub!\n", iface, desc); + struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface); + const D2D1_RENDER_TARGET_PROPERTIES *target_desc = &render_target->desc;
- return FALSE; + TRACE("iface %p, desc %p.\n", iface, desc); + + if (!(target_desc->type == desc->type + || (target_desc->type == D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type == D2D1_RENDER_TARGET_TYPE_HARDWARE) + || (target_desc->type == D2D1_RENDER_TARGET_TYPE_HARDWARE && desc->type == D2D1_RENDER_TARGET_TYPE_DEFAULT))) + return FALSE; + + if (!(target_desc->pixelFormat.format == desc->pixelFormat.format + || (target_desc->pixelFormat.format == DXGI_FORMAT_UNKNOWN && desc->pixelFormat.format == DXGI_FORMAT_B8G8R8A8_UNORM) + || (target_desc->pixelFormat.format == DXGI_FORMAT_B8G8R8A8_UNORM && desc->pixelFormat.format == DXGI_FORMAT_UNKNOWN))) + return FALSE; + + if (!(target_desc->pixelFormat.alphaMode == desc->pixelFormat.alphaMode + || desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_UNKNOWN)) + return FALSE; + + if (!(target_desc->usage == desc->usage + || (target_desc->usage == D2D1_RENDER_TARGET_USAGE_FORCE_BITMAP_REMOTING + && desc->usage == D2D1_RENDER_TARGET_USAGE_NONE))) + return FALSE; + + return TRUE; }
static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmap(ID2D1DeviceContext1 *iface, diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index d19166d8c51..b44913adbda 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -13220,7 +13220,7 @@ static void test_target_is_supported(BOOL d3d11) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(device_context == (ID2D1DeviceContext *)rt, "Got unexpected interface pointer.\n"); supported = ID2D1RenderTarget_IsSupported(rt, &template_desc); - todo_wine ok(supported, "Expected supported.\n"); + ok(supported, "Expected supported.\n");
test_desc = template_desc; test_desc.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE; @@ -13261,7 +13261,7 @@ static void test_target_is_supported(BOOL d3d11) supported = ID2D1RenderTarget_IsSupported(rt, &test_desc); if (i == j || (i == D2D1_RENDER_TARGET_TYPE_DEFAULT && j == D2D1_RENDER_TARGET_TYPE_HARDWARE) || (i == D2D1_RENDER_TARGET_TYPE_HARDWARE && j == D2D1_RENDER_TARGET_TYPE_DEFAULT)) - todo_wine ok(supported, "Expected supported.\n"); + ok(supported, "Expected supported.\n"); else ok(!supported, "Expected unsupported.\n");
@@ -13295,7 +13295,7 @@ static void test_target_is_supported(BOOL d3d11) supported = ID2D1RenderTarget_IsSupported(rt, &test_desc); if (i == j || (i == DXGI_FORMAT_UNKNOWN && j == DXGI_FORMAT_B8G8R8A8_UNORM) || (i == DXGI_FORMAT_B8G8R8A8_UNORM && j == DXGI_FORMAT_UNKNOWN)) - todo_wine ok(supported, "Expected supported.\n"); + ok(supported, "Expected supported.\n"); else ok(!supported, "Expected unsupported.\n");
@@ -13322,7 +13322,7 @@ static void test_target_is_supported(BOOL d3d11) test_desc.pixelFormat.alphaMode = j; supported = ID2D1RenderTarget_IsSupported(rt, &test_desc); if (i == j || j == D2D1_ALPHA_MODE_UNKNOWN) - todo_wine ok(supported, "Expected supported.\n"); + ok(supported, "Expected supported.\n"); else ok(!supported, "Expected unsupported.\n");
@@ -13350,7 +13350,7 @@ static void test_target_is_supported(BOOL d3d11) test_desc.dpiX = j; test_desc.dpiY = j; supported = ID2D1RenderTarget_IsSupported(rt, &test_desc); - todo_wine ok(supported, "Expected supported.\n"); + ok(supported, "Expected supported.\n");
winetest_pop_context(); } @@ -13376,7 +13376,7 @@ static void test_target_is_supported(BOOL d3d11) supported = ID2D1RenderTarget_IsSupported(rt, &test_desc); if (i == j || (i == D2D1_RENDER_TARGET_USAGE_FORCE_BITMAP_REMOTING && j == D2D1_RENDER_TARGET_USAGE_NONE)) - todo_wine ok(supported, "Expected supported.\n"); + ok(supported, "Expected supported.\n"); else ok(!supported, "Expected unsupported.\n");
@@ -13402,7 +13402,7 @@ static void test_target_is_supported(BOOL d3d11) test_desc = template_desc; test_desc.minLevel = levels[j]; supported = ID2D1RenderTarget_IsSupported(rt, &test_desc); - todo_wine ok(supported, "Expected supported.\n"); + ok(supported, "Expected supported.\n");
winetest_pop_context(); }
On Fri Sep 9 11:56:51 2022 +0000, Nikolay Sivov wrote:
This should really be two MRs, one for BindDC and one for IsSupported, so one fix does not hold another. Regarding BindDC, tests look inconclusive to me. Empty draw could indeed mean that surface is initialized, but it can also mean that what we do in d2d_dc_render_target_present() should not be called at all for empty draws. What you need to test is underlying surface directly, right after BindDC. You can do that by rt->QI(device_context) -> GetTarget -> QI(Bitmap1) -> GetSurface() -> GetDC(). This will tell you if target bitmap is initialized on BindDC(). To test if empty draws actually copy contents back, you could alter bound hdc with e.g. FillRect(), do empty draw, and check if it was changed back to initial contents. Also note that BindDC() has a rectangle argument, and if tests show you need to initialize the target, we probably should be using this rectangle in BitBlt(), instead of (0,0) origin.
Thanks for the review. I will address these issues in a separate MR.
On Fri Sep 9 11:56:51 2022 +0000, Zhiyi Zhang wrote:
Thanks for the review. I will address these issues in a separate MR.
Test are doing a lot of brute force permutation probing, which is not always a bad idea. But for this test what we'll need to know is whether dxgi, bitmap, dc, or WIC targets are different in IsSupported() sense. Same for plain device context - it also has this method.