Rework XRandR support to list all modes and refresh rates.

This commit is contained in:
Brandon Wright 2018-04-28 18:36:40 -05:00
parent 363fdc9848
commit c48f212a8a
6 changed files with 110 additions and 108 deletions

View File

@ -162,8 +162,6 @@ Snes9xConfig::load_defaults (void)
full_screen_on_open = 0;
change_display_resolution = 0;
xrr_index = 0;
xrr_width = 0;
xrr_height = 0;
scale_to_fit = 1;
maintain_aspect_ratio = 0;
aspect_ratio = 0;
@ -324,8 +322,6 @@ Snes9xConfig::save_config_file (void)
xml_out_int (xml, "full_screen_on_open", full_screen_on_open);
xml_out_int (xml, "change_display_resolution", change_display_resolution);
xml_out_int (xml, "video_mode", xrr_index);
xml_out_int (xml, "video_mode_width", xrr_width);
xml_out_int (xml, "video_mode_height", xrr_height);
xml_out_int (xml, "scale_to_fit", scale_to_fit);
xml_out_int (xml, "maintain_aspect_ratio", maintain_aspect_ratio);
xml_out_int (xml, "aspect_ratio", aspect_ratio);
@ -498,14 +494,7 @@ Snes9xConfig::set_option (const char *name, const char *value)
}
else if (!strcasecmp (name, "video_mode"))
{
}
else if (!strcasecmp (name, "video_mode_width"))
{
xrr_width = atoi (value);
}
else if (!strcasecmp (name, "video_mode_height"))
{
xrr_height = atoi (value);
xrr_index = atoi (value);
}
else if (!strcasecmp (name, "scale_to_fit"))
{

View File

@ -58,9 +58,7 @@ class Snes9xConfig
unsigned char statusbar_visible;
unsigned char default_esc_behavior;
unsigned char prevent_screensaver;
unsigned int xrr_index;
int xrr_width;
int xrr_height;
int xrr_index;
unsigned char scale_to_fit;
unsigned char maintain_aspect_ratio;
int aspect_ratio;
@ -138,14 +136,12 @@ class Snes9xConfig
unsigned int rewind_buffer_size;
#ifdef USE_XRANDR
XRRScreenConfiguration *xrr_config;
XRRScreenSize *xrr_sizes;
int xrr_num_sizes;
Rotation xrr_rotation;
SizeID xrr_original_size;
XRRScreenResources *xrr_screen_resources;
XRROutputInfo *xrr_output_info;
XRRCrtcInfo *xrr_crtc_info;
RROutput xrr_output;
#endif
#ifdef USE_OPENGL
unsigned char sync_to_vblank;
unsigned char opengl_activated;

View File

@ -1703,30 +1703,35 @@ S9xQueryDrivers (void)
gui_config->allow_opengl = 0;
#endif
gui_config->allow_xrandr = 0;
#ifdef USE_XRANDR
int error_base_p, event_base_p;
Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
int major_version, minor_version;
Display *dpy = gdk_x11_display_get_xdisplay (gtk_widget_get_display (GTK_WIDGET (top_level->get_window())));
Window xid = gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (top_level->get_window())));
if (!XRRQueryExtension (dpy, &event_base_p, &error_base_p))
{
gui_config->change_display_resolution = FALSE;
return;
}
if (!XRRQueryVersion (dpy, &major_version, &minor_version))
{
gui_config->change_display_resolution = FALSE;
return;
}
if (minor_version < 3)
{
gui_config->change_display_resolution = FALSE;
return;
}
gui_config->allow_xrandr = 1;
if (!XRRQueryExtension (display, &event_base_p, &error_base_p))
{
gui_config->allow_xrandr = 0;
gui_config->change_display_resolution = FALSE;
}
if (gui_config->allow_xrandr)
{
gui_config->xrr_config = XRRGetScreenInfo (display,
DefaultRootWindow (display));
gui_config->xrr_original_size =
XRRConfigCurrentConfiguration (gui_config->xrr_config,
&(gui_config->xrr_rotation));
gui_config->xrr_sizes = XRRConfigSizes (gui_config->xrr_config,
&(gui_config->xrr_num_sizes));
}
#else
gui_config->allow_xrandr = 0;
gui_config->xrr_screen_resources = XRRGetScreenResources (dpy, xid);
gui_config->xrr_output = XRRGetOutputPrimary (dpy, xid);
gui_config->xrr_output_info = XRRGetOutputInfo (dpy, gui_config->xrr_screen_resources, gui_config->xrr_output);
gui_config->xrr_crtc_info = XRRGetCrtcInfo (dpy, gui_config->xrr_screen_resources, gui_config->xrr_output_info->crtc);
#endif
return;

