From 95352c096f0bbb0c2be3dc09c972792894d5315e Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Tue, 26 Jul 2022 18:15:28 -0500 Subject: [PATCH] wined3d: Build a list of wined3d_display_mode structures in wined3d_output_get_mode[_count](). --- dlls/wined3d/directx.c | 140 ++++++++++++++++++--------------- dlls/wined3d/wined3d_private.h | 3 + include/wine/wined3d.h | 8 +- 3 files changed, 85 insertions(+), 66 deletions(-) diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 9eac1a04c42..d90d6c6c52d 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -1228,43 +1228,78 @@ HRESULT CDECL wined3d_output_get_desc(const struct wined3d_output *output, /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes of the same bpp but different resolutions */ -static bool mode_matches_filter(const DEVMODEW *mode, const struct wined3d_format *format, - enum wined3d_scanline_ordering scanline_ordering) +static void wined3d_output_update_modes(struct wined3d_output *output) { - if (mode->dmFields & DM_DISPLAYFLAGS) - { - if (scanline_ordering == WINED3D_SCANLINE_ORDERING_PROGRESSIVE - && (mode->u2.dmDisplayFlags & DM_INTERLACED)) - return false; + struct wined3d_display_mode *wined3d_mode; + DEVMODEW mode = {.dmSize = sizeof(mode)}; + unsigned int i; - if (scanline_ordering == WINED3D_SCANLINE_ORDERING_INTERLACED - && !(mode->u2.dmDisplayFlags & DM_INTERLACED)) - return false; + output->mode_count = 0; + + for (i = 0; EnumDisplaySettingsExW(output->device_name, i, &mode, 0); ++i) + { + if (!wined3d_array_reserve((void **)&output->modes, &output->modes_size, + output->mode_count + 1, sizeof(*output->modes))) + return; + + wined3d_mode = &output->modes[output->mode_count++]; + wined3d_mode->width = mode.dmPelsWidth; + wined3d_mode->height = mode.dmPelsHeight; + wined3d_mode->format_id = pixelformat_for_depth(mode.dmBitsPerPel); + + if (mode.dmFields & DM_DISPLAYFREQUENCY) + wined3d_mode->refresh_rate = mode.dmDisplayFrequency; + else + wined3d_mode->refresh_rate = DEFAULT_REFRESH_RATE; + + if (mode.dmFields & DM_DISPLAYFLAGS) + { + if (mode.u2.dmDisplayFlags & DM_INTERLACED) + wined3d_mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_INTERLACED; + else + wined3d_mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_PROGRESSIVE; + } + else + { + wined3d_mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN; + } } +} + +static bool mode_matches_filter(const struct wined3d_adapter *adapter, const struct wined3d_display_mode *mode, + const struct wined3d_format *format, enum wined3d_scanline_ordering scanline_ordering) +{ + if (scanline_ordering != WINED3D_SCANLINE_ORDERING_UNKNOWN + && mode->scanline_ordering != WINED3D_SCANLINE_ORDERING_UNKNOWN + && scanline_ordering != mode->scanline_ordering) + return false; if (format->id == WINED3DFMT_UNKNOWN) { /* This is for d3d8, do not enumerate P8 here. */ - if (mode->dmBitsPerPel != 32 && mode->dmBitsPerPel != 16) + if (mode->format_id != WINED3DFMT_B5G6R5_UNORM && mode->format_id != WINED3DFMT_B8G8R8X8_UNORM) return false; } - else if (mode->dmBitsPerPel != format->byte_count * CHAR_BIT) + else { - return false; + const struct wined3d_format *mode_format = wined3d_get_format(adapter, + mode->format_id, WINED3D_BIND_RENDER_TARGET); + + if (format->byte_count != mode_format->byte_count) + return false; } return true; } /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */ -unsigned int CDECL wined3d_output_get_mode_count(const struct wined3d_output *output, +unsigned int CDECL wined3d_output_get_mode_count(struct wined3d_output *output, enum wined3d_format_id format_id, enum wined3d_scanline_ordering scanline_ordering) { const struct wined3d_adapter *adapter; const struct wined3d_format *format; - unsigned int i = 0; - unsigned int j = 0; - DEVMODEW mode; + unsigned int count = 0; + SIZE_T i; TRACE("output %p, format %s, scanline_ordering %#x.\n", output, debug_d3dformat(format_id), scanline_ordering); @@ -1272,30 +1307,27 @@ unsigned int CDECL wined3d_output_get_mode_count(const struct wined3d_output *ou adapter = output->adapter; format = wined3d_get_format(adapter, format_id, WINED3D_BIND_RENDER_TARGET); - memset(&mode, 0, sizeof(mode)); - mode.dmSize = sizeof(mode); + wined3d_output_update_modes(output); - while (EnumDisplaySettingsExW(output->device_name, j++, &mode, 0)) + for (i = 0; i < output->mode_count; ++i) { - if (mode_matches_filter(&mode, format, scanline_ordering)) - ++i; + if (mode_matches_filter(adapter, &output->modes[i], format, scanline_ordering)) + ++count; } - TRACE("Returning %u matching modes (out of %u total) for output %p.\n", i, j, output); + TRACE("Returning %u matching modes (out of %Iu total).\n", count, output->mode_count); - return i; + return count; } /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */ -HRESULT CDECL wined3d_output_get_mode(const struct wined3d_output *output, +HRESULT CDECL wined3d_output_get_mode(struct wined3d_output *output, enum wined3d_format_id format_id, enum wined3d_scanline_ordering scanline_ordering, unsigned int mode_idx, struct wined3d_display_mode *mode) { const struct wined3d_adapter *adapter; const struct wined3d_format *format; - DEVMODEW m; - UINT i = 0; - int j = 0; + SIZE_T i, match_idx = 0; TRACE("output %p, format %s, scanline_ordering %#x, mode_idx %u, mode %p.\n", output, debug_d3dformat(format_id), scanline_ordering, mode_idx, mode); @@ -1306,46 +1338,30 @@ HRESULT CDECL wined3d_output_get_mode(const struct wined3d_output *output, adapter = output->adapter; format = wined3d_get_format(adapter, format_id, WINED3D_BIND_RENDER_TARGET); - memset(&m, 0, sizeof(m)); - m.dmSize = sizeof(m); + wined3d_output_update_modes(output); - while (i <= mode_idx) + for (i = 0; i < output->mode_count; ++i) { - if (!EnumDisplaySettingsExW(output->device_name, j++, &m, 0)) - { - WARN("Invalid mode_idx %u.\n", mode_idx); - return WINED3DERR_INVALIDCALL; - } + const struct wined3d_display_mode *wined3d_mode = &output->modes[i]; - if (mode_matches_filter(&m, format, scanline_ordering)) - ++i; + if (mode_matches_filter(adapter, wined3d_mode, format, scanline_ordering) && match_idx++ == mode_idx) + { + *mode = *wined3d_mode; + if (format_id != WINED3DFMT_UNKNOWN) + mode->format_id = format_id; + + TRACE("%ux%u@%u %u bpp, %s %#x.\n", mode->width, mode->height, mode->refresh_rate, + wined3d_get_format(adapter, mode->format_id, WINED3D_BIND_RENDER_TARGET)->byte_count * CHAR_BIT, + debug_d3dformat(mode->format_id), mode->scanline_ordering); + return WINED3D_OK; + } } - mode->width = m.dmPelsWidth; - mode->height = m.dmPelsHeight; - mode->refresh_rate = DEFAULT_REFRESH_RATE; - if (m.dmFields & DM_DISPLAYFREQUENCY) - mode->refresh_rate = m.dmDisplayFrequency; - - if (format_id == WINED3DFMT_UNKNOWN) - mode->format_id = pixelformat_for_depth(m.dmBitsPerPel); - else - mode->format_id = format_id; - - if (!(m.dmFields & DM_DISPLAYFLAGS)) - mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN; - else if (m.u2.dmDisplayFlags & DM_INTERLACED) - mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_INTERLACED; - else - mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_PROGRESSIVE; - - TRACE("%ux%u@%u %u bpp, %s %#x.\n", mode->width, mode->height, mode->refresh_rate, - m.dmBitsPerPel, debug_d3dformat(mode->format_id), mode->scanline_ordering); - - return WINED3D_OK; + WARN("Invalid mode_idx %u.\n", mode_idx); + return WINED3DERR_INVALIDCALL; } -HRESULT CDECL wined3d_output_find_closest_matching_mode(const struct wined3d_output *output, +HRESULT CDECL wined3d_output_find_closest_matching_mode(struct wined3d_output *output, struct wined3d_display_mode *mode) { unsigned int i, j, mode_count, matching_mode_count, closest; @@ -2158,7 +2174,7 @@ HRESULT CDECL wined3d_check_device_format_conversion(const struct wined3d_output } HRESULT CDECL wined3d_check_device_type(const struct wined3d *wined3d, - const struct wined3d_output *output, enum wined3d_device_type device_type, + struct wined3d_output *output, enum wined3d_device_type device_type, enum wined3d_format_id display_format, enum wined3d_format_id backbuffer_format, BOOL windowed) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 4e0879a3985..36274ee24bc 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3502,6 +3502,9 @@ struct wined3d_output D3DKMT_HANDLE kmt_device; D3DDDI_VIDEO_PRESENT_SOURCE_ID vidpn_source_id; + + struct wined3d_display_mode *modes; + SIZE_T mode_count, modes_size; }; HRESULT wined3d_output_get_gamma_ramp(struct wined3d_output *output, struct wined3d_gamma_ramp *ramp) DECLSPEC_HIDDEN; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index ce2da6e4c04..44e8c7d6546 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2346,7 +2346,7 @@ HRESULT __cdecl wined3d_check_device_multisample_type(const struct wined3d_adapt enum wined3d_device_type device_type, enum wined3d_format_id surface_format_id, BOOL windowed, enum wined3d_multisample_type multisample_type, unsigned int *quality_levels); HRESULT __cdecl wined3d_check_device_type(const struct wined3d *wined3d, - const struct wined3d_output *output, enum wined3d_device_type device_type, + struct wined3d_output *output, enum wined3d_device_type device_type, enum wined3d_format_id display_format_id, enum wined3d_format_id backbuffer_format_id, BOOL windowed); struct wined3d * __cdecl wined3d_create(DWORD flags); @@ -2586,17 +2586,17 @@ void __cdecl wined3d_device_context_update_sub_resource(struct wined3d_device_co struct wined3d_resource *resource, unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, unsigned int depth_pitch, unsigned int flags); -HRESULT __cdecl wined3d_output_find_closest_matching_mode(const struct wined3d_output *output, +HRESULT __cdecl wined3d_output_find_closest_matching_mode(struct wined3d_output *output, struct wined3d_display_mode *mode); struct wined3d_adapter * __cdecl wined3d_output_get_adapter(const struct wined3d_output *output); HRESULT __cdecl wined3d_output_get_desc(const struct wined3d_output *output, struct wined3d_output_desc *desc); HRESULT __cdecl wined3d_output_get_display_mode(const struct wined3d_output *output, struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation); -HRESULT __cdecl wined3d_output_get_mode(const struct wined3d_output *output, +HRESULT __cdecl wined3d_output_get_mode(struct wined3d_output *output, enum wined3d_format_id format_id, enum wined3d_scanline_ordering scanline_ordering, unsigned int mode_idx, struct wined3d_display_mode *mode); -unsigned int __cdecl wined3d_output_get_mode_count(const struct wined3d_output *output, +unsigned int __cdecl wined3d_output_get_mode_count(struct wined3d_output *output, enum wined3d_format_id format_id, enum wined3d_scanline_ordering scanline_ordering); HRESULT __cdecl wined3d_output_get_raster_status(const struct wined3d_output *output, struct wined3d_raster_status *raster_status);