From: Nikolay Sivov nsivov@codeweavers.com
--- dlls/d2d1/d2d1_private.h | 3 +- dlls/d2d1/dc_render_target.c | 30 ++++- dlls/d2d1/tests/d2d1.c | 233 +++++++++++++++++++++++++++++++++++ 3 files changed, 262 insertions(+), 4 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index c3714a92511..e343c9998c1 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -242,13 +242,14 @@ struct d2d_dc_render_target LONG refcount;
IDXGISurface1 *dxgi_surface; - D2D1_PIXEL_FORMAT pixel_format; ID3D10Device1 *d3d_device; ID2D1RenderTarget *dxgi_target; IUnknown *dxgi_inner;
RECT dst_rect; HDC hdc; + + D2D1_RENDER_TARGET_PROPERTIES desc; };
HRESULT d2d_dc_render_target_init(struct d2d_dc_render_target *render_target, ID2D1Factory1 *factory, diff --git a/dlls/d2d1/dc_render_target.c b/dlls/d2d1/dc_render_target.c index 30eafe361d1..99b2a1d4da9 100644 --- a/dlls/d2d1/dc_render_target.c +++ b/dlls/d2d1/dc_render_target.c @@ -673,10 +673,32 @@ static BOOL STDMETHODCALLTYPE d2d_dc_render_target_IsSupported(ID2D1DCRenderTarg const D2D1_RENDER_TARGET_PROPERTIES *desc) { struct d2d_dc_render_target *render_target = impl_from_ID2D1DCRenderTarget(iface); + const D2D1_RENDER_TARGET_PROPERTIES *target_desc = &render_target->desc; + D2D1_PIXEL_FORMAT pixel_format;
TRACE("iface %p, desc %p.\n", iface, desc);
- return ID2D1RenderTarget_IsSupported(render_target->dxgi_target, desc); + if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT + && target_desc->type != desc->type) + { + return FALSE; + } + + pixel_format = ID2D1RenderTarget_GetPixelFormat(render_target->dxgi_target); + + if (desc->pixelFormat.format != DXGI_FORMAT_UNKNOWN + && pixel_format.format != desc->pixelFormat.format) + { + return FALSE; + } + + if (desc->pixelFormat.alphaMode != D2D1_ALPHA_MODE_UNKNOWN + && pixel_format.alphaMode != desc->pixelFormat.alphaMode) + { + return FALSE; + } + + return (target_desc->usage & desc->usage) == desc->usage; }
static HRESULT STDMETHODCALLTYPE d2d_dc_render_target_BindDC(ID2D1DCRenderTarget *iface, @@ -705,7 +727,7 @@ static HRESULT STDMETHODCALLTYPE d2d_dc_render_target_BindDC(ID2D1DCRenderTarget bitmap_size.height = rect->bottom - rect->top;
memset(&bitmap_desc, 0, sizeof(bitmap_desc)); - bitmap_desc.pixelFormat = render_target->pixel_format; + bitmap_desc.pixelFormat = render_target->desc.pixelFormat; bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE; if (FAILED(hr = ID2D1DeviceContext_CreateBitmap(context, bitmap_size, NULL, 0, &bitmap_desc, @@ -813,7 +835,9 @@ HRESULT d2d_dc_render_target_init(struct d2d_dc_render_target *render_target, ID SetRectEmpty(&render_target->dst_rect); render_target->hdc = NULL;
- render_target->pixel_format = desc->pixelFormat; + render_target->desc = *desc; + render_target->desc.usage |= D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE; + switch (desc->pixelFormat.format) { case DXGI_FORMAT_B8G8R8A8_UNORM: diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index df1b99776e4..3ae9409ecd0 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -13597,6 +13597,238 @@ static void test_hwnd_target_is_supported(BOOL d3d11) release_test_context(&ctx); }
+static void test_dc_target_is_supported(BOOL d3d11) +{ + static const unsigned int target_types[] = + { + D2D1_RENDER_TARGET_TYPE_DEFAULT, + D2D1_RENDER_TARGET_TYPE_SOFTWARE, + D2D1_RENDER_TARGET_TYPE_HARDWARE, + }; + static const unsigned int usages[] = + { + D2D1_RENDER_TARGET_USAGE_NONE, + D2D1_RENDER_TARGET_USAGE_FORCE_BITMAP_REMOTING, + D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE, + D2D1_RENDER_TARGET_USAGE_FORCE_BITMAP_REMOTING | D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE, + }; + static const D2D1_PIXEL_FORMAT pixel_formats[] = + { + { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_UNKNOWN }, + { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED }, + { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_IGNORE }, + { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_STRAIGHT }, + + { DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_UNKNOWN }, + { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_UNKNOWN }, + + { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED }, + { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE }, + }; + static const D2D1_PIXEL_FORMAT unsupported_pixel_formats[] = + { + { DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED }, + { DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_IGNORE }, + { DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_STRAIGHT }, + + { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_STRAIGHT }, + + { DXGI_FORMAT_R16G16B16A16_UNORM, D2D1_ALPHA_MODE_UNKNOWN }, + }; + D2D1_RENDER_TARGET_PROPERTIES desc, template_desc, test_desc; + D2D1_BITMAP_PROPERTIES1 bitmap_desc; + ID2D1DeviceContext *device_context; + D2D1_PIXEL_FORMAT pixel_format; + struct d2d1_test_context ctx; + BOOL expected, supported; + ID2D1DCRenderTarget *rt; + ID2D1Bitmap1 *bitmap; + unsigned int i, j; + D2D1_SIZE_U size; + HRESULT hr; + + if (!init_test_context(&ctx, d3d11)) + return; + + template_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT; + template_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; + template_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; + 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; + + /* Make sure the render target description template is valid. */ + hr = ID2D1Factory_CreateDCRenderTarget(ctx.factory, &template_desc, &rt); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + supported = ID2D1DCRenderTarget_IsSupported(rt, &template_desc); + ok(supported, "Expected supported.\n"); + ID2D1DCRenderTarget_Release(rt); + + /* Test that SetTarget() with a bitmap of a different usage doesn't change the render target usage. */ + hr = ID2D1Factory_CreateDCRenderTarget(ctx.factory, &template_desc, &rt); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1DCRenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&device_context); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + test_desc = template_desc; + test_desc.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE; + supported = ID2D1DCRenderTarget_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; + 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); + ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap); + supported = ID2D1DCRenderTarget_IsSupported(rt, &test_desc); + ok(supported, "Expected unsupported.\n"); + ID2D1Bitmap1_Release(bitmap); + + /* Test that SetTarget() with a bitmap of a different format changes the render target format. */ + test_desc = template_desc; + test_desc.pixelFormat.format = DXGI_FORMAT_R8G8B8A8_UNORM; + test_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; + supported = ID2D1DCRenderTarget_IsSupported(rt, &test_desc); + ok(!supported, "Expected unsupported.\n"); + + memset(&bitmap_desc, 0, sizeof(bitmap_desc)); + bitmap_desc.pixelFormat.format = DXGI_FORMAT_R8G8B8A8_UNORM; + bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; + bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET; + 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); + ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap); + pixel_format = ID2D1DeviceContext_GetPixelFormat(device_context); + ok(pixel_format.format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected format %#x.\n", pixel_format.format); + ok(pixel_format.alphaMode == D2D1_ALPHA_MODE_PREMULTIPLIED, "Got unexpected alpha %u.\n", pixel_format.alphaMode); + supported = ID2D1DCRenderTarget_IsSupported(rt, &test_desc); + ok(supported, "Expected supported.\n"); + ID2D1Bitmap1_Release(bitmap); + + ID2D1DeviceContext_Release(device_context); + ID2D1DCRenderTarget_Release(rt); + + /* Target type. */ + for (i = 0; i < ARRAY_SIZE(target_types); ++i) + { + /* Default target type resolves to either HW or SW, there is no way to tell. */ + desc = template_desc; + desc.type = target_types[i]; + hr = ID2D1Factory_CreateDCRenderTarget(ctx.factory, &desc, &rt); + if (desc.type == D2D1_RENDER_TARGET_TYPE_DEFAULT) + { + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + test_desc = template_desc; + test_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT; + supported = ID2D1DCRenderTarget_IsSupported(rt, &test_desc); + ok(supported, "Unexpected return value %d.\n", supported); + } + else + { + if (FAILED(hr)) + continue; + + for (j = 0; j < ARRAY_SIZE(target_types); ++j) + { + winetest_push_context("type test %u/%u", i, j); + + test_desc = template_desc; + test_desc.type = target_types[j]; + supported = ID2D1DCRenderTarget_IsSupported(rt, &test_desc); + expected = target_types[j] == D2D1_RENDER_TARGET_TYPE_DEFAULT + || target_types[i] == target_types[j]; + ok(supported == expected, "Unexpected return value %d.\n", supported); + + winetest_pop_context(); + } + } + + ID2D1DCRenderTarget_Release(rt); + } + + /* Pixel formats. */ + for (i = 0; i < ARRAY_SIZE(pixel_formats); ++i) + { + desc = template_desc; + desc.pixelFormat = pixel_formats[i]; + hr = ID2D1Factory_CreateDCRenderTarget(ctx.factory, &desc, &rt); + if (pixel_formats[i].format == DXGI_FORMAT_UNKNOWN + || pixel_formats[i].alphaMode == D2D1_ALPHA_MODE_UNKNOWN) + { + ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "%u: unexpected hr %#lx.\n", i, hr); + continue; + } + ok(hr == S_OK, "%u: unexpected hr %#lx.\n", i, hr); + + for (j = 0; j < ARRAY_SIZE(pixel_formats); ++j) + { + BOOL format_supported, alpha_mode_supported; + + winetest_push_context("format test %u/%u.", i, j); + + test_desc = template_desc; + test_desc.pixelFormat = pixel_formats[j]; + supported = ID2D1DCRenderTarget_IsSupported(rt, &test_desc); + + format_supported = pixel_formats[j].format == DXGI_FORMAT_UNKNOWN + || pixel_formats[j].format == desc.pixelFormat.format; + alpha_mode_supported = pixel_formats[j].alphaMode == D2D1_ALPHA_MODE_UNKNOWN + || pixel_formats[j].alphaMode == desc.pixelFormat.alphaMode; + expected = format_supported && alpha_mode_supported; + ok(supported == expected, "Unexpected return value.\n"); + + winetest_pop_context(); + } + + for (j = 0; j < ARRAY_SIZE(unsupported_pixel_formats); ++j) + { + winetest_push_context("unsupported format test %u/%u.", i, j); + + test_desc = template_desc; + test_desc.pixelFormat = unsupported_pixel_formats[j]; + supported = ID2D1DCRenderTarget_IsSupported(rt, &test_desc); + ok(!supported, "Unexpected return value.\n"); + + winetest_pop_context(); + } + + ID2D1DCRenderTarget_Release(rt); + } + + /* Target usage. */ + for (i = 0; i < ARRAY_SIZE(usages); ++i) + { + desc = template_desc; + desc.usage = usages[i]; + hr = ID2D1Factory_CreateDCRenderTarget(ctx.factory, &desc, &rt); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + for (j = 0; j < ARRAY_SIZE(usages); ++j) + { + winetest_push_context("usage %#x testing usage %#x", usages[i], usages[j]); + + desc = template_desc; + desc.usage = usages[j]; + supported = ID2D1DCRenderTarget_IsSupported(rt, &desc); + expected = ((usages[i] | D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE) & usages[j]) == usages[j]; + ok(supported == expected, "Unexpected result %d.\n", supported); + + winetest_pop_context(); + } + + ID2D1DCRenderTarget_Release(rt); + } + + release_test_context(&ctx); +} + START_TEST(d2d1) { HMODULE d2d1_dll = GetModuleHandleA("d2d1.dll"); @@ -13682,6 +13914,7 @@ START_TEST(d2d1) queue_test(test_bitmap_map); queue_test(test_bitmap_create); queue_test(test_hwnd_target_is_supported); + queue_test(test_dc_target_is_supported);
run_queued_tests(); }