View File

@ -497,6 +497,10 @@ static double XRRGetExactRefreshRate (Display *dpy, Window window)
XRRModeInfo *m = &resources->modes[i];
refresh_rate = (double) m->dotClock / m->hTotal / m->vTotal;
refresh_rate /= m->modeFlags & RR_DoubleScan ? 2 : 1;
refresh_rate /= m->modeFlags & RR_ClockDivideBy2 ? 2 : 1;
refresh_rate *= m->modeFlags & RR_DoubleClock ? 2 : 1;
break;
}
}
@ -633,6 +637,10 @@ Snes9xPreferences::Snes9xPreferences (Snes9xConfig *config) :
last_toggled = NULL;
this->config = config;
#ifdef USE_XRANDR
mode_indices = NULL;
#endif
gtk_widget_realize (window);
signal_connect (callbacks);
@ -649,6 +657,10 @@ Snes9xPreferences::Snes9xPreferences (Snes9xConfig *config) :
Snes9xPreferences::~Snes9xPreferences (void)
{
#ifdef USE_XRANDR
delete[] mode_indices;
#endif
return;
}
@ -847,16 +859,12 @@ Snes9xPreferences::get_settings_from_dialog (void)
{
top_level->leave_fullscreen_mode ();
config->xrr_index = get_combo ("resolution_combo");
config->xrr_width = config->xrr_sizes[config->xrr_index].width;
config->xrr_height = config->xrr_sizes[config->xrr_index].height;
config->change_display_resolution = get_check ("change_display_resolution");
top_level->enter_fullscreen_mode ();
}
else
{
config->xrr_index = get_combo ("resolution_combo");
config->xrr_width = config->xrr_sizes[config->xrr_index].width;
config->xrr_height = config->xrr_sizes[config->xrr_index].height;
}
#endif
@ -1102,22 +1110,38 @@ Snes9xPreferences::show (void)
combo = get_widget ("resolution_combo");
config->xrr_index = 0;
for (int i = 0; i < config->xrr_num_sizes; i++)
mode_indices = new unsigned int[config->xrr_output_info->nmode];
for (int i = 0; i < config->xrr_output_info->nmode; i++)
{
if (config->xrr_width == config->xrr_sizes[i].width &&
config->xrr_height == config->xrr_sizes[i].height)
config->xrr_index = i;
for (int j = 0; j < config->xrr_screen_resources->nmode; j++)
{
if (config->xrr_screen_resources->modes[j].id == config->xrr_output_info->modes[i])
{
mode_indices[i] = j;
}
}
XRRModeInfo *m = &config->xrr_screen_resources->modes[mode_indices[i]];
unsigned long dotClock = m->dotClock;
if (m->modeFlags & RR_ClockDivideBy2)
dotClock /= 2;
if (m->modeFlags & RR_DoubleScan)
dotClock /= 2;
if (m->modeFlags & RR_DoubleClock)
dotClock *= 2;
snprintf (size_string,
256,
"%dx%d",
config->xrr_sizes[i].width,
config->xrr_sizes[i].height);
"%dx%d @ %.3fHz",
m->width,
m->height,
(double) dotClock / m->hTotal / m->vTotal);
combo_box_append (GTK_COMBO_BOX (combo), size_string);
}
if (config->xrr_index > config->xrr_output_info->nmode)
config->xrr_index = 0;
#endif
}
else

View File

@ -40,6 +40,10 @@ class Snes9xPreferences : public GtkBuilderWindow
private:
void get_settings_from_dialog (void);
void move_settings_to_dialog (void);
#ifdef USE_XRANDR
unsigned int *mode_indices;
#endif
};
#endif /* __GTK_PREFERENCES_H */

View File

