From c48f212a8aa1c62f1afa042e68b6177d3806d980 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Sat, 28 Apr 2018 18:36:40 -0500 Subject: [PATCH] Rework XRandR support to list all modes and refresh rates. --- gtk/src/gtk_config.cpp | 13 +----- gtk/src/gtk_config.h | 14 ++---- gtk/src/gtk_display.cpp | 45 ++++++++++-------- gtk/src/gtk_preferences.cpp | 50 ++++++++++++++------ gtk/src/gtk_preferences.h | 4 ++ gtk/src/gtk_s9xwindow.cpp | 92 +++++++++++++++---------------------- 6 files changed, 110 insertions(+), 108 deletions(-) diff --git a/gtk/src/gtk_config.cpp b/gtk/src/gtk_config.cpp index 339a5308..6f4f892d 100644 --- a/gtk/src/gtk_config.cpp +++ b/gtk/src/gtk_config.cpp @@ -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")) { diff --git a/gtk/src/gtk_config.h b/gtk/src/gtk_config.h index 30e26feb..be2d8bb6 100644 --- a/gtk/src/gtk_config.h +++ b/gtk/src/gtk_config.h @@ -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; diff --git a/gtk/src/gtk_display.cpp b/gtk/src/gtk_display.cpp index 6fe10dde..3bd767fc 100644 --- a/gtk/src/gtk_display.cpp +++ b/gtk/src/gtk_display.cpp @@ -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; diff --git a/gtk/src/gtk_preferences.cpp b/gtk/src/gtk_preferences.cpp index a0a43152..003cc5e2 100644 --- a/gtk/src/gtk_preferences.cpp +++ b/gtk/src/gtk_preferences.cpp @@ -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 diff --git a/gtk/src/gtk_preferences.h b/gtk/src/gtk_preferences.h index c080530f..c0b09a99 100644 --- a/gtk/src/gtk_preferences.h +++ b/gtk/src/gtk_preferences.h @@ -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 */ diff --git a/gtk/src/gtk_s9xwindow.cpp b/gtk/src/gtk_s9xwindow.cpp index 67e555ce..c3af2d55 100644 --- a/gtk/src/gtk_s9xwindow.cpp +++ b/gtk/src/gtk_s9xwindow.cpp @@ -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);