From eb2028fa90c41d3b7b8b4f924cd86059c5ba1e0d Mon Sep 17 00:00:00 2001 From: Andrew Eikum Date: Mon, 28 Oct 2019 16:59:18 +0330 Subject: [PATCH] dxgi: Sort reported output modes. Sekiro: Shadows Die Twice depends on this for its mode switching. Signed-off-by: Andrew Eikum Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/dxgi/output.c | 29 +++++++++++++++++++++++++++++ dlls/dxgi/tests/dxgi.c | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/dlls/dxgi/output.c b/dlls/dxgi/output.c index abe1aef950c..a66628cc60d 100644 --- a/dlls/dxgi/output.c +++ b/dlls/dxgi/output.c @@ -75,6 +75,25 @@ static HRESULT dxgi_output_find_closest_matching_mode(struct dxgi_output *output return hr; } +static int dxgi_mode_desc_compare(const void *l, const void *r) +{ + const DXGI_MODE_DESC *left = l, *right = r; + int a, b; + + if (left->Width != right->Width) + return left->Width - right->Width; + + if (left->Height != right->Height) + return left->Height - right->Height; + + a = left->RefreshRate.Numerator * right->RefreshRate.Denominator; + b = right->RefreshRate.Numerator * left->RefreshRate.Denominator; + if (a != b) + return a - b; + + return 0; +} + enum dxgi_mode_struct_version { DXGI_MODE_STRUCT_VERSION_0, @@ -151,6 +170,16 @@ static HRESULT dxgi_output_get_display_mode_list(struct dxgi_output *output, } wined3d_mutex_unlock(); + switch (struct_version) + { + case DXGI_MODE_STRUCT_VERSION_0: + qsort(modes, *mode_count, sizeof(DXGI_MODE_DESC), dxgi_mode_desc_compare); + break; + case DXGI_MODE_STRUCT_VERSION_1: + qsort(modes, *mode_count, sizeof(DXGI_MODE_DESC1), dxgi_mode_desc_compare); + break; + } + return S_OK; } diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index a7517c8b0ab..cbb5806e2d2 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -1153,12 +1153,13 @@ static void test_parents(void) static void test_output(void) { + unsigned int mode_count, mode_count_comp, i, last_height, last_width; + double last_refresh_rate; IDXGIAdapter *adapter; IDXGIDevice *device; HRESULT hr; IDXGIOutput *output; ULONG refcount; - UINT mode_count, mode_count_comp, i; DXGI_MODE_DESC *modes; if (!(device = create_device(0))) @@ -1227,9 +1228,38 @@ static void test_output(void) ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr); ok(mode_count == mode_count_comp, "Got unexpected mode_count %u, expected %u.\n", mode_count, mode_count_comp); + last_width = last_height = 0; + last_refresh_rate = 0.; for (i = 0; i < mode_count; i++) { - ok(modes[i].Height && modes[i].Width, "Proper mode was expected\n"); + double refresh_rate = modes[i].RefreshRate.Numerator / (double)modes[i].RefreshRate.Denominator; + + ok(modes[i].Width && modes[i].Height, "Mode %u: Invalid dimensions %ux%u.\n", + i, modes[i].Width, modes[i].Height); + + ok(modes[i].Width >= last_width, + "Mode %u: Modes should have been sorted, width %u < %u.\n", i, modes[i].Width, last_width); + if (modes[i].Width != last_width) + { + last_width = modes[i].Width; + last_height = 0; + last_refresh_rate = 0.; + continue; + } + + ok(modes[i].Height >= last_height, + "Mode %u: Modes should have been sorted, height %u < %u.\n", i, modes[i].Height, last_height); + if (modes[i].Height != last_height) + { + last_height = modes[i].Height; + last_refresh_rate = 0.; + continue; + } + + ok(refresh_rate >= last_refresh_rate, + "Mode %u: Modes should have been sorted, refresh rate %f < %f.\n", i, refresh_rate, last_refresh_rate); + if (refresh_rate != last_refresh_rate) + last_refresh_rate = refresh_rate; } mode_count += 5;