@ -1550,53 +1550,40 @@ Snes9xWindow::enter_fullscreen_mode (void)
gtk_window_get_position (GTK_WINDOW (window), &nfs_x, &nfs_y);
/* Make sure everything is done synchronously */
gdk_display_sync (gdk_display_get_default ());
gtk_window_fullscreen (GTK_WINDOW (window));
#ifdef USE_XRANDR
if (config->change_display_resolution)
{
int mode = -1;
GdkDisplay *gdk_display = gtk_widget_get_display (window);
Display *dpy = gdk_x11_display_get_xdisplay (gdk_display);
for (int i = 0; i < config->xrr_num_sizes; i++)
{
if (config->xrr_sizes[i].width == config->xrr_width &&
config->xrr_sizes[i].height == config->xrr_height)
{
mode = i;
}
}
if (mode < 0)
gdk_display_sync (gdk_display);
if (XRRSetCrtcConfig (dpy,
config->xrr_screen_resources,
config->xrr_output_info->crtc,
CurrentTime,
config->xrr_crtc_info->x,
config->xrr_crtc_info->y,
config->xrr_output_info->modes[config->xrr_index],
config->xrr_crtc_info->rotation,
&config->xrr_output,
1) != 0)
{
config->change_display_resolution = 0;
}
else
{
GdkDisplay *gdk_display = gtk_widget_get_display (window);
Display *display = gdk_x11_display_get_xdisplay (gdk_display);
GdkScreen *screen = gtk_widget_get_screen (window);
GdkWindow *root = gdk_screen_get_root_window (screen);
gdk_display_sync (gdk_display_get_default ());
XRRSetScreenConfig (display,
config->xrr_config,
GDK_COMPAT_WINDOW_XID (root),
(SizeID) mode,
config->xrr_rotation,
CurrentTime);
}
}
#endif
set_bypass_compositor (gdk_x11_display_get_xdisplay (gtk_widget_get_display (window)),
gdk_x11_window_get_xid (gtk_widget_get_window (window)),
1);
/* Make sure everything is done synchronously */
gdk_display_sync (gdk_display_get_default ());
gtk_window_fullscreen (GTK_WINDOW (window));
gdk_display_sync (gdk_display_get_default ());
gtk_window_present (GTK_WINDOW (window));
set_bypass_compositor (gdk_x11_display_get_xdisplay (gtk_widget_get_display (window)),
gdk_x11_window_get_xid (gtk_widget_get_window (window)),
1);
config->fullscreen = 1;
config->rom_loaded = rom_loaded;
@ -1619,37 +1606,34 @@ Snes9xWindow::leave_fullscreen_mode (void)
config->rom_loaded = 0;
set_bypass_compositor (gdk_x11_display_get_xdisplay (gtk_widget_get_display (window)),
gdk_x11_window_get_xid (gtk_widget_get_window (window)),
0);
#ifdef USE_XRANDR
if (config->change_display_resolution)
{
gtk_widget_hide (window);
GdkDisplay *gdk_display = gtk_widget_get_display (window);
Display *display = gdk_x11_display_get_xdisplay (gdk_display);
GdkScreen *screen = gtk_widget_get_screen (window);
GdkWindow *root = gdk_screen_get_root_window (screen);
Display *dpy = gdk_x11_display_get_xdisplay (gdk_display);
XRRSetScreenConfig (display,
config->xrr_config,
GDK_COMPAT_WINDOW_XID (root),
(SizeID) config->xrr_original_size,
config->xrr_rotation,
CurrentTime);
if (config->xrr_index > config->xrr_output_info->nmode)
config->xrr_index = 0;
gdk_display_sync (gdk_display);
XRRSetCrtcConfig (dpy,
config->xrr_screen_resources,
config->xrr_output_info->crtc,
CurrentTime,
config->xrr_crtc_info->x,
config->xrr_crtc_info->y,
config->xrr_crtc_info->mode,
config->xrr_crtc_info->rotation,
&config->xrr_output,
1);
}
#endif
gtk_window_unfullscreen (GTK_WINDOW (window));
#ifdef USE_XRANDR
if (config->change_display_resolution)
{
gtk_widget_show (window);
}
#endif
set_bypass_compositor (gdk_x11_display_get_xdisplay (gtk_widget_get_display (window)),
gdk_x11_window_get_xid (gtk_widget_get_window (window)),
0);
resize (nfs_width, nfs_height);
gtk_window_move (GTK_WINDOW (window), nfs_x, nfs_y);