wined3d: Build a list of wined3d_display_mode structures in wined3d_output_get_mode[_count]().

This commit is contained in:
Zebediah Figura 2022-07-26 18:15:28 -05:00 committed by Alexandre Julliard
parent 9f79a79e95
commit 95352c096f
3 changed files with 85 additions and 66 deletions

View file

@ -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)
{

View file

@ -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;

View file

@ -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);