Module: wine Branch: master Commit: 41d29a79f51cca0452fb37db38dc6b6df4b32dc1 URL: http://source.winehq.org/git/wine.git/?a=commit;h=41d29a79f51cca0452fb37db38...
Author: Józef Kucia jkucia@codeweavers.com Date: Thu Aug 25 12:22:51 2016 +0200
wined3d: Introduce wined3d_find_closest_matching_adapter_mode().
Signed-off-by: Józef Kucia jkucia@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/wined3d/directx.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 1 + include/wine/wined3d.h | 2 + 3 files changed, 103 insertions(+)
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 9ff88a8..4213df3 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -4199,6 +4199,106 @@ HRESULT CDECL wined3d_enum_adapter_modes(const struct wined3d *wined3d, UINT ada return WINED3D_OK; }
+HRESULT CDECL wined3d_find_closest_matching_adapter_mode(const struct wined3d *wined3d, + unsigned int adapter_idx, struct wined3d_display_mode *mode) +{ + unsigned int i, j, mode_count, matching_mode_count, closest; + struct wined3d_display_mode **matching_modes; + struct wined3d_display_mode *modes; + HRESULT hr; + + TRACE("wined3d %p, adapter_idx %u, mode %p.\n", wined3d, adapter_idx, mode); + + if (!(mode_count = wined3d_get_adapter_mode_count(wined3d, adapter_idx, + mode->format_id, WINED3D_SCANLINE_ORDERING_UNKNOWN))) + { + WARN("Adapter has 0 matching modes.\n"); + return E_FAIL; + } + + if (!(modes = wined3d_calloc(mode_count, sizeof(*modes)))) + return E_OUTOFMEMORY; + if (!(matching_modes = wined3d_calloc(mode_count, sizeof(*matching_modes)))) + { + HeapFree(GetProcessHeap(), 0, modes); + return E_OUTOFMEMORY; + } + + for (i = 0; i < mode_count; ++i) + { + if (FAILED(hr = wined3d_enum_adapter_modes(wined3d, adapter_idx, + mode->format_id, WINED3D_SCANLINE_ORDERING_UNKNOWN, i, &modes[i]))) + { + HeapFree(GetProcessHeap(), 0, matching_modes); + HeapFree(GetProcessHeap(), 0, modes); + return hr; + } + matching_modes[i] = &modes[i]; + } + + matching_mode_count = mode_count; + + if (mode->scanline_ordering != WINED3D_SCANLINE_ORDERING_UNKNOWN) + { + for (i = 0, j = 0; i < matching_mode_count; ++i) + { + if (matching_modes[i]->scanline_ordering == mode->scanline_ordering) + matching_modes[j++] = matching_modes[i]; + } + if (j > 0) + matching_mode_count = j; + } + + if (mode->refresh_rate) + { + for (i = 0, j = 0; i < matching_mode_count; ++i) + { + if (matching_modes[i]->refresh_rate == mode->refresh_rate) + matching_modes[j++] = matching_modes[i]; + } + if (j > 0) + matching_mode_count = j; + } + + if (!mode->width || !mode->height) + { + struct wined3d_display_mode current_mode; + if (FAILED(hr = wined3d_get_adapter_display_mode(wined3d, adapter_idx, + ¤t_mode, NULL))) + { + HeapFree(GetProcessHeap(), 0, matching_modes); + HeapFree(GetProcessHeap(), 0, modes); + return hr; + } + mode->width = current_mode.width; + mode->height = current_mode.height; + } + + closest = ~0u; + for (i = 0, j = 0; i < matching_mode_count; ++i) + { + unsigned int d = abs(mode->width - matching_modes[i]->width) + + abs(mode->height - matching_modes[i]->height); + + if (closest > d) + { + closest = d; + j = i; + } + } + + *mode = *matching_modes[j]; + + HeapFree(GetProcessHeap(), 0, matching_modes); + HeapFree(GetProcessHeap(), 0, modes); + + TRACE("Returning %ux%u@%u %s %#x.\n", mode->width, mode->height, + mode->refresh_rate, debug_d3dformat(mode->format_id), + mode->scanline_ordering); + + return WINED3D_OK; +} + HRESULT CDECL wined3d_get_adapter_display_mode(const struct wined3d *wined3d, UINT adapter_idx, struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation) { diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index c3899ed..0db371d 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -10,6 +10,7 @@ @ cdecl wined3d_create(long) @ cdecl wined3d_decref(ptr) @ cdecl wined3d_enum_adapter_modes(ptr long long long long ptr) +@ cdecl wined3d_find_closest_matching_adapter_mode(ptr long ptr) @ cdecl wined3d_get_adapter_count(ptr) @ cdecl wined3d_get_adapter_display_mode(ptr long ptr ptr) @ cdecl wined3d_get_adapter_identifier(ptr long long ptr) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 1c9b262..bc343ec 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2105,6 +2105,8 @@ ULONG __cdecl wined3d_decref(struct wined3d *wined3d); HRESULT __cdecl wined3d_enum_adapter_modes(const struct wined3d *wined3d, UINT adapter_idx, enum wined3d_format_id format_id, enum wined3d_scanline_ordering scanline_ordering, UINT mode_idx, struct wined3d_display_mode *mode); +HRESULT __cdecl wined3d_find_closest_matching_adapter_mode(const struct wined3d *wined3d, + unsigned int adapter_idx, struct wined3d_display_mode *mode); UINT __cdecl wined3d_get_adapter_count(const struct wined3d *wined3d); HRESULT __cdecl wined3d_get_adapter_display_mode(const struct wined3d *wined3d, UINT adapter_idx, struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation);