mirror of
git://source.winehq.org/git/wine.git
synced 2024-07-21 11:44:10 +00:00
win32u: Introduce new add_mode device manager callback.
And use it to enumerate display modes in winex11 and wineandroid.
This commit is contained in:
parent
237778d7f6
commit
20414797ed
|
@ -178,6 +178,8 @@ static const WCHAR x_panningW[] = {'X','P','a','n','n','i','n','g',0};
|
|||
static const WCHAR y_panningW[] = {'Y','P','a','n','n','i','n','g',0};
|
||||
static const WCHAR orientationW[] = {'O','r','i','e','n','t','a','t','i','o','n',0};
|
||||
static const WCHAR fixed_outputW[] = {'F','i','x','e','d','O','u','t','p','u','t',0};
|
||||
static const WCHAR driver_extraW[] = {'D','r','i','v','e','r','E','x','t','r','a',0};
|
||||
static const WCHAR mode_countW[] = {'M','o','d','e','C','o','u','n','t',0};
|
||||
|
||||
static const char guid_devclass_displayA[] = "{4D36E968-E325-11CE-BFC1-08002BE10318}";
|
||||
static const WCHAR guid_devclass_displayW[] =
|
||||
|
@ -420,19 +422,20 @@ static void release_display_device_init_mutex( HANDLE mutex )
|
|||
NtClose( mutex );
|
||||
}
|
||||
|
||||
static BOOL write_adapter_mode( HKEY adapter_key, const DEVMODEW *mode )
|
||||
static BOOL write_adapter_mode( HKEY adapter_key, DWORD index, const DEVMODEW *mode )
|
||||
{
|
||||
static const WCHAR default_settingsW[] = {'D','e','f','a','u','l','t','S','e','t','t','i','n','g','s','.',0};
|
||||
WCHAR bufferW[MAX_PATH];
|
||||
char buffer[MAX_PATH];
|
||||
HKEY hkey;
|
||||
BOOL ret;
|
||||
|
||||
#define set_mode_field( name, field, flag ) \
|
||||
do \
|
||||
{ \
|
||||
lstrcpyW( bufferW, default_settingsW ); \
|
||||
lstrcatW( bufferW, (name) ); \
|
||||
if (!set_reg_value( adapter_key, bufferW, REG_DWORD, &mode->field, sizeof(mode->field) )) \
|
||||
return FALSE; \
|
||||
} while (0)
|
||||
sprintf( buffer, "Modes\\%08X", index );
|
||||
if (!(hkey = reg_create_key( adapter_key, bufferW, asciiz_to_unicode( bufferW, buffer ) - sizeof(WCHAR),
|
||||
REG_OPTION_VOLATILE, NULL )))
|
||||
return FALSE;
|
||||
|
||||
#define set_mode_field( name, field, flag ) \
|
||||
if (!(ret = set_reg_value( hkey, (name), REG_DWORD, &mode->field, sizeof(mode->field) ))) goto done;
|
||||
|
||||
set_mode_field( bits_per_pelW, dmBitsPerPel, DM_BITSPERPEL );
|
||||
set_mode_field( x_resolutionW, dmPelsWidth, DM_PELSWIDTH );
|
||||
|
@ -443,26 +446,34 @@ static BOOL write_adapter_mode( HKEY adapter_key, const DEVMODEW *mode )
|
|||
set_mode_field( fixed_outputW, dmDisplayFixedOutput, DM_DISPLAYFIXEDOUTPUT );
|
||||
set_mode_field( x_panningW, dmPosition.x, DM_POSITION );
|
||||
set_mode_field( y_panningW, dmPosition.y, DM_POSITION );
|
||||
ret = set_reg_value( hkey, driver_extraW, REG_BINARY, mode + 1, mode->dmDriverExtra );
|
||||
|
||||
#undef set_mode_field
|
||||
|
||||
return TRUE;
|
||||
done:
|
||||
NtClose( hkey );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL read_adapter_mode( HKEY adapter_key, DEVMODEW *mode )
|
||||
static BOOL read_adapter_mode( HKEY adapter_key, DWORD index, DEVMODEW *mode )
|
||||
{
|
||||
static const WCHAR default_settingsW[] = {'D','e','f','a','u','l','t','S','e','t','t','i','n','g','s','.',0};
|
||||
char value_buf[offsetof(KEY_VALUE_PARTIAL_INFORMATION, Data[sizeof(DWORD)])];
|
||||
KEY_VALUE_PARTIAL_INFORMATION *value = (void *)value_buf;
|
||||
WCHAR bufferW[MAX_PATH];
|
||||
char buffer[MAX_PATH];
|
||||
HKEY hkey;
|
||||
BOOL ret;
|
||||
|
||||
sprintf( buffer, "Modes\\%08X", index );
|
||||
if (!(hkey = reg_open_key( adapter_key, bufferW, asciiz_to_unicode( bufferW, buffer ) - sizeof(WCHAR) )))
|
||||
return FALSE;
|
||||
|
||||
#define query_mode_field( name, field, flag ) \
|
||||
do \
|
||||
{ \
|
||||
lstrcpyW( bufferW, default_settingsW ); \
|
||||
lstrcatW( bufferW, (name) ); \
|
||||
if (!query_reg_value( adapter_key, bufferW, value, sizeof(value_buf) ) || \
|
||||
value->Type != REG_DWORD) return FALSE; \
|
||||
ret = query_reg_value( hkey, (name), value, sizeof(value_buf) ) && \
|
||||
value->Type == REG_DWORD; \
|
||||
if (!ret) goto done; \
|
||||
mode->field = *(const DWORD *)value->Data; \
|
||||
mode->dmFields |= (flag); \
|
||||
} while (0)
|
||||
|
@ -479,6 +490,13 @@ static BOOL read_adapter_mode( HKEY adapter_key, DEVMODEW *mode )
|
|||
|
||||
#undef query_mode_field
|
||||
|
||||
ret = query_reg_value( hkey, driver_extraW, value, sizeof(value_buf) ) &&
|
||||
value->Type == REG_BINARY;
|
||||
if (ret && value->DataLength <= mode->dmDriverExtra)
|
||||
memcpy( mode + 1, value->Data, mode->dmDriverExtra );
|
||||
|
||||
done:
|
||||
NtClose( hkey );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -494,7 +512,7 @@ static BOOL read_registry_settings( const WCHAR *adapter_path, DEVMODEW *mode )
|
|||
else if (!(hkey = reg_open_key( config_key, adapter_path, lstrlenW( adapter_path ) * sizeof(WCHAR) ))) ret = FALSE;
|
||||
else
|
||||
{
|
||||
ret = read_adapter_mode( hkey, mode );
|
||||
ret = read_adapter_mode( hkey, ENUM_REGISTRY_SETTINGS, mode );
|
||||
NtClose( hkey );
|
||||
}
|
||||
|
||||
|
@ -514,7 +532,7 @@ static BOOL write_registry_settings( const WCHAR *adapter_path, const DEVMODEW *
|
|||
if (!(hkey = reg_open_key( config_key, adapter_path, lstrlenW( adapter_path ) * sizeof(WCHAR) ))) ret = FALSE;
|
||||
else
|
||||
{
|
||||
ret = write_adapter_mode( hkey, mode );
|
||||
ret = write_adapter_mode( hkey, ENUM_REGISTRY_SETTINGS, mode );
|
||||
NtClose( hkey );
|
||||
}
|
||||
|
||||
|
@ -909,6 +927,7 @@ struct device_manager_ctx
|
|||
unsigned int video_count;
|
||||
unsigned int monitor_count;
|
||||
unsigned int output_count;
|
||||
unsigned int mode_count;
|
||||
HANDLE mutex;
|
||||
WCHAR gpuid[128];
|
||||
WCHAR gpu_guid[64];
|
||||
|
@ -998,6 +1017,7 @@ static void add_gpu( const struct gdi_gpu *gpu, void *param )
|
|||
gpu_index = ctx->gpu_count++;
|
||||
ctx->adapter_count = 0;
|
||||
ctx->monitor_count = 0;
|
||||
ctx->mode_count = 0;
|
||||
|
||||
if (!enum_key && !(enum_key = reg_create_key( NULL, enum_keyW, sizeof(enum_keyW), 0, NULL )))
|
||||
return;
|
||||
|
@ -1127,6 +1147,7 @@ static void add_adapter( const struct gdi_adapter *adapter, void *param )
|
|||
adapter_index = ctx->adapter_count++;
|
||||
video_index = ctx->video_count++;
|
||||
ctx->monitor_count = 0;
|
||||
ctx->mode_count = 0;
|
||||
|
||||
len = asciiz_to_unicode( bufferW, "\\Registry\\Machine\\System\\CurrentControlSet\\"
|
||||
"Control\\Video\\" ) / sizeof(WCHAR) - 1;
|
||||
|
@ -1282,11 +1303,34 @@ static void add_monitor( const struct gdi_monitor *monitor, void *param )
|
|||
if (hkey) NtClose( hkey );
|
||||
}
|
||||
|
||||
static void add_mode( const DEVMODEW *mode, void *param )
|
||||
{
|
||||
struct device_manager_ctx *ctx = param;
|
||||
|
||||
if (!ctx->adapter_count)
|
||||
{
|
||||
static const struct gdi_adapter default_adapter =
|
||||
{
|
||||
.state_flags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE,
|
||||
};
|
||||
TRACE( "adding default fake adapter\n" );
|
||||
add_adapter( &default_adapter, ctx );
|
||||
}
|
||||
|
||||
if (write_adapter_mode( ctx->adapter_key, ctx->mode_count, mode ))
|
||||
{
|
||||
if (!ctx->mode_count++) set_reg_value( ctx->adapter_key, driver_extraW, REG_DWORD,
|
||||
&mode->dmDriverExtra, sizeof(mode->dmDriverExtra) );
|
||||
set_reg_value( ctx->adapter_key, mode_countW, REG_DWORD, &ctx->mode_count, sizeof(ctx->mode_count) );
|
||||
}
|
||||
}
|
||||
|
||||
static const struct gdi_device_manager device_manager =
|
||||
{
|
||||
add_gpu,
|
||||
add_adapter,
|
||||
add_monitor,
|
||||
add_mode,
|
||||
};
|
||||
|
||||
static void release_display_manager_ctx( struct device_manager_ctx *ctx )
|
||||
|
@ -1431,22 +1475,38 @@ static BOOL update_display_cache(void)
|
|||
|
||||
if (!user_driver->pUpdateDisplayDevices( &device_manager, TRUE, &ctx ))
|
||||
{
|
||||
static const DEVMODEW modes[] =
|
||||
{
|
||||
{ .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY,
|
||||
.dmBitsPerPel = 32, .dmPelsWidth = 640, .dmPelsHeight = 480, .dmDisplayFrequency = 60, },
|
||||
{ .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY,
|
||||
.dmBitsPerPel = 32, .dmPelsWidth = 800, .dmPelsHeight = 600, .dmDisplayFrequency = 60, },
|
||||
{ .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY,
|
||||
.dmBitsPerPel = 32, .dmPelsWidth = 1024, .dmPelsHeight = 768, .dmDisplayFrequency = 60, },
|
||||
{ .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY,
|
||||
.dmBitsPerPel = 16, .dmPelsWidth = 640, .dmPelsHeight = 480, .dmDisplayFrequency = 60, },
|
||||
{ .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY,
|
||||
.dmBitsPerPel = 16, .dmPelsWidth = 800, .dmPelsHeight = 600, .dmDisplayFrequency = 60, },
|
||||
{ .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY,
|
||||
.dmBitsPerPel = 16, .dmPelsWidth = 1024, .dmPelsHeight = 768, .dmDisplayFrequency = 60, },
|
||||
};
|
||||
static const struct gdi_gpu gpu;
|
||||
static const struct gdi_adapter adapter =
|
||||
{
|
||||
.state_flags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE,
|
||||
};
|
||||
DEVMODEW mode = {.dmPelsWidth = 1024, .dmPelsHeight = 768};
|
||||
struct gdi_monitor monitor =
|
||||
{
|
||||
.state_flags = DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED,
|
||||
.rc_monitor = {.right = mode.dmPelsWidth, .bottom = mode.dmPelsHeight},
|
||||
.rc_work = {.right = mode.dmPelsWidth, .bottom = mode.dmPelsHeight},
|
||||
.rc_monitor = {.right = modes[2].dmPelsWidth, .bottom = modes[2].dmPelsHeight},
|
||||
.rc_work = {.right = modes[2].dmPelsWidth, .bottom = modes[2].dmPelsHeight},
|
||||
};
|
||||
UINT i;
|
||||
|
||||
add_gpu( &gpu, &ctx );
|
||||
add_adapter( &adapter, &ctx );
|
||||
add_monitor( &monitor, &ctx );
|
||||
for (i = 0; i < ARRAY_SIZE(modes); ++i) add_mode( modes + i, &ctx );
|
||||
}
|
||||
release_display_manager_ctx( &ctx );
|
||||
|
||||
|
|
|
@ -288,9 +288,15 @@ BOOL ANDROID_UpdateDisplayDevices( const struct gdi_device_manager *device_manag
|
|||
.rc_work = monitor_rc_work,
|
||||
.state_flags = DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED,
|
||||
};
|
||||
const DEVMODEW mode =
|
||||
{
|
||||
.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY,
|
||||
.dmBitsPerPel = screen_bpp, .dmPelsWidth = screen_width, .dmPelsHeight = screen_height, .dmDisplayFrequency = 60,
|
||||
};
|
||||
device_manager->add_gpu( &gpu, param );
|
||||
device_manager->add_adapter( &adapter, param );
|
||||
device_manager->add_monitor( &gdi_monitor, param );
|
||||
device_manager->add_mode( &mode, param );
|
||||
force_display_devices_refresh = FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -918,6 +918,73 @@ better:
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static DEVMODEW *display_get_modes(CGDirectDisplayID display_id, int *modes_count)
|
||||
{
|
||||
int default_bpp = get_default_bpp(), synth_count = 0, count, i;
|
||||
BOOL modes_has_8bpp = FALSE, modes_has_16bpp = FALSE;
|
||||
struct display_mode_descriptor *desc;
|
||||
DEVMODEW *devmodes;
|
||||
CFArrayRef modes;
|
||||
|
||||
modes = copy_display_modes(display_id, TRUE);
|
||||
if (!modes)
|
||||
return NULL;
|
||||
|
||||
count = CFArrayGetCount(modes);
|
||||
for (i = 0; i < count && !(modes_has_8bpp && modes_has_16bpp); i++)
|
||||
{
|
||||
CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i);
|
||||
int bpp = display_mode_bits_per_pixel(mode);
|
||||
if (bpp == 8)
|
||||
modes_has_8bpp = TRUE;
|
||||
else if (bpp == 16)
|
||||
modes_has_16bpp = TRUE;
|
||||
}
|
||||
|
||||
if (!(devmodes = calloc(count * 3, sizeof(DEVMODEW))))
|
||||
{
|
||||
CFRelease(modes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
desc = create_original_display_mode_descriptor(display_id);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i);
|
||||
display_mode_to_devmode(display_id, mode, devmodes + i);
|
||||
|
||||
if (retina_enabled && display_mode_matches_descriptor(mode, desc))
|
||||
{
|
||||
devmodes[i].dmPelsWidth *= 2;
|
||||
devmodes[i].dmPelsHeight *= 2;
|
||||
}
|
||||
}
|
||||
free_display_mode_descriptor(desc);
|
||||
|
||||
for (i = 0; !modes_has_16bpp && i < count; i++)
|
||||
{
|
||||
/* We only synthesize modes from those having the default bpp. */
|
||||
if (devmodes[i].dmBitsPerPel != default_bpp) continue;
|
||||
devmodes[count + synth_count] = devmodes[i];
|
||||
devmodes[count + synth_count].dmBitsPerPel = 16;
|
||||
synth_count++;
|
||||
}
|
||||
|
||||
for (i = 0; !modes_has_8bpp && i < count; i++)
|
||||
{
|
||||
/* We only synthesize modes from those having the default bpp. */
|
||||
if (devmodes[i].dmBitsPerPel != default_bpp) continue;
|
||||
devmodes[count + synth_count] = devmodes[i];
|
||||
devmodes[count + synth_count].dmBitsPerPel = 8;
|
||||
synth_count++;
|
||||
}
|
||||
|
||||
CFRelease(modes);
|
||||
*modes_count = count + synth_count;
|
||||
return devmodes;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* EnumDisplaySettingsEx (MACDRV.@)
|
||||
*
|
||||
|
@ -1301,7 +1368,8 @@ BOOL macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device_manage
|
|||
struct macdrv_adapter *adapters, *adapter;
|
||||
struct macdrv_monitor *monitors, *monitor;
|
||||
struct macdrv_gpu *gpus, *gpu;
|
||||
INT gpu_count, adapter_count, monitor_count;
|
||||
INT gpu_count, adapter_count, monitor_count, mode_count;
|
||||
DEVMODEW *mode, *modes;
|
||||
DWORD len;
|
||||
|
||||
if (!force && !force_display_devices_refresh) return TRUE;
|
||||
|
@ -1359,6 +1427,19 @@ BOOL macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device_manage
|
|||
device_manager->add_monitor( &gdi_monitor, param );
|
||||
}
|
||||
|
||||
if (!(modes = display_get_modes(adapter->id, &mode_count))) break;
|
||||
TRACE("adapter: %#x, mode count: %d\n", adapter->id, mode_count);
|
||||
|
||||
/* Initialize modes */
|
||||
for (mode = modes; mode < modes + mode_count; mode++)
|
||||
{
|
||||
TRACE("mode: %dx%dx%dbpp @%d Hz, %sstretched %sinterlaced\n", mode->dmPelsWidth, mode->dmPelsHeight,
|
||||
mode->dmBitsPerPel, mode->dmDisplayFrequency,
|
||||
mode->dmDisplayFixedOutput == DMDFO_STRETCH ? "" : "un",
|
||||
mode->dmDisplayFlags & DM_INTERLACED ? "" : "non-");
|
||||
device_manager->add_mode( mode, param );
|
||||
}
|
||||
|
||||
macdrv_free_monitors(monitors);
|
||||
}
|
||||
|
||||
|
|
|
@ -1026,6 +1026,8 @@ BOOL X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manage
|
|||
struct gdi_gpu *gpus;
|
||||
INT gpu_count, adapter_count, monitor_count;
|
||||
INT gpu, adapter, monitor;
|
||||
DEVMODEW *modes, *mode;
|
||||
DWORD mode_count;
|
||||
|
||||
if (!force && !force_display_devices_refresh) return TRUE;
|
||||
force_display_devices_refresh = FALSE;
|
||||
|
@ -1060,6 +1062,20 @@ BOOL X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manage
|
|||
}
|
||||
|
||||
handler->free_monitors(monitors, monitor_count);
|
||||
|
||||
if (!settings_handler.get_modes( adapters[adapter].id, EDS_ROTATEDMODE, &modes, &mode_count ))
|
||||
continue;
|
||||
|
||||
qsort( modes, mode_count, sizeof(*modes) + modes[0].dmDriverExtra, mode_compare );
|
||||
|
||||
for (mode = modes; mode_count; mode_count--)
|
||||
{
|
||||
TRACE( "mode: %p\n", mode );
|
||||
device_manager->add_mode( mode, param );
|
||||
mode = (DEVMODEW *)((char *)mode + sizeof(*modes) + modes[0].dmDriverExtra);
|
||||
}
|
||||
|
||||
settings_handler.free_modes( modes );
|
||||
}
|
||||
|
||||
handler->free_adapters(adapters);
|
||||
|
|
|
@ -266,6 +266,7 @@ struct gdi_device_manager
|
|||
void (*add_gpu)( const struct gdi_gpu *gpu, void *param );
|
||||
void (*add_adapter)( const struct gdi_adapter *adapter, void *param );
|
||||
void (*add_monitor)( const struct gdi_monitor *monitor, void *param );
|
||||
void (*add_mode)( const DEVMODEW *mode, void *param );
|
||||
};
|
||||
|
||||
struct tagUPDATELAYEREDWINDOWINFO;
|
||||
|
|
Loading…
Reference in a new issue