diff --git a/dlls/d2d1/effect.c b/dlls/d2d1/effect.c index e7215c4b38a..601932b005b 100644 --- a/dlls/d2d1/effect.c +++ b/dlls/d2d1/effect.c @@ -27,6 +27,7 @@ static const struct d2d_effect_info builtin_effects[] = {&CLSID_D2D1Composite, 2, 1, 0xffffffff}, {&CLSID_D2D1Crop, 1, 1, 1}, {&CLSID_D2D1Shadow, 1, 1, 1}, + {&CLSID_D2D1Grayscale, 1, 1, 1}, }; static inline struct d2d_effect *impl_from_ID2D1Effect(ID2D1Effect *iface) diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 722f46bffe6..826526d9d38 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -20,7 +20,7 @@ #include #include #include -#include "d2d1_1.h" +#include "d2d1_3.h" #include "d3d11.h" #include "wincrypt.h" #include "wine/test.h" @@ -9925,13 +9925,15 @@ static void test_mt_factory(BOOL d3d11) static void test_effect(BOOL d3d11) { - unsigned int i, j, min_inputs, max_inputs, str_size, input_count; + unsigned int i, j, min_inputs, max_inputs, str_size, input_count, factory_version; D2D1_BITMAP_PROPERTIES bitmap_desc; D2D1_BUFFER_PRECISION precision; ID2D1Image *image_a, *image_b; struct d2d1_test_context ctx; ID2D1DeviceContext *context; - ID2D1Factory1 *factory; + ID2D1Factory1 *factory1; + ID2D1Factory2 *factory2; + ID2D1Factory3 *factory3; ID2D1Bitmap *bitmap; ID2D1Effect *effect; D2D1_SIZE_U size; @@ -9943,28 +9945,43 @@ static void test_effect(BOOL d3d11) const struct effect_test { const CLSID *clsid; + UINT32 factory_version; UINT32 default_input_count; UINT32 min_inputs; UINT32 max_inputs; } effect_tests[] = { - {&CLSID_D2D12DAffineTransform, 1, 1, 1}, - {&CLSID_D2D13DPerspectiveTransform, 1, 1, 1}, - {&CLSID_D2D1Composite, 2, 1, 0xffffffff}, - {&CLSID_D2D1Crop, 1, 1, 1}, - {&CLSID_D2D1Shadow, 1, 1, 1}, + {&CLSID_D2D12DAffineTransform, 1, 1, 1, 1}, + {&CLSID_D2D13DPerspectiveTransform, 1, 1, 1, 1}, + {&CLSID_D2D1Composite, 1, 2, 1, 0xffffffff}, + {&CLSID_D2D1Crop, 1, 1, 1, 1}, + {&CLSID_D2D1Shadow, 1, 1, 1, 1}, + {&CLSID_D2D1Grayscale, 3, 1, 1, 1}, }; if (!init_test_context(&ctx, d3d11)) return; - if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory))) + if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory1))) { win_skip("ID2D1Factory1 is not supported.\n"); release_test_context(&ctx); return; } + factory_version = 1; + if (SUCCEEDED(ID2D1Factory1_QueryInterface(factory1, &IID_ID2D1Factory2, (void **)&factory2))) + { + ID2D1Factory2_Release(factory2); + factory_version = 2; + } + if (SUCCEEDED(ID2D1Factory1_QueryInterface(factory1, &IID_ID2D1Factory3, (void **)&factory3))) + { + ID2D1Factory3_Release(factory3); + factory_version = 3; + } + if (factory_version < 3) + win_skip("ID2D1Factory%u is not supported.\n", factory_version + 1); hr = ID2D1RenderTarget_QueryInterface(ctx.rt, &IID_ID2D1DeviceContext, (void **)&context); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); @@ -9973,6 +9990,9 @@ static void test_effect(BOOL d3d11) { const struct effect_test *test = effect_tests + i; + if (factory_version < test->factory_version) + continue; + winetest_push_context("Test %u", i); hr = ID2D1DeviceContext_CreateEffect(context, test->clsid, &effect); @@ -10109,7 +10129,7 @@ static void test_effect(BOOL d3d11) } ID2D1DeviceContext_Release(context); - ID2D1Factory1_Release(factory); + ID2D1Factory1_Release(factory1); release_test_context(&ctx); } @@ -10350,6 +10370,84 @@ static void test_effect_crop(BOOL d3d11) release_test_context(&ctx); } +static void test_effect_grayscale(BOOL d3d11) +{ + DWORD colour, expected_colour, luminance; + D2D1_BITMAP_PROPERTIES1 bitmap_desc; + struct d2d1_test_context ctx; + struct resource_readback rb; + ID2D1DeviceContext *context; + D2D1_SIZE_U input_size; + ID2D1Factory3 *factory; + ID2D1Bitmap1 *bitmap; + ID2D1Effect *effect; + ID2D1Image *output; + unsigned int i; + HRESULT hr; + + const DWORD test_pixels[] = {0xffffffff, 0x12345678, 0x89abcdef, 0x77777777, 0xdeadbeef}; + + if (!init_test_context(&ctx, d3d11)) + return; + + if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory3, NULL, (void **)&factory))) + { + win_skip("ID2D1Factory3 is not supported.\n"); + release_test_context(&ctx); + return; + } + + hr = ID2D1RenderTarget_QueryInterface(ctx.rt, &IID_ID2D1DeviceContext, (void **)&context); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ID2D1DeviceContext_CreateEffect(context, &CLSID_D2D1Grayscale, &effect); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + for (i = 0; i < ARRAY_SIZE(test_pixels); ++i) + { + DWORD pixel = test_pixels[i]; + winetest_push_context("Test %u", i); + + set_size_u(&input_size, 1, 1); + bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; + bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE; + bitmap_desc.dpiX = 96.0f; + bitmap_desc.dpiY = 96.0f; + bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_NONE; + bitmap_desc.colorContext = NULL; + hr = ID2D1DeviceContext_CreateBitmap(context, input_size, &pixel, sizeof(pixel), &bitmap_desc, &bitmap); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + ID2D1Effect_SetInput(effect, 0, (ID2D1Image *)bitmap, FALSE); + ID2D1Effect_GetOutput(effect, &output); + + ID2D1DeviceContext_BeginDraw(context); + ID2D1DeviceContext_Clear(context, 0); + ID2D1DeviceContext_DrawImage(context, output, NULL, NULL, 0, 0); + hr = ID2D1DeviceContext_EndDraw(context, NULL, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + get_surface_readback(&ctx, &rb); + colour = get_readback_colour(&rb, 0, 0); + luminance = (DWORD)(0.299f * ((pixel >> 16) & 0xff) + + 0.587f * ((pixel >> 8) & 0xff) + + 0.114f * ((pixel >> 0) & 0xff) + 0.5f); + expected_colour = (pixel & 0xff000000) | (luminance << 16) | (luminance << 8) | luminance; + todo_wine ok(compare_colour(colour, expected_colour, 1), + "Got unexpected colour %#lx, expected %#lx.\n", colour, expected_colour); + release_resource_readback(&rb); + + ID2D1Image_Release(output); + ID2D1Bitmap1_Release(bitmap); + winetest_pop_context(); + } + + ID2D1Effect_Release(effect); + ID2D1DeviceContext_Release(context); + ID2D1Factory3_Release(factory); + release_test_context(&ctx); +} + static void test_stroke_contains_point(BOOL d3d11) { ID2D1TransformedGeometry *transformed_geometry; @@ -10735,6 +10833,7 @@ START_TEST(d2d1) queue_test(test_effect); queue_test(test_effect_2d_affine); queue_test(test_effect_crop); + queue_test(test_effect_grayscale); queue_d3d10_test(test_stroke_contains_point); run_queued_tests(); diff --git a/include/d2d1effects_2.idl b/include/d2d1effects_2.idl index 79895361118..9cd93a8d3bf 100644 --- a/include/d2d1effects_2.idl +++ b/include/d2d1effects_2.idl @@ -18,6 +18,7 @@ import "d2d1effects_1.idl"; +cpp_quote("DEFINE_GUID(CLSID_D2D1Grayscale, 0x36dde0eb,0x3725,0x42e0,0x83,0x6d,0x52,0xfb,0x20,0xae,0xe6,0x44);") cpp_quote("DEFINE_GUID(CLSID_D2D1HighlightsShadows, 0xcadc8384,0x323f,0x4c7e,0xa3,0x61,0x2e,0x2b,0x24,0xdf,0x6e,0xe4);") typedef enum D2D1_HIGHLIGHTSANDSHADOWS_PROP