diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2013-07-01 08:52:43 -0700 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2013-07-01 08:52:43 -0700 |
commit | 90b956556b1fb77ee07192ce329551602bd78680 (patch) | |
tree | 04ec1c1ed21dcabc81ce83fbdd34af484a105c9d | |
parent | d5c86902432529996ef5ac12cb7721a18516b000 (diff) |
325.08325.08
47 files changed, 1737 insertions, 1489 deletions
diff --git a/doc/nvidia-settings.1.m4 b/doc/nvidia-settings.1.m4 index 790ded8..5579319 100644 --- a/doc/nvidia-settings.1.m4 +++ b/doc/nvidia-settings.1.m4 @@ -294,7 +294,8 @@ For example, querying the DigitalVibrance of display device DVI-I-1 may be done nvidia-settings --query [dpy:DVI-I-1]/DigitalVibrance .fi -When a target name is specified, the target type name may be omitted, though this should be used with caution since the name will be matched across all target types. The above example could be written as: +When a target name is specified, the target type name may be omitted, though this should be used with caution since the name will be matched across all target types. +The above example could be written as: .nf nvidia-settings --query [DVI-I-1]/DigitalVibrance @@ -309,8 +310,10 @@ For exmple, querying the BusRate of all GPUs may be done like so: .fi .PP -The target specification may also include a target qualifier. This is useful to limit processing to a subset of targets, based on an existing relationship(s) to other targets. -The target qualifier is specified by prepending a target type name, a colon, the target id, and a period to the existing specification. Only one qualitfer may be specified. +The target specification may also include a target qualifier. +This is useful to limit processing to a subset of targets, based on an existing relationship(s) to other targets. +The target qualifier is specified by prepending a target type name, a colon, the target id, and a period to the existing specification. +Only one qualitfer may be specified. .PP For example, querying the RefreshRate of all DFP devices on GPU 1 may be done like so: .nf @@ -318,7 +321,8 @@ For example, querying the RefreshRate of all DFP devices on GPU 1 may be done li nvidia-settings --query [GPU:1.DPY:DFP]/RefreshRate .fi -Likewise, a simple target name (or target type name) may be used as the qualifier. For example, to query the BusType of all GPUs that have DFPs can be done like so: +Likewise, a simple target name (or target type name) may be used as the qualifier. +For example, to query the BusType of all GPUs that have DFPs can be done like so: .nf nvidia-settings --query [DFP.GPU]/BusType @@ -358,8 +362,9 @@ For example: .fi .PP Multiple queries and assignments may be specified on the command line for a single invocation of -.B nvidia\-settings. -Assignments are processed in the order they are entered on the command line. If multiple assignments are made to the same attribute or to multiple attributes with dependencies, then the later assignments will have priority. +.B nvidia\-settings. +Assignments are processed in the order they are entered on the command line. +If multiple assignments are made to the same attribute or to multiple attributes with dependencies, then the later assignments will have priority. .PP If either the .B \-\-query diff --git a/doc/version.mk b/doc/version.mk index 47298b6..a8b6fa4 100644 --- a/doc/version.mk +++ b/doc/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 319.32 +NVIDIA_VERSION = 325.08 diff --git a/samples/nv-control-targets.c b/samples/nv-control-targets.c index 88f5eb5..3d24fb4 100644 --- a/samples/nv-control-targets.c +++ b/samples/nv-control-targets.c @@ -238,8 +238,22 @@ int main(int argc, char *argv[]) return 1; } printf(" Product Name : %s\n", str); + XFree(str); + str = NULL; + + /* GPU UUID */ + + ret = XNVCTRLQueryTargetStringAttribute(dpy, + NV_CTRL_TARGET_TYPE_GPU, + gpu, // target_id + 0, // display_mask + NV_CTRL_STRING_GPU_UUID, + &str); + printf(" GPU UUID : %s\n", + (ret ? str : "Unknown")); + XFree(str); + str = NULL; - /* Connected Display Devices on GPU */ ret = XNVCTRLQueryTargetAttribute(dpy, diff --git a/samples/version.mk b/samples/version.mk index 47298b6..a8b6fa4 100644 --- a/samples/version.mk +++ b/samples/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 319.32 +NVIDIA_VERSION = 325.08 diff --git a/src/app-profiles.c b/src/app-profiles.c index 4b37006..b6f98cc 100644 --- a/src/app-profiles.c +++ b/src/app-profiles.c @@ -199,16 +199,6 @@ static char *nv_dirname(const char *path) } } -static char *nv_basename(const char *path) -{ - char *last_slash = strrchr(path, '/'); - if (last_slash) { - return strdup(last_slash+1); - } else { - return strdup(path); - } -} - static json_t *app_profile_config_insert_file_object(AppProfileConfig *config, json_t *new_file) { json_t *json_filename, *json_new_filename; @@ -770,8 +760,8 @@ static json_t *app_profile_config_load_global_options(const char *global_config_ json_t *options_from_file; json_t *option; - // By default, app profiles are disabled - json_object_set_new(options, "enabled", json_false()); + // By default, app profiles are enabled + json_object_set_new(options, "enabled", json_true()); if (!global_config_file) { return options; diff --git a/src/command-line.c b/src/command-line.c index 70c001d..ad27d9c 100644 --- a/src/command-line.c +++ b/src/command-line.c @@ -107,8 +107,6 @@ static void print_attribute_help(char *attr) nv_msg(NULL, " - Attribute is not written to the rc file."); if (entry->flags & NV_PARSER_TYPE_GUI_ATTRIBUTE) nv_msg(NULL, " - Is GUI attribute."); - if (entry->flags & NV_PARSER_TYPE_XVIDEO_ATTRIBUTE) - nv_msg(NULL, " - Is X Video attribute."); if (entry->flags & NV_PARSER_TYPE_PACKED_ATTRIBUTE) nv_msg(NULL, " - Attribute value is packed integer."); if (entry->flags & NV_PARSER_TYPE_VALUE_IS_DISPLAY) diff --git a/src/common-utils/common-utils.c b/src/common-utils/common-utils.c index 9b734f3..b2958a7 100644 --- a/src/common-utils/common-utils.c +++ b/src/common-utils/common-utils.c @@ -492,8 +492,6 @@ void nv_text_rows_append(TextRows *t, const char *msg) * result in t0 */ -#define NV_MAX(x,y) ((x) > (y) ? (x) : (y)) - void nv_concat_text_rows(TextRows *t0, TextRows *t1) { int n, i; @@ -707,6 +705,107 @@ char *nvstrchrnul(char *s, int c) return result; } +/****************************************************************************/ +/* file helper functions */ +/****************************************************************************/ + +/* + * nv_open() - open(2) wrapper; prints an error message if open(2) + * fails and calls exit(). This function only returns on success. + */ + +int nv_open(const char *pathname, int flags, mode_t mode) +{ + int fd; + fd = open(pathname, flags, mode); + if (fd == -1) { + fprintf(stderr, "Failure opening %s (%s).\n", + pathname, strerror(errno)); + exit(1); + } + return fd; + +} /* nv_name() */ + + + +/* + * nv_get_file_length() - stat(2) wrapper; prints an error message if + * the system call fails and calls exit(). This function only returns + * on success. + */ + +int nv_get_file_length(const char *filename) +{ + struct stat stat_buf; + int ret; + + ret = stat(filename, &stat_buf); + if (ret == -1) { + fprintf(stderr, "Unable to determine '%s' file length (%s).\n", + filename, strerror(errno)); + exit(1); + } + return stat_buf.st_size; + +} /* nv_get_file_length() */ + + + +/* + * nv_set_file_length() - wrapper for lseek() and write(); prints an + * error message if the system calls fail and calls exit(). This + * function only returns on success. + */ + +void nv_set_file_length(const char *filename, int fd, int len) +{ + if ((lseek(fd, len - 1, SEEK_SET) == -1) || + (write(fd, "", 1) == -1)) { + fprintf(stderr, "Unable to set file '%s' length %d (%s).\n", + filename, fd, strerror(errno)); + exit(1); + } +} /* nv_set_file_length() */ + + + +/* + * nv_mmap() - mmap(2) wrapper; prints an error message if mmap(2) + * fails and calls exit(). This function only returns on success. + */ + +void *nv_mmap(const char *filename, size_t len, int prot, int flags, int fd) +{ + void *ret; + + ret = mmap(0, len, prot, flags, fd, 0); + if (ret == (void *) -1) { + fprintf(stderr, "Unable to mmap file %s (%s).\n", + filename, strerror(errno)); + exit(1); + } + return ret; + +} /* nv_mmap() */ + + +/* + * nv_basename() - alternative to basename(3) which avoids differences in + * behavior from different implementations: this implementation never modifies + * the original string, and the return value can always be passed to free(3). + */ + +char *nv_basename(const char *path) +{ + char *last_slash = strrchr(path, '/'); + if (last_slash) { + return strdup(last_slash+1); + } else { + return strdup(path); + } +} + /****************************************************************************/ /* string helper functions */ @@ -741,8 +840,12 @@ char *nv_trim_space(char *string) { static char *trim_char(char *string, char trim, int *count) { int len, replaced = 0; - if (!string || trim == '\0') { - return NULL; + if (count) { + *count = 0; + } + + if (string == NULL || trim == '\0') { + return string; } if (string[0] == trim) { @@ -781,7 +884,7 @@ char *nv_trim_char(char *string, char trim) { */ char *nv_trim_char_strict(char *string, char trim) { - int count = 0; + int count; char *trimmed; trimmed = trim_char(string, trim, &count); @@ -792,3 +895,4 @@ char *nv_trim_char_strict(char *string, char trim) { return NULL; } + diff --git a/src/common-utils/common-utils.h b/src/common-utils/common-utils.h index 6dced25..92c57dd 100644 --- a/src/common-utils/common-utils.h +++ b/src/common-utils/common-utils.h @@ -19,6 +19,8 @@ #include <stdio.h> #include <stdarg.h> +#include <sys/types.h> +#include <stdint.h> #if !defined(TRUE) #define TRUE 1 @@ -30,6 +32,9 @@ #define ARRAY_LEN(_arr) (sizeof(_arr) / sizeof(_arr[0])) +#define NV_MIN(x,y) ((x) < (y) ? (x) : (y)) +#define NV_MAX(x,y) ((x) > (y) ? (x) : (y)) + #define TAB " " #define BIGTAB " " @@ -90,6 +95,12 @@ void fmt(FILE *stream, const char *prefix, const char *fmt, ...) NV_ATTRIBUTE_PR char *fget_next_line(FILE *fp, int *eof); +int nv_open(const char *pathname, int flags, mode_t mode); +int nv_get_file_length(const char *filename); +void nv_set_file_length(const char *filename, int fd, int len); +void *nv_mmap(const char *filename, size_t len, int prot, int flags, int fd); +char *nv_basename(const char *path); + char *nv_trim_space(char *string); char *nv_trim_char(char *string, char trim); char *nv_trim_char_strict(char *string, char trim); @@ -139,4 +150,38 @@ do { \ } \ } while (0) +#if defined(__GNUC__) +# define NV_INLINE __inline__ +#else +# define NV_INLINE +#endif + +/* + * Simple function which encodes a version number, given as major, minor, micro, + * and nano, as a 64-bit unsigned integer. This is defined in an inline function + * rather than as a macro for convenience so it can be examined by the debugger. + * Encoded version numbers can be compared directly in version checks. + */ +static NV_INLINE uint64_t nv_encode_version(unsigned int major, + unsigned int minor, + unsigned int micro, + unsigned int nano) +{ + return (((uint64_t)(nano & 0xFFFF)) | + (((uint64_t)(micro & 0xFFFF)) << 16) | + (((uint64_t)(minor & 0xFFFF)) << 32) | + (((uint64_t)(major & 0xFFFF)) << 48)); +} + +/* + * Wrapper macros for nv_encode_version(). For K in {2,3,4}, NV_VERSIONK() takes + * a K-part version number. + */ +#define NV_VERSION2(major, minor) \ + nv_encode_version(major, minor, 0, 0) +#define NV_VERSION3(major, minor, micro) \ + nv_encode_version(major, minor, micro, 0) +#define NV_VERSION4(major, minor, micro, nano) \ + nv_encode_version(major, minor, micro, nano) + #endif /* __COMMON_UTILS_H__ */ diff --git a/src/config-file.c b/src/config-file.c index 1195f99..bb0b691 100644 --- a/src/config-file.c +++ b/src/config-file.c @@ -80,6 +80,9 @@ static int parse_config_property(const char *file, const char *line, static void write_config_properties(FILE *stream, ConfigProperties *conf, char *locale); +static char *create_display_device_target_string(CtrlHandleTarget *t, + ConfigProperties *conf); + extern int __verbosity; extern int __verbosity_level_changed; @@ -413,12 +416,9 @@ int nv_write_config_file(const char *filename, CtrlHandles *h, randr_gamma_available = 0; } - /* - * use the full display name as the prefix for display targets - * until we can parse other display target names - */ + /* Get the prefix we want to use for the display device target */ - prefix = t->name; + prefix = create_display_device_target_string(t, conf); /* loop over all the entries in the table */ @@ -449,6 +449,8 @@ int nv_write_config_file(const char *filename, CtrlHandles *h, get_color_value(a->attr, c, b, g)); } } + + free(prefix); } /* @@ -923,3 +925,61 @@ void init_config_properties(ConfigProperties *conf) conf->locale = strdup(setlocale(LC_NUMERIC, NULL)); } /* init_config_properties() */ + + +/* + * create_display_device_target_string() - create the string + * to specify the display device target in the config file. + */ + +static char *create_display_device_target_string(CtrlHandleTarget *t, + ConfigProperties *conf) +{ + char *target_name = NULL; + char *target_prefix_name = NULL; + char *display_name = NULL; + char *s; + int target_type; + + if (t->protoNames[NV_DPY_PROTO_NAME_RANDR]) { + target_name = t->protoNames[NV_DPY_PROTO_NAME_RANDR]; + } + + /* If we don't have a target name here, use the full name and return. */ + if (!target_name) { + return nvstrdup(t->name); + } + + /* Get the display name if the user requested it to be used. */ + if (conf->booleans & + CONFIG_PROPERTIES_INCLUDE_DISPLAY_NAME_IN_CONFIG_FILE) { + display_name = NvCtrlGetDisplayName(t->h); + } + + /* Get the target type prefix. */ + target_type = NvCtrlGetTargetType(t->h); + if (target_type >= 0) { + target_prefix_name = + nvstrdup(targetTypeTable[target_type].parsed_name); + nvstrtoupper(target_prefix_name); + } + + /* Build the string */ + + if (display_name && target_prefix_name) { + s = nvasprintf("%s[%s:%s]", display_name, + target_prefix_name, target_name); + } else if (target_prefix_name) { + s = nvasprintf("[%s:%s]", target_prefix_name, target_name); + } else if (display_name) { + s = nvasprintf("%s[%s]", display_name, target_name); + } else { + s = nvasprintf("[%s]", target_name); + } + + free(target_prefix_name); + free(display_name); + + return s; +} + diff --git a/src/gtk+-2.x/ctk3dvisionpro.c b/src/gtk+-2.x/ctk3dvisionpro.c index 312be78..bfe2377 100644 --- a/src/gtk+-2.x/ctk3dvisionpro.c +++ b/src/gtk+-2.x/ctk3dvisionpro.c @@ -27,6 +27,7 @@ #include "ctkconfig.h" #include "ctkhelp.h" #include "ctkdropdownmenu.h" +#include "ctkutils.h" #include <string.h> #include <stdlib.h> @@ -447,16 +448,8 @@ static void create_glasses_info_table(GlassesInfoTable *table, GlassesInfo** gla /* Create the data table */ data_table = gtk_table_new(table->rows, table->columns, FALSE); event = gtk_event_box_new(); - - gtk_widget_modify_fg(data_table, GTK_STATE_NORMAL, - &(data_table->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(data_table, GTK_STATE_NORMAL, - &(data_table->style->base[GTK_STATE_NORMAL])); + ctk_force_text_colors_on_widget(event); gtk_container_add (GTK_CONTAINER(event), data_table); - gtk_widget_modify_fg(event, GTK_STATE_NORMAL, - &(event->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(event, GTK_STATE_NORMAL, - &(event->style->base[GTK_STATE_NORMAL])); gtk_container_add(GTK_CONTAINER(data_viewport), event); /* Pack the glasses info header and data tables */ diff --git a/src/gtk+-2.x/ctkappprofile.c b/src/gtk+-2.x/ctkappprofile.c index 9e31333..0b34630 100644 --- a/src/gtk+-2.x/ctkappprofile.c +++ b/src/gtk+-2.x/ctkappprofile.c @@ -724,11 +724,15 @@ static void populate_tree_view(GtkTreeView *tree_view, g_signal_connect(G_OBJECT(cell_renderer), "edited", column_template->edit_callback, column_template->func_data); - // Generic code to implement navigating between fields with tab/shift-tab - g_signal_connect_data(G_OBJECT(cell_renderer), "editing-started", - G_CALLBACK(cell_renderer_register_key_shortcuts), - (gpointer)rk_data, destroy_cell_renderer_register_key_data, - 0); + // Generic code to implement navigating between fields with + // tab/shift-tab. The "editing-started" signal is only available + // in GTK+ versions >= 2.6. + if (ctk_check_min_gtk_version(2, 6, 0)) { + g_signal_connect_data(G_OBJECT(cell_renderer), "editing-started", + G_CALLBACK(cell_renderer_register_key_shortcuts), + (gpointer)rk_data, destroy_cell_renderer_register_key_data, + 0); + } } if (help_data) { diff --git a/src/gtk+-2.x/ctkbanner.c b/src/gtk+-2.x/ctkbanner.c index 88c645c..5919a5e 100644 --- a/src/gtk+-2.x/ctkbanner.c +++ b/src/gtk+-2.x/ctkbanner.c @@ -25,6 +25,7 @@ #include <stdio.h> #include "ctkbanner.h" +#include "common-utils.h" /* pixdata headers */ @@ -220,9 +221,9 @@ static gboolean ctk_banner_configure_event( /* copy the base image into the backing pixbuf */ - w = MIN(ctk_banner->background->w, ctk_banner->back.w); - h = MIN(ctk_banner->background->h, ctk_banner->back.h); - + w = NV_MIN(ctk_banner->background->w, ctk_banner->back.w); + h = NV_MIN(ctk_banner->background->h, ctk_banner->back.h); + gdk_pixbuf_copy_area(ctk_banner->background->pixbuf, // src 0, // src_x @@ -320,12 +321,12 @@ static void ctk_banner_size_request( { CtkBanner *ctk_banner = CTK_BANNER(widget); - requisition->width = MAX(400, - ctk_banner->logo->w + - ctk_banner->artwork.w + - ctk_banner->logo_pad_x + - ctk_banner->artwork_pad_x); - + requisition->width = NV_MAX(400, + ctk_banner->logo->w + + ctk_banner->artwork.w + + ctk_banner->logo_pad_x + + ctk_banner->artwork_pad_x); + requisition->height = ctk_banner->background->h; } diff --git a/src/gtk+-2.x/ctkconfig.c b/src/gtk+-2.x/ctkconfig.c index a35561a..f6a0cbe 100644 --- a/src/gtk+-2.x/ctkconfig.c +++ b/src/gtk+-2.x/ctkconfig.c @@ -228,13 +228,6 @@ GtkWidget* ctk_config_new(ConfigProperties *conf, CtrlHandles *pCtrlHandles) /* initialize the statusbar widget */ ctk_statusbar_init(&ctk_config->status_bar); - /* XXX force the status bar window to be vertically centered */ - - gtk_misc_set_alignment - (GTK_MISC(GTK_STATUSBAR(ctk_config->status_bar.widget)->label), - 0.0, 0.5); - - /* initialize the tooltips widget */ ctk_config->tooltips.object = gtk_tooltips_new(); diff --git a/src/gtk+-2.x/ctkcurve.c b/src/gtk+-2.x/ctkcurve.c index 709373f..d3eed4d 100644 --- a/src/gtk+-2.x/ctkcurve.c +++ b/src/gtk+-2.x/ctkcurve.c @@ -249,6 +249,8 @@ GtkWidget* ctk_curve_new(NvCtrlAttributeHandle *handle, GtkWidget *color) ctk_curve->gdk_colormap = gdk_colormap = gdk_colormap_get_system(); + g_object_ref(gdk_colormap); + gdk_color = &ctk_curve->gdk_color_red; memset(gdk_color, 0, sizeof(GdkColor)); gdk_color->red = 65535; diff --git a/src/gtk+-2.x/ctkdisplayconfig-utils.c b/src/gtk+-2.x/ctkdisplayconfig-utils.c index ee58898..5e33365 100644 --- a/src/gtk+-2.x/ctkdisplayconfig-utils.c +++ b/src/gtk+-2.x/ctkdisplayconfig-utils.c @@ -41,7 +41,8 @@ static void xconfig_update_buffer(GtkWidget *widget, gpointer user_data); -static gchar *display_pick_config_name(nvDisplayPtr display, int be_generic); +static gchar *display_pick_config_name(nvDisplayPtr display, + int force_target_id_name); static Bool screen_check_metamodes(nvScreenPtr screen); @@ -866,8 +867,8 @@ void apply_underscan_to_viewportout(const nvSize raster_size, viewPortOut->height = (gint) (raster_size.height - (2 * y_offset)); /* Limit ViewPortOut to a minimum size */ - viewPortOut->width = MAX(viewPortOut->width, 10); - viewPortOut->height = MAX(viewPortOut->height, 10); + viewPortOut->width = NV_MAX(viewPortOut->width, 10); + viewPortOut->height = NV_MAX(viewPortOut->height, 10); } @@ -923,7 +924,7 @@ void get_underscan_settings_from_viewportout(const nvSize raster_size, * "mode_name @WxH +X+Y" * **/ -static gchar *mode_get_str(nvModePtr mode, int be_generic) +static gchar *mode_get_str(nvModePtr mode, int force_target_id_name) { gchar *mode_str; gchar *tmp; @@ -937,8 +938,8 @@ static gchar *mode_get_str(nvModePtr mode, int be_generic) return NULL; } - /* Don't display dummy modes */ - if (be_generic && mode->dummy && !mode->modeline) { + /* Don't include dummy modes */ + if (mode->dummy && !mode->modeline) { return NULL; } @@ -949,7 +950,7 @@ static gchar *mode_get_str(nvModePtr mode, int be_generic) } /* Pick a suitable display name qualifier */ - mode_str = display_pick_config_name(display, be_generic); + mode_str = display_pick_config_name(display, force_target_id_name); if (mode_str[0] != '\0') { tmp = mode_str; mode_str = g_strconcat(tmp, ": ", NULL); @@ -972,8 +973,8 @@ static gchar *mode_get_str(nvModePtr mode, int be_generic) /* Panning domain */ - if (!be_generic || (mode->pan.width != mode->viewPortIn.width || - mode->pan.height != mode->viewPortIn.height)) { + if ((mode->pan.width != mode->viewPortIn.width) || + (mode->pan.height != mode->viewPortIn.height)) { tmp = g_strdup_printf("%s @%dx%d", mode_str, mode->pan.width, mode->pan.height); g_free(mode_str); @@ -1043,13 +1044,13 @@ static gchar *mode_get_str(nvModePtr mode, int be_generic) switch (mode->rotation) { case ROTATION_90: - str = "90"; + str = "left"; break; case ROTATION_180: - str = "180"; + str = "invert"; break; case ROTATION_270: - str = "270"; + str = "right"; break; default: break; @@ -1182,37 +1183,39 @@ static Bool display_names_match(const char *name1, const char *name2) * of other display devices. * **/ -static gchar *display_pick_config_name(nvDisplayPtr display, int be_generic) +static gchar *display_pick_config_name(nvDisplayPtr display, + int force_target_id_name) { - nvDisplayPtr other; + nvScreenPtr screen; + nvGpuPtr gpu; - /* Be specific */ - if (!be_generic) { - goto return_specific; + /* Use target ID name for talking to X server */ + if (force_target_id_name) { + return g_strdup(display->targetIdName); } - /* Only one display, so no need for a qualifier */ - if (display->gpu->num_displays == 1) { - return g_strdup(""); - } + screen = display->screen; + gpu = display->gpu; - /* Find the best generic name possible. If any display connected to the - * GPU has the same typeBaseName, then return the typeIdName instead + + /* If one of the Mosaic Modes is configured, and the X server supports + * GPU UUIDs, qualify the display device with the GPU UUID. */ - for (other = display->gpu->displays; other; other = other->next_on_gpu) { - if (other == display) continue; - if (strcmp(other->typeBaseName, display->typeBaseName) == 0) { - goto return_specific; - } + if (screen->num_gpus >= 1 && + gpu->mosaic_enabled && + gpu->uuid) { + return g_strconcat(gpu->uuid, ".", display->randrName, NULL); } - /* No other display device on the GPU shares the same type basename, - * so we can use it + /* If the X screen is driven by a single display on a single GPU, omit the + * display name qualifier, so the configuration will be portable. */ - return g_strdup(display->typeBaseName); + if (screen->num_displays == 1 && gpu->num_displays == 1) { + return g_strdup(""); + } - return_specific: - return g_strdup(display->typeIdName); + /* Otherwise, use the RandR based name */ + return g_strdup(display->randrName); } @@ -1537,7 +1540,7 @@ Bool display_add_modelines_from_server(nvDisplayPtr display, nvGpuPtr gpu, * **/ static gchar *display_get_mode_str(nvDisplayPtr display, int mode_idx, - int be_generic) + int force_target_id_name) { nvModePtr mode = display->modes; @@ -1547,7 +1550,7 @@ static gchar *display_get_mode_str(nvDisplayPtr display, int mode_idx, } if (mode) { - return mode_get_str(mode, be_generic); + return mode_get_str(mode, force_target_id_name); } return NULL; @@ -1652,6 +1655,36 @@ void clamp_screen_size_rect(GdkRectangle *rect) +/** get_screen_max_displays () *************************************** + * + * Returns the maximum number of allowable enabled displays for the X screen. + * This is based on the screen's driving GPU's max number of enabled displays, + * in conjunction with whether or not Mosaic mode is enabled and which type. + * Limited Base Mosaic mode only supports up to 3 enabled display devices, + * while other Mosaic Modes (Base Mosaic and SLI Mosaic) support unlimited + * displays. + * + **/ + +int get_screen_max_displays(nvScreenPtr screen) +{ + nvGpuPtr gpu = screen->display_owner_gpu; + + /* If mosaic is enabled, check the type so we can properly limit the number + * of display devices + */ + if (gpu->mosaic_enabled) { + if (gpu->mosaic_type == MOSAIC_TYPE_BASE_MOSAIC_LIMITED) { + return 3; + } + return -1; /* Not limited */ + } + + return screen->max_displays; +} + + + /** screen_find_named_display() ************************************** * * Finds a display named 'display_name' in the list of displays on the @@ -1918,7 +1951,7 @@ static void screen_remove_displays(nvScreenPtr screen) * **/ gchar *screen_get_metamode_str(nvScreenPtr screen, int metamode_idx, - int be_generic) + int force_target_id_name) { nvDisplayPtr display; @@ -1930,7 +1963,8 @@ gchar *screen_get_metamode_str(nvScreenPtr screen, int metamode_idx, display; display = display->next_in_screen) { - mode_str = display_get_mode_str(display, metamode_idx, be_generic); + mode_str = display_get_mode_str(display, metamode_idx, + force_target_id_name); if (!mode_str) continue; if (!metamode_str) { @@ -2041,8 +2075,9 @@ static Bool screen_add_metamode(nvScreenPtr screen, const char *metamode_str, nvMetaModePtr metamode = NULL; int mode_count = 0; - - if (!screen || !screen->gpu || !metamode_str) goto fail; + if (!screen || !metamode_str) { + goto fail; + } metamode = (nvMetaModePtr)calloc(1, sizeof(nvMetaMode)); @@ -2143,11 +2178,9 @@ static Bool screen_add_metamode(nvScreenPtr screen, const char *metamode_str, /* Make sure something was added */ if (mode_count == 0) { - nv_warning_msg("Failed to find any display on screen %d (on GPU-%d)\n" + nv_warning_msg("Failed to find any display on screen %d\n" "while parsing metamode:\n\n'%s'", - screen->scrnum, - NvCtrlGetTargetId(screen->gpu->handle), - metamode_str); + screen->scrnum, metamode_str); goto fail; } @@ -2301,9 +2334,7 @@ static Bool screen_add_metamodes(nvScreenPtr screen, gchar **err_str) &len); if (ret != NvCtrlSuccess) { *err_str = g_strdup_printf("Failed to query list of metamodes on\n" - "screen %d (on GPU-%d).", - screen->scrnum, - NvCtrlGetTargetId(screen->gpu->handle)); + "screen %d.", screen->scrnum); nv_error_msg(*err_str); goto fail; } @@ -2315,9 +2346,7 @@ static Bool screen_add_metamodes(nvScreenPtr screen, gchar **err_str) &cur_metamode_str); if (ret != NvCtrlSuccess) { *err_str = g_strdup_printf("Failed to query current metamode of\n" - "screen %d (on GPU-%d).", - screen->scrnum, - NvCtrlGetTargetId(screen->gpu->handle)); + "screen %d.", screen->scrnum); nv_error_msg(*err_str); goto fail; } @@ -2336,10 +2365,8 @@ static Bool screen_add_metamodes(nvScreenPtr screen, gchar **err_str) * This populates the display device's mode list. */ if (!screen_add_metamode(screen, str, err_str)) { - nv_warning_msg("Failed to add metamode '%s' to screen %d (on " - "GPU-%d).", - str, screen->scrnum, - NvCtrlGetTargetId(screen->gpu->handle)); + nv_warning_msg("Failed to add metamode '%s' to screen %d.", + str, screen->scrnum); continue; } @@ -2358,9 +2385,8 @@ static Bool screen_add_metamodes(nvScreenPtr screen, gchar **err_str) metamode_strs = NULL; if (!screen->metamodes) { - nv_warning_msg("Failed to add any metamode to screen %d (on GPU-%d).", - screen->scrnum, - NvCtrlGetTargetId(screen->gpu->handle)); + nv_warning_msg("Failed to add any metamode to screen %d.", + screen->scrnum); goto fail; } @@ -2418,6 +2444,11 @@ static void screen_free(nvScreenPtr screen) NvCtrlAttributeClose(screen->handle); } + nvfree(screen->gpus); + screen->num_gpus = 0; + + XFree(screen->sli_mode); + XFree(screen->multigpu_mode); free(screen); } @@ -2425,6 +2456,76 @@ static void screen_free(nvScreenPtr screen) +/** link_screen_to_gpu() ********************************************* + * + * Updates the X screen to track the given GPU as a driver. + * + **/ +void link_screen_to_gpu(nvScreenPtr screen, nvGpuPtr gpu) +{ + screen->num_gpus++; + screen->gpus = nvrealloc(screen->gpus, + screen->num_gpus * sizeof(nvGpuPtr)); + + screen->gpus[screen->num_gpus -1] = gpu; + + /* Consolidate screen's capabilities based on all GPUs involved */ + if (screen->num_gpus == 1) { + screen->max_width = gpu->max_width; + screen->max_height = gpu->max_height; + screen->max_displays = gpu->max_displays; + screen->allow_depth_30 = gpu->allow_depth_30; + screen->display_owner_gpu = gpu; + return; + } + + screen->max_width = MIN(screen->max_width, gpu->max_width); + screen->max_height = MIN(screen->max_height, gpu->max_height); + screen->max_displays = MIN(screen->max_displays, gpu->max_displays); + screen->allow_depth_30 = screen->allow_depth_30 && gpu->allow_depth_30; + + /* Set the display owner GPU. */ + if (screen->display_owner_gpu_id >= 0) { + /* Link to the multi GPU display owner, if it is specified */ + if (screen->display_owner_gpu_id == NvCtrlGetTargetId(gpu->handle)) { + screen->display_owner_gpu = gpu; + } + } else if (gpu->multigpu_master_possible && + !screen->display_owner_gpu->multigpu_master_possible) { + /* Pick the best GPU to be the display owner. This is the first + * GPU that can be a multigpu master, or the first linked GPU, + * if none of the GPU(s) can be set as master. + */ + screen->display_owner_gpu = gpu; + } +} + + + +/** screen_has_gpu() ************************************************* + * + * Returns whether or not the screen is driven by the given GPU. + * + **/ + +Bool screen_has_gpu(nvScreenPtr screen, nvGpuPtr gpu) +{ + int i; + + if (!gpu) { + return FALSE; + } + + for (i = 0; i < screen->num_gpus; i++) { + if (gpu == screen->gpus[i]) { + return TRUE; + } + } + + return FALSE; +} + + /*****************************************************************************/ /** GPU FUNCTIONS ************************************************************/ @@ -2890,6 +2991,7 @@ static void gpu_free(nvGpuPtr gpu) gpu_remove_displays(gpu); XFree(gpu->name); + XFree(gpu->uuid); XFree(gpu->flags_memory); g_free(gpu->pci_bus_id); free(gpu->gvo_mode_data); @@ -3049,6 +3151,7 @@ static Bool layout_add_gpu_from_server(nvLayoutPtr layout, unsigned int gpu_id, nvGpuPtr gpu = NULL; unsigned int *pData; int len; + int val; /* Create the GPU structure */ @@ -3081,6 +3184,15 @@ static Bool layout_add_gpu_from_server(nvLayoutPtr layout, unsigned int gpu_id, goto fail; } + ret = NvCtrlGetStringAttribute(gpu->handle, NV_CTRL_STRING_GPU_UUID, + &gpu->uuid); + if (ret != NvCtrlSuccess) { + nv_warning_msg("Failed to query GPU UUID of GPU-%d '%s'. GPU UUID " + "qualifiers will not be used.", + gpu_id, gpu->name); + gpu->uuid = NULL; + } + get_bus_id_str(gpu->handle, &(gpu->pci_bus_id)); ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_MAX_SCREEN_WIDTH, @@ -3117,6 +3229,12 @@ static Bool layout_add_gpu_from_server(nvLayoutPtr layout, unsigned int gpu_id, gpu->allow_depth_30 = FALSE; } + ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_MULTIGPU_MASTER_POSSIBLE, + &(gpu->multigpu_master_possible)); + if (ret != NvCtrlSuccess) { + gpu->multigpu_master_possible = FALSE; + } + ret = NvCtrlGetBinaryAttribute(gpu->handle, 0, NV_CTRL_BINARY_DATA_GPU_FLAGS, @@ -3132,6 +3250,59 @@ static Bool layout_add_gpu_from_server(nvLayoutPtr layout, unsigned int gpu_id, gpu->flags = &pData[1]; } + + /* Determine available and current Mosaic configuration */ + + gpu->mosaic_type = MOSAIC_TYPE_UNSUPPORTED; + gpu->mosaic_enabled = FALSE; + + ret = NvCtrlGetAttribute(gpu->handle, + NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE, + &(val)); + + if ((ret == NvCtrlSuccess) && + (val == NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE_TRUE)) { + char *sli_str; + + gpu->mosaic_type = MOSAIC_TYPE_SLI_MOSAIC; + + ret = NvCtrlGetStringAttribute(gpu->handle, + NV_CTRL_STRING_SLI_MODE, + &sli_str); + if ((ret == NvCtrlSuccess) && sli_str) { + if (!strcasecmp(sli_str, "Mosaic")) { + gpu->mosaic_enabled = TRUE; + } + XFree(sli_str); + } + + } else { + NVCTRLAttributeValidValuesRec valid; + + ret = NvCtrlGetValidAttributeValues(gpu->handle, + NV_CTRL_BASE_MOSAIC, + &valid); + if ((ret == NvCtrlSuccess) && + (valid.type == ATTRIBUTE_TYPE_INT_BITS)) { + + if (valid.u.bits.ints & NV_CTRL_BASE_MOSAIC_FULL) { + gpu->mosaic_type = MOSAIC_TYPE_BASE_MOSAIC; + } else if (valid.u.bits.ints & NV_CTRL_BASE_MOSAIC_LIMITED) { + gpu->mosaic_type = MOSAIC_TYPE_BASE_MOSAIC_LIMITED; + } + + if (gpu->mosaic_type != MOSAIC_TYPE_UNSUPPORTED) { + ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_BASE_MOSAIC, + &(val)); + if ((ret == NvCtrlSuccess) && + (val == NV_CTRL_BASE_MOSAIC_FULL || + val == NV_CTRL_BASE_MOSAIC_LIMITED)) { + gpu->mosaic_enabled = TRUE; + } + } + } + } + /* Add the display devices to the GPU */ if (!gpu_add_displays_from_server(gpu, err_str)) { nv_warning_msg("Failed to add displays to GPU-%d '%s'.", @@ -3218,56 +3389,71 @@ static void layout_remove_screens(nvLayoutPtr layout) -/** link_screen_to_gpu() ********************************************* +/** link_screen_to_gpus() ******************************************** * - * Finds the GPU driving the screen and links the two. + * Finds the GPU(s) driving the screen and tracks the link(s). * **/ -static Bool link_screen_to_gpu(nvLayoutPtr layout, nvScreenPtr screen) +static Bool link_screen_to_gpus(nvLayoutPtr layout, nvScreenPtr screen) { - int val; + Bool status = FALSE; ReturnStatus ret; - nvGpuPtr gpu; + int *pData = NULL; + int len; + int i; + int scrnum = NvCtrlGetTargetId(screen->handle); /* Link the screen to the display owner GPU. If there is no display owner, * which is the case when SLI Mosaic Mode is configured, link screen - * to the first GPU we find. + * to the first (multi gpu master possible) GPU we find. */ ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_MULTIGPU_DISPLAY_OWNER, - &val); + &(screen->display_owner_gpu_id)); if (ret != NvCtrlSuccess) { - int *pData = NULL; - int len; - - ret = NvCtrlGetBinaryAttribute(screen->handle, - 0, - NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN, - (unsigned char **)(&pData), - &len); - if (ret != NvCtrlSuccess || !pData) { - return FALSE; - } - if (pData[0] < 1) { - XFree(pData); - return FALSE; - } + screen->display_owner_gpu_id = -1; + } - /* Pick the first GPU */ - val = pData[1]; - XFree(pData); + ret = NvCtrlGetBinaryAttribute(screen->handle, + 0, + NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN, + (unsigned char **)(&pData), + &len); + if ((ret != NvCtrlSuccess) || !pData || (pData[0] < 1)) { + goto done; } - for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { - if (val == NvCtrlGetTargetId(gpu->handle)) { - screen->gpu = gpu; - return TRUE; + /* Point to all the gpus */ + + for (i = 0; i < pData[0]; i++) { + nvGpuPtr gpu; + + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + int gpuid = NvCtrlGetTargetId(gpu->handle); + + if (gpuid != pData[1+i]) { + continue; + } + + link_screen_to_gpu(screen, gpu); } } - return FALSE; + /* Make sure a display owner was picked */ + if (screen->num_gpus <= 0) { + nv_error_msg("Failed to link X screen %d to any GPU.", scrnum); + goto done; + } + + status = TRUE; -} /* link_screen_to_gpu() */ + done: + if (pData) { + XFree(pData); + } + + return status; +} @@ -3372,8 +3558,8 @@ static Bool layout_add_screen_from_server(nvLayoutPtr layout, goto fail; } - /* Link screen to the GPU driving it */ - if (!link_screen_to_gpu(layout, screen)) { + /* Link screen to the GPUs driving it */ + if (!link_screen_to_gpus(layout, screen)) { *err_str = g_strdup_printf("Failed to find GPU that drives screen %d.", screen_id); nv_warning_msg(*err_str); @@ -3387,11 +3573,25 @@ static Bool layout_add_screen_from_server(nvLayoutPtr layout, screen->sli = (ret == NvCtrlSuccess); + /* Query SLI mode */ + ret = NvCtrlGetStringAttribute(screen->handle, + NV_CTRL_STRING_SLI_MODE, + &screen->sli_mode); + if (ret != NvCtrlSuccess) { + screen->sli_mode = NULL; + } + + /* Query MULTIGPU mode */ + ret = NvCtrlGetStringAttribute(screen->handle, + NV_CTRL_STRING_MULTIGPU_MODE, + &screen->multigpu_mode); + if (ret != NvCtrlSuccess) { + screen->multigpu_mode = NULL; + } /* Listen to NV-CONTROL events on this screen handle */ screen->ctk_event = CTK_EVENT(ctk_event_new(screen->handle)); - /* Query the depth of the screen */ screen->depth = NvCtrlGetScreenPlanes(screen->handle); @@ -3625,17 +3825,27 @@ nvScreenPtr layout_get_a_screen(nvLayoutPtr layout, nvGpuPtr preferred_gpu) { nvScreenPtr screen = NULL; nvScreenPtr cur; + Bool found_preferred_gpu; if (!layout || !layout->screens) return NULL; screen = layout->screens; + found_preferred_gpu = screen_has_gpu(screen, preferred_gpu); + for (cur = screen->next_in_layout; cur; cur = cur->next_in_layout) { - if (cur->gpu == preferred_gpu) { - if (screen->gpu != preferred_gpu) { + Bool gpu_match = screen_has_gpu(cur, preferred_gpu); + + /* Pick screens that are driven by the preferred gpu */ + if (gpu_match) { + if (!found_preferred_gpu) { screen = cur; continue; } + } else if (found_preferred_gpu) { + continue; } + + /* Pick lower numbered screens */ if (screen->scrnum > cur->scrnum) { screen = cur; } diff --git a/src/gtk+-2.x/ctkdisplayconfig-utils.h b/src/gtk+-2.x/ctkdisplayconfig-utils.h index 8b31f69..e903377 100644 --- a/src/gtk+-2.x/ctkdisplayconfig-utils.h +++ b/src/gtk+-2.x/ctkdisplayconfig-utils.h @@ -91,12 +91,15 @@ Bool display_set_modes_rotation(nvDisplayPtr display, Rotation rotation); /* Screen functions */ void clamp_screen_size_rect(GdkRectangle *rect); +int get_screen_max_displays(nvScreenPtr screen); void renumber_xscreens(nvLayoutPtr layout); void screen_unlink_display(nvDisplayPtr display); void screen_link_display(nvScreenPtr screen, nvDisplayPtr display); void screen_remove_display(nvDisplayPtr display); gchar * screen_get_metamode_str(nvScreenPtr screen, int metamode_idx, - int be_generic); + int force_target_id_name); +void link_screen_to_gpu(nvScreenPtr screen, nvGpuPtr gpu); +Bool screen_has_gpu(nvScreenPtr screen, nvGpuPtr match_gpu); /* GPU functions */ diff --git a/src/gtk+-2.x/ctkdisplayconfig.c b/src/gtk+-2.x/ctkdisplayconfig.c index 10feb75..c9e7b39 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.c +++ b/src/gtk+-2.x/ctkdisplayconfig.c @@ -58,6 +58,8 @@ static void update_selected_page(CtkDisplayConfig *ctk_object); static void setup_display_page(CtkDisplayConfig *ctk_object); +static void mosaic_state_toggled(GtkWidget *widget, gpointer user_data); + static void display_config_changed(GtkWidget *widget, gpointer user_data); static void display_resolution_changed(GtkWidget *widget, gpointer user_data); static void display_refresh_changed(GtkWidget *widget, gpointer user_data); @@ -150,11 +152,6 @@ typedef struct SwitchModeCallbackInfoRec { #define VALIDATE_APPLY 0 #define VALIDATE_SAVE 1 -/* Display configuration index */ -#define DPY_CFG_DISABLED 0 -#define DPY_CFG_SEPARATE_X_SCREEN 1 -#define DPY_CFG_TWINVIEW 2 - /* Underscan range of values */ #define UNDERSCAN_MIN_PERCENT 0 #define UNDERSCAN_MAX_PERCENT 35 @@ -189,6 +186,16 @@ static const char * __dpy_configuration_mnu_help = "The Configure drop-down allows you to select the desired configuration " "for the currently selected display device."; +static const char * __layout_sli_mosaic_button_help = +"The Enable SLI Mosaic checkbox enables SLI Mosaic Mode for all GPUs"; + +static const char * __layout_base_mosaic_limited_button_help = +"The Enable Base Mosaic (Limited) checkbox enables Limited Base Mosaic Mode. " +"In limited Base Mosaic, only 3 displays are supported."; + +static const char * __layout_base_mosaic_full_button_help = +"The Enable Base Mosaic checkbox enables Base Mosaic Mode."; + static const char * __dpy_resolution_mnu_help = "The Resolution drop-down allows you to select a desired resolution " "for the currently selected display device. The 'scaled' qualifier indicates " @@ -385,11 +392,9 @@ static void check_screen_pos_changed(CtkDisplayConfig *ctk_object) static gboolean layout_supports_depth_30(nvLayoutPtr layout) { nvScreenPtr screen; - nvGpuPtr gpu; for (screen = layout->screens; screen; screen = screen->next_in_layout) { - gpu = screen->gpu; - if (!gpu->allow_depth_30) { + if (!screen->allow_depth_30) { return FALSE; } } @@ -619,7 +624,7 @@ static int generate_xconf_metamode_str(CtkDisplayConfig *ctk_object, nvScreenPtr screen, gchar **pMetamode_strs) { - nvLayoutPtr layout = screen->gpu->layout; + nvLayoutPtr layout = screen->layout; gchar *metamode_strs = NULL; gchar *metamode_str; gchar *tmp; @@ -654,7 +659,7 @@ static int generate_xconf_metamode_str(CtkDisplayConfig *ctk_object, */ if (!ctk_object->advanced_mode) { metamode_strs = screen_get_metamode_str(screen, - screen->cur_metamode_idx, 1); + screen->cur_metamode_idx, 0); len = strlen(metamode_strs); start_width = screen->cur_metamode->edim.width; start_height = screen->cur_metamode->edim.height; @@ -690,7 +695,7 @@ static int generate_xconf_metamode_str(CtkDisplayConfig *ctk_object, (metamode->edim.height > start_height))) continue; - metamode_str = screen_get_metamode_str(screen, metamode_idx, 1); + metamode_str = screen_get_metamode_str(screen, metamode_idx, 0); if (!metamode_str) continue; @@ -846,33 +851,6 @@ static void assign_screen_positions(CtkDisplayConfig *ctk_object) -/** find_first_screen_on_gpu() *************************************** - * - * Returns the X screen with the lowest screen number on the given - * GPU. - * - **/ - -static nvScreenPtr find_first_screen_on_gpu(nvGpuPtr gpu) -{ - nvLayoutPtr layout = gpu->layout; - nvScreenPtr first = NULL; - nvScreenPtr screen; - - for (screen = layout->screens; screen; screen = screen->next_in_layout) { - if (screen->gpu != gpu) continue; - if (!first || - (first->scrnum > screen->scrnum)) { - first = screen; - } - } - - return first; - -} /* find_first_screen_on_gpu() */ - - - /* Widget creation functions *****************************************/ @@ -1320,8 +1298,14 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, G_CALLBACK(screen_size_changed), (gpointer) ctk_object); - /* Xinerama button */ + /* Mosaic button */ + ctk_object->chk_mosaic_enabled = + gtk_check_button_new_with_label(""); + g_signal_connect(G_OBJECT(ctk_object->chk_mosaic_enabled), "toggled", + G_CALLBACK(mosaic_state_toggled), + (gpointer) ctk_object); + /* Xinerama button */ ctk_object->chk_xinerama_enabled = gtk_check_button_new_with_label("Enable Xinerama"); ctk_config_set_tooltip(ctk_config, ctk_object->chk_xinerama_enabled, @@ -1330,7 +1314,6 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, G_CALLBACK(xinerama_state_toggled), (gpointer) ctk_object); - /* Selected display/X screen dropdown */ ctk_object->mnu_selected_item = gtk_option_menu_new(); ctk_config_set_tooltip(ctk_config, ctk_object->mnu_selected_item, @@ -1341,15 +1324,6 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, /* Display configuration (Disabled, TwinView, Separate X screen) */ ctk_object->mnu_display_config = gtk_option_menu_new(); - menu = gtk_menu_new(); - ctk_object->mnu_display_config_disabled = gtk_menu_item_new_with_label("Disabled"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), ctk_object->mnu_display_config_disabled); - ctk_object->mnu_display_config_xscreen = gtk_menu_item_new_with_label("Separate X screen (requires X restart)"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), ctk_object->mnu_display_config_xscreen); - ctk_object->mnu_display_config_twinview = gtk_menu_item_new_with_label("TwinView"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), ctk_object->mnu_display_config_twinview); - gtk_option_menu_set_menu - (GTK_OPTION_MENU(ctk_object->mnu_display_config), menu); ctk_config_set_tooltip(ctk_config, ctk_object->mnu_display_config, __dpy_configuration_mnu_help); g_signal_connect(G_OBJECT(ctk_object->mnu_display_config), "changed", @@ -1419,11 +1393,11 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, menu = gtk_menu_new(); menu_item = gtk_menu_item_new_with_label("No Rotation"); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - menu_item = gtk_menu_item_new_with_label("Rotate 90"); + menu_item = gtk_menu_item_new_with_label("Rotate Left"); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - menu_item = gtk_menu_item_new_with_label("Rotate 180"); + menu_item = gtk_menu_item_new_with_label("Invert"); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - menu_item = gtk_menu_item_new_with_label("Rotate 270"); + menu_item = gtk_menu_item_new_with_label("Rotate Right"); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); gtk_option_menu_set_menu (GTK_OPTION_MENU(ctk_object->mnu_display_rotation), menu); @@ -1791,6 +1765,10 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), eventbox, TRUE, TRUE, 0); + /* Mosaic checkbox */ + gtk_box_pack_start(GTK_BOX(vbox), ctk_object->chk_mosaic_enabled, + FALSE, FALSE, 0); + /* Xinerama checkbox */ gtk_box_pack_start(GTK_BOX(vbox), ctk_object->chk_xinerama_enabled, FALSE, FALSE, 0); @@ -1874,7 +1852,7 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, /* Display rotation & reflection dropdowns */ { - GtkWidget *hbox2 = gtk_hbox_new(TRUE, 0); + GtkWidget *hbox2 = gtk_hbox_new(TRUE, 5); label = gtk_label_new("Orientation:"); labels = g_slist_append(labels, label); @@ -2322,6 +2300,64 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table, /* Widget setup & helper functions ***********************************/ +static void setup_mosaic_config(CtkDisplayConfig *ctk_object) +{ + nvDisplayPtr display = ctk_display_layout_get_selected_display + (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); + nvGpuPtr gpu; + const char *tooltip; + const gchar *label; + + + if (!display || !display->gpu || !ctk_object->advanced_mode || + display->gpu->mosaic_type == MOSAIC_TYPE_UNSUPPORTED) { + gtk_widget_hide(ctk_object->chk_mosaic_enabled); + return; + } + gtk_widget_show(ctk_object->chk_mosaic_enabled); + + gpu = display->gpu; + + switch (gpu->mosaic_type) { + case MOSAIC_TYPE_SLI_MOSAIC: + tooltip = __layout_sli_mosaic_button_help; + label = "Enable SLI Mosaic Mode"; + break; + case MOSAIC_TYPE_BASE_MOSAIC: + tooltip = __layout_base_mosaic_full_button_help; + label = "Enable Base Mosaic Mode"; + break; + case MOSAIC_TYPE_BASE_MOSAIC_LIMITED: + tooltip = __layout_base_mosaic_limited_button_help; + label = "Enable Base Mosaic Mode (Limited)"; + break; + default: + gtk_widget_hide(ctk_object->chk_mosaic_enabled); + return; + } + + g_signal_handlers_block_by_func + (G_OBJECT(ctk_object->chk_mosaic_enabled), + G_CALLBACK(mosaic_state_toggled), (gpointer) ctk_object); + + gtk_button_set_label(GTK_BUTTON(ctk_object->chk_mosaic_enabled), + label); + + ctk_config_set_tooltip(ctk_object->ctk_config, + ctk_object->chk_mosaic_enabled, + tooltip); + + gtk_toggle_button_set_active + (GTK_TOGGLE_BUTTON(ctk_object->chk_mosaic_enabled), + gpu->mosaic_enabled); + + g_signal_handlers_unblock_by_func + (G_OBJECT(ctk_object->chk_mosaic_enabled), + G_CALLBACK(mosaic_state_toggled), (gpointer) ctk_object); +} + + + /** setup_layout_frame() ********************************************* * * Sets up the layout frame to reflect the currently selected layout. @@ -2341,6 +2377,8 @@ static void setup_layout_frame(CtkDisplayConfig *ctk_object) s = gtk_widget_get_screen(GTK_WIDGET(ctk_object)); screen_size_changed(s, ctk_object); + setup_mosaic_config(ctk_object); + /* Xinerama requires 2 or more X screens */ if (layout->num_screens < 2) { layout->xinerama_enabled = 0; @@ -2449,12 +2487,6 @@ static GtkWidget* generate_selected_item_dropdown(CtkDisplayConfig *ctk_object, } str = g_strdup_printf("X screen %d", screen->scrnum); - if (show_gpu_info) { - tmp = str; - str = g_strdup_printf("%s (on GPU-%d)", tmp, - NvCtrlGetTargetId(screen->gpu->handle)); - g_free(tmp); - } menu_item = gtk_menu_item_new_with_label(str); g_free(str); @@ -2590,8 +2622,8 @@ static void setup_display_modename(CtkDisplayConfig *ctk_object) /** setup_display_config() ******************************************* * - * Updates the text of the configure button to reflect the current - * setting of the selected display. + * Updates the "Configure" dropdown menu to list the currently + * available configurations of the selected display. * **/ @@ -2599,68 +2631,119 @@ static void setup_display_config(CtkDisplayConfig *ctk_object) { nvDisplayPtr display = ctk_display_layout_get_selected_display (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); + nvLayoutPtr layout = ctk_object->layout; nvScreenPtr screen = NULL; int num_screens_on_gpu = 0; + DisplayConfigOption *options; + int max_options; + int cur_option = -1; + int num_options = 0; + + + /* Allocate the max space we'll need for the lookup table (list all the + * X screens + disable + new) + */ + max_options = layout->num_screens + 2; + options = nvalloc(max_options * sizeof(DisplayConfigOption)); + /* Don't allow disabling the last display device */ - if (ctk_object->layout->num_screens == 1 && - display->screen && - display->screen->num_displays == 1) { - gtk_widget_set_sensitive(ctk_object->mnu_display_config_disabled, - FALSE); - } else { - gtk_widget_set_sensitive(ctk_object->mnu_display_config_disabled, - TRUE); + if (layout->num_screens > 1 || + !display->screen || + display->screen->num_displays >= 1) { + if (!display->screen) { + cur_option = num_options; + } + options[num_options].config = DPY_CFG_DISABLED; + num_options++; } - - /* We can only have as many X screens on the GPU as it supports outputs */ - for (screen = ctk_object->layout->screens; + /* Include the possible X screen(s) that this display can be part of */ + for (screen = layout->screens; screen; screen = screen->next_in_layout) { - if (screen->gpu == display->gpu) { + if (screen_has_gpu(screen, display->gpu) || + display->gpu->mosaic_enabled) { + int max_displays = get_screen_max_displays(screen); + + num_screens_on_gpu++; + if (display->screen == screen) { + cur_option = num_options; + } else if (max_displays >= 0 && + screen->num_displays > max_displays) { + /* Skip screens that are full */ + continue; + } + options[num_options].config = DPY_CFG_X_SCREEN; + options[num_options].screen = screen; + num_options++; } } - - if (!display->screen && - (num_screens_on_gpu >= display->gpu->max_displays)) { - gtk_widget_set_sensitive(ctk_object->mnu_display_config_xscreen, - FALSE); - } else { - gtk_widget_set_sensitive(ctk_object->mnu_display_config_xscreen, - TRUE); - } - - /* We can't setup TwinView if there is only one display connected, - * there are no existing X screens on the GPU, or this display is - * the only enabled device on the GPU, or when SLI is enabled. + /* Only allow creation of a new X screen if Mosaic mode is disabled, the GPU + * can support another X screen, and the display is not already the only + * display in the X screen. */ - if (display->gpu->num_displays == 1 || - !num_screens_on_gpu || - (num_screens_on_gpu == 1 && - display->screen && - display->screen->num_displays == 1) || - (display->screen && display->screen->sli)) { - gtk_widget_set_sensitive(ctk_object->mnu_display_config_twinview, - FALSE); - } else { - gtk_widget_set_sensitive(ctk_object->mnu_display_config_twinview, - TRUE); + + if (!display->gpu->mosaic_enabled && + (num_screens_on_gpu < display->gpu->max_displays) && + (!display->screen || (display->screen->num_displays > 1))) { + options[num_options].config = DPY_CFG_NEW_X_SCREEN; + num_options++; } - /* Select the current configuration option */ - if (!display->screen) { - gtk_option_menu_set_history(GTK_OPTION_MENU(ctk_object->mnu_display_config), - DPY_CFG_DISABLED); // Disabled - } else if (display->screen->num_displays > 1) { - gtk_option_menu_set_history(GTK_OPTION_MENU(ctk_object->mnu_display_config), - DPY_CFG_TWINVIEW); // TwinView - } else { + + /* Apply the new options */ + nvfree(ctk_object->display_config_table); + ctk_object->display_config_table = options; + ctk_object->display_config_table_len = num_options; + + { + GtkWidget *menu = gtk_menu_new(); + int i; + gchar *label; + + for (i = 0; i < num_options; i++) { + GtkWidget *menu_item = NULL; + + switch (options[i].config) { + case DPY_CFG_DISABLED: + menu_item = gtk_menu_item_new_with_label("Disabled"); + break; + case DPY_CFG_NEW_X_SCREEN: + menu_item = + gtk_menu_item_new_with_label("New X screen (requires X " + "restart)"); + break; + case DPY_CFG_X_SCREEN: + label = g_strdup_printf("X screen %d", + options[i].screen->scrnum); + menu_item = gtk_menu_item_new_with_label(label); + g_free(label); + break; + } + if (menu_item) { + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); + gtk_widget_show(menu_item); + } + } + + g_signal_handlers_block_by_func(G_OBJECT(ctk_object->mnu_display_config), + G_CALLBACK(display_config_changed), + (gpointer) ctk_object); + + gtk_option_menu_set_menu + (GTK_OPTION_MENU(ctk_object->mnu_display_config), menu); gtk_option_menu_set_history(GTK_OPTION_MENU(ctk_object->mnu_display_config), - DPY_CFG_SEPARATE_X_SCREEN); // XScreen - } + cur_option); + gtk_widget_set_sensitive(ctk_object->mnu_display_config, TRUE); + + g_signal_handlers_unblock_by_func(G_OBJECT(ctk_object->mnu_display_config), + G_CALLBACK(display_config_changed), + (gpointer) ctk_object); + } + } /* setup_display_config() */ @@ -3348,9 +3431,9 @@ static void setup_display_resolution_dropdown(CtkDisplayConfig *ctk_object) /* If dropdown has only one item, disable menu selection */ if (ctk_object->resolution_table_len > 1) { - gtk_widget_set_sensitive(ctk_object->mnu_display_resolution, True); + gtk_widget_set_sensitive(ctk_object->mnu_display_resolution, TRUE); } else { - gtk_widget_set_sensitive(ctk_object->mnu_display_resolution, False); + gtk_widget_set_sensitive(ctk_object->mnu_display_resolution, FALSE); } g_signal_handlers_unblock_by_func @@ -3362,14 +3445,12 @@ static void setup_display_resolution_dropdown(CtkDisplayConfig *ctk_object) return; - /* Handle failures */ fail: - gtk_option_menu_remove_menu (GTK_OPTION_MENU(ctk_object->mnu_display_resolution)); - gtk_widget_set_sensitive(ctk_object->mnu_display_resolution, False); + gtk_widget_set_sensitive(ctk_object->mnu_display_resolution, FALSE); setup_display_refresh_dropdown(ctk_object); @@ -3444,29 +3525,32 @@ static void setup_display_stereo_dropdown(CtkDisplayConfig *ctk_object) static Bool are_display_composition_transformations_allowed(nvScreenPtr screen) { - int i; + int i, j; Bool ret = TRUE; - if (!screen || !screen->gpu) { + if (!screen) { return FALSE; } - for (i = 0; i < screen->gpu->num_flags; i++) - { - switch (screen->gpu->flags[i]) { - case NV_CTRL_BINARY_DATA_GPU_FLAGS_STEREO_DISPLAY_TRANSFORM_EXCLUSIVE: - if (screen->stereo != NV_CTRL_STEREO_OFF) { - ret = FALSE; - } - break; - case NV_CTRL_BINARY_DATA_GPU_FLAGS_OVERLAY_DISPLAY_TRANSFORM_EXCLUSIVE: - if (screen->overlay != NV_CTRL_OVERLAY_OFF) { - ret = FALSE; + for (i = 0; i < screen->num_gpus; i++) { + nvGpuPtr gpu = screen->gpus[i]; + + for (j = 0; j < gpu->num_flags; j++) { + switch (gpu->flags[j]) { + case NV_CTRL_BINARY_DATA_GPU_FLAGS_STEREO_DISPLAY_TRANSFORM_EXCLUSIVE: + if (screen->stereo != NV_CTRL_STEREO_OFF) { + ret = FALSE; + } + break; + case NV_CTRL_BINARY_DATA_GPU_FLAGS_OVERLAY_DISPLAY_TRANSFORM_EXCLUSIVE: + if (screen->overlay != NV_CTRL_OVERLAY_OFF) { + ret = FALSE; + } + break; + default: + /* We don't care about other flags */ + break; } - break; - default: - /* We don't care about other flags */ - break; } } @@ -3499,13 +3583,13 @@ static void setup_display_rotation_dropdown(CtkDisplayConfig *ctk_object) case ROTATION_0: idx = 0; break; - case ROTATION_90: + case ROTATION_90: // Rotate left idx = 1; break; - case ROTATION_180: + case ROTATION_180: // Invert idx = 2; break; - case ROTATION_270: + case ROTATION_270: // Rotate right idx = 3; break; } @@ -3676,6 +3760,7 @@ static void setup_display_underscan(CtkDisplayConfig *ctk_object) g_signal_handlers_unblock_by_func (G_OBJECT(ctk_object-> txt_display_underscan), G_CALLBACK(display_underscan_activate), (gpointer) ctk_object); + } /* setup_display_underscan() */ @@ -4222,9 +4307,9 @@ static void setup_screen_depth_dropdown(CtkDisplayConfig *ctk_object) */ if (ctk_object->layout->xinerama_enabled) { - add_depth_30_option = layout_supports_depth_30(screen->gpu->layout); + add_depth_30_option = layout_supports_depth_30(screen->layout); } else { - add_depth_30_option = screen->gpu->allow_depth_30; + add_depth_30_option = screen->allow_depth_30; } if (add_depth_30_option) { @@ -4648,6 +4733,7 @@ static gint validation_fix_crowded_metamodes(CtkDisplayConfig *ctk_object, nvModePtr mode; int num; int i, j; + int max_displays = get_screen_max_displays(screen); /* Verify each metamode with the metamodes that come before it */ @@ -4683,7 +4769,7 @@ static gint validation_fix_crowded_metamodes(CtkDisplayConfig *ctk_object, } /* Disable extra modes */ - if (num > screen->gpu->max_displays) { + if (max_displays >= 0 && num > max_displays) { ctk_display_layout_set_mode_modeline (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), mode, @@ -4695,7 +4781,7 @@ static gint validation_fix_crowded_metamodes(CtkDisplayConfig *ctk_object, "for MetaMode %d on Screen %d. (There are " "already %d active display devices for this " "MetaMode.", display->logName, i, screen->scrnum, - screen->gpu->max_displays); + max_displays); } } @@ -4830,6 +4916,7 @@ static gchar * validate_screen(nvScreenPtr screen) nvDisplayPtr display; nvModePtr mode; int i, j; + int max_displays = get_screen_max_displays(screen); int num_displays; gchar *err_str = NULL; gchar *tmp; @@ -4876,11 +4963,11 @@ static gchar * validate_screen(nvScreenPtr screen) /* There can be at most max supported displays active in the metamode. */ - if (num_displays > screen->gpu->max_displays) { + if (max_displays >= 0 && num_displays > max_displays) { tmp = g_strdup_printf("%s MetaMode %d of Screen %d has more than " "%d active display devices.\n\n", bullet, i+1, screen->scrnum, - screen->gpu->max_displays); + max_displays); tmp2 = g_strconcat((err_str ? err_str : ""), tmp, NULL); g_free(err_str); g_free(tmp); @@ -5152,21 +5239,43 @@ static void selected_item_changed(GtkWidget *widget, gpointer user_data) -/** do_enable_display_for_xscreen() ********************************** +/** do_enable_display_on_new_xscreen() ******************************* + * + * Adds the display device to a new X screen in the layout. * - * Adds the display device to a separate X screen in the layout. + * This handles the "Disabled -> New X screen" transition. * **/ -static void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object, - nvDisplayPtr display) +static void do_enable_display_on_new_xscreen(CtkDisplayConfig *ctk_object, + nvDisplayPtr display) { nvLayoutPtr layout = ctk_object->layout; nvScreenPtr screen; + nvGpuPtr gpu; nvScreenPtr rightmost = NULL; nvScreenPtr other; nvMetaModePtr metamode; nvModePtr mode; + int num_screens_on_gpu = 0; + + + gpu = display->gpu; + + for (screen = layout->screens; + screen; + screen = screen->next_in_layout) { + if (screen_has_gpu(screen, gpu)) { + num_screens_on_gpu++; + } + } + + /* Make sure we're allowed to enable this display */ + if (gpu->mosaic_enabled || + (num_screens_on_gpu >= gpu->max_displays) || + display->screen) { + return; + } /* Get resources */ @@ -5202,9 +5311,10 @@ static void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object, /* Setup the screen */ screen->scrnum = layout->num_screens; - screen->gpu = display->gpu; + screen->display_owner_gpu_id = -1; + link_screen_to_gpu(screen, gpu); - other = layout_get_a_screen(layout, display->gpu); + other = layout_get_a_screen(layout, gpu); screen->depth = other ? other->depth : 24; screen->metamodes = metamode; @@ -5241,134 +5351,33 @@ static void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object, /* We can't dynamically add new X screens */ ctk_object->apply_possible = FALSE; - -} /* do_enable_display_for_xscreen() */ +} -/** prepare_gpu_for_twinview() *************************************** - * - * Prepares a GPU for having TwinView enabled. - * - * Currently, this means: +/** do_enable_display_on_xscreen() *********************************** * - * - Deleting all the implicit metamodes from the X screens that the - * GPU is driving. - * - * - Making all the X screens in the layout that are relative to - * X screens driven by this GPU relative to 'use_screen' instead. - * - **/ - -static void prepare_gpu_for_twinview(CtkDisplayConfig *ctk_object, - nvGpuPtr gpu, - nvScreenPtr use_screen) -{ - nvLayoutPtr layout = ctk_object->layout; - nvMetaModePtr metamode; - nvScreenPtr screen; - int m; - - if (!gpu) return; - - /* Delete implicit metamodes from all screens involved */ - for (screen = layout->screens; screen; screen = screen->next_in_layout) { - nvMetaModePtr next; - Bool updated = FALSE; - - if (screen->gpu != gpu) continue; - - m = 0; - metamode = screen->metamodes; - while (metamode) { - next = metamode->next; - - if ((metamode->source == METAMODE_SOURCE_IMPLICIT) && - (metamode != screen->cur_metamode)) { - - ctk_display_layout_delete_screen_metamode - (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), screen, m, - FALSE); - updated = TRUE; - } else { - m++; - } - metamode = next; - } - - /* Now that all the implicit metamodes have been deleted, - * we can recalculate and reselect the current mode - * for the screen. - */ - if (updated) { - ctk_display_layout_set_screen_metamode - (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), - screen, screen->cur_metamode_idx); - } - } - - /* Make all other X screens in the layout relative to the GPU's - * 'use_screen' X screen if they are relative to any X screen driven - * by the GPU. Also, make the 'use_screen' inherit any primary - * device specified by other screens on the same GPU, as well as - * the NV-CONTROL handle and event objects so we can apply changes - * to the screen later on. - */ - if (use_screen) { - for (screen = layout->screens; - screen; - screen = screen->next_in_layout) { - - if (screen->gpu == gpu) { - if (!use_screen->primaryDisplay && screen->primaryDisplay) { - use_screen->primaryDisplay = screen->primaryDisplay; - } - if (!use_screen->handle && screen->handle) { - use_screen->handle = screen->handle; - screen->handle = NULL; - use_screen->ctk_event = screen->ctk_event; - screen->ctk_event = NULL; - } - continue; - } - - if (screen->relative_to && - screen->relative_to->gpu == gpu) { - screen->relative_to = use_screen; - } - } - } - -} /* prepare_gpu_for_twinview() */ - - - -/** do_enable_display_for_twinview() ********************************* + * Adds the display device to an existing X screen. * - * Adds the display device to the TwinView setup that already exists - * on the GPU. + * Handles the "Disabled -> Existing X screen" transition. * **/ -static void do_enable_display_for_twinview(CtkDisplayConfig *ctk_object, - nvDisplayPtr display) +static void do_enable_display_on_xscreen(CtkDisplayConfig *ctk_object, + nvDisplayPtr display, + nvScreenPtr screen) { - nvGpuPtr gpu; - nvScreenPtr screen; nvMetaModePtr metamode; nvModePtr mode; + int max_displays = get_screen_max_displays(screen); - /* Make sure a screen exists */ - gpu = display->gpu; - screen = find_first_screen_on_gpu(gpu); - - if (!screen) return; - - /* Delete implicit metamodes on all X Screens driven by the GPU */ - prepare_gpu_for_twinview(ctk_object, gpu, screen); + /* Make sure we're allowed to enable this display */ + if (max_displays >= 0 && screen->num_displays > max_displays) { + return; + } - /* Fix up the display's metamode list */ + /* Inject the display (create modes) into all the existing metamodes */ display_remove_modes(display); for (metamode = screen->metamodes; metamode; metamode = metamode->next) { @@ -5423,307 +5432,49 @@ static void do_enable_display_for_twinview(CtkDisplayConfig *ctk_object, /* Link the screen and display together */ screen_link_display(screen, display); - -} /* do_enable_display_for_twinview() */ +} -/** do_configure_display_for_xscreen() ******************************* +/** do_configure_display_on_new_xscreen() **************************** + * + * Configures the display's GPU for Multiple X screens. * - * Configures the display's GPU for Multiple X screens + * Handles the "X screen -> New X screen" transition. * **/ -static void do_configure_display_for_xscreen(CtkDisplayConfig *ctk_object, - nvDisplayPtr display) +static void do_configure_display_on_new_xscreen(CtkDisplayConfig *ctk_object, + nvDisplayPtr display) { - nvLayoutPtr layout = ctk_object->layout; - nvGpuPtr gpu; - nvScreenPtr screen; - nvMetaModePtr metamode; - nvModePtr mode; - int scrnum = 0; - - - if (!display || !display->gpu) return; - - - /* Get the next available screen number */ - scrnum = layout->num_screens; - - gpu = display->gpu; - - - /* Make sure there is just one display device per X screen */ - for (display = gpu->displays; display; display = display->next_on_gpu) { - - nvScreenPtr new_screen; - - screen = display->screen; - if (!screen || screen->num_displays == 1) continue; - - /* Create a new X screen for this display */ - new_screen = (nvScreenPtr)calloc(1, sizeof(nvScreen)); - if (!new_screen) continue; /* XXX Fail */ - - new_screen->gpu = gpu; - new_screen->scrnum = scrnum++; - - new_screen->depth = screen->depth; - - /* Create a metamode for each mode on the display */ - new_screen->num_metamodes = 0; - for (mode = display->modes; mode; mode = mode->next) { + ctk_display_layout_disable_display(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), + display); - /* Create the metamode */ - metamode = (nvMetaModePtr)calloc(1, sizeof(nvMetaMode)); - if (!metamode) continue; /* XXX Fail ! */ - - metamode->source = METAMODE_SOURCE_NVCONTROL; - - /* Make the mode point to the new metamode */ - mode->metamode = metamode; - - /* Set the current metamode if this is the current mode */ - if (display->cur_mode == mode) { - new_screen->cur_metamode = metamode; - new_screen->cur_metamode_idx = new_screen->num_metamodes; - } - - /* Append the metamode */ - xconfigAddListItem((GenericListPtr *)(&new_screen->metamodes), - (GenericListPtr)metamode); - new_screen->num_metamodes++; - } - - /* Move the display to the new screen */ - screen_unlink_display(display); - screen_link_display(new_screen, display); - - if (display == screen->primaryDisplay) { - new_screen->primaryDisplay = display; - screen->primaryDisplay = NULL; - } - - /* Earlier display devices get first dibs on low screen numbers */ - new_screen->handle = screen->handle; - new_screen->ctk_event = screen->ctk_event; - new_screen->scrnum = screen->scrnum; - screen->handle = NULL; - screen->ctk_event = NULL; - screen->scrnum = scrnum -1; - - /* Add the screen to the layout */ - layout_add_screen(layout, new_screen); - - /* Can't apply creation of new screens */ - ctk_object->apply_possible = FALSE; - } - - - /* Set the position of all the new screens to the position of the displays - * for the current mode. - */ - for (display = gpu->displays; display; display = display->next_on_gpu) { - nvModePtr cur_mode; - - if (!display->screen) continue; - - cur_mode = display->cur_mode; - if (!cur_mode) { - continue; - } - - /* Translate the positional relationship of the current mode from - * the display to its screen. - */ - if (cur_mode->relative_to && - (cur_mode->relative_to->gpu == cur_mode->display->gpu)) { - display->screen->position_type = cur_mode->position_type; - display->screen->relative_to = cur_mode->relative_to->screen; - } - - /* Position the modes of the display to be where the current mode is, - * and to use absolute positioning since it should now be the only - * display in the X screen. - */ - for (mode = display->modes; mode; mode = mode->next) { - mode->pan.x = cur_mode->pan.x; - mode->pan.y = cur_mode->pan.y; - mode->position_type = CONF_ADJ_ABSOLUTE; - mode->relative_to = NULL; - } - } - -} /* do_configure_display_for_xscreen() */ + do_enable_display_on_new_xscreen(ctk_object, display); +} -/** do_configure_display_for_twinview() ****************************** +/** do_configure_display_on_xscreen() ******************************** * - * Configures the display's GPU for TwinView. + * Moves the display from it's current screen to the new given X + * screen. * **/ -static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object, - nvDisplayPtr display) +static void do_configure_display_on_xscreen(CtkDisplayConfig *ctk_object, + nvDisplayPtr display, + nvScreenPtr use_screen) { - nvLayoutPtr layout = ctk_object->layout; - nvScreenPtr use_screen; /* Screen that inherits all displays */ - nvMetaModePtr metamode; - nvModePtr mode; - nvModePtr last_mode; - nvGpuPtr gpu = display->gpu; - int m; - - - if (!gpu) return; - - /* Find screen on GPU with the lowest screen number */ - use_screen = find_first_screen_on_gpu(gpu); - - /* Need at least one screen to toggle into TwinView */ - if (!use_screen) return; - - - /* Delete implicit metamodes on all X screens driven by the GPU */ - prepare_gpu_for_twinview(ctk_object, gpu, use_screen); - - - /* Make sure the screen has enough metamodes to accommodate all - * the displays. - */ - for (display = gpu->displays; display; display = display->next_on_gpu) { - - /* Only consider enabled displays for TwinView setup */ - if (!display->screen) continue; - - /* Make sure the screen has enough metamodes */ - for (m = display->num_modes - use_screen->num_metamodes; m > 0; m--) { - - metamode = (nvMetaModePtr)calloc(1, sizeof(nvMetaMode)); - if (!metamode) break; // XXX Sigh. - - metamode->source = METAMODE_SOURCE_NVCONTROL; - - /* Add the metamode at the end of the screen's metamode list */ - xconfigAddListItem((GenericListPtr *)(&use_screen->metamodes), - (GenericListPtr)metamode); - use_screen->num_metamodes++; - } - } - - - /* Make sure each display has the right number of modes and that - * the modes point to the right metamode in the screen. - */ - for (display = gpu->displays; display; display = display->next_on_gpu) { - - /* Only add enabled displays to TwinView setup */ - if (!display->screen) continue; - - /* Make the display mode point to the right metamode */ - metamode = use_screen->metamodes; - mode = display->modes; - last_mode = NULL; - while (metamode && mode) { - - if (metamode == use_screen->cur_metamode) { - display->cur_mode = mode; - } - - /* Keep the relationship between displays if possible. If - * this display's screen is relative to another screen - * on the same gpu, translate the relationship to the - * display's mode. - */ - if (display->screen->relative_to && - (display->screen->relative_to->gpu == gpu)) { - - nvDisplayPtr other; - - /* Make the display relative to the other display */ - for (other = gpu->displays; - other; - other = other->next_on_gpu) { - if (other->screen == display->screen->relative_to) { - mode->position_type = display->screen->position_type; - mode->relative_to = other; - break; - } - } - } - mode->metamode = metamode; - - if (mode && !mode->next) { - last_mode = mode; - } - metamode = metamode->next; - mode = mode->next; - } - - /* Add dummy modes */ - while (metamode) { - - mode = mode_parse(display, "NULL"); - mode->dummy = 1; - mode->metamode = metamode; - - if (metamode == use_screen->cur_metamode) { - display->cur_mode = mode; - } - - /* Duplicate position information of the last mode */ - if (last_mode) { - mode->pan.x = last_mode->pan.x; - mode->pan.y = last_mode->pan.y; - mode->position_type = last_mode->position_type; - mode->relative_to = last_mode->relative_to; - } - - /* Add the mode at the end of display's mode list */ - xconfigAddListItem((GenericListPtr *)(&display->modes), - (GenericListPtr)mode); - display->num_modes++; - metamode = metamode->next; - } - } - - - /* Make the GPU's active displays part of the screen */ - for (display = gpu->displays; display; display = display->next_on_gpu) { - - if (!display->screen) continue; - if (display->screen == use_screen) continue; - - screen_unlink_display(display); - screen_link_display(use_screen, display); - } - - - /* Delete extra screens on the GPU */ - { - nvScreenPtr other; - nvScreenPtr next; - - other = layout->screens; - next = layout->screens; - while (next) { - other = next; - next = other->next_in_layout; - - if (other->gpu != gpu) continue; - if (other == use_screen) continue; - - layout_remove_and_free_screen(other); - } + if (display->screen == use_screen) { + return; } + ctk_display_layout_disable_display(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), + display); - /* Make sure screen numbering is consistent */ - renumber_xscreens(ctk_object->layout); - -} /* do_configure_display_for_twinview() */ + do_enable_display_on_xscreen(ctk_object, display, use_screen); +} @@ -5816,6 +5567,136 @@ static void do_disable_display(CtkDisplayConfig *ctk_object, +static Bool display_build_modepool(nvDisplayPtr display, Bool *updated) +{ + if (!display->modelines) { + char *tokens = NULL; + gchar *err_str = NULL; + + NvCtrlStringOperation(display->handle, 0, + NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL, + "", &tokens); + XFree(tokens); + *updated = TRUE; + if (!display_add_modelines_from_server(display, display->gpu, + &err_str)) { + nv_warning_msg(err_str); + g_free(err_str); + return FALSE; + } + } + + return display->modelines ? TRUE : FALSE; +} + + + +static void do_enable_mosaic(CtkDisplayConfig *ctk_object) +{ + nvLayoutPtr layout = ctk_object->layout; + nvGpuPtr gpu; + nvScreenPtr mosaic_screen; + + /* Pick first X screen as mosaic X screen */ + + mosaic_screen = layout->screens; + + /* Consolidate all GPUs */ + + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + if (!screen_has_gpu(mosaic_screen, gpu)) { + link_screen_to_gpu(mosaic_screen, gpu); + } + + gpu->mosaic_enabled = TRUE; + } + + /* Consolidate all enabled displays */ + + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + nvDisplayPtr display; + + for (display = gpu->displays; + display; + display = display->next_on_gpu) { + if (display->screen && + display->screen != mosaic_screen) { + do_configure_display_on_xscreen(ctk_object, display, + mosaic_screen); + } + } + } +} + + + +static void do_disable_mosaic(CtkDisplayConfig *ctk_object) +{ + nvLayoutPtr layout = ctk_object->layout; + nvGpuPtr gpu; + nvScreenPtr mosaic_screen; + + /* Track the original Mosaic X screen */ + mosaic_screen = layout->screens; + + /* Disable Mosaic on all GPUs, and move the enabled displays that are not + * on the display owner GPU to their own X screen + */ + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + + gpu->mosaic_enabled = FALSE; + + if (gpu != mosaic_screen->display_owner_gpu) { + nvDisplayPtr display; + for (display = gpu->displays; + display; + display = display->next_on_gpu) { + if (!display->screen) { + continue; + } + do_configure_display_on_new_xscreen(ctk_object, display); + } + } + } + + /* Re-link the original screen to the GPU (unlinks all other gpus from the + * screen.) + */ + mosaic_screen->num_gpus = 0; + link_screen_to_gpu(mosaic_screen, mosaic_screen->display_owner_gpu); +} + + + +static void mosaic_state_toggled(GtkWidget *widget, gpointer user_data) +{ + CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data); + gboolean enabled; + + + enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + + /* Can't dynamically toggle Mosaic */ + ctk_object->apply_possible = FALSE; + + if (enabled) { + do_enable_mosaic(ctk_object); + } else { + do_disable_mosaic(ctk_object); + } + + /* Update the GUI */ + ctk_display_layout_update_zorder(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); + + ctk_display_layout_update(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); + + update_gui(ctk_object); + + user_changed_attributes(ctk_object); +} + + + /** display_config_changed() ***************************************** * * Called when user selects an option in the display configuration menu. @@ -5828,72 +5709,56 @@ static void display_config_changed(GtkWidget *widget, gpointer user_data) nvLayoutPtr layout = ctk_object->layout; nvDisplayPtr display = ctk_display_layout_get_selected_display (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); - nvScreenPtr screen; gboolean update = FALSE; - gint position_idx; + nvScreenPtr screen; + + gint table_idx; + DisplayConfigOption *option; if (!display) { return; } - position_idx = gtk_option_menu_get_history(GTK_OPTION_MENU( - ctk_object->mnu_display_config)); + table_idx = + gtk_option_menu_get_history(GTK_OPTION_MENU(ctk_object->mnu_display_config)); + option = &(ctk_object->display_config_table[table_idx]); + + switch (option->config) { - /* Disabled was selected. */ - if (position_idx == DPY_CFG_DISABLED) { + case DPY_CFG_DISABLED: if (display->screen) { do_disable_display(ctk_object, display); update = TRUE; } - } else { + break; - /* Make sure the display has modelines */ - if (!display->modelines) { - char *tokens; - gchar *err_str = NULL; - NvCtrlStringOperation(display->handle, 0, - NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL, - "", &tokens); - update = TRUE; - if (!display_add_modelines_from_server(display, display->gpu, &err_str)) { - nv_warning_msg(err_str); - g_free(err_str); - return; - } + case DPY_CFG_NEW_X_SCREEN: + if (!display_build_modepool(display, &update)) { + return; } - if (!display->modelines) return; - if (!display->screen) { - - /* Enable display as a separate X screen */ - if (position_idx == DPY_CFG_SEPARATE_X_SCREEN) { - - do_enable_display_for_xscreen(ctk_object, display); - update = TRUE; - } - - /* Enable display in TwinView with an existing screen */ - if (position_idx == DPY_CFG_TWINVIEW) { - do_enable_display_for_twinview(ctk_object, display); - update = TRUE; - } - + do_enable_display_on_new_xscreen(ctk_object, display); } else { + do_configure_display_on_new_xscreen(ctk_object, display); + } + update = TRUE; + break; - /* Move display to a new X screen */ - if (display->screen->num_displays > 1 && - position_idx == DPY_CFG_SEPARATE_X_SCREEN) { - do_configure_display_for_xscreen(ctk_object, display); - update = TRUE; - } - - /* Setup TwinView on the first X screen */ - if (display->screen->num_displays == 1 && - position_idx == DPY_CFG_TWINVIEW) { - do_configure_display_for_twinview(ctk_object, display); - update = TRUE; - } + case DPY_CFG_X_SCREEN: + if (display->screen == option->screen) { + return; + } + if (!display_build_modepool(display, &update)) { + return; + } + if (!display->screen) { + do_enable_display_on_xscreen(ctk_object, display, option->screen); + } else { + do_configure_display_on_xscreen(ctk_object, display, + option->screen); } + update = TRUE; + break; } @@ -5903,10 +5768,6 @@ static void display_config_changed(GtkWidget *widget, gpointer user_data) /* Update the z-order */ ctk_display_layout_update_zorder(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); - /* Make sure the display is still selected */ - ctk_display_layout_select_display(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), - display); - /* Recalculate */ ctk_display_layout_update(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); @@ -5914,7 +5775,9 @@ static void display_config_changed(GtkWidget *widget, gpointer user_data) for (screen = layout->screens; screen; screen = screen->next_in_layout) { - if (screen->gpu != display->gpu) continue; + if (!screen_has_gpu(screen, display->gpu)) { + continue; + } validation_auto_fix_screen(ctk_object, screen); } @@ -6059,7 +5922,7 @@ static void display_resolution_changed(GtkWidget *widget, gpointer user_data) /** display_stereo_changed() ***************************** * - * Called when user selectes a new passive stereo eye + * Called when user selects a new passive stereo eye * configuration. * **/ @@ -6206,6 +6069,7 @@ static void post_display_underscan_value_changed(CtkDisplayConfig *ctk_object, nvDisplayPtr display; nvModePtr cur_mode; nvSize raster_size; + GdkRectangle rotatedViewPortIn; ctk_display = CTK_DISPLAY_LAYOUT(ctk_object->obj_layout); display = ctk_display_layout_get_selected_display(ctk_display); @@ -6223,19 +6087,25 @@ static void post_display_underscan_value_changed(CtkDisplayConfig *ctk_object, apply_underscan_to_viewportout(raster_size, hpixel_value, &cur_mode->viewPortOut); + if (cur_mode->rotation == ROTATION_90 || + cur_mode->rotation == ROTATION_270) + { + rotatedViewPortIn.width = cur_mode->viewPortOut.height; + rotatedViewPortIn.height = cur_mode->viewPortOut.width; + } else { + rotatedViewPortIn.width = cur_mode->viewPortOut.width; + rotatedViewPortIn.height = cur_mode->viewPortOut.height; + } + ctk_display_layout_set_mode_viewport_in(ctk_display, cur_mode, - cur_mode->viewPortOut.width, - cur_mode->viewPortOut.height, + rotatedViewPortIn.width, + rotatedViewPortIn.height, TRUE /* update_panning_size */); /* Enable the apply button */ gtk_widget_set_sensitive(ctk_object->btn_apply, TRUE); - /* Update status bar */ - ctk_config_statusbar_message(ctk_object->ctk_config, - "Underscan set to %d horizontal pixels.", - hpixel_value); } @@ -6276,6 +6146,7 @@ static void display_underscan_value_changed(GtkAdjustment *adjustment, g_free(txt_entry); post_display_underscan_value_changed(ctk_object, hpixel_value); + } @@ -6289,7 +6160,7 @@ static void display_underscan_value_changed(GtkAdjustment *adjustment, * **/ static void display_underscan_activate(GtkWidget *widget, - gpointer user_data) + gpointer user_data) { CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data); const gchar *txt_entry = gtk_entry_get_text(GTK_ENTRY(widget)); @@ -6317,8 +6188,8 @@ static void display_underscan_activate(GtkWidget *widget, adj_value = ((gfloat) hpixel_value / hdisplay) * 100; /* Sanitize adjustment value */ - adj_value = MIN(adj_value, UNDERSCAN_MAX_PERCENT); - adj_value = MAX(adj_value, UNDERSCAN_MIN_PERCENT); + adj_value = NV_MIN(adj_value, UNDERSCAN_MAX_PERCENT); + adj_value = NV_MAX(adj_value, UNDERSCAN_MIN_PERCENT); /* This sends a value_changed signal to the adjustment object */ gtk_adjustment_set_value(GTK_ADJUSTMENT(ctk_object->adj_display_underscan), @@ -6919,7 +6790,7 @@ static void screen_metamode_clicked(GtkWidget *widget, gpointer user_data) for (i = 0; i < screen->num_metamodes; i++) { /* Setup the menu item text */ - tmp = screen_get_metamode_str(screen, i, 1); + tmp = screen_get_metamode_str(screen, i, 0); str = g_strdup_printf("%d - \"%s\"", i+1, tmp); menu_item = gtk_menu_item_new_with_label(str); g_free(str); @@ -7379,9 +7250,8 @@ static Bool add_cpl_metamode_to_X(nvScreenPtr screen, nvMetaModePtr metamode, /* Grab the metamode ID from the returned tokens */ if ((ret != NvCtrlSuccess) || !tokens) { nv_error_msg("Failed to add MetaMode '%s' to X for " - "screen %d (GPU:%s)", - metamode->string, - screen->scrnum, screen->gpu->name); + "screen %d", + metamode->string, screen->scrnum); return FALSE; } @@ -7455,7 +7325,7 @@ static void preprocess_metamodes(nvScreenPtr screen, char *metamode_strs, free(metamode->string); metamode->id = -1; metamode->x_idx = -1; - metamode->string = screen_get_metamode_str(screen, metamode_idx, 0); + metamode->string = screen_get_metamode_str(screen, metamode_idx, 1); if (!metamode->string) continue; /* See if the metamode already exists and if so, get its ID */ @@ -7812,8 +7682,7 @@ static int update_screen_metamodes(CtkDisplayConfig *ctk_object, if (!cur_metamode_ptr) { nv_error_msg("Failed to identify current MetaMode in X list of " - "MetaModes for screen %d (GPU:%s)", screen->scrnum, - screen->gpu->name); + "MetaModes for screen %d", screen->scrnum); return 1; } @@ -7922,9 +7791,8 @@ static void apply_clicked(GtkWidget *widget, gpointer user_data) screen->primaryDisplay->typeIdName, NULL); if (ret != NvCtrlSuccess) { - nv_error_msg("Failed to set primary display" - "for screen %d (GPU:%s)", screen->scrnum, - screen->gpu->name); + nv_error_msg("Failed to set primary display for screen %d", + screen->scrnum); } else { /* Make sure other parts of nvidia-settings get updated */ ctk_event_emit_string(screen->ctk_event, 0, @@ -8362,7 +8230,6 @@ static int add_screen_to_xconfig(CtkDisplayConfig *ctk_object, } /* Set the nvidiaXineramaInfoOrder option */ - if (screen->primaryDisplay) { xconfigAddNewOption(&conf_screen->options, "nvidiaXineramaInfoOrder", @@ -8379,7 +8246,7 @@ static int add_screen_to_xconfig(CtkDisplayConfig *ctk_object, if (!metamode_strs) { metamode_strs = screen_get_metamode_str(screen, screen->cur_metamode_idx, - 1); + 0); } if (metamode_strs) { @@ -8387,6 +8254,45 @@ static int add_screen_to_xconfig(CtkDisplayConfig *ctk_object, metamode_strs); free(metamode_strs); } + + /* Set Mosaic configuration */ + if (screen->display_owner_gpu->mosaic_enabled) { + xconfigAddNewOption(&conf_screen->options, "MultiGPU", "Off"); + + switch (screen->display_owner_gpu->mosaic_type) { + case MOSAIC_TYPE_SLI_MOSAIC: + xconfigAddNewOption(&conf_screen->options, "SLI", "Mosaic"); + xconfigAddNewOption(&conf_screen->options, "BaseMosaic", "off"); + break; + case MOSAIC_TYPE_BASE_MOSAIC: + case MOSAIC_TYPE_BASE_MOSAIC_LIMITED: + xconfigAddNewOption(&conf_screen->options, "SLI", "off"); + xconfigAddNewOption(&conf_screen->options, "BaseMosaic", "on"); + break; + default: + nv_warning_msg("Uknonwn mosaic mode %d", + screen->display_owner_gpu->mosaic_type); + xconfigAddNewOption(&conf_screen->options, "SLI", + screen->sli_mode ? screen->sli_mode : "Off"); + xconfigAddNewOption(&conf_screen->options, "BaseMosaic", "off"); + break; + } + } else { + /* Set SLI configuration */ + if (screen->sli_mode && + !g_ascii_strcasecmp(screen->sli_mode, "Mosaic")) { + xconfigAddNewOption(&conf_screen->options, "SLI", "Off"); + } else { + xconfigAddNewOption(&conf_screen->options, "SLI", + screen->sli_mode ? screen->sli_mode : "Off"); + } + + xconfigAddNewOption(&conf_screen->options, "MultiGPU", + screen->multigpu_mode ? screen->multigpu_mode : "Off"); + + xconfigAddNewOption(&conf_screen->options, "BaseMosaic", "off"); + + } } @@ -8450,7 +8356,9 @@ static int get_device_screen_id(nvGpuPtr gpu, nvScreenPtr screen) device_screen_id = 0; num_screens_on_gpu = 0; for (other = layout->screens; other; other = other->next_in_layout) { - if (other->gpu != gpu) continue; + if (!screen_has_gpu(other, gpu)) { + continue; + } num_screens_on_gpu++; @@ -8504,7 +8412,7 @@ static int add_screens_to_xconfig(CtkDisplayConfig *ctk_object, /* Generate the Device sections and Screen sections */ for (screen = layout->screens; screen; screen = screen->next_in_layout) { - nvGpuPtr gpu = screen->gpu; + nvGpuPtr gpu = screen->display_owner_gpu; /* Figure out what screen number to use for the device section. */ device_screen_id = get_device_screen_id(gpu, screen); diff --git a/src/gtk+-2.x/ctkdisplayconfig.h b/src/gtk+-2.x/ctkdisplayconfig.h index d6dd7d0..ba9acff 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.h +++ b/src/gtk+-2.x/ctkdisplayconfig.h @@ -63,6 +63,16 @@ typedef struct SelectableItemRec { } u; } SelectableItem; +/* Display configuration special index */ +#define DPY_CFG_DISABLED 0 +#define DPY_CFG_X_SCREEN 1 +#define DPY_CFG_NEW_X_SCREEN 2 + +typedef struct DisplayConfigOptionRec { + int config; + nvScreenPtr screen; +} DisplayConfigOption; + typedef struct _CtkDisplayConfig { @@ -78,6 +88,7 @@ typedef struct _CtkDisplayConfig GtkWidget *obj_layout; GtkWidget *label_layout; + GtkWidget *chk_mosaic_enabled; GtkWidget *chk_xinerama_enabled; GtkWidget *chk_primary_display; gboolean primary_display_changed; @@ -95,9 +106,8 @@ typedef struct _CtkDisplayConfig GtkWidget *box_display_config; GtkWidget *mnu_display_config; - GtkWidget *mnu_display_config_disabled; - GtkWidget *mnu_display_config_xscreen; - GtkWidget *mnu_display_config_twinview; + DisplayConfigOption *display_config_table; + int display_config_table_len; /* Display - Settings */ GtkWidget *box_screen_drag_info_display; diff --git a/src/gtk+-2.x/ctkdisplaylayout.c b/src/gtk+-2.x/ctkdisplaylayout.c index ada22b1..82db694 100644 --- a/src/gtk+-2.x/ctkdisplaylayout.c +++ b/src/gtk+-2.x/ctkdisplaylayout.c @@ -206,8 +206,6 @@ static void zorder_layout(CtkDisplayLayout *ctk_object) ctk_object->Zorder = NULL; } ctk_object->Zcount = 0; - ctk_object->selected_display = NULL; - ctk_object->selected_screen = NULL; /* Count the number of Z-orderable elements in the layout */ @@ -403,11 +401,9 @@ static Bool get_modify_info(CtkDisplayLayout *ctk_object) info->target_position_type = &(info->display->cur_mode->position_type); info->target_dim = &(info->display->cur_mode->pan); - info->gpu = info->display->gpu; } else { info->target_position_type = &(info->screen->position_type); info->target_dim = screen_rect; - info->gpu = info->screen->gpu; } info->orig_position_type = *(info->target_position_type); info->orig_dim = *(info->target_dim); @@ -1009,17 +1005,17 @@ static void calc_layout(nvLayoutPtr layout) memset(dim, 0, sizeof(*dim)); for (screen = layout->screens; screen; screen = screen->next_in_layout) { - GdkRectangle *screem_rect; + GdkRectangle *screen_rect; calc_screen(screen); - screem_rect = get_screen_rect(screen, 0); + screen_rect = get_screen_rect(screen, 0); if (init) { - *dim = *screem_rect; + *dim = *screen_rect; init = 0; continue; } - gdk_rectangle_union(dim, screem_rect, dim); + gdk_rectangle_union(dim, screen_rect, dim); } /* Position disabled display devices off to the top right */ @@ -1036,14 +1032,14 @@ static void calc_layout(nvLayoutPtr layout) x += display->cur_mode->pan.width; dim->width += display->cur_mode->pan.width; - dim->height = MAX(dim->height, display->cur_mode->pan.height); + dim->height = NV_MAX(dim->height, display->cur_mode->pan.height); } } } -/** recenter_screen() ************************************************ +/** realign_screen() ************************************************* * * Makes sure that all the top left corners of all the screen's metamodes * coincide. This is done by offsetting metamodes back to the screen's @@ -1051,7 +1047,7 @@ static void calc_layout(nvLayoutPtr layout) * **/ -static Bool recenter_screen(nvScreenPtr screen) +static Bool realign_screen(nvScreenPtr screen) { nvMetaModePtr metamode; int idx; @@ -1074,8 +1070,7 @@ static Bool recenter_screen(nvScreenPtr screen) } return modified; - -} /* recenter_screen() */ +} @@ -1131,7 +1126,7 @@ static void reposition_screen(nvScreenPtr screen, int resolve_all_modes) /* Reestablish the screen's original position */ screen->dim.x = orig_screen_x; screen->dim.y = orig_screen_y; - recenter_screen(screen); + realign_screen(screen); } /* reposition_screen() */ @@ -1141,10 +1136,10 @@ static void reposition_screen(nvScreenPtr screen, int resolve_all_modes) * * Prepare a screen for using absolute positioning. This is needed * since screens using relative positioning may not have all their - * metamodes's top left corner coincident the same place. This - * function makes sure that all metamodes in the screen have the - * same top left corner by offsetting the modes of metamodes that - * are offset from the screen's bounding box top left corner. + * metamodes's top left corner coincide. This function makes sure + * that all metamodes in the screen have the same top left corner by + * offsetting the modes of metamodes that are offset from the screen's + * bounding box top left corner. * **/ @@ -1153,7 +1148,7 @@ static void switch_screen_to_absolute(nvScreenPtr screen) screen->position_type = CONF_ADJ_ABSOLUTE; screen->relative_to = NULL; - recenter_screen(screen); + realign_screen(screen); } /* switch_screen_to_absolute() */ @@ -1499,17 +1494,17 @@ static void snap_move(CtkDisplayLayout *ctk_object) bh = &info->best_snap_h; if (info->display) { - dist = abs( (info->screen->dim.x + info->gpu->max_width) + dist = abs( (info->screen->dim.x + info->screen->max_width) -(info->src_dim.x + info->src_dim.width)); if (dist < *bh) { - info->dst_dim.x = info->screen->dim.x + info->gpu->max_width - + info->dst_dim.x = info->screen->dim.x + info->screen->max_width - info->src_dim.width; *bh = dist; } - dist = abs( (info->screen->dim.y + info->gpu->max_height) + dist = abs( (info->screen->dim.y + info->screen->max_height) -(info->src_dim.y + info->src_dim.height)); if (dist < *bv) { - info->dst_dim.y = info->screen->dim.y + info->gpu->max_height - + info->dst_dim.y = info->screen->dim.y + info->screen->max_height - info->src_dim.height; *bv = dist; } @@ -1709,19 +1704,19 @@ static void snap_pan(CtkDisplayLayout *ctk_object) bv = &(info->best_snap_v); /* Snap to the maximum screen width */ - dist = abs((info->screen->dim.x + info->gpu->max_width) + dist = abs((info->screen->dim.x + info->screen->max_width) -(info->src_dim.x + info->src_dim.width)); if (dist < *bh) { - info->dst_dim.width = info->screen->dim.x + info->gpu->max_width - + info->dst_dim.width = info->screen->dim.x + info->screen->max_width - info->src_dim.x; *bh = dist; } /* Snap to the maximum screen height */ - dist = abs((info->screen->dim.y + info->gpu->max_height) + dist = abs((info->screen->dim.y + info->screen->max_height) -(info->src_dim.y + info->src_dim.height)); if (dist < *bv) { - info->dst_dim.height = info->screen->dim.y + info->gpu->max_height - + info->dst_dim.height = info->screen->dim.y + info->screen->max_height - info->src_dim.y; *bv = dist; } @@ -1854,22 +1849,22 @@ static int move_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap) } /* Prevent screen from growing too big */ - x = sdim->x + info->gpu->max_width - dim->width; + x = sdim->x + info->screen->max_width - dim->width; if (info->dst_dim.x > x) { info->modify_dim.x += x - info->dst_dim.x; info->dst_dim.x = x; } - y = sdim->y + info->gpu->max_height - dim->height; + y = sdim->y + info->screen->max_height - dim->height; if (info->dst_dim.y > y) { info->modify_dim.y += y - info->dst_dim.y; info->dst_dim.y = y; } - x = sdim->x + sdim->width - info->gpu->max_width; + x = sdim->x + sdim->width - info->screen->max_width; if (info->dst_dim.x < x) { info->modify_dim.x += x - info->dst_dim.x; info->dst_dim.x = x; } - y = sdim->y + sdim->height - info->gpu->max_height; + y = sdim->y + sdim->height - info->screen->max_height; if (info->dst_dim.y < y) { info->modify_dim.y += y - info->dst_dim.y; info->dst_dim.y = y; @@ -2029,12 +2024,12 @@ static int pan_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap) /* Panning should not cause us to exceed the maximum screen dimensions */ dim = get_screen_rect(info->screen, 1); - x = dim->x + info->gpu->max_width - info->dst_dim.x; + x = dim->x + info->screen->max_width - info->dst_dim.x; if (info->dst_dim.width > x) { info->modify_dim.width += x - info->dst_dim.width; info->dst_dim.width = x; } - y = dim->y + info->gpu->max_height - info->dst_dim.y; + y = dim->y + info->screen->max_height - info->dst_dim.y; if (info->dst_dim.height > y) { info->modify_dim.height += y - info->dst_dim.height; info->dst_dim.height = y; @@ -2228,6 +2223,9 @@ static void select_default_item(CtkDisplayLayout *ctk_object) int best_dst = -1; // Distance squared to element. int dst; + /* Clear the selection */ + ctk_object->selected_display = NULL; + ctk_object->selected_screen = NULL; for (i = 0; i < ctk_object->Zcount; i++) { @@ -2364,16 +2362,12 @@ static char *get_display_tooltip(nvDisplayPtr display, Bool advanced) /** get_screen_tooltip() ********************************************* * * Returns the text to use for displaying a tooltip from the given - * screen: - * - * SCREEN NUMBER (GPU NAME) - * - * The caller should free the string that is returned. + * screen. The caller should free the string that is returned. * **/ -static char *get_screen_tooltip(nvScreenPtr screen, Bool advanced) -{ +static char *get_screen_tooltip(nvScreenPtr screen) +{ char *tip; @@ -2382,23 +2376,9 @@ static char *get_screen_tooltip(nvScreenPtr screen, Bool advanced) return NULL; } + tip = g_strdup_printf("X Screen %d%s", screen->scrnum, + screen->no_scanout ? " : No Scanout" : ""); - /* Basic view */ - if (!advanced) { - - tip = g_strdup_printf("X Screen %d%s", screen->scrnum, - screen->no_scanout ? " : No Scanout" : "" - ); - - /* Advanced view */ - } else { - - tip = g_strdup_printf("X Screen %d%s\n(GPU: %s)", - screen->scrnum, - screen->no_scanout ? " : No Scanout" : "", - screen->gpu->name); - } - return tip; } /* get_screen_tooltip() */ @@ -2451,7 +2431,7 @@ static char *get_tooltip_under_mouse(CtkDisplayLayout *ctk_object, if (screen == last_screen) { goto found; } - tip = get_screen_tooltip(screen, ctk_object->advanced_mode); + tip = get_screen_tooltip(screen); goto found; } } @@ -2647,8 +2627,6 @@ GtkWidget* ctk_display_layout_new(NvCtrlAttributeHandle *handle, /* Setup the layout state variables */ ctk_object->snap_strength = DEFAULT_SNAP_STRENGTH; - ctk_object->first_selected_display = NULL; - ctk_object->first_selected_screen = NULL; /* Make the drawing area */ @@ -3182,7 +3160,7 @@ static Bool sync_layout(CtkDisplayLayout *ctk_object) /* Align all metamodes of each screen */ for (screen = layout->screens; screen; screen = screen->next_in_layout) { - if (recenter_screen(screen)) { + if (realign_screen(screen)) { modified = TRUE; } } @@ -3290,31 +3268,9 @@ nvScreenPtr ctk_display_layout_get_selected_screen(CtkDisplayLayout *ctk_object) -/** ctk_display_layout_get_selected_gpu() **************************** - * - * Returns the selected gpu. - * - **/ - -nvGpuPtr ctk_display_layout_get_selected_gpu(CtkDisplayLayout *ctk_object) -{ - if (ctk_object->selected_display) { - return ctk_object->selected_display->gpu; - } - - if (ctk_object->selected_screen) { - return ctk_object->selected_screen->gpu; - } - - return NULL; - -} /* ctk_display_layout_get_selected_gpu() */ - - - /** ctk_display_layout_set_screen_metamode() ************************* * - * Sets which metamode the screen should be use. + * Sets which metamode the screen should use. * **/ @@ -3354,7 +3310,7 @@ void ctk_display_layout_add_screen_metamode(CtkDisplayLayout *ctk_object, nvMetaModePtr metamode; - if (!screen || !screen->gpu) return; + if (!screen) return; /* Add a metamode to the screen */ @@ -3433,7 +3389,7 @@ void ctk_display_layout_delete_screen_metamode(CtkDisplayLayout *ctk_object, int i; - if (!screen || !screen->gpu || metamode_idx >= screen->num_metamodes) { + if (!screen || metamode_idx >= screen->num_metamodes) { return; } @@ -3534,9 +3490,6 @@ void ctk_display_layout_disable_display(CtkDisplayLayout *ctk_object, layout_remove_and_free_screen(screen); /* Unselect the screen if it was selected */ - if (screen == ctk_object->first_selected_screen) { - ctk_object->first_selected_screen = NULL; - } if (screen == ctk_object->selected_screen) { ctk_object->selected_screen = NULL; } @@ -3548,6 +3501,11 @@ void ctk_display_layout_disable_display(CtkDisplayLayout *ctk_object, /* Add the fake mode to the display */ gpu_add_screenless_modes_to_displays(display->gpu); + /* Re-select the display to sync the loss of the screen */ + if (display == ctk_object->selected_display) { + select_display(ctk_object, display); + } + queue_layout_redraw(ctk_object); } /* ctk_display_layout_disable_display() */ @@ -3972,23 +3930,6 @@ void ctk_display_layout_set_display_reflection(CtkDisplayLayout *ctk_object, -/** select_topmost_item() ************************************** - * - * Select top item from Z order list. - * - **/ - -static void select_topmost_item(CtkDisplayLayout *ctk_object) -{ - if (ctk_object->Zorder[0].type == ZNODE_TYPE_DISPLAY) { - select_display(ctk_object, ctk_object->Zorder[0].u.display); - } else if (ctk_object->Zorder[0].type == ZNODE_TYPE_SCREEN) { - select_screen(ctk_object, ctk_object->Zorder[0].u.screen); - } -} /* select_topmost_item() */ - - - /** ctk_display_layout_select_display() *********************** * * Updates the currently selected display. @@ -4026,32 +3967,6 @@ void ctk_display_layout_select_screen(CtkDisplayLayout *ctk_object, -/** ctk_display_layout_update_display_count() ************************ - * - * Updates the number of displays shown in the layout by re-building - * the Z-order list. - * - **/ - -void ctk_display_layout_update_display_count(CtkDisplayLayout *ctk_object, - nvDisplayPtr display) -{ - /* Update the Z order */ - zorder_layout(ctk_object); - - /* Select the previously selected display */ - if (display) { - ctk_display_layout_select_display(ctk_object, display); - } else { - select_topmost_item(ctk_object); - } - - queue_layout_redraw(ctk_object); - -} /* ctk_display_layout_update_display_count() */ - - - /** ctk_display_layout_set_screen_virtual_size() ********************* * * Sets the virtual size of the screen @@ -4390,12 +4305,6 @@ motion_event_callback(GtkWidget *widget, GdkEventMotion *event, gpointer data) ctk_object->mouse_x = x; ctk_object->mouse_y = y; - - /* If mouse moved, allow user to reselect the current display/screen */ - ctk_object->first_selected_display = NULL; - ctk_object->first_selected_screen = NULL; - - /* Modify screen layout */ if (ctk_object->button1 && !ctk_object->clicked_outside) { int modified = 0; diff --git a/src/gtk+-2.x/ctkdisplaylayout.h b/src/gtk+-2.x/ctkdisplaylayout.h index 499e7b7..a5c7c74 100644 --- a/src/gtk+-2.x/ctkdisplaylayout.h +++ b/src/gtk+-2.x/ctkdisplaylayout.h @@ -90,10 +90,6 @@ G_BEGIN_DECLS /*** M A C R O S *************************************************************/ -#define NV_MIN(A, B) ((A)<(B)?(A):(B)) -#define NV_MAX(A, B) ((A)>(B)?(A):(B)) - - /* Determines if the mode is the nvidia-auto-select mode. */ #define IS_NVIDIA_DEFAULT_MODE(m) \ (!strcmp(( m )->data.identifier, "nvidia-auto-select")) @@ -140,13 +136,18 @@ typedef enum { METAMODE_SOURCE_RANDR, } MetaModeSource; +typedef enum { + MOSAIC_TYPE_UNSUPPORTED = 0, + MOSAIC_TYPE_SLI_MOSAIC, + MOSAIC_TYPE_BASE_MOSAIC, + MOSAIC_TYPE_BASE_MOSAIC_LIMITED, +} MosaicType; typedef struct nvSizeRec { int width; int height; } nvSize; - typedef struct nvModeLineRec { struct nvModeLineRec *next; @@ -296,7 +297,16 @@ typedef struct nvScreenRec { int scrnum; struct nvLayoutRec *layout; /* Layout this X screen belongs to */ - struct nvGpuRec *gpu; /* GPU driving this X screen */ + struct nvGpuRec **gpus; /* List of GPUs driving this screen */ + int num_gpus; + + int display_owner_gpu_id; /* Display owner GPU, or -1 */ + struct nvGpuRec *display_owner_gpu; /* GPU to use for Device section */ + + int max_width; /* Max based on all GPUs */ + int max_height; + int max_displays; + Bool allow_depth_30; int depth; /* Depth of the screen */ int stereo; /* Stereo mode enabled on this screen */ @@ -319,6 +329,8 @@ typedef struct nvScreenRec { int y_offset; Bool sli; + char *sli_mode; + char *multigpu_mode; Bool dynamic_twinview; /* This screen supports dynamic twinview */ Bool no_scanout; /* This screen has no display devices */ Bool stereo_supported; /* Can stereo be configured on this screen */ @@ -349,8 +361,13 @@ typedef struct nvGpuRec { int max_height; int max_displays; Bool allow_depth_30; + Bool multigpu_master_possible; + + MosaicType mosaic_type; + Bool mosaic_enabled; char *name; /* Name of the GPU */ + char *uuid; /* e.g. "GPU-11111111-1111-1111-1111-111111111111" */ gchar *pci_bus_id; @@ -404,7 +421,6 @@ typedef struct ModifyInfoRec { nvDisplayPtr display; nvScreenPtr screen; GdkRectangle orig_screen_dim; // Used when moding display = moding screen. - nvGpuPtr gpu; int orig_position_type; // Original values of what is being GdkRectangle orig_dim; // modified. @@ -490,8 +506,6 @@ typedef struct _CtkDisplayLayout /* - multiple modes */ /* State */ - void *first_selected_display; /* First thing clicked on (used to cycle) */ - void *first_selected_screen; int clicked_outside; /* User clicked outside displays, don't move */ ModifyInfo modify_info; /* Used to move/pan screens/displays */ @@ -535,7 +549,6 @@ void ctk_display_layout_update_zorder(CtkDisplayLayout *ctk_object); nvDisplayPtr ctk_display_layout_get_selected_display (CtkDisplayLayout *); nvScreenPtr ctk_display_layout_get_selected_screen (CtkDisplayLayout *); -nvGpuPtr ctk_display_layout_get_selected_gpu (CtkDisplayLayout *); void ctk_display_layout_set_mode_modeline(CtkDisplayLayout *, diff --git a/src/gtk+-2.x/ctkevent.c b/src/gtk+-2.x/ctkevent.c index 0cc1cd1..72fb330 100644 --- a/src/gtk+-2.x/ctkevent.c +++ b/src/gtk+-2.x/ctkevent.c @@ -326,6 +326,8 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_SIGNAL(NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_IMMEDIATE); MAKE_SIGNAL(NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_REBOOT); MAKE_SIGNAL(NV_CTRL_DPY_HDMI_3D); + MAKE_SIGNAL(NV_CTRL_BASE_MOSAIC); + MAKE_SIGNAL(NV_CTRL_MULTIGPU_MASTER_POSSIBLE); MAKE_SIGNAL(NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE); #undef MAKE_SIGNAL @@ -387,9 +389,11 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_STRING_SIGNAL(NV_CTRL_STRING_DISPLAY_NAME_EDID_HASH); MAKE_STRING_SIGNAL(NV_CTRL_STRING_DISPLAY_NAME_TARGET_INDEX); MAKE_STRING_SIGNAL(NV_CTRL_STRING_DISPLAY_NAME_RANDR); + MAKE_STRING_SIGNAL(NV_CTRL_STRING_GPU_UUID); + MAKE_STRING_SIGNAL(NV_CTRL_STRING_MULTIGPU_MODE); #undef MAKE_STRING_SIGNAL -#if NV_CTRL_STRING_LAST_ATTRIBUTE != NV_CTRL_STRING_DISPLAY_NAME_RANDR +#if NV_CTRL_STRING_LAST_ATTRIBUTE != NV_CTRL_STRING_MULTIGPU_MODE #warning "There are attributes that do not emit signals!" #endif diff --git a/src/gtk+-2.x/ctkgauge.c b/src/gtk+-2.x/ctkgauge.c index 276dbd3..e63bb4e 100644 --- a/src/gtk+-2.x/ctkgauge.c +++ b/src/gtk+-2.x/ctkgauge.c @@ -203,6 +203,8 @@ GtkWidget* ctk_gauge_new(gint lower, gint upper) ctk_gauge->gdk_colormap = gdk_colormap = gdk_colormap_get_system(); + g_object_ref(gdk_colormap); + gdk_color = &ctk_gauge->gdk_color_gray; memset(gdk_color, 0, sizeof(GdkColor)); gdk_color->red = 32768; diff --git a/src/gtk+-2.x/ctkglx.c b/src/gtk+-2.x/ctkglx.c index 28b8544..c4356f1 100644 --- a/src/gtk+-2.x/ctkglx.c +++ b/src/gtk+-2.x/ctkglx.c @@ -310,10 +310,9 @@ GtkWidget* ctk_glx_new(NvCtrlAttributeHandle *handle, hbox = gtk_hbox_new(FALSE, 0); vbox = gtk_vbox_new(FALSE, 5); event = gtk_event_box_new(); + ctk_force_text_colors_on_widget(event); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollWin), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); - gtk_widget_modify_fg(event, GTK_STATE_NORMAL, &(event->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(event, GTK_STATE_NORMAL, &(event->style->base[GTK_STATE_NORMAL])); gtk_container_add(GTK_CONTAINER(event), hbox); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollWin), event); @@ -407,16 +406,8 @@ GtkWidget* ctk_glx_new(NvCtrlAttributeHandle *handle, data_table = gtk_table_new(num_fbconfigs, NUM_FBCONFIG_ATTRIBS, FALSE); event = gtk_event_box_new(); - - gtk_widget_modify_fg(data_table, GTK_STATE_NORMAL, - &(data_table->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(data_table, GTK_STATE_NORMAL, - &(data_table->style->base[GTK_STATE_NORMAL])); + ctk_force_text_colors_on_widget(event); gtk_container_add (GTK_CONTAINER(event), data_table); - gtk_widget_modify_fg(event, GTK_STATE_NORMAL, - &(event->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(event, GTK_STATE_NORMAL, - &(event->style->base[GTK_STATE_NORMAL])); gtk_container_add(GTK_CONTAINER(data_viewport), event); /* Pack the fbconfig header and data tables */ diff --git a/src/gtk+-2.x/ctkgpu.c b/src/gtk+-2.x/ctkgpu.c index ccbd5a8..2f9d7d2 100644 --- a/src/gtk+-2.x/ctkgpu.c +++ b/src/gtk+-2.x/ctkgpu.c @@ -192,6 +192,7 @@ GtkWidget* ctk_gpu_new( GtkWidget *table; char *product_name, *vbios_version, *video_ram, *gpu_memory_text, *irq; + char *gpu_uuid; gchar *pci_bus_id; gchar pci_device_id[ARRAY_ELEMENTS]; gchar pci_vendor_id[ARRAY_ELEMENTS]; @@ -237,8 +238,16 @@ GtkWidget* ctk_gpu_new( ret = NvCtrlGetStringAttribute(handle, NV_CTRL_STRING_PRODUCT_NAME, &product_name); - if (ret != NvCtrlSuccess) product_name = NULL; - + if (ret != NvCtrlSuccess) { + product_name = NULL; + } + + ret = NvCtrlGetStringAttribute(handle, NV_CTRL_STRING_GPU_UUID, + &gpu_uuid); + if (ret != NvCtrlSuccess) { + gpu_uuid = NULL; + } + /* Get Bus related information */ get_bus_id_str(handle, &pci_bus_id); @@ -429,6 +438,9 @@ GtkWidget* ctk_gpu_new( add_table_row(table, row++, 0, 0.5, "Graphics Processor:", 0, 0.5, product_name); + add_table_row(table, row++, + 0, 0.5, "GPU UUID:", + 0, 0.5, gpu_uuid); if ( ctk_gpu->gpu_cores ) { gtk_table_resize(GTK_TABLE(table), ++total_rows, 2); add_table_row(table, row++, diff --git a/src/gtk+-2.x/ctklicense.c b/src/gtk+-2.x/ctklicense.c index 02027a7..a28edf3 100644 --- a/src/gtk+-2.x/ctklicense.c +++ b/src/gtk+-2.x/ctklicense.c @@ -23,6 +23,7 @@ #include <NvCtrlAttributes.h> #include "ctklicense.h" +#include "ctkutils.h" #include "ctkconfig.h" #include "ctkhelp.h" @@ -264,13 +265,9 @@ GtkWidget* ctk_license_dialog_new(GtkWidget *parent, gchar *panel_name) hbox = gtk_hbox_new(FALSE, 0); label = gtk_label_new(""); event = gtk_event_box_new(); + ctk_force_text_colors_on_widget(event); ctk_license_dialog->window = scrollWin; - gtk_widget_modify_fg(event, GTK_STATE_NORMAL, - &(event->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(event, GTK_STATE_NORMAL, - &(event->style->base[GTK_STATE_NORMAL])); - gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_label_set_use_markup(GTK_LABEL(label), TRUE); gtk_label_set_markup(GTK_LABEL(label), __license_msg); diff --git a/src/gtk+-2.x/ctkpowermizer.c b/src/gtk+-2.x/ctkpowermizer.c index d4c8208..184a763 100644 --- a/src/gtk+-2.x/ctkpowermizer.c +++ b/src/gtk+-2.x/ctkpowermizer.c @@ -37,7 +37,7 @@ #define DEFAULT_UPDATE_POWERMIZER_INFO_TIME_INTERVAL 1000 static gboolean update_powermizer_info(gpointer); -static void update_powermizer_menu_info(gpointer); +static void update_powermizer_menu_info(CtkPowermizer *ctk_powermizer); static void powermizer_menu_changed(GtkWidget*, gpointer); static void update_powermizer_menu_event(GtkObject *object, gpointer arg1, @@ -146,12 +146,6 @@ typedef struct { gint nvclock; gint memclock; gint processorclock; - gint nvclockmin; - gint nvclockmax; - gint memclockmin; - gint memclockmax; - gint processorclockmin; - gint processorclockmax; } perfModeEntry, * perfModeEntryPtr; @@ -163,22 +157,10 @@ static void apply_perf_mode_token(char *token, char *value, void *data) pEntry->perf_level = atoi(value); } else if (!strcasecmp("nvclock", token)) { pEntry->nvclock = atoi(value); - } else if (!strcasecmp("nvclockmin", token)) { - pEntry->nvclockmin = atoi(value); - } else if (!strcasecmp("nvclockmax", token)) { - pEntry->nvclockmax = atoi(value); } else if (!strcasecmp("memclock", token)) { pEntry->memclock = atoi(value); - } else if (!strcasecmp("memclockmin", token)) { - pEntry->memclockmin = atoi(value); - } else if (!strcasecmp("memclockmax", token)) { - pEntry->memclockmax = atoi(value); } else if (!strcasecmp("processorclock", token)) { pEntry->processorclock = atoi(value); - } else if (!strcasecmp("processorclockmin", token)) { - pEntry->processorclockmin = atoi(value); - } else if (!strcasecmp("processorclockmax", token)) { - pEntry->processorclockmax = atoi(value); } else { nv_warning_msg("Unknown Perf Mode token value pair: %s=%s", token, value); @@ -192,322 +174,97 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, GtkWidget *table; GtkWidget *label; char *perf_modes = NULL; - char *tmp_perf_modes = NULL; char *tokens; char tmp_str[24]; + perfModeEntry entry; gint ret; - gint row_idx = 0; /* Where to insert into the perf mode table */ + gint row_idx; /* Where to insert into the perf mode table */ gboolean active; - GtkWidget *vsep; - perfModeEntryPtr pEntry = NULL; - perfModeEntryPtr tmpEntry = NULL; - gint index = 0; - gint i = 0; - - /* Get the current list of perf levels */ - - ret = NvCtrlGetStringAttribute(ctk_powermizer->attribute_handle, - NV_CTRL_STRING_PERFORMANCE_MODES, - &perf_modes); - - if (ret != NvCtrlSuccess) { - /* Bail */ - return; - } - - /* Calculate the number of rows we needed vseparator in the table */ - tmp_perf_modes = g_strdup(perf_modes); - for (tokens = strtok(tmp_perf_modes, ";"); - tokens; - tokens = strtok(NULL, ";")) { - - tmpEntry = realloc(pEntry, sizeof(*pEntry) * (index + 1)); - - if (!tmpEntry) { - continue; - } - pEntry = tmpEntry; - tmpEntry = NULL; - - /* Invalidate perf mode entry */ - memset(pEntry + index, -1, sizeof(*pEntry)); - - parse_token_value_pairs(tokens, apply_perf_mode_token, - (void *) &pEntry[index]); - - /* Only add complete perf mode entries */ - if ((pEntry[index].perf_level != -1) && - (pEntry[index].nvclockmax != -1) && - (pEntry[index].memclockmax != -1)) { - /* Set hasDecoupledClocks flag to decide new/old clock - * interface to show. - */ - if (!ctk_powermizer->hasDecoupledClock && - ((pEntry[index].nvclockmax != pEntry[index].nvclockmin) || - (pEntry[index].memclockmax != pEntry[index].memclockmin) || - (pEntry[index].processorclockmax != - pEntry[index].processorclockmin))) { - ctk_powermizer->hasDecoupledClock = TRUE; - } - row_idx++; - } - index++; - } - g_free(tmp_perf_modes); /* Since table cell management in GTK lacks, just remove and rebuild * the table from scratch. */ - + /* Dump out the old table */ ctk_empty_container(ctk_powermizer->performance_table_hbox); /* Generate a new table */ - if (ctk_powermizer->hasDecoupledClock) { - table = gtk_table_new(2, 15, FALSE); - row_idx = row_idx + 3; - gtk_table_set_row_spacings(GTK_TABLE(table), 3); - gtk_table_set_col_spacings(GTK_TABLE(table), 15); - gtk_container_set_border_width(GTK_CONTAINER(table), 5); - - gtk_box_pack_start(GTK_BOX(ctk_powermizer->performance_table_hbox), - table, FALSE, FALSE, 0); - - if (ctk_powermizer->performance_level) { - label = gtk_label_new("Level"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - - /* Vertical separator */ - vsep = gtk_vseparator_new(); - gtk_table_attach(GTK_TABLE(table), vsep, 1, 2, 0, row_idx, - GTK_FILL, GTK_FILL | GTK_EXPAND, 0, 0); - } - - if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) { - /* Graphics clock */ - label = gtk_label_new("Graphics Clock"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 2, 5, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("Current"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 2, 3, 1, 2, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("Min"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 3, 4, 1, 2, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("Max"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 4, 5, 1, 2, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - - /* Vertical separator */ - vsep = gtk_vseparator_new(); - gtk_table_attach(GTK_TABLE(table), vsep, 5, 6, 0, row_idx, - GTK_FILL, GTK_FILL | GTK_EXPAND, 0, 0); - - /* Memory clock */ - label = gtk_label_new("Memory Clock"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 6, 9, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("Current"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 6, 7, 1, 2, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("Min"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 7, 8, 1, 2, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("Max"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 8, 9, 1, 2, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - - /* Vertical separator */ - vsep = gtk_vseparator_new(); - gtk_table_attach(GTK_TABLE(table), vsep, 9, 10, 0, row_idx, - GTK_FILL, GTK_FILL | GTK_EXPAND, 0, 0); - } - if (ctk_powermizer->processor_clock) { - /* Processor clock */ - label = gtk_label_new("Processor Clock"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 10, 11, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("Current"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 11, 12, 1, 2, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("Min"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 12, 13, 1, 2, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("Max"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 13, 14, 1, 2, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - - /* Vertical separator */ - vsep = gtk_vseparator_new(); - gtk_table_attach(GTK_TABLE(table), vsep, 14, 15, 0, row_idx, - GTK_FILL, GTK_FILL | GTK_EXPAND, 0, 0); - } - } else { + table = gtk_table_new(1, 4, FALSE); + gtk_table_set_row_spacings(GTK_TABLE(table), 3); + gtk_table_set_col_spacings(GTK_TABLE(table), 15); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); - table = gtk_table_new(1, 4, FALSE); - gtk_table_set_row_spacings(GTK_TABLE(table), 3); - gtk_table_set_col_spacings(GTK_TABLE(table), 15); - gtk_container_set_border_width(GTK_CONTAINER(table), 5); + gtk_box_pack_start(GTK_BOX(ctk_powermizer->performance_table_hbox), + table, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(ctk_powermizer->performance_table_hbox), - table, FALSE, FALSE, 0); + if (ctk_powermizer->performance_level) { + label = gtk_label_new("Performance Level"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } - if (ctk_powermizer->performance_level) { - label = gtk_label_new("Performance Level"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } + if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) { + label = gtk_label_new("Graphics Clock"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 1, 2, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) { - label = gtk_label_new("Graphics Clock"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 1, 2, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Memory Clock"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } + if (ctk_powermizer->processor_clock) { + label = gtk_label_new("Processor Clock"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 3, 4, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } + /* Get the current list of perf levels */ - label = gtk_label_new("Memory Clock"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } + ret = NvCtrlGetStringAttribute(ctk_powermizer->attribute_handle, + NV_CTRL_STRING_PERFORMANCE_MODES, + &perf_modes); - if (ctk_powermizer->processor_clock) { - label = gtk_label_new("Processor Clock"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 3, 4, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } + if (ret != NvCtrlSuccess) { + gtk_widget_show_all(table); + /* Bail */ + return; } /* Parse the perf levels and populate the table */ - row_idx = 0; //reset value used to calculate vseparator. - row_idx = 3; - for (i = 0; i < index; i++) { - /* Only add complete perf mode entries */ - if (ctk_powermizer->hasDecoupledClock && - (pEntry[i].perf_level != -1) && - (pEntry[i].nvclockmax != -1) && - (pEntry[i].memclockmax != -1)) { - - active = (pEntry[i].perf_level == perf_level); - - /* XXX Assume the perf levels are sorted by the server */ - - gtk_table_resize(GTK_TABLE(table), row_idx+1, 10); - if (ctk_powermizer->performance_level) { - g_snprintf(tmp_str, 24, "%d", pEntry[i].perf_level); - label = gtk_label_new(tmp_str); - gtk_widget_set_sensitive(label, active); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, - row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } - - if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) { - if (active) { - g_snprintf(tmp_str, 24, "%d MHz", ctk_powermizer->nvclock); - label = gtk_label_new(tmp_str); - gtk_widget_set_sensitive(label, active); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 2, 3, - row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } - g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].nvclockmin); - label = gtk_label_new(tmp_str); - gtk_widget_set_sensitive(label, active); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 3, 4, - row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].nvclockmax); - label = gtk_label_new(tmp_str); - gtk_widget_set_sensitive(label, active); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 4, 5, - row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - - if (active) { - g_snprintf(tmp_str, 24, "%d MHz", ctk_powermizer->memclock); - label = gtk_label_new(tmp_str); - gtk_widget_set_sensitive(label, active); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 6, 7, - row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } - g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].memclockmin); - label = gtk_label_new(tmp_str); - gtk_widget_set_sensitive(label, active); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 7, 8, - row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].memclockmax); - label = gtk_label_new(tmp_str); - gtk_widget_set_sensitive(label, active); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 8, 9, - row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } - if (ctk_powermizer->processor_clock) { - if (active) { - g_snprintf(tmp_str, 24, "%d MHz", ctk_powermizer->processorclock); - label = gtk_label_new(tmp_str); - gtk_widget_set_sensitive(label, active); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 11, 12, row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } - g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].processorclockmin); - label = gtk_label_new(tmp_str); - gtk_widget_set_sensitive(label, active); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 12, 13, - row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].processorclockmax); - label = gtk_label_new(tmp_str); - gtk_widget_set_sensitive(label, active); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 13, 14, - row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } - row_idx++; - } else if ((pEntry[i].perf_level != -1) && - (pEntry[i].nvclock != -1) && - (pEntry[i].memclock != -1)) { + row_idx = 1; + for (tokens = strtok(perf_modes, ";"); + tokens; + tokens = strtok(NULL, ";")) { - active = (pEntry[i].perf_level == perf_level); + /* Invalidate perf mode entry */ + entry.perf_level = -1; + entry.nvclock = -1; + entry.memclock = -1; + entry.processorclock = -1; + + parse_token_value_pairs(tokens, apply_perf_mode_token, + &entry); + + /* Only add complete perf mode entries */ + if ((entry.perf_level != -1) && + (entry.nvclock != -1) && + (entry.memclock != -1)) { + + active = (entry.perf_level == perf_level); /* XXX Assume the perf levels are sorted by the server */ - gtk_table_resize(GTK_TABLE(table), row_idx+1, 10); + gtk_table_resize(GTK_TABLE(table), row_idx+1, 4); if (ctk_powermizer->performance_level) { - g_snprintf(tmp_str, 24, "%d", pEntry[i].perf_level); + g_snprintf(tmp_str, 24, "%d", entry.perf_level); label = gtk_label_new(tmp_str); gtk_widget_set_sensitive(label, active); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); @@ -517,7 +274,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, } if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) { - g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].nvclock); + g_snprintf(tmp_str, 24, "%d MHz", entry.nvclock); label = gtk_label_new(tmp_str); gtk_widget_set_sensitive(label, active); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); @@ -525,7 +282,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, row_idx, row_idx+1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].memclock); + g_snprintf(tmp_str, 24, "%d MHz", entry.memclock); label = gtk_label_new(tmp_str); gtk_widget_set_sensitive(label, active); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); @@ -534,7 +291,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); } if (ctk_powermizer->processor_clock) { - g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].processorclock); + g_snprintf(tmp_str, 24, "%d MHz", entry.processorclock); label = gtk_label_new(tmp_str); gtk_widget_set_sensitive(label, active); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); @@ -545,16 +302,14 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, } else { nv_warning_msg("Incomplete Perf Mode (perf=%d, nvclock=%d," " memclock=%d)", - pEntry[i].perf_level, pEntry[i].nvclock, - pEntry[i].memclock); + entry.perf_level, entry.nvclock, + entry.memclock); } } gtk_widget_show_all(table); XFree(perf_modes); - XFree(pEntry); - pEntry = NULL; } @@ -598,9 +353,6 @@ static gboolean update_powermizer_info(gpointer user_data) memory_clock = clockret & 0x0000FFFF; gpu_clock = (clockret >> 16); - ctk_powermizer->nvclock = gpu_clock; - ctk_powermizer->memclock = memory_clock; - s = g_strdup_printf("%d Mhz", gpu_clock); gtk_label_set_text(GTK_LABEL(ctk_powermizer->gpu_clock), s); g_free(s); @@ -614,7 +366,6 @@ static gboolean update_powermizer_info(gpointer user_data) NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS, &processor_clock); if (ret == NvCtrlSuccess && ctk_powermizer->processor_clock) { - ctk_powermizer->processorclock = processor_clock; s = g_strdup_printf("%d Mhz", processor_clock); gtk_label_set_text(GTK_LABEL(ctk_powermizer->processor_clock), s); g_free(s); @@ -808,7 +559,7 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, if (ret == NvCtrlSuccess) { pcie_gen_queriable = TRUE; } - + /* return early if query to attributes fail */ if (!power_source_available && !perf_level_available && !adaptive_clock_state_available && clock_freqs_available && @@ -823,7 +574,6 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, ctk_powermizer->attribute_handle = handle; ctk_powermizer->ctk_config = ctk_config; ctk_powermizer->pcie_gen_queriable = pcie_gen_queriable; - ctk_powermizer->hasDecoupledClock = FALSE; /* set container properties for the CtkPowermizer widget */ @@ -1237,18 +987,36 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, return GTK_WIDGET(ctk_powermizer); } + + +static void post_powermizer_menu_update(CtkPowermizer *ctk_powermizer) +{ + CtkDropDownMenu *menu = + CTK_DROP_DOWN_MENU(ctk_powermizer->powermizer_menu); + const char *label = ctk_drop_down_menu_get_current_name(menu); + + ctk_config_statusbar_message(ctk_powermizer->ctk_config, + "Preferred Mode set to %s.", label); +} + + + static void update_powermizer_menu_event(GtkObject *object, gpointer arg1, gpointer user_data) { - update_powermizer_menu_info(user_data); + CtkPowermizer *ctk_powermizer = CTK_POWERMIZER(user_data); + + update_powermizer_menu_info(ctk_powermizer); + + post_powermizer_menu_update(ctk_powermizer); } -static void update_powermizer_menu_info(gpointer user_data) + + +static void update_powermizer_menu_info(CtkPowermizer *ctk_powermizer) { - CtkPowermizer *ctk_powermizer = CTK_POWERMIZER(user_data); gint powerMizerMode, defaultPowerMizerMode, actualPowerMizerMode; - gchar* label; ReturnStatus ret1, ret2; CtkDropDownMenu *menu; @@ -1290,32 +1058,33 @@ static void update_powermizer_menu_info(gpointer user_data) } } + + static void powermizer_menu_changed(GtkWidget *widget, gpointer user_data) { - CtkPowermizer *ctk_powermizer; - guint powerMizerMode; + CtkPowermizer *ctk_powermizer = CTK_POWERMIZER(user_data); CtkDropDownMenu *menu = CTK_DROP_DOWN_MENU(widget); + guint powerMizerMode; + ReturnStatus ret; const char *label = ctk_drop_down_menu_get_current_name(menu); - ctk_powermizer = CTK_POWERMIZER(user_data); powerMizerMode = ctk_drop_down_menu_get_current_value(menu); - if (NvCtrlSuccess != NvCtrlSetAttribute(ctk_powermizer->attribute_handle, - NV_CTRL_GPU_POWER_MIZER_MODE, - powerMizerMode)) { + ret = NvCtrlSetAttribute(ctk_powermizer->attribute_handle, + NV_CTRL_GPU_POWER_MIZER_MODE, + powerMizerMode); + if (ret != NvCtrlSuccess) { ctk_config_statusbar_message(ctk_powermizer->ctk_config, "Unable to set Preferred Mode to %s.", label); return; } - ctk_config_statusbar_message(ctk_powermizer->ctk_config, - "Preferred Mode set to %s.", - label); - update_powermizer_menu_info(user_data); + + post_powermizer_menu_update(ctk_powermizer); } diff --git a/src/gtk+-2.x/ctkpowermizer.h b/src/gtk+-2.x/ctkpowermizer.h index e1919e8..02a12d6 100644 --- a/src/gtk+-2.x/ctkpowermizer.h +++ b/src/gtk+-2.x/ctkpowermizer.h @@ -70,11 +70,7 @@ struct _CtkPowermizer GtkWidget *configuration_button; gboolean dp_enabled; gboolean dp_toggle_warning_dlg_shown; - gboolean hasDecoupledClock; gint attribute; - gint nvclock; - gint memclock; - gint processorclock; GtkWidget *status; GtkWidget *link_width; diff --git a/src/gtk+-2.x/ctkscale.c b/src/gtk+-2.x/ctkscale.c index 5eaebff..fb68ceb 100644 --- a/src/gtk+-2.x/ctkscale.c +++ b/src/gtk+-2.x/ctkscale.c @@ -23,6 +23,8 @@ #include "ctkscale.h" #include <stdio.h> +static void ctk_scale_finalize(GObject *object); +static void ctk_scale_init(CtkScaleClass *ctk_object_class); enum { PROP_0, @@ -41,7 +43,7 @@ GType ctk_scale_get_type( sizeof (CtkScaleClass), NULL, /* base_init */ NULL, /* base_finalize */ - NULL, /* class_init, */ + (GClassInitFunc) ctk_scale_init, /* class_init, */ NULL, /* class_finalize */ NULL, /* class_data */ sizeof (CtkScale), @@ -58,6 +60,26 @@ GType ctk_scale_get_type( } +static void ctk_scale_init(CtkScaleClass *ctk_object_class) +{ + GObjectClass *gobject_class = (GObjectClass *)ctk_object_class; + gobject_class->finalize = ctk_scale_finalize; +} + +static void ctk_scale_finalize(GObject *object) +{ + CtkScale *ctk_scale = CTK_SCALE(object); + + g_signal_handlers_disconnect_matched(G_OBJECT(ctk_scale->ctk_config), + G_SIGNAL_MATCH_DATA, + 0, + 0, + NULL, + NULL, + (gpointer) G_OBJECT(ctk_scale)); + +} + /* * ctk_scale_key_event() - GTK's default handling of the up/down keys @@ -185,46 +207,46 @@ GtkWidget* ctk_scale_new(GtkAdjustment *gtk_adjustment, GtkWidget *label; GtkWidget *frame; GtkWidget *hbox; - + g_return_val_if_fail(GTK_IS_ADJUSTMENT(gtk_adjustment), NULL); g_return_val_if_fail(label_text != NULL, NULL); - + /* create and initialize the object */ object = g_object_new(CTK_TYPE_SCALE, NULL); - + ctk_scale = CTK_SCALE(object); ctk_scale->gtk_adjustment = gtk_adjustment; ctk_scale->label = label_text; ctk_scale->ctk_config = ctk_config; ctk_scale->value_type = value_type; - + gtk_box_set_spacing (GTK_BOX (object), 2); - + /* scale label */ - + label = gtk_label_new(ctk_scale->label); gtk_box_pack_start(GTK_BOX (object), label, FALSE, FALSE, 0); - + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - + /* frame around slider and text box */ - + frame = gtk_frame_new(NULL); gtk_box_pack_start(GTK_BOX(object), frame, TRUE, TRUE, 0); ctk_scale->tooltip_widget = frame; - + /* hbox to contain slider and text box */ hbox = gtk_hbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(ctk_scale->tooltip_widget), hbox); /* text entry */ - + ctk_scale->text_entry = gtk_entry_new_with_max_length(6); gtk_entry_set_width_chars(GTK_ENTRY(ctk_scale->text_entry), 6); - + /* text entry container */ ctk_scale->text_entry_container = gtk_frame_new(NULL); @@ -232,16 +254,16 @@ GtkWidget* ctk_scale_new(GtkAdjustment *gtk_adjustment, GTK_SHADOW_NONE); gtk_container_set_border_width (GTK_CONTAINER(ctk_scale->text_entry_container), 0); - + gtk_container_add(GTK_CONTAINER(ctk_scale->text_entry_container), ctk_scale->text_entry); ctk_scale->text_entry_packed = TRUE; g_object_ref(G_OBJECT(ctk_scale->text_entry)); - + gtk_box_pack_start(GTK_BOX(hbox), ctk_scale->text_entry_container, FALSE, FALSE, 0); - + text_entry_toggled(ctk_scale->ctk_config, (gpointer) ctk_scale); /* wire up the adjustment events */ @@ -255,7 +277,7 @@ GtkWidget* ctk_scale_new(GtkAdjustment *gtk_adjustment, g_signal_connect(G_OBJECT(ctk_scale->text_entry), "activate", G_CALLBACK(text_entry_activate), (gpointer) ctk_scale); - + g_signal_connect(G_OBJECT(ctk_config), "slider_text_entry_toggled", G_CALLBACK(text_entry_toggled), (gpointer) ctk_scale); @@ -264,17 +286,17 @@ GtkWidget* ctk_scale_new(GtkAdjustment *gtk_adjustment, ctk_scale->gtk_scale = gtk_hscale_new(GTK_ADJUSTMENT(ctk_scale->gtk_adjustment)); - + gtk_scale_set_draw_value(GTK_SCALE(ctk_scale->gtk_scale), FALSE); - + gtk_scale_set_digits(GTK_SCALE(ctk_scale->gtk_scale), 0); gtk_box_pack_start(GTK_BOX(hbox), ctk_scale->gtk_scale, TRUE, TRUE, 3); - + g_signal_connect(ctk_scale->gtk_scale, "key_press_event", G_CALLBACK(ctk_scale_key_event), G_OBJECT(ctk_scale)); - + return GTK_WIDGET (object); - + } /* ctk_scale_new() */ diff --git a/src/gtk+-2.x/ctkslimm.c b/src/gtk+-2.x/ctkslimm.c index 15afce4..85f4f7a 100644 --- a/src/gtk+-2.x/ctkslimm.c +++ b/src/gtk+-2.x/ctkslimm.c @@ -294,6 +294,32 @@ static XConfigPtr xconfig_generate(XConfigPtr xconfCur, +static void set_overlap_controls_status(CtkSLIMM *ctk_object) +{ + CtkDropDownMenu *menu; + GridConfig *grid_config; + gint config_idx, x_displays, y_displays; + + menu = CTK_DROP_DOWN_MENU(ctk_object->mnu_display_config); + config_idx = ctk_drop_down_menu_get_current_value(menu); + + /* Get grid configuration values from index */ + grid_config = get_ith_valid_grid_config(config_idx); + if (grid_config) { + x_displays = grid_config->columns; + y_displays = grid_config->rows; + } else { + x_displays = y_displays = 0; + } + + gtk_widget_set_sensitive(ctk_object->spbtn_hedge_overlap, + x_displays > 1 ? True : False); + gtk_widget_set_sensitive(ctk_object->spbtn_vedge_overlap, + y_displays > 1 ? True : False); +} + + + static Bool compute_screen_size(CtkSLIMM *ctk_object, gint *width, gint *height) { @@ -320,11 +346,6 @@ static Bool compute_screen_size(CtkSLIMM *ctk_object, gint *width, } else { x_displays = y_displays = 0; } - - gtk_widget_set_sensitive(ctk_object->spbtn_hedge_overlap, - x_displays > 1 ? True : False); - gtk_widget_set_sensitive(ctk_object->spbtn_vedge_overlap, - y_displays > 1 ? True : False); h_overlap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ctk_object->spbtn_hedge_overlap)); v_overlap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ctk_object->spbtn_vedge_overlap)); @@ -402,6 +423,9 @@ static void display_config_changed(GtkWidget *widget, gpointer user_data) CtkSLIMM *ctk_object = CTK_SLIMM(user_data); /* Update total size label */ setup_total_size_label(ctk_object); + + /* Update the sensitivity of the overlap controls */ + set_overlap_controls_status(ctk_object); } @@ -472,9 +496,8 @@ static void slimm_checkbox_toggled(GtkWidget *widget, gpointer user_data) } gtk_widget_set_sensitive(ctk_object->mnu_display_resolution, True); gtk_widget_set_sensitive(ctk_object->mnu_display_config, True); - gtk_widget_set_sensitive(ctk_object->spbtn_hedge_overlap, True); - gtk_widget_set_sensitive(ctk_object->spbtn_vedge_overlap, True); gtk_widget_set_sensitive(ctk_object->box_total_size, True); + set_overlap_controls_status(ctk_object); } else { if (GTK_WIDGET_SENSITIVE(ctk_object->mnu_display_refresh)) { ctk_object->mnu_refresh_disabled = True; @@ -1699,6 +1722,8 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle, NV_CTRL_STRING_SLI_MODE, &sli_mode); + set_overlap_controls_status(ctk_slimm); + if ((ret != NvCtrlSuccess) || (ret == NvCtrlSuccess && g_ascii_strcasecmp(sli_mode, "Mosaic"))) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), FALSE); diff --git a/src/gtk+-2.x/ctkthermal.c b/src/gtk+-2.x/ctkthermal.c index 92673ac..e5594b5 100644 --- a/src/gtk+-2.x/ctkthermal.c +++ b/src/gtk+-2.x/ctkthermal.c @@ -1389,7 +1389,7 @@ sensor_end: /* Create cooler level control sliders/checkbox */ ctk_thermal->cooler_control = (CoolerControlPtr) - malloc(ctk_thermal->cooler_count * sizeof(CoolerControlRec)); + calloc(ctk_thermal->cooler_count, sizeof(CoolerControlRec)); for (j = 1; j <= ctk_thermal->cooler_count; j++) { cooler_handle = h->targets[COOLER_TARGET].t[pDataCooler[j]].h; @@ -1471,8 +1471,8 @@ sensor_end: gtk_widget_set_sensitive(ctk_thermal->cooler_control [cur_cooler_idx].widget, cooler_control_enabled); - cur_cooler_idx++; } + cur_cooler_idx++; } if ( ctk_thermal->cooler_count && ctk_thermal->show_fan_control_frame ) { diff --git a/src/gtk+-2.x/ctkutils.c b/src/gtk+-2.x/ctkutils.c index a65b411..7f3516e 100644 --- a/src/gtk+-2.x/ctkutils.c +++ b/src/gtk+-2.x/ctkutils.c @@ -23,6 +23,22 @@ #include "ctkutils.h" #include "msg.h" +/* + * This function checks that the GTK+ library in use is at least as new as the + * given version number. Note this differs from gtk_check_version(), which + * checks that the library in use is "compatible" with the given version (which + * requires the library in use have both (1) a newer or equal version number and + * (2) an equal major version number). + */ +gboolean ctk_check_min_gtk_version(guint required_major, + guint required_minor, + guint required_micro) +{ + return (NV_VERSION3(required_major, required_minor, + required_micro) <= + NV_VERSION3(gtk_major_version, gtk_minor_version, + gtk_micro_version)); +} gchar *get_pcie_generation_string(NvCtrlAttributeHandle *handle) @@ -370,3 +386,51 @@ void ctk_empty_container(GtkWidget *container) g_list_free(list); } /* ctk_empty_container() */ + + +/* Updates the widget to use the text colors ('text' and 'base') for the + * foreground and background colors. + */ +static void widget_use_text_colors_for_state(GtkWidget *widget, + GtkStateType state) +{ + gtk_widget_modify_fg(widget, state, &(widget->style->text[state])); + gtk_widget_modify_bg(widget, state, &(widget->style->base[state])); + +} + + +/* Callback for the "style-set" event, used to ensure that widgets that should + * use the text colors for drawing still do so after a Theme update. + */ +static void force_text_colors_handler(GtkWidget *widget, + GtkStyle *previous_style, + gpointer user_data) +{ + g_signal_handlers_block_by_func + (G_OBJECT(widget), + G_CALLBACK(force_text_colors_handler), user_data); + + /* Use text colors for foreground and background */ + widget_use_text_colors_for_state(widget, GTK_STATE_NORMAL); + widget_use_text_colors_for_state(widget, GTK_STATE_ACTIVE); + widget_use_text_colors_for_state(widget, GTK_STATE_PRELIGHT); + widget_use_text_colors_for_state(widget, GTK_STATE_SELECTED); + widget_use_text_colors_for_state(widget, GTK_STATE_INSENSITIVE); + + g_signal_handlers_unblock_by_func + (G_OBJECT(widget), + G_CALLBACK(force_text_colors_handler), user_data); +} + +void ctk_force_text_colors_on_widget(GtkWidget *widget) +{ + /* Set the intial state */ + force_text_colors_handler(widget, NULL, NULL); + + /* Ensure state is updated when style changes */ + g_signal_connect(G_OBJECT(widget), + "style-set", G_CALLBACK(force_text_colors_handler), + (gpointer) NULL); +} + diff --git a/src/gtk+-2.x/ctkutils.h b/src/gtk+-2.x/ctkutils.h index 8e4cac5..40d055b 100644 --- a/src/gtk+-2.x/ctkutils.h +++ b/src/gtk+-2.x/ctkutils.h @@ -75,6 +75,12 @@ void ctk_empty_container(GtkWidget *); void update_display_enabled_flag(NvCtrlAttributeHandle *handle, gboolean *display_enabled); +gboolean ctk_check_min_gtk_version(guint required_major, + guint required_minor, + guint required_micro); + +void ctk_force_text_colors_on_widget(GtkWidget *widget); + G_END_DECLS #endif /* __CTK_UTILS_H__ */ diff --git a/src/gtk+-2.x/ctkvcs.c b/src/gtk+-2.x/ctkvcs.c index ab337d3..4d9a08c 100644 --- a/src/gtk+-2.x/ctkvcs.c +++ b/src/gtk+-2.x/ctkvcs.c @@ -567,10 +567,9 @@ GtkWidget* ctk_vcs_new(NvCtrlAttributeHandle *handle, hbox_scroll = gtk_hbox_new(FALSE, 0); vbox_scroll = gtk_vbox_new(FALSE, 5); event = gtk_event_box_new(); + ctk_force_text_colors_on_widget(event); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollWin), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); - gtk_widget_modify_fg(event, GTK_STATE_NORMAL, &(event->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(event, GTK_STATE_NORMAL, &(event->style->base[GTK_STATE_NORMAL])); gtk_container_add(GTK_CONTAINER(event), hbox_scroll); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollWin), event); diff --git a/src/gtk+-2.x/ctkvdpau.c b/src/gtk+-2.x/ctkvdpau.c index ac4c388..2c4f561 100644 --- a/src/gtk+-2.x/ctkvdpau.c +++ b/src/gtk+-2.x/ctkvdpau.c @@ -200,12 +200,8 @@ static int queryBaseInfo(CtkVDPAU *ctk_vdpau, VdpDevice device, vbox = gtk_vbox_new(FALSE, 0); eventbox = gtk_event_box_new(); + ctk_force_text_colors_on_widget(eventbox); gtk_container_add(GTK_CONTAINER(eventbox), vbox); - gtk_widget_modify_fg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->base[GTK_STATE_NORMAL])); - gtk_notebook_append_page(GTK_NOTEBOOK(ctk_vdpau->notebook), eventbox, gtk_label_new("Base Information")); @@ -223,11 +219,8 @@ static int queryBaseInfo(CtkVDPAU *ctk_vdpau, VdpDevice device, label = gtk_label_new("Supported Codecs:"); event = gtk_event_box_new(); + ctk_force_text_colors_on_widget(event); gtk_container_add(GTK_CONTAINER(event), label); - gtk_widget_modify_fg(event, GTK_STATE_NORMAL, - &(event->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(event, GTK_STATE_NORMAL, - &(event->style->base[GTK_STATE_NORMAL])); ctk_config_set_tooltip(ctk_vdpau->ctk_config, event, __supported_codecs_help); gtk_label_set_selectable(GTK_LABEL(label), TRUE); @@ -331,16 +324,10 @@ static int queryVideoSurface(CtkVDPAU *ctk_vdpau, VdpDevice device, hbox = gtk_hbox_new(FALSE, 0); label = gtk_label_new("Video Surface:"); eventbox = gtk_event_box_new(); - gtk_widget_modify_fg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->base[GTK_STATE_NORMAL])); + ctk_force_text_colors_on_widget(eventbox); event = gtk_event_box_new(); + ctk_force_text_colors_on_widget(event); gtk_container_add(GTK_CONTAINER(event), label); - gtk_widget_modify_fg(event, GTK_STATE_NORMAL, - &(event->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(event, GTK_STATE_NORMAL, - &(event->style->base[GTK_STATE_NORMAL])); ctk_config_set_tooltip(ctk_vdpau->ctk_config, event, __video_surface_help); hseparator = gtk_hseparator_new(); @@ -521,11 +508,8 @@ static int queryDecoderCaps(CtkVDPAU *ctk_vdpau, VdpDevice device, vbox = gtk_vbox_new(FALSE, 0); eventbox = gtk_event_box_new(); + ctk_force_text_colors_on_widget(eventbox); gtk_container_add(GTK_CONTAINER(eventbox), vbox); - gtk_widget_modify_fg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->base[GTK_STATE_NORMAL])); /* Add tab to notebook */ @@ -535,15 +519,11 @@ static int queryDecoderCaps(CtkVDPAU *ctk_vdpau, VdpDevice device, /* Generate a new table */ table = gtk_table_new(2, 5, FALSE); + ctk_force_text_colors_on_widget(table); gtk_table_set_row_spacings(GTK_TABLE(table), 3); gtk_table_set_col_spacings(GTK_TABLE(table), 15); gtk_container_set_border_width(GTK_CONTAINER(table), 5); - gtk_widget_modify_fg(table, GTK_STATE_NORMAL, - &(table->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(table, GTK_STATE_NORMAL, - &(table->style->base[GTK_STATE_NORMAL])); - label = gtk_label_new("Name"); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); @@ -675,11 +655,8 @@ static int queryOutputSurface(CtkVDPAU *ctk_vdpau, VdpDevice device, hbox = gtk_hbox_new(FALSE, 0); label = gtk_label_new("Output Surface:"); eventbox = gtk_event_box_new(); + ctk_force_text_colors_on_widget(eventbox); gtk_container_add(GTK_CONTAINER(eventbox), label); - gtk_widget_modify_fg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->base[GTK_STATE_NORMAL])); ctk_config_set_tooltip(ctk_vdpau->ctk_config, eventbox, __ouput_surface_help); hseparator = gtk_hseparator_new(); @@ -829,11 +806,8 @@ static int queryBitmapSurface(CtkVDPAU *ctk_vdpau, VdpDevice device, hbox = gtk_hbox_new(FALSE, 0); label = gtk_label_new("Bitmap Surface:"); eventbox = gtk_event_box_new(); + ctk_force_text_colors_on_widget(eventbox); gtk_container_add(GTK_CONTAINER(eventbox), label); - gtk_widget_modify_fg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->base[GTK_STATE_NORMAL])); ctk_config_set_tooltip(ctk_vdpau->ctk_config, eventbox, __bitmap_surface_help); hseparator = gtk_hseparator_new(); @@ -1062,23 +1036,17 @@ static int queryVideoMixer(CtkVDPAU *ctk_vdpau, VdpDevice device, vbox = gtk_vbox_new(FALSE, 0); label = gtk_label_new("Video Mixer:"); eventbox = gtk_event_box_new(); + ctk_force_text_colors_on_widget(eventbox); gtk_container_add(GTK_CONTAINER(eventbox), label); - gtk_widget_modify_fg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->base[GTK_STATE_NORMAL])); ctk_config_set_tooltip(ctk_vdpau->ctk_config, eventbox, __video_mixer_help); scrollWin = gtk_scrolled_window_new(NULL, NULL); hbox = gtk_hbox_new(FALSE, 0); event = gtk_event_box_new(); + ctk_force_text_colors_on_widget(event); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollWin), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); - gtk_widget_modify_fg(event, GTK_STATE_NORMAL, - &(event->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(event, GTK_STATE_NORMAL, - &(event->style->base[GTK_STATE_NORMAL])); gtk_container_add(GTK_CONTAINER(event), hbox); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollWin), event); @@ -1093,25 +1061,19 @@ static int queryVideoMixer(CtkVDPAU *ctk_vdpau, VdpDevice device, /* Generate a new table */ table = gtk_table_new(2, 5, FALSE); + ctk_force_text_colors_on_widget(table); gtk_table_set_row_spacings(GTK_TABLE(table), 3); gtk_table_set_col_spacings(GTK_TABLE(table), 15); gtk_container_set_border_width(GTK_CONTAINER(table), 5); - gtk_widget_modify_fg(table, GTK_STATE_NORMAL, - &(table->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(table, GTK_STATE_NORMAL, - &(table->style->base[GTK_STATE_NORMAL])); label = gtk_label_new("Feature Name"); eventbox = gtk_event_box_new(); + ctk_force_text_colors_on_widget(eventbox); gtk_container_add(GTK_CONTAINER(eventbox), label); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), eventbox, 0, 1, 0, 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - gtk_widget_modify_fg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->base[GTK_STATE_NORMAL])); ctk_config_set_tooltip(ctk_vdpau->ctk_config, eventbox, __video_mixer_feature_help); @@ -1181,14 +1143,11 @@ static int queryVideoMixer(CtkVDPAU *ctk_vdpau, VdpDevice device, label = gtk_label_new("Parameter Name"); eventbox = gtk_event_box_new(); + ctk_force_text_colors_on_widget(eventbox); gtk_container_add(GTK_CONTAINER(eventbox), label); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), eventbox, 0, 1, 0, 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - gtk_widget_modify_fg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->base[GTK_STATE_NORMAL])); ctk_config_set_tooltip(ctk_vdpau->ctk_config, eventbox, __video_mixer_parameter_help); @@ -1275,15 +1234,12 @@ static int queryVideoMixer(CtkVDPAU *ctk_vdpau, VdpDevice device, label = gtk_label_new("Attribute Name"); eventbox = gtk_event_box_new(); + ctk_force_text_colors_on_widget(eventbox); gtk_container_add(GTK_CONTAINER(eventbox), label); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), eventbox, 0, 1, 0, 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - gtk_widget_modify_fg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, - &(eventbox->style->base[GTK_STATE_NORMAL])); ctk_config_set_tooltip(ctk_vdpau->ctk_config, eventbox, __video_mixer_attribute_help); @@ -1481,12 +1437,9 @@ GtkWidget* ctk_vdpau_new(NvCtrlAttributeHandle *handle, scrollWin = gtk_scrolled_window_new(NULL, NULL); hbox = gtk_hbox_new(FALSE, 0); event = gtk_event_box_new(); + ctk_force_text_colors_on_widget(event); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollWin), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); - gtk_widget_modify_fg(event, GTK_STATE_NORMAL, - &(event->style->text[GTK_STATE_NORMAL])); - gtk_widget_modify_bg(event, GTK_STATE_NORMAL, - &(event->style->base[GTK_STATE_NORMAL])); gtk_container_add(GTK_CONTAINER(event), hbox); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollWin), event); diff --git a/src/gtk+-2.x/ctkwindow.c b/src/gtk+-2.x/ctkwindow.c index 03c187d..b92c076 100644 --- a/src/gtk+-2.x/ctkwindow.c +++ b/src/gtk+-2.x/ctkwindow.c @@ -881,6 +881,11 @@ GtkWidget *ctk_window_new(ParsedAttribute *p, ConfigProperties *conf, G_CALLBACK(update_display_devices), (gpointer) data); + g_signal_connect(G_OBJECT(ctk_event), + CTK_EVENT_NAME(NV_CTRL_MODE_SET_EVENT), + G_CALLBACK(update_display_devices), + (gpointer) data); + add_display_devices(ctk_window, &iter, gpu_handle, ctk_event, tag_table, data, ctk_window->attribute_list); } @@ -1445,6 +1450,12 @@ static void add_display_devices(CtkWindow *ctk_window, GtkTreeIter *iter, continue; } + /* + * Rebuild Sub-systems of display handle + */ + NvCtrlAttributeRebuildSubsystems(display_handle, + NV_CTRL_ATTRIBUTES_ALL_SUBSYSTEMS); + ctk_event = CTK_EVENT(ctk_event_new(display_handle)); /* Query display's names */ @@ -1498,6 +1509,35 @@ static void add_display_devices(CtkWindow *ctk_window, GtkTreeIter *iter, } /* add_display_devices() */ +/* + * Select display page whose name is passed through 'name' parameter + */ +static void select_display_page(UpdateDisplaysData *data, gchar *name) +{ + CtkWindow *ctk_window = data->window; + GtkTreeSelection *tree_selection = + gtk_tree_view_get_selection(ctk_window->treeview); + gint num_displays = data->num_displays; + + while (num_displays) { + GtkTreeIter *iter = &(data->display_iters[num_displays -1]); + CtkDisplayDevice *ctk_obj = NULL; + GtkWidget *widget = NULL; + + gtk_tree_model_get(GTK_TREE_MODEL(ctk_window->tree_store), iter, + CTK_WINDOW_WIDGET_COLUMN, &widget, -1); + + ctk_obj = CTK_DISPLAY_DEVICE(widget); + + if (strcmp(name, ctk_obj->name) == 0) { + gtk_tree_selection_select_iter(tree_selection, iter); + break; + } + + num_displays--; + } + +} /* * update_display_devices() - Callback handler for the NV_CTRL_PROBE_DISPLAYS @@ -1520,6 +1560,7 @@ static void update_display_devices(GtkObject *object, gpointer arg1, GtkTreeSelection *tree_selection = gtk_tree_view_get_selection(ctk_window->treeview); GtkWidget *widget; + gchar *selected_display_name = NULL; /* Keep track if the parent row is expanded */ @@ -1534,16 +1575,23 @@ static void update_display_devices(GtkObject *object, gpointer arg1, while (data->num_displays) { GtkTreeIter *iter = &(data->display_iters[data->num_displays -1]); + gboolean is_selected = FALSE; /* Select the parent (GPU) iter if we're removing the selected page */ if (gtk_tree_selection_iter_is_selected(tree_selection, iter)) { + is_selected = TRUE; gtk_tree_selection_select_iter(tree_selection, &parent_iter); } /* Remove the entry */ gtk_tree_model_get(GTK_TREE_MODEL(ctk_window->tree_store), iter, CTK_WINDOW_WIDGET_COLUMN, &widget, -1); - + + if (is_selected) { + CtkDisplayDevice *ctk_obj = CTK_DISPLAY_DEVICE(widget); + selected_display_name = g_strdup(ctk_obj->name); + } + gtk_tree_store_remove(ctk_window->tree_store, iter); /* unref the page so we don't leak memory */ @@ -1566,4 +1614,9 @@ static void update_display_devices(GtkObject *object, gpointer arg1, gtk_tree_view_expand_row(ctk_window->treeview, parent_path, TRUE); } + if (selected_display_name) { + select_display_page(data, selected_display_name); + g_free(selected_display_name); + } + } /* update_display_devices() */ diff --git a/src/gtk+-2.x/ctkxvideo.c b/src/gtk+-2.x/ctkxvideo.c index a7f8a4f..7449391 100644 --- a/src/gtk+-2.x/ctkxvideo.c +++ b/src/gtk+-2.x/ctkxvideo.c @@ -43,7 +43,8 @@ static GtkWidget *xv_sync_to_display_radio_button_add(CtkXVideo *ctk_xvideo, int index); static void -xv_sync_to_display_update_radio_buttons(CtkXVideo *ctk_xvideo, gint value); +xv_sync_to_display_update_radio_buttons(CtkXVideo *ctk_xvideo, gint value, + gboolean update_status); static void xv_sync_to_display_changed(GtkWidget *widget, gpointer user_data); @@ -51,8 +52,7 @@ static void xv_sync_to_display_update_received(GtkObject *object, gpointer arg1, gpointer user_data); static void post_xv_sync_to_display_changed(CtkXVideo *ctk_xvideo, - gboolean enabled, - gchar *label); + GtkWidget *widget); static void nv_ctrl_enabled_displays(GtkObject *object, gpointer arg1, gpointer user_data); static void xv_sync_to_display_radio_button_remove(CtkXVideo *ctk_xvideo, @@ -131,7 +131,8 @@ static GtkWidget *xv_sync_to_display_radio_button_add(CtkXVideo *ctk_xvideo, static void -xv_sync_to_display_update_radio_buttons(CtkXVideo *ctk_xvideo, gint value) +xv_sync_to_display_update_radio_buttons(CtkXVideo *ctk_xvideo, + gint value, gboolean update_status) { GtkWidget *b, *button = NULL; int i; @@ -165,7 +166,11 @@ xv_sync_to_display_update_radio_buttons(CtkXVideo *ctk_xvideo, gint value) (G_OBJECT(b), G_CALLBACK(xv_sync_to_display_changed), (gpointer) ctk_xvideo); } - + + if (update_status) { + post_xv_sync_to_display_changed(ctk_xvideo, button); + } + } /* xv_sync_to_display_update_radio_buttons() */ @@ -179,32 +184,35 @@ static void xv_sync_to_display_changed(GtkWidget *widget, gpointer user_data) { CtkXVideo *ctk_xvideo = CTK_XVIDEO(user_data); gboolean enabled; - gint value; - gchar *label; + gint device_mask; enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - if (enabled) { + if (!enabled) { + /* Ignore 'disable' events. */ + return; + } - user_data = g_object_get_data(G_OBJECT(widget), "xv_sync_to_display"); - - value = GPOINTER_TO_INT(user_data); - - NvCtrlSetAttribute(ctk_xvideo->handle, - NV_CTRL_XV_SYNC_TO_DISPLAY, value); - - gtk_label_get(GTK_LABEL(GTK_BIN(widget)->child), &label); + user_data = g_object_get_data(G_OBJECT(widget), "xv_sync_to_display"); + + device_mask = GPOINTER_TO_INT(user_data); + + NvCtrlSetAttribute(ctk_xvideo->handle, + NV_CTRL_XV_SYNC_TO_DISPLAY, device_mask); + + post_xv_sync_to_display_changed(ctk_xvideo, widget); - post_xv_sync_to_display_changed(ctk_xvideo, enabled, label); - } }/* xv_sync_to_display_changed() */ static void post_xv_sync_to_display_changed(CtkXVideo *ctk_xvideo, - gboolean enabled, - gchar *label) -{ - ctk_config_statusbar_message(ctk_xvideo->ctk_config, + GtkWidget *active_button) +{ + const gchar *label; + + label = gtk_button_get_label(GTK_BUTTON(active_button)); + + ctk_config_statusbar_message(ctk_xvideo->ctk_config, "XVideo application syncing to %s.", label); } @@ -240,14 +248,26 @@ static void nv_ctrl_enabled_displays(GtkObject *object, gpointer arg1, gpointer user_data) { CtkXVideo *ctk_xvideo = CTK_XVIDEO(user_data); - CtkEventStruct *event_struct = (CtkEventStruct *) arg1; int i, enabled, prev_enabled = 0; int remove_devices_mask, add_devices_mask; unsigned int mask; gpointer udata; GtkWidget *b; + ReturnStatus ret; + + /* + * The event data passed in gives us the enabled displays mask + * for all displays on all X Screens on this GPU. Since we can + * only sync to a display on this X Screen, we need to have the + * correct enabled displays. + */ + ret = NvCtrlGetAttribute(ctk_xvideo->handle, + NV_CTRL_ENABLED_DISPLAYS, + &enabled); + if (ret != NvCtrlSuccess) { + enabled = 0; + } - enabled = event_struct->value; /* Extract the previous value. */ for ( i = 0; i < 24; i++) { b = ctk_xvideo->xv_sync_to_display_buttons[i]; @@ -345,9 +365,10 @@ static void xv_sync_to_display_update_received(GtkObject *object, b = ctk_xvideo->xv_sync_to_display_buttons[i]; if (!b) continue; user_data = g_object_get_data(G_OBJECT(b), "xv_sync_to_display"); - + if (GPOINTER_TO_INT(user_data) == event_struct->value) { - xv_sync_to_display_update_radio_buttons(ctk_xvideo, i); + xv_sync_to_display_update_radio_buttons(ctk_xvideo, i, + TRUE); break; } } @@ -497,9 +518,10 @@ GtkWidget* ctk_xvideo_new(NvCtrlAttributeHandle *handle, G_CALLBACK(nv_ctrl_enabled_displays), (gpointer) ctk_xvideo); - if (current != -1) - xv_sync_to_display_update_radio_buttons(ctk_xvideo, current); - + if (current != -1) { + xv_sync_to_display_update_radio_buttons(ctk_xvideo, + current, FALSE); + } } } } diff --git a/src/libXNVCtrl/NVCtrl.h b/src/libXNVCtrl/NVCtrl.h index 0a7d8de..ab644f1 100644 --- a/src/libXNVCtrl/NVCtrl.h +++ b/src/libXNVCtrl/NVCtrl.h @@ -3273,6 +3273,26 @@ #define NV_CTRL_DPY_HDMI_3D_ENABLED 1 /* + * NV_CTRL_BASE_MOSAIC - Returns whether Base Mosaic is currently enabled on the + * given GPU. Querying the valid values of this attribute returns capabilities. + */ + +#define NV_CTRL_BASE_MOSAIC 398 /* R--G */ +#define NV_CTRL_BASE_MOSAIC_DISABLED 0 +#define NV_CTRL_BASE_MOSAIC_FULL 1 +#define NV_CTRL_BASE_MOSAIC_LIMITED 2 + +/* + * NV_CTRL_MULTIGPU_MASTER_POSSIBLE - Returns whether the GPU can be configured + * as the master GPU in a Multi GPU configuration (SLI, SLI Mosaic, + * Base Mosaic). + */ + +#define NV_CTRL_MULTIGPU_MASTER_POSSIBLE 399 /* R--G */ +#define NV_CTRL_MULTIGPU_MASTER_POSSIBLE_FALSE 0 +#define NV_CTRL_MULTIGPU_MASTER_POSSIBLE_TRUE 1 + +/* * NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE - Returns the default PowerMizer mode * for the given GPU. */ @@ -3663,37 +3683,20 @@ * NV_CTRL_STRING_PERFORMANCE_MODES - returns a string with all the * performance modes defined for this GPU along with their associated * NV Clock and Memory Clock values. - * Not all tokens will be reported on all GPUs, and additional tokens - * may be added in the future. - * For backwards compatibility we still provide nvclock, memclock, and - * processorclock those are the same as nvclockmin, memclockmin and - * processorclockmin. * * Each performance modes are returned as a comma-separated list of * "token=value" pairs. Each set of performance mode tokens are separated * by a ";". Valid tokens: * - * Token Value - * "perf" integer - the Performance level - * "nvclock" integer - the GPU clocks (in MHz) for the perf level - * "nvclockmin" integer - the GPU clocks min (in MHz) for the perf level - * "nvclockmax" integer - the GPU clocks max (in MHz) for the perf level - * "memclock" integer - the memory clocks (in MHz) for the perf level - * "memclockmin" integer - the memory clocks min (in MHz) for the perf level - * "memclockmax" integer - the memory clocks max (in MHz) for the perf level - * "processorclock" integer - the processor clocks (in MHz) - * for the perf level - * "processorclockmin" integer - the processor clocks min (in MHz) - * for the perf level - * "processorclockmax" integer - the processor clocks max (in MHz) - * for the perf level + * Token Value + * "perf" integer - the Performance level + * "nvclock" integer - the GPU clocks (in MHz) for the perf level + * "memclock" integer - the memory clocks (in MHz) for the perf level + * * * Example: * - * perf=0, nvclock=324, nvclockmin=324, nvclockmax=324, memclock=324, - * memclockmin=324, memclockmax=324 ; - * perf=1, nvclock=324, nvclockmin=324, nvclockmax=640, memclock=810, - * memclockmin=810, memclockmax=810 ; + * perf=0, nvclock=500, memclock=505 ; perf=1, nvclock=650, memclock=505 * * This attribute may be queried through XNVCTRLQueryTargetStringAttribute() * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. @@ -3805,9 +3808,7 @@ * NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS - returns a string with the * associated NV Clock, Memory Clock and Processor Clock values. * - * Current valid tokens are "nvclock", "nvclockmin", "nvclockmax", - * "memclock", "memclockmin", "memclockmax", "processorclock", - * "processorclockmin" and "processorclockmax". + * Current valid tokens are "nvclock", "memclock", and "processorclock". * Not all tokens will be reported on all GPUs, and additional tokens * may be added in the future. * @@ -3815,24 +3816,17 @@ * "token=value" pairs. * Valid tokens: * - * Token Value - * "nvclock" integer - the GPU clocks (in MHz) for the perf level - * "nvclockmin" integer - the GPU clocks min (in MHz) for the perf level - * "nvclockmax" integer - the GPU clocks max (in MHz) for the perf level - * "memclock" integer - the memory clocks (in MHz) for the perf level - * "memclockmin" integer - the memory clocks min (in MHz) for the perf level - * "memclockmax" integer - the memory clocks (max in MHz) for the perf level - * "processorclock" integer - the processor clocks (in MHz) - * for the perf level - * "processorclockmin" integer - the processor clocks min (in MHz) - * for the perf level - * "processorclockmax" integer - the processor clocks max (in MHz) - * for the perf level + * Token Value + * "nvclock" integer - the GPU clocks (in MHz) for the current + * perf level + * "memclock" integer - the memory clocks (in MHz) for the current + * perf level + * "processorclock" integer - the processor clocks (in MHz) for the perf level + * * * Example: * - * nvclock=324, nvclockmin=324, nvclockmax=324, - * memclock=324, memclockmin=324, memclockmax=324 + * nvclock=459, memclock=400, processorclock=918 * * This attribute may be queried through XNVCTRLQueryTargetStringAttribute() * using an NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. @@ -3972,8 +3966,22 @@ */ #define NV_CTRL_STRING_DISPLAY_NAME_RANDR 51 /* R-D- */ + +/* + * NV_CTRL_STRING_GPU_UUID - Returns the UUID of the given GPU. + */ +#define NV_CTRL_STRING_GPU_UUID 52 /* R--G */ + + +/* + * NV_CTRL_STRING_MULTIGPU_MODE - returns a string describing the current + * MULTIGPU mode, if any, or FALSE if MULTIGPU is not currently enabled. + */ +#define NV_CTRL_STRING_MULTIGPU_MODE 54 /* R--- */ + + #define NV_CTRL_STRING_LAST_ATTRIBUTE \ - NV_CTRL_STRING_DISPLAY_NAME_RANDR + NV_CTRL_STRING_MULTIGPU_MODE /**************************************************************************/ diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributes.c b/src/libXNVCtrlAttributes/NvCtrlAttributes.c index be7b033..543ef7f 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributes.c +++ b/src/libXNVCtrlAttributes/NvCtrlAttributes.c @@ -112,6 +112,28 @@ NvCtrlAttributeHandle *NvCtrlAttributeInit(Display *dpy, int target_type, } /* NvCtrlAttributeInit() */ +/* + * NvCtrlAttributeRebuildSubsystems() - Rebuild specified private subsystem handles + */ +void NvCtrlAttributeRebuildSubsystems(NvCtrlAttributeHandle *handle, + unsigned int subsystem) +{ + NvCtrlAttributePrivateHandle *h; + + if (!handle) { + return; + } + + h = (NvCtrlAttributePrivateHandle*)handle; + + if (subsystem & NV_CTRL_ATTRIBUTES_XRANDR_SUBSYSTEM) { + NvCtrlXrandrAttributesClose(h); + h->xrandr = NvCtrlInitXrandrAttributes(h); + } + +} /* NvCtrlAttributeRebuildSubsystems() */ + + /* * NvCtrlGetDisplayName() - return a string of the form: diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributes.h b/src/libXNVCtrlAttributes/NvCtrlAttributes.h index c59a001..f00c84d 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributes.h +++ b/src/libXNVCtrlAttributes/NvCtrlAttributes.h @@ -285,6 +285,9 @@ NvCtrlAttributeHandle *NvCtrlAttributeInit(Display *dpy, int target_type, int target_id, unsigned int subsystems); +void NvCtrlAttributeRebuildSubsystems(NvCtrlAttributeHandle *handle, + unsigned int subsystem); + char *NvCtrlGetDisplayName(NvCtrlAttributeHandle *handle); Display *NvCtrlGetDisplayPtr(NvCtrlAttributeHandle *handle); int NvCtrlGetScreen(NvCtrlAttributeHandle *handle); diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesNvControl.c b/src/libXNVCtrlAttributes/NvCtrlAttributesNvControl.c index 2567cb6..1e1a89d 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributesNvControl.c +++ b/src/libXNVCtrlAttributes/NvCtrlAttributesNvControl.c @@ -53,13 +53,13 @@ NvCtrlInitNvControlAttributes (NvCtrlAttributePrivateHandle *h) return NULL; } - if (major < NV_MINMAJOR || (major == NV_MINMAJOR && minor < NV_MINMINOR)) { + if (NV_VERSION2(major, minor) < NV_VERSION2(NV_MINMAJOR, NV_MINMINOR)) { nv_error_msg("NV-CONTROL extension version %d.%d is too old; " "the minimum required version is %d.%d.", major, minor, NV_MINMAJOR, NV_MINMINOR); return NULL; } - + if (h->target_type == NV_CTRL_TARGET_TYPE_X_SCREEN) { ret = XNVCTRLIsNvScreen (h->dpy, h->target_id); if (ret != True) { @@ -83,7 +83,7 @@ NvCtrlInitNvControlAttributes (NvCtrlAttributePrivateHandle *h) * 1.15 */ - if (((major > 1) || ((major == 1) && (minor >= 15)))) { + if (NV_VERSION2(major, minor) >= NV_VERSION2(1, 15)) { ret = XNVCtrlSelectTargetNotify(h->dpy, h->target_type, h->target_id, TARGET_ATTRIBUTE_AVAILABILITY_CHANGED_EVENT, True); @@ -98,7 +98,7 @@ NvCtrlInitNvControlAttributes (NvCtrlAttributePrivateHandle *h) * 1.16 */ - if (((major > 1) || ((major == 1) && (minor >= 16)))) { + if (NV_VERSION2(major, minor) >= NV_VERSION2(1, 16)) { ret = XNVCtrlSelectTargetNotify(h->dpy, h->target_type, h->target_id, TARGET_STRING_ATTRIBUTE_CHANGED_EVENT, True); @@ -112,7 +112,7 @@ NvCtrlInitNvControlAttributes (NvCtrlAttributePrivateHandle *h) * TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT was added in NV-CONTROL * 1.17 */ - if (((major > 1) || ((major == 1) && (minor >= 17)))) { + if (NV_VERSION2(major, minor) >= NV_VERSION2(1, 17)) { ret = XNVCtrlSelectTargetNotify(h->dpy, h->target_type, h->target_id, TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT, True); @@ -155,7 +155,7 @@ ReturnStatus NvCtrlNvControlGetAttribute (NvCtrlAttributePrivateHandle *h, minor = h->nv->minor_version; if (attr <= NV_CTRL_LAST_ATTRIBUTE) { - if ((major > 1) || ((major == 1) && (minor > 20))) { + if (NV_VERSION2(major, minor) > NV_VERSION2(1, 20)) { status = XNVCTRLQueryTargetAttribute64(h->dpy, h->target_type, h->target_id, display_mask, attr, @@ -241,8 +241,8 @@ NvCtrlNvControlGetValidStringDisplayAttributeValues int attr, NVCTRLAttributeValidValuesRec *val) { if (attr <= NV_CTRL_STRING_LAST_ATTRIBUTE) { - if ((h->nv->major_version > 1) || - ((h->nv->major_version == 1) && (h->nv->minor_version >= 22))) { + if (NV_VERSION2(h->nv->major_version, h->nv->minor_version) + >= NV_VERSION2(1, 22)) { if (XNVCTRLQueryValidTargetStringAttributeValues (h->dpy, h->target_type, h->target_id, @@ -319,8 +319,8 @@ NvCtrlNvControlSetStringAttribute (NvCtrlAttributePrivateHandle *h, /* NV-CONTROL 1.19 and above has support for setting string attributes * on targets other than X screens. */ - if (h->nv->major_version > 1 || - (h->nv->major_version == 1 && h->nv->minor_version >= 19)) { + if (NV_VERSION2(h->nv->major_version, h->nv->minor_version) >= + NV_VERSION2(1, 19)) { *ret = XNVCTRLSetTargetStringAttribute(h->dpy, h->target_type, h->target_id, display_mask, @@ -357,8 +357,8 @@ NvCtrlNvControlGetBinaryAttribute(NvCtrlAttributePrivateHandle *h, /* the X_nvCtrlQueryBinaryData opcode was added in 1.7 */ - if ((h->nv->major_version < 1) || - ((h->nv->major_version == 1) && (h->nv->minor_version < 7))) { + if (NV_VERSION2(h->nv->major_version, h->nv->minor_version) < + NV_VERSION2(1, 7)) { return NvCtrlNoAttribute; } diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesVidMode.c b/src/libXNVCtrlAttributes/NvCtrlAttributesVidMode.c index 0949ceb..3192f0f 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributesVidMode.c +++ b/src/libXNVCtrlAttributes/NvCtrlAttributesVidMode.c @@ -49,8 +49,8 @@ NvCtrlInitVidModeAttributes(NvCtrlAttributePrivateHandle *h) ret = XF86VidModeQueryVersion(h->dpy, &(vm->major_version), &(vm->minor_version)); if (!ret) goto failed; - if (vm->major_version < VM_MINMAJOR || - (vm->major_version == VM_MINMAJOR && vm->minor_version < VM_MINMINOR)) { + if (NV_VERSION2(vm->major_version, vm->minor_version) < + NV_VERSION2(VM_MINMAJOR, VM_MINMINOR)) { nv_warning_msg("The version of the XF86VidMode extension present " "on this display (%d.%d) does not support updating " "gamma ramps. If you'd like to be able to adjust " diff --git a/src/parse.c b/src/parse.c index c547abc..1f7d125 100644 --- a/src/parse.c +++ b/src/parse.c @@ -50,7 +50,6 @@ static int count_number_of_chars(char *o, char d); #define C NV_PARSER_TYPE_COLOR_ATTRIBUTE #define N NV_PARSER_TYPE_NO_CONFIG_WRITE #define G NV_PARSER_TYPE_GUI_ATTRIBUTE -#define V NV_PARSER_TYPE_XVIDEO_ATTRIBUTE #define P NV_PARSER_TYPE_PACKED_ATTRIBUTE #define D NV_PARSER_TYPE_VALUE_IS_DISPLAY #define A NV_PARSER_TYPE_NO_QUERY_ALL @@ -128,6 +127,7 @@ const AttributeTableEntry attributeTable[] = { { "StereoEyesExchange", NV_CTRL_STEREO_EYES_EXCHANGE, 0, "Swaps the left and right eyes of stereo images." }, { "SLIMode", NV_CTRL_STRING_SLI_MODE, S|N, "Returns a string describing the current SLI mode, if any." }, { "SliMosaicModeAvailable", NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE, N, "Returns whether or not SLI Mosaic Mode is supported." }, + { "MultiGpuMode", NV_CTRL_STRING_MULTIGPU_MODE, S|N, "Returns a string describing the current MultiGPU mode, if any." }, /* GPU */ { "BusType", NV_CTRL_BUS_TYPE, N, "Returns the type of bus connecting the specified device to the computer. If the target is an X screen, then it uses the GPU driving the X screen as the device." }, @@ -183,7 +183,10 @@ const AttributeTableEntry attributeTable[] = { { "ThermalSensorTarget", NV_CTRL_THERMAL_SENSOR_TARGET, N, "Returns what hardware component the thermal sensor is measuring." }, { "GPUDoublePrecisionBoostImmediate", NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_IMMEDIATE, N, "Toggles GPU double precision; the change is applied immediately. Only available when the change can be made immediately." }, { "GPUDoublePrecisionBoostReboot", NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_REBOOT, N, "Toggles GPU double precision; the change is applied on the next reboot. Only available when the change requires a reboot." }, - + { "BaseMosaic", NV_CTRL_BASE_MOSAIC, N, "Returns the current Base Mosaic configuration." }, + { "GpuUUID", NV_CTRL_STRING_GPU_UUID, S|N, "Returns the global unique identifier of the GPU." }, + { "MultiGpuMasterPossible", NV_CTRL_MULTIGPU_MASTER_POSSIBLE, N, "Returns whether or not the GPU can be configured as the master GPU for a Multi GPU configuration (SLI, SLI Mosaic, Base Mosaic, ...)." }, + /* Framelock */ { "FrameLockAvailable", NV_CTRL_FRAMELOCK, N|F|G, "Returns whether the underlying GPU supports Frame Lock. All of the other frame lock attributes are only applicable if this attribute is enabled (Supported)." }, { "FrameLockMaster", NV_CTRL_FRAMELOCK_MASTER, N|F|G|D, "Get/set which display device to use as the frame lock master for the entire sync group. Note that only one node in the sync group should be configured as the master." }, diff --git a/src/parse.h b/src/parse.h index 5f81eb7..d83cf2c 100644 --- a/src/parse.h +++ b/src/parse.h @@ -43,18 +43,17 @@ #define NV_PARSER_TYPE_COLOR_ATTRIBUTE (1<<17) #define NV_PARSER_TYPE_NO_CONFIG_WRITE (1<<18) #define NV_PARSER_TYPE_GUI_ATTRIBUTE (1<<19) -#define NV_PARSER_TYPE_XVIDEO_ATTRIBUTE (1<<20) -#define NV_PARSER_TYPE_PACKED_ATTRIBUTE (1<<21) -#define NV_PARSER_TYPE_VALUE_IS_DISPLAY (1<<22) -#define NV_PARSER_TYPE_NO_QUERY_ALL (1<<23) -#define NV_PARSER_TYPE_NO_ZERO_VALUE (1<<24) -#define NV_PARSER_TYPE_100Hz (1<<25) -#define NV_PARSER_TYPE_STRING_ATTRIBUTE (1<<26) -#define NV_PARSER_TYPE_ASSIGN_ALL_DISPLAYS (1<<27) -#define NV_PARSER_TYPE_VALUE_IS_SWITCH_DISPLAY (1<<28) -#define NV_PARSER_TYPE_1000Hz (1<<29) -#define NV_PARSER_TYPE_SDI (1<<30) -#define NV_PARSER_TYPE_SDI_CSC (1<<31) +#define NV_PARSER_TYPE_PACKED_ATTRIBUTE (1<<20) +#define NV_PARSER_TYPE_VALUE_IS_DISPLAY (1<<21) +#define NV_PARSER_TYPE_NO_QUERY_ALL (1<<22) +#define NV_PARSER_TYPE_NO_ZERO_VALUE (1<<23) +#define NV_PARSER_TYPE_100Hz (1<<24) +#define NV_PARSER_TYPE_STRING_ATTRIBUTE (1<<25) +#define NV_PARSER_TYPE_ASSIGN_ALL_DISPLAYS (1<<26) +#define NV_PARSER_TYPE_VALUE_IS_SWITCH_DISPLAY (1<<27) +#define NV_PARSER_TYPE_1000Hz (1<<28) +#define NV_PARSER_TYPE_SDI (1<<29) +#define NV_PARSER_TYPE_SDI_CSC (1<<30) #define NV_PARSER_ASSIGNMENT 0 #define NV_PARSER_QUERY 1 diff --git a/src/query-assign.c b/src/query-assign.c index 54b4537..95ae6c4 100644 --- a/src/query-assign.c +++ b/src/query-assign.c @@ -132,7 +132,7 @@ static char *query_x_name(const CtrlHandleTarget *t, int attr) /*! * Retrieves and adds all the display device names for the given target. * - * \param[in] t The CtrlHandleTarget to load names for. + * \param[in/out] t The CtrlHandleTarget to load names for. */ static void load_display_target_proto_names(CtrlHandleTarget *t) @@ -159,34 +159,57 @@ static void load_display_target_proto_names(CtrlHandleTarget *t) /*! - * Adds the default names for the given target to the list of protocol names. + * Adds the default name for the given target to the list of protocol names at + * the given proto name index. * - * \param[in] t The CtrlHandleTarget to load names for. + * \param[in/out] t The CtrlHandleTarget to load names for. + * \param[in] proto_idx The name index where to add the name. */ -static void load_default_target_proto_name(CtrlHandleTarget *t) +static void load_default_target_proto_name(CtrlHandleTarget *t, + const int proto_idx) { const int target_type = NvCtrlGetTargetType(t->h); const int target_id = NvCtrlGetTargetId(t->h); - const TargetTypeEntry *targetTypeEntry = nv_get_target_type_entry_by_nvctrl(target_type); + if (proto_idx >= NV_PROTO_NAME_MAX) { + return; + } + if (targetTypeEntry) { - t->protoNames[0] = nvasprintf("%s-%d", - targetTypeEntry->parsed_name, - target_id); - nvstrtoupper(t->protoNames[0]); + t->protoNames[proto_idx] = nvasprintf("%s-%d", + targetTypeEntry->parsed_name, + target_id); + nvstrtoupper(t->protoNames[proto_idx]); } } /*! - * Adds the all the appropriate names for the given target to the list of protocol names. + * Adds the GPU names to the given target to the list of protocol names. * - * \param[in] t The CtrlHandleTarget to load names for. + * \param[in/out] t The CtrlHandleTarget to load names for. + */ + +static void load_gpu_target_proto_names(CtrlHandleTarget *t) +{ + load_default_target_proto_name(t, NV_GPU_PROTO_NAME_TYPE_ID); + + t->protoNames[NV_GPU_PROTO_NAME_UUID] = + query_x_name(t, NV_CTRL_STRING_GPU_UUID); +} + + + +/*! + * Adds the all the appropriate names for the given target to the list of + * protocol names. + * + * \param[in/out] t The CtrlHandleTarget to load names for. */ static void load_target_proto_names(CtrlHandleTarget *t) @@ -198,8 +221,12 @@ static void load_target_proto_names(CtrlHandleTarget *t) load_display_target_proto_names(t); break; + case NV_CTRL_TARGET_TYPE_GPU: + load_gpu_target_proto_names(t); + break; + default: - load_default_target_proto_name(t); + load_default_target_proto_name(t, 0); break; } } @@ -528,7 +555,7 @@ static int nv_target_has_name(const CtrlHandleTarget *t, const char *name) { int n; - for (n = 0; n < NV_DPY_PROTO_NAME_MAX; n++) { + for (n = 0; n < NV_PROTO_NAME_MAX; n++) { if (t->protoNames[n] && nv_strcasecmp(t->protoNames[n], name)) { return NV_TRUE; @@ -1174,7 +1201,7 @@ static void nv_free_ctrl_handles(CtrlHandles *h) NvCtrlAttributeClose(t->h); free(t->name); - for (n = 0; n < NV_DPY_PROTO_NAME_MAX; n++) { + for (n = 0; n < NV_PROTO_NAME_MAX; n++) { if (t->protoNames[n]) { XFree(t->protoNames[n]); } diff --git a/src/query-assign.h b/src/query-assign.h index 60ce1e9..28e210c 100644 --- a/src/query-assign.h +++ b/src/query-assign.h @@ -40,6 +40,15 @@ enum { NV_DPY_PROTO_NAME_MAX, }; +enum { + NV_GPU_PROTO_NAME_TYPE_ID = 0, + NV_GPU_PROTO_NAME_UUID, + NV_GPU_PROTO_NAME_MAX, +}; + +#define NV_PROTO_NAME_MAX (NV_MAX((int)NV_DPY_PROTO_NAME_MAX, (int)NV_GPU_PROTO_NAME_MAX)) + + /* * The CtrlHandles struct contains an array of target types for an X * server. For each target type, we store the number of those targets @@ -53,7 +62,7 @@ typedef struct { uint32 d; /* display device mask for this target */ uint32 c; /* Connected display device mask for target */ char *name; /* Name for this target */ - char *protoNames[NV_DPY_PROTO_NAME_MAX]; /* List of valid names for this target */ + char *protoNames[NV_PROTO_NAME_MAX]; /* List of valid names for this target */ struct _CtrlHandleTargetNode *relations; /* List of associated targets */ } CtrlHandleTarget; diff --git a/src/version.mk b/src/version.mk index 47298b6..a8b6fa4 100644 --- a/src/version.mk +++ b/src/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 319.32 +NVIDIA_VERSION = 325.08 @@ -1 +1 @@ -NVIDIA_VERSION = 319.32 +NVIDIA_VERSION = 325.08 |