diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2011-05-19 12:19:12 -0700 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2011-05-19 12:19:12 -0700 |
commit | 04bc597a5fe9cacf0ae470ae433b50c2ea1aeb71 (patch) | |
tree | 910342c8d024694427b93c5534c9a62b8b09ca1b | |
parent | f5cb6655d9de05bdd5c6713e35dbf9cdc3f8bc5c (diff) |
275.09275.09
-rw-r--r-- | src/common-utils/nvgetopt.h | 8 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkcolorcontrols.c | 12 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplayconfig-utils.c | 1045 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplayconfig-utils.h | 6 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplayconfig.c | 1165 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplayconfig.h | 15 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplaylayout.c | 468 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplaylayout.h | 26 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkditheringcontrols.c | 28 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkevent.c | 6 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkimagesliders.c | 10 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkpowermizer.c | 4 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkslimm.c | 13 | ||||
-rw-r--r-- | src/libXNVCtrl/NVCtrl.h | 65 | ||||
-rw-r--r-- | src/libXNVCtrl/nv_control.h | 3 | ||||
-rw-r--r-- | src/parse.c | 10 | ||||
-rw-r--r-- | src/parse.h | 3 | ||||
-rw-r--r-- | src/query-assign.c | 153 | ||||
-rw-r--r-- | version.mk | 2 |
19 files changed, 1579 insertions, 1463 deletions
diff --git a/src/common-utils/nvgetopt.h b/src/common-utils/nvgetopt.h index 7083860..13b54d4 100644 --- a/src/common-utils/nvgetopt.h +++ b/src/common-utils/nvgetopt.h @@ -30,6 +30,14 @@ /* + * mask of bits not used by nvgetopt in NVGetoptOption::flags; + * these bits are available for use within specific users of + * nvgetopt + */ + +#define NVGETOPT_UNUSED_FLAG_RANGE 0xffff0000 + +/* * indicates that the option is a boolean value; the presence of the * option will be interpretted as a TRUE value; if the option is * prepended with '--no-', the option will be interpretted as a FALSE diff --git a/src/gtk+-2.x/ctkcolorcontrols.c b/src/gtk+-2.x/ctkcolorcontrols.c index c818087..97bc873 100644 --- a/src/gtk+-2.x/ctkcolorcontrols.c +++ b/src/gtk+-2.x/ctkcolorcontrols.c @@ -333,6 +333,7 @@ void post_color_range_update(CtkColorControls *ctk_color_controls, "Limited", /* NV_CTRL_COLOR_RANGE_LIMITED */ }; + gtk_widget_set_sensitive(ctk_color_controls->reset_button, TRUE); ctk_config_statusbar_message(ctk_color_controls->ctk_config, "Color Range set to %s for %s.", color_range_table[color_range], @@ -349,6 +350,7 @@ void post_color_space_update(CtkColorControls *ctk_color_controls, "YCbCr444" /* NV_CTRL_COLOR_SPACE_YCbCr444 */ }; + gtk_widget_set_sensitive(ctk_color_controls->reset_button, TRUE); ctk_config_statusbar_message(ctk_color_controls->ctk_config, "Color Space set to %s for %s.", color_space_table[ctk_color_controls->color_space_table[color_space]], @@ -386,7 +388,6 @@ static void color_range_menu_changed(GtkOptionMenu *color_range_menu, /* reflecting the change to statusbar message and the reset button */ post_color_range_update(ctk_color_controls, color_range); - gtk_widget_set_sensitive(ctk_color_controls->reset_button, TRUE); } /* color_range_menu_changed() */ @@ -426,7 +427,6 @@ static void color_space_menu_changed(GtkOptionMenu *color_space_menu, /* reflecting the change in color space to other widgets & reset button */ ctk_color_controls_setup(ctk_color_controls); post_color_space_update(ctk_color_controls, color_space); - gtk_widget_set_sensitive(ctk_color_controls->reset_button, TRUE); } /* color_space_menu_changed() */ @@ -485,6 +485,14 @@ static void color_control_update_received(GtkObject *object, gpointer arg1, } ctk_color_controls_setup(ctk_object); + + /* update status bar message */ + switch (event_struct->attribute) { + case NV_CTRL_COLOR_RANGE: + post_color_range_update(ctk_object, event_struct->value); break; + case NV_CTRL_COLOR_SPACE: + post_color_space_update(ctk_object, event_struct->value); break; + } } /* color_control_update_received() */ diff --git a/src/gtk+-2.x/ctkdisplayconfig-utils.c b/src/gtk+-2.x/ctkdisplayconfig-utils.c index 4199429..42755e3 100644 --- a/src/gtk+-2.x/ctkdisplayconfig-utils.c +++ b/src/gtk+-2.x/ctkdisplayconfig-utils.c @@ -1064,7 +1064,6 @@ static void display_free(nvDisplayPtr display) void renumber_xscreens(nvLayoutPtr layout) { - nvGpuPtr gpu; nvScreenPtr screen; nvScreenPtr lowest; int scrnum; @@ -1074,12 +1073,13 @@ void renumber_xscreens(nvLayoutPtr layout) /* Find screen w/ lowest # >= current screen index being assigned */ lowest = NULL; - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - for (screen = gpu->screens; screen; screen = screen->next) { - if ((screen->scrnum >= scrnum) && - (!lowest || (lowest->scrnum > screen->scrnum))) { - lowest = screen; - } + for (screen = layout->screens; + screen; + screen = screen->next_in_layout) { + + if ((screen->scrnum >= scrnum) && + (!lowest || (lowest->scrnum > screen->scrnum))) { + lowest = screen; } } @@ -1095,6 +1095,72 @@ void renumber_xscreens(nvLayoutPtr layout) +/** screen_link_display() ******************************************** + * + * Makes the given display part of the screen + * + **/ +void screen_link_display(nvScreenPtr screen, nvDisplayPtr display) +{ + if (!display || !screen || (display->screen == screen)) return; + + display->screen = screen; + display->next_in_screen = NULL; + + /* Add the display at the end of the screen's display list */ + if (!screen->displays) { + screen->displays = display; + } else { + nvDisplayPtr last = screen->displays; + while (last) { + if (!last->next_in_screen) { + last->next_in_screen = display; + break; + } + } + } + screen->displays_mask |= display->device_mask; + screen->num_displays++; + +} /* screen_link_display() */ + + + +/** screen_unlink_display() ****************************************** + * + * Removes the display from the screen's list of displays + * + **/ +void screen_unlink_display(nvDisplayPtr display) +{ + nvScreenPtr screen; + + if (!display || !display->screen) return; + + screen = display->screen; + + /* Remove the display from the screen */ + if (screen->displays == display) { + screen->displays = display->next_in_screen; + } else { + nvDisplayPtr cur = screen->displays; + while (cur) { + if (cur->next_in_screen == display) { + cur->next_in_screen = display->next_in_screen; + break; + } + cur = cur->next_in_screen; + } + } + screen->displays_mask &= ~(display->device_mask); + screen->num_displays--; + + display->screen = NULL; + +} /* screen_unlink_display() */ + + + /** screen_remove_display() ****************************************** * * Removes a display device from the screen @@ -1102,43 +1168,38 @@ void renumber_xscreens(nvLayoutPtr layout) **/ void screen_remove_display(nvDisplayPtr display) { - nvGpuPtr gpu; nvScreenPtr screen; nvDisplayPtr other; nvModePtr mode; + if (!display || !display->screen) return; - if (display && display->screen) { - screen = display->screen; - gpu = display->gpu; - /* Make any display relative to this one use absolute position */ - for (other = gpu->displays; other; other = other->next) { + screen = display->screen; - if (other == display) continue; - if (other->screen != screen) continue; + /* Make any display relative to this one use absolute position */ + for (other = screen->displays; other; other = other->next_in_screen) { - for (mode = other->modes; mode; mode = mode->next) { - if (mode->relative_to == display) { - mode->position_type = CONF_ADJ_ABSOLUTE; - mode->relative_to = NULL; - } + if (other == display) continue; + + for (mode = other->modes; mode; mode = mode->next) { + if (mode->relative_to == display) { + mode->position_type = CONF_ADJ_ABSOLUTE; + mode->relative_to = NULL; } } + } - /* Remove the display from the screen */ - screen->displays_mask &= ~(display->device_mask); - screen->num_displays--; - - if (screen->primaryDisplay == display) { - screen->primaryDisplay = NULL; - } + /* Remove the display from the screen */ + screen_unlink_display(display); - /* Clean up old references to the screen in the display */ - display_remove_modes(display); - display->screen = NULL; + /* Clean up old references */ + if (screen->primaryDisplay == display) { + screen->primaryDisplay = NULL; } + display_remove_modes(display); + } /* screen_remove_display() */ @@ -1151,18 +1212,10 @@ void screen_remove_display(nvDisplayPtr display) **/ static void screen_remove_displays(nvScreenPtr screen) { - nvGpuPtr gpu; - nvDisplayPtr display; + if (!screen) return; - if (screen && screen->gpu) { - gpu = screen->gpu; - - for (display = gpu->displays; display; display = display->next) { - - if (display->screen != screen) continue; - - screen_remove_display(display); - } + while (screen->displays) { + screen_remove_display(screen->displays); } } /* screen_remove_displays() */ @@ -1186,10 +1239,10 @@ gchar *screen_get_metamode_str(nvScreenPtr screen, int metamode_idx, gchar *mode_str; gchar *tmp; - for (display = screen->gpu->displays; display; display = display->next) { + for (display = screen->displays; + display; + display = display->next_in_screen) { - if (display->screen != screen) continue; /* Display not in screen */ - mode_str = display_get_mode_str(display, metamode_idx, be_generic); if (!mode_str) continue; @@ -1217,35 +1270,29 @@ gchar *screen_get_metamode_str(nvScreenPtr screen, int metamode_idx, **/ static void screen_remove_metamodes(nvScreenPtr screen) { - nvGpuPtr gpu; nvDisplayPtr display; nvMetaModePtr metamode; - if (screen) { - gpu = screen->gpu; - - /* Remove the modes from this screen's displays */ - if (gpu) { - for (display = gpu->displays; display; display = display->next) { - - if (display->screen != screen) continue; + if (!screen) return; - display_remove_modes(display); - } - } + /* Remove the modes from this screen's displays */ + for (display = screen->displays; + display; + display = display->next_in_screen) { + display_remove_modes(display); + } - /* Clear the screen's metamode list */ - while (screen->metamodes) { - metamode = screen->metamodes; - screen->metamodes = metamode->next; - free(metamode->string); - free(metamode); - } - screen->num_metamodes = 0; - screen->cur_metamode = NULL; - screen->cur_metamode_idx = -1; + /* Clear the screen's metamode list */ + while (screen->metamodes) { + metamode = screen->metamodes; + screen->metamodes = metamode->next; + free(metamode->string); + free(metamode); } - + screen->num_metamodes = 0; + screen->cur_metamode = NULL; + screen->cur_metamode_idx = -1; + } /* screen_remove_metamodes() */ @@ -1367,7 +1414,7 @@ static Bool screen_add_metamode(nvScreenPtr screen, const char *metamode_str, /* Make the display part of the screen */ - display->screen = screen; + screen_link_display(screen, display); /* Set the panning offset */ @@ -1415,9 +1462,9 @@ static Bool screen_check_metamodes(nvScreenPtr screen) nvModePtr last_mode = NULL; - for (display = screen->gpu->displays; display; display = display->next) { - - if (display->screen != screen) continue; + for (display = screen->displays; + display; + display = display->next_in_screen) { if (display->num_modes == screen->num_metamodes) continue; @@ -1480,11 +1527,12 @@ void screen_assign_dummy_metamode_positions(nvScreenPtr screen) nvDisplayPtr display; nvModePtr ok_mode; nvModePtr mode; - - for (display = screen->gpu->displays; display; display = display->next) { - if (display->screen != screen) continue; - + + for (display = screen->displays; + display; + display = display->next_in_screen) { + /* Get the first non-dummy mode */ for (ok_mode = display->modes; ok_mode; ok_mode = ok_mode->next) { if (!ok_mode->dummy) break; @@ -1500,7 +1548,7 @@ void screen_assign_dummy_metamode_positions(nvScreenPtr screen) } } } - + } /* screen_assign_dummy_metamode_positions() */ @@ -1599,18 +1647,12 @@ static Bool screen_add_metamodes(nvScreenPtr screen, gchar **err_str) for (i = 0; i < screen->cur_metamode_idx; i++) { screen->cur_metamode = screen->cur_metamode->next; } - - /* Make each display within the screen point to the current mode. - * Also, count the number of displays on the screen - */ - screen->num_displays = 0; - for (display = screen->gpu->displays; display; display = display->next) { - - if (display->screen != screen) continue; /* Display not in screen */ - screen->num_displays++; - screen->displays_mask |= display->device_mask; + /* Make each display within the screen point to the current mode */ + for (display = screen->displays; + display; + display = display->next_in_screen) { display->cur_mode = display->modes; for (i = 0; i < screen->cur_metamode_idx; i++) { @@ -1623,12 +1665,12 @@ static Bool screen_add_metamodes(nvScreenPtr screen, gchar **err_str) /* Failure case */ fail: - + /* Remove modes we may have added */ screen_remove_metamodes(screen); XFree(metamode_strs); - return FALSE; + return FALSE; } /* screen_add_metamodes() */ @@ -1673,7 +1715,7 @@ nvDisplayPtr gpu_get_display(nvGpuPtr gpu, unsigned int device_mask) { nvDisplayPtr display; - for (display = gpu->displays; display; display = display->next) { + for (display = gpu->displays; display; display = display->next_on_gpu) { if (display->device_mask == device_mask) return display; } @@ -1693,27 +1735,33 @@ void gpu_remove_and_free_display(nvDisplayPtr display) nvGpuPtr gpu; nvScreenPtr screen; + if (!display || !display->gpu) return; + + gpu = display->gpu; + screen = display->screen; - if (display && display->gpu) { - gpu = display->gpu; - screen = display->screen; + /* Remove the display from the X screen */ + if (screen) { + screen_remove_display(display); - /* Remove the display from the screen it may be in */ - if (screen) { - screen_remove_display(display); + if (!screen->num_displays) { + layout_remove_and_free_screen(screen); + } + } - /* If the screen is empty, remove it too */ - if (!screen->num_displays) { - gpu_remove_and_free_screen(screen); + /* Remove the display from the GPU */ + if (gpu->displays == display) { + gpu->displays = display->next_on_gpu; + } else { + nvDisplayPtr cur; + for (cur = gpu->displays; cur; cur = cur->next_on_gpu) { + if (cur->next_on_gpu == display) { + cur->next_on_gpu = display->next_on_gpu; + break; } } - - /* Remove the display from the GPU */ - xconfigRemoveListItem((GenericListPtr *)(&gpu->displays), - (GenericListPtr)display); - gpu->connected_displays &= ~(display->device_mask); - gpu->num_displays--; } + gpu->num_displays--; display_free(display); @@ -1728,23 +1776,47 @@ void gpu_remove_and_free_display(nvDisplayPtr display) **/ static void gpu_remove_displays(nvGpuPtr gpu) { - nvDisplayPtr display; + if (!gpu) return; - if (gpu) { - while (gpu->displays) { - display = gpu->displays; - screen_remove_display(display); - gpu->displays = display->next; - display_free(display); - } - //gpu->connected_displays = 0; - gpu->num_displays = 0; + while (gpu->displays) { + gpu_remove_and_free_display(gpu->displays); } } /* gpu_remove_displays() */ +/** gpu_add_display() ************************************************ + * + * Adds the display to (the end of) the GPU display list. + * + **/ +static void gpu_add_display(nvGpuPtr gpu, nvDisplayPtr display) +{ + + if (!display || !gpu || (display->gpu == gpu)) return; + + display->gpu = gpu; + display->next_on_gpu = NULL; + + /* Add the display at the end of the GPU's display list */ + if (!gpu->displays) { + gpu->displays = display; + } else { + nvDisplayPtr last; + for (last = gpu->displays; last; last = last->next_on_gpu) { + if (!last->next_on_gpu) { + last->next_on_gpu = display; + break; + } + } + } + gpu->num_displays++; + +} /* gpu_add_display() */ + + + /** gpu_query_gvo_mode_info() **************************************** * * Adds GVO mode information to the GPU's gvo mode data table at @@ -1797,19 +1869,18 @@ nvDisplayPtr gpu_add_display_from_server(nvGpuPtr gpu, gchar **err_str) { ReturnStatus ret; - nvDisplayPtr display = NULL; + nvDisplayPtr display; + - /* Create the display structure */ display = (nvDisplayPtr)calloc(1, sizeof(nvDisplay)); if (!display) goto fail; /* Init the display structure */ - display->gpu = gpu; display->device_mask = device_mask; - + /* Query the display information */ ret = NvCtrlGetStringDisplayAttribute(gpu->handle, device_mask, @@ -1920,6 +1991,10 @@ nvDisplayPtr gpu_add_display_from_server(nvGpuPtr gpu, } + /* Add the display at the end of gpu's display list */ + gpu_add_display(gpu, display); + + /* Query the modelines for the display device */ if (!display_add_modelines_from_server(display, err_str)) { nv_warning_msg("Failed to add modelines to display device 0x%08x " @@ -1930,11 +2005,6 @@ nvDisplayPtr gpu_add_display_from_server(nvGpuPtr gpu, } - /* Add the display at the end of gpu's display list */ - xconfigAddListItem((GenericListPtr *)(&gpu->displays), - (GenericListPtr)display); - gpu->connected_displays |= device_mask; - gpu->num_displays++; return display; @@ -1954,6 +2024,7 @@ nvDisplayPtr gpu_add_display_from_server(nvGpuPtr gpu, **/ static Bool gpu_add_displays_from_server(nvGpuPtr gpu, gchar **err_str) { + ReturnStatus ret; unsigned int mask; @@ -1961,14 +2032,23 @@ static Bool gpu_add_displays_from_server(nvGpuPtr gpu, gchar **err_str) gpu_remove_displays(gpu); - // XXX Query connected_displays here... + /* Get the list of connected displays */ + ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_CONNECTED_DISPLAYS, + (int *)&(gpu->connected_displays)); + if (ret != NvCtrlSuccess) { + *err_str = g_strdup_printf("Failed to query connected display " + "devices on GPU-%d '%s'.", + NvCtrlGetTargetId(gpu), gpu->name); + nv_error_msg(*err_str); + goto fail; + } /* Add each connected display */ for (mask = 1; mask; mask <<= 1) { if (!(mask & (gpu->connected_displays))) continue; - + if (!gpu_add_display_from_server(gpu, mask, err_str)) { nv_warning_msg("Failed to add display device 0x%08x to GPU-%d " "'%s'.", @@ -1979,8 +2059,6 @@ static Bool gpu_add_displays_from_server(nvGpuPtr gpu, gchar **err_str) return TRUE; - - /* Failure case */ fail: gpu_remove_displays(gpu); return FALSE; @@ -1989,339 +2067,179 @@ static Bool gpu_add_displays_from_server(nvGpuPtr gpu, gchar **err_str) -/** gpu_remove_and_free_screen() ************************************* +/** gpu_add_screenless_modes_to_displays() *************************** * - * Removes a screen from its GPU and frees it. + * Adds fake modes to display devices that have no screens so we + * can show them on the layout page. * **/ -void gpu_remove_and_free_screen(nvScreenPtr screen) +Bool gpu_add_screenless_modes_to_displays(nvGpuPtr gpu) { - nvGpuPtr gpu; - nvScreenPtr other; - - if (screen && screen->gpu) { - - /* Remove the screen from the GPU */ - gpu = screen->gpu; - - xconfigRemoveListItem((GenericListPtr *)(&gpu->screens), - (GenericListPtr)screen); - gpu->num_screens--; - - /* Make sure other screens in the layout aren't relative - * to this screen - */ - for (gpu = screen->gpu->layout->gpus; gpu; gpu = gpu->next) { - for (other = gpu->screens; other; other = other->next) { - if (other->relative_to == screen) { - other->position_type = CONF_ADJ_ABSOLUTE; - other->relative_to = NULL; - } - } - } - } - - screen_free(screen); + nvDisplayPtr display; + nvModePtr mode; -} /* gpu_remove_and_free_screen() */ + for (display = gpu->displays; display; display = display->next_on_gpu) { + if (display->screen) continue; + if (display->modes) continue; + /* Create a fake mode */ + mode = (nvModePtr)calloc(1, sizeof(nvMode)); + if (!mode) return FALSE; + mode->display = display; + mode->dummy = 1; -/** gpu_remove_screens() ********************************************* - * - * Removes all screens from a gpu and frees them - * - **/ -static void gpu_remove_screens(nvGpuPtr gpu) -{ - nvScreenPtr screen; + mode->dim[W] = 800; + mode->dim[H] = 600; + mode->pan[W] = mode->dim[W]; + mode->pan[H] = mode->dim[H]; - if (gpu) { - while (gpu->screens) { - screen = gpu->screens; - gpu->screens = screen->next; - screen_free(screen); - } - gpu->num_screens = 0; + /* Add the mode to the display */ + display->modes = mode; + display->cur_mode = mode; + display->num_modes = 1; } -} /* gpu_remove_screens() */ + return TRUE; + +} /* gpu_add_screenless_modes_to_displays() */ -/** gpu_add_screen_from_server() ************************************* +/** gpu_free() ******************************************************* * - * Adds screen 'screen_id' that is connected to the gpu. + * Frees memory used by the gpu. * **/ -static int gpu_add_screen_from_server(nvGpuPtr gpu, int screen_id, - gchar **err_str) +static void gpu_free(nvGpuPtr gpu) { - Display *display; - nvScreenPtr screen; - int val, tmp; - ReturnStatus ret; - gchar *primary_str = NULL; - - /* Create the screen structure */ - screen = (nvScreenPtr)calloc(1, sizeof(nvScreen)); - if (!screen) goto fail; - - screen->gpu = gpu; - screen->scrnum = screen_id; - - - /* Make an NV-CONTROL handle to talk to the screen */ - display = NvCtrlGetDisplayPtr(gpu->handle); - screen->handle = - NvCtrlAttributeInit(display, - NV_CTRL_TARGET_TYPE_X_SCREEN, - screen_id, - NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM | - NV_CTRL_ATTRIBUTES_XRANDR_SUBSYSTEM); - if (!screen->handle) { - *err_str = g_strdup_printf("Failed to create NV-CONTROL handle for\n" - "screen %d (on GPU-%d).", - screen_id, NvCtrlGetTargetId(gpu->handle)); - nv_error_msg(*err_str); - goto fail; - } - - - /* See if the screen supports dynamic twinview */ - ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_DYNAMIC_TWINVIEW, &val); - if (ret != NvCtrlSuccess) { - *err_str = g_strdup_printf("Failed to query Dynamic TwinView for " - "screen %d.", - screen_id); - nv_warning_msg(*err_str); - goto fail; - } - screen->dynamic_twinview = !!val; - - - /* See if the screen is set to not scanout */ - ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_NO_SCANOUT, &val); - if (ret != NvCtrlSuccess) { - *err_str = g_strdup_printf("Failed to query NoScanout for " - "screen %d.", - screen_id); - nv_warning_msg(*err_str); - goto fail; - } - screen->no_scanout = (val == NV_CTRL_NO_SCANOUT_ENABLED); - - - /* XXX Currently there is no support for screens that are scanning - * out but have TwinView disabled. - */ - if (!screen->dynamic_twinview && !screen->no_scanout) { - *err_str = g_strdup_printf("nvidia-settings currently does not " - "support scanout screens (%d) that have " - "dynamic twinview disabled.", - screen_id); - nv_warning_msg(*err_str); - goto fail; - } + if (gpu) { + gpu_remove_displays(gpu); + XFree(gpu->name); + g_free(gpu->pci_bus_id); + free(gpu->gvo_mode_data); - /* The display owner GPU gets the screen(s) */ - ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_MULTIGPU_DISPLAY_OWNER, - &val); - if (ret != NvCtrlSuccess || val != NvCtrlGetTargetId(gpu->handle)) { - screen_free(screen); - return TRUE; + if (gpu->handle) { + NvCtrlAttributeClose(gpu->handle); + } + free(gpu); } - ret = NvCtrlGetAttribute(screen->handle, - NV_CTRL_SHOW_SLI_VISUAL_INDICATOR, - &tmp); +} /* gpu_free() */ - screen->sli = (ret == NvCtrlSuccess); - /* Listen to NV-CONTROL events on this screen handle */ - screen->ctk_event = CTK_EVENT(ctk_event_new(screen->handle)); +/*****************************************************************************/ +/** LAYOUT FUNCTIONS *********************************************************/ +/*****************************************************************************/ - /* Query the depth of the screen */ - screen->depth = NvCtrlGetScreenPlanes(screen->handle); - /* Initialize the virtual X screen size */ - screen->dim[W] = NvCtrlGetScreenWidth(screen->handle); - screen->dim[H] = NvCtrlGetScreenHeight(screen->handle); +/** layout_add_gpu() ************************************************* + * + * Adds a GPU to the (end of the) layout's list of GPUs. + * + **/ +static void layout_add_gpu(nvLayoutPtr layout, nvGpuPtr gpu) +{ + gpu->layout = layout; + gpu->next_in_layout = NULL; - /* Parse the screen's metamodes (ties displays on the gpu to the screen) */ - if (!screen->no_scanout) { - if (!screen_add_metamodes(screen, err_str)) { - nv_warning_msg("Failed to add metamodes to screen %d (on GPU-%d).", - screen_id, NvCtrlGetTargetId(gpu->handle)); - goto fail; - } - - /* Query & parse the screen's primary display */ - screen->primaryDisplay = NULL; - ret = NvCtrlGetStringDisplayAttribute - (screen->handle, - 0, - NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER, - &primary_str); - - if (ret == NvCtrlSuccess) { - nvDisplayPtr d; - unsigned int device_mask; - - /* Parse the device mask */ - parse_read_display_name(primary_str, &device_mask); - - /* Find the matching primary display */ - for (d = gpu->displays; d; d = d->next) { - if (d->screen == screen && - d->device_mask & device_mask) { - screen->primaryDisplay = d; - break; - } + if (!layout->gpus) { + layout->gpus = gpu; + } else { + nvGpuPtr last; + for (last = layout->gpus; last; last = last->next_in_layout) { + if (!last->next_in_layout) { + last->next_in_layout = gpu; + break; } } } + layout->num_gpus++; - /* Add the screen at the end of the gpu's screen list */ - xconfigAddListItem((GenericListPtr *)(&gpu->screens), - (GenericListPtr)screen); - gpu->num_screens++; - return TRUE; - - - fail: - screen_free(screen); - return FALSE; - -} /* gpu_add_screen_from_server() */ +} /* layout_add_gpu() */ -/** gpu_add_screens_from_server() ************************************ +/** layout_add_screen() ********************************************** * - * Queries the list of screens on the gpu. + * Adds a screen to the (end of the) layout's list of screens. * - */ -static Bool gpu_add_screens_from_server(nvGpuPtr gpu, gchar **err_str) + **/ +void layout_add_screen(nvLayoutPtr layout, nvScreenPtr screen) { - ReturnStatus ret; - int *pData; - int len; - int i; - - - /* Clean up the GPU list */ - gpu_remove_screens(gpu); - + screen->layout = layout; + screen->next_in_layout = NULL; - /* Query the list of X screens this GPU is driving */ - ret = NvCtrlGetBinaryAttribute(gpu->handle, 0, - NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU, - (unsigned char **)(&pData), &len); - if (ret != NvCtrlSuccess) { - *err_str = g_strdup_printf("Failed to query list of screens driven\n" - "by GPU-%d '%s'.", - NvCtrlGetTargetId(gpu->handle), gpu->name); - nv_error_msg(*err_str); - goto fail; - } - - - /* Add each X screen */ - for (i = 1; i <= pData[0]; i++) { - if (!gpu_add_screen_from_server(gpu, pData[i], err_str)) { - nv_warning_msg("Failed to add screen %d to GPU-%d '%s'.", - pData[i], NvCtrlGetTargetId(gpu->handle), - gpu->name); - XFree(pData); - goto fail; + if (!layout->screens) { + layout->screens = screen; + } else { + nvScreenPtr last; + for (last = layout->screens; last; last = last->next_in_layout) { + if (!last->next_in_layout) { + last->next_in_layout = screen; + break; + } } } - XFree(pData); - return TRUE; - - - /* Failure case */ - fail: - gpu_remove_screens(gpu); - return FALSE; + layout->num_screens++; -} /* gpu_add_screens_from_server() */ +} /* layout_add_screen() */ -/** gpu_add_screenless_modes_to_displays() *************************** +/** layout_remove_and_free_screen() ********************************** * - * Adds fake modes to display devices that have no screens so we - * can show them on the layout page. + * Removes a screen from the layout and frees it. * **/ -Bool gpu_add_screenless_modes_to_displays(nvGpuPtr gpu) + +void layout_remove_and_free_screen(nvScreenPtr screen) { - nvDisplayPtr display; - nvModePtr mode; + nvLayoutPtr layout = screen->layout; + nvScreenPtr other; - for (display = gpu->displays; display; display = display->next) { - if (display->screen) continue; + if (!screen) return; - /* Create a fake mode */ - mode = (nvModePtr)calloc(1, sizeof(nvMode)); - if (!mode) return FALSE; - mode->display = display; - mode->dummy = 1; - - mode->dim[W] = 800; - mode->dim[H] = 600; - mode->pan[W] = mode->dim[W]; - mode->pan[H] = mode->dim[H]; + /* Make sure other screens in the layout aren't relative + * to this screen + */ + for (other = layout->screens; + other; + other = other->next_in_layout) { - /* Add the mode to the display */ - display->modes = mode; - display->cur_mode = mode; - display->num_modes = 1; + if (other->relative_to == screen) { + other->position_type = CONF_ADJ_ABSOLUTE; + other->relative_to = NULL; + } } - return TRUE; - -} /* gpu_add_screenless_modes_to_displays() */ - - - -/** gpu_free() ******************************************************* - * - * Frees memory used by the gpu. - * - **/ -static void gpu_free(nvGpuPtr gpu) -{ - if (gpu) { - gpu_remove_screens(gpu); - gpu_remove_displays(gpu); - XFree(gpu->name); - g_free(gpu->pci_bus_id); - if (gpu->handle) { - NvCtrlAttributeClose(gpu->handle); + /* Remove the screen from the layout */ + if (layout->screens == screen) { + layout->screens = screen->next_in_layout; + } else { + nvScreenPtr cur; + for (cur = layout->screens; cur; cur = cur->next_in_layout) { + if (cur->next_in_layout == screen) { + cur->next_in_layout = screen->next_in_layout; + break; + } } - free(gpu); } + layout->num_screens--; -} /* gpu_free() */ + screen_free(screen); +} /* layout_remove_and_free_screen() */ -/*****************************************************************************/ -/** LAYOUT FUNCTIONS *********************************************************/ -/*****************************************************************************/ - - /** layout_remove_gpus() ********************************************* * * Removes all GPUs from the layout structure. @@ -2329,14 +2247,16 @@ static void gpu_free(nvGpuPtr gpu) **/ static void layout_remove_gpus(nvLayoutPtr layout) { - if (layout) { - while (layout->gpus) { - nvGpuPtr gpu = layout->gpus; - layout->gpus = gpu->next; - gpu_free(gpu); - } - layout->num_gpus = 0; + nvGpuPtr gpu; + + if (!layout) return; + + while (layout->gpus) { + gpu = layout->gpus; + layout->gpus = gpu->next_in_layout; + gpu_free(gpu); } + layout->num_gpus = 0; } /* layout_remove_gpus() */ @@ -2385,16 +2305,6 @@ static Bool layout_add_gpu_from_server(nvLayoutPtr layout, unsigned int gpu_id, goto fail; } - ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_CONNECTED_DISPLAYS, - (int *)&(gpu->connected_displays)); - if (ret != NvCtrlSuccess) { - *err_str = g_strdup_printf("Failed to query connected display " - "devices on GPU-%d '%s'.", - gpu_id, gpu->name); - nv_error_msg(*err_str); - goto fail; - } - get_bus_id_str(gpu->handle, &(gpu->pci_bus_id)); ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_MAX_SCREEN_WIDTH, @@ -2438,27 +2348,9 @@ static Bool layout_add_gpu_from_server(nvLayoutPtr layout, unsigned int gpu_id, goto fail; } - - /* Add the X screens to the GPU */ - if (!gpu_add_screens_from_server(gpu, err_str)) { - nv_warning_msg("Failed to add screens to GPU-%d '%s'.", - gpu_id, gpu->name); - goto fail; - } - - - /* Add fake modes to screenless display devices */ - if (!gpu_add_screenless_modes_to_displays(gpu)) { - nv_warning_msg("Failed to add screenless modes to GPU-%d '%s'.", - gpu_id, gpu->name); - goto fail; - } - - /* Add the GPU at the end of the layout's GPU list */ - xconfigAddListItem((GenericListPtr *)(&layout->gpus), - (GenericListPtr)gpu); - layout->num_gpus++; + layout_add_gpu(layout, gpu); + return TRUE; @@ -2518,6 +2410,253 @@ static int layout_add_gpus_from_server(nvLayoutPtr layout, gchar **err_str) +/** layout_remove_screens() ****************************************** + * + * Removes all X screens from the layout structure. + * + **/ +static void layout_remove_screens(nvLayoutPtr layout) +{ + if (!layout) return; + + while (layout->screens) { + layout_remove_and_free_screen(layout->screens); + } + +} /* layout_remove_screens() */ + + + +/** layout_add_screen_from_server() ********************************** + * + * Adds an X screen to the layout structure. + * + **/ +static Bool layout_add_screen_from_server(nvLayoutPtr layout, + unsigned int screen_id, + gchar **err_str) +{ + Display *display; + nvScreenPtr screen; + int val, tmp; + ReturnStatus ret; + gchar *primary_str = NULL; + nvGpuPtr gpu; + + + screen = (nvScreenPtr)calloc(1, sizeof(nvScreen)); + if (!screen) goto fail; + + screen->scrnum = screen_id; + + + /* Make an NV-CONTROL handle to talk to the screen (use the + * first gpu's display) + */ + display = NvCtrlGetDisplayPtr(layout->gpus->handle); + screen->handle = + NvCtrlAttributeInit(display, + NV_CTRL_TARGET_TYPE_X_SCREEN, + screen_id, + NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM | + NV_CTRL_ATTRIBUTES_XRANDR_SUBSYSTEM); + if (!screen->handle) { + *err_str = g_strdup_printf("Failed to create NV-CONTROL handle for\n" + "screen %d.", + screen_id); + nv_error_msg(*err_str); + goto fail; + } + + + /* See if the screen supports dynamic twinview */ + ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_DYNAMIC_TWINVIEW, &val); + if (ret != NvCtrlSuccess) { + *err_str = g_strdup_printf("Failed to query Dynamic TwinView for " + "screen %d.", + screen_id); + nv_warning_msg(*err_str); + goto fail; + } + screen->dynamic_twinview = !!val; + + + /* See if the screen is set to not scanout */ + ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_NO_SCANOUT, &val); + if (ret != NvCtrlSuccess) { + *err_str = g_strdup_printf("Failed to query NoScanout for " + "screen %d.", + screen_id); + nv_warning_msg(*err_str); + goto fail; + } + screen->no_scanout = (val == NV_CTRL_NO_SCANOUT_ENABLED); + + + /* XXX Currently there is no support for screens that are scanning + * out but have TwinView disabled. + */ + if (!screen->dynamic_twinview && !screen->no_scanout) { + *err_str = g_strdup_printf("nvidia-settings currently does not " + "support scanout screens (%d) that have " + "dynamic twinview disabled.", + screen_id); + nv_warning_msg(*err_str); + goto fail; + } + + + /* The display owner GPU gets the screen(s) */ + ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_MULTIGPU_DISPLAY_OWNER, + &val); + if (ret != NvCtrlSuccess) { + screen_free(screen); + return TRUE; + } + + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + if (val == NvCtrlGetTargetId(gpu->handle)) { + screen->gpu = gpu; + } + } + if (!screen->gpu) { + *err_str = g_strdup_printf("Failed to find GPU that drives screen %d.", + screen_id); + nv_warning_msg(*err_str); + goto fail; + } + + /* Query SLI status */ + ret = NvCtrlGetAttribute(screen->handle, + NV_CTRL_SHOW_SLI_VISUAL_INDICATOR, + &tmp); + + screen->sli = (ret == NvCtrlSuccess); + + + /* 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); + + /* Initialize the virtual X screen size */ + screen->dim[W] = NvCtrlGetScreenWidth(screen->handle); + screen->dim[H] = NvCtrlGetScreenHeight(screen->handle); + + + + /* Add the screen at the end of the gpu's screen list */ + layout_add_screen(layout, screen); + + + /* Parse the screen's metamodes (ties displays on the gpu to the screen) */ + if (!screen->no_scanout) { + if (!screen_add_metamodes(screen, err_str)) { + nv_warning_msg("Failed to add metamodes to screen %d.", + screen_id); + goto fail; + } + + /* Query & parse the screen's primary display */ + screen->primaryDisplay = NULL; + ret = NvCtrlGetStringDisplayAttribute + (screen->handle, + 0, + NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER, + &primary_str); + + if (ret == NvCtrlSuccess) { + unsigned int device_mask; + + /* Parse the device mask */ + parse_read_display_name(primary_str, &device_mask); + + /* Find the matching primary display */ + screen->primaryDisplay = gpu_get_display(screen->gpu, device_mask); + } + } + + return TRUE; + + fail: + screen_free(screen); + + return FALSE; + +} /* layout_add_screen_from_server() */ + + + +/** layout_add_screens_from_server() ********************************* + * + * Adds the screens found on the server to the layout structure. + * + **/ +static int layout_add_screens_from_server(nvLayoutPtr layout, gchar **err_str) +{ + ReturnStatus ret; + int i, nscreens; + + + layout_remove_screens(layout); + + + ret = NvCtrlQueryTargetCount(layout->handle, NV_CTRL_TARGET_TYPE_X_SCREEN, + &nscreens); + if (ret != NvCtrlSuccess || !nscreens) { + *err_str = g_strdup("Failed to query number of X screens (or no X " + "screens found) in the system."); + nv_error_msg(*err_str); + nscreens = 0; + goto fail; + } + + for (i = 0; i < nscreens; i++) { + if (!layout_add_screen_from_server(layout, i, err_str)) { + nv_warning_msg("Failed to add X screen %d to layout.", i); + goto fail; + } + } + + return nscreens; + + + fail: + layout_remove_screens(layout); + return 0; + +} /* layout_add_screens_from_server() */ + + + +/** layout_add_screenless_modes_to_displays()************************* + * + * Adds fake modes to display devices that are currently not + * associated with an X screen so we can see them on the layout. + * + **/ +static Bool layout_add_screenless_modes_to_displays(nvLayoutPtr layout) +{ + nvGpuPtr gpu; + + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + + /* Add fake modes to screenless display devices */ + if (!gpu_add_screenless_modes_to_displays(gpu)) { + nv_warning_msg("Failed to add screenless modes to GPU-%d '%s'.", + NvCtrlGetTargetId(gpu->handle), gpu->name); + return FALSE; + } + } + + return TRUE; + +} /* layout_add_screenless_modes_to_displays() */ + + + /** layout_free() **************************************************** * * Frees a layout structure. @@ -2553,7 +2692,7 @@ nvLayoutPtr layout_load_from_server(NvCtrlAttributeHandle *handle, /* Cache the handle for talking to the X server */ layout->handle = handle; - + /* Is Xinerma enabled? */ ret = NvCtrlGetAttribute(handle, NV_CTRL_XINERAMA, @@ -2564,14 +2703,24 @@ nvLayoutPtr layout_load_from_server(NvCtrlAttributeHandle *handle, goto fail; } - - /* Add GPUs to the layout */ if (!layout_add_gpus_from_server(layout, err_str)) { nv_warning_msg("Failed to add GPU(s) to layout for display " "configuration page."); goto fail; } + if (!layout_add_screens_from_server(layout, err_str)) { + nv_warning_msg("Failed to add Screens(s) to layout for display " + "configuration page."); + goto fail; + } + + if (!layout_add_screenless_modes_to_displays(layout)) { + nv_warning_msg("Failed to add Screenless modes to layout for " + "display configuration page."); + goto fail; + } + return layout; @@ -2593,28 +2742,22 @@ nvLayoutPtr layout_load_from_server(NvCtrlAttributeHandle *handle, **/ nvScreenPtr layout_get_a_screen(nvLayoutPtr layout, nvGpuPtr preferred_gpu) { - nvGpuPtr gpu; nvScreenPtr screen = NULL; - nvScreenPtr other; - - if (!layout) return NULL; + nvScreenPtr cur; - if (preferred_gpu && preferred_gpu->screens) { - gpu = preferred_gpu; - } else { - preferred_gpu = NULL; - gpu = layout->gpus; - } + if (!layout || !layout->screens) return NULL; - for (; gpu; gpu = gpu->next) { - for (other = gpu->screens; other; other = other->next) { - if (!screen || screen->scrnum > other->scrnum) { - screen = other; + screen = layout->screens; + for (cur = screen->next_in_layout; cur; cur = cur->next_in_layout) { + if (cur->gpu == preferred_gpu) { + if (screen->gpu != preferred_gpu) { + screen = cur; + continue; } } - - /* We found a preferred screen */ - if (gpu == preferred_gpu) break; + if (screen->scrnum > cur->scrnum) { + screen = cur; + } } return screen; diff --git a/src/gtk+-2.x/ctkdisplayconfig-utils.h b/src/gtk+-2.x/ctkdisplayconfig-utils.h index fc62337..847654e 100644 --- a/src/gtk+-2.x/ctkdisplayconfig-utils.h +++ b/src/gtk+-2.x/ctkdisplayconfig-utils.h @@ -78,6 +78,8 @@ void display_remove_modes(nvDisplayPtr display); /* Screen functions */ 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); @@ -91,17 +93,17 @@ nvDisplayPtr gpu_add_display_from_server(nvGpuPtr gpu, unsigned int device_mask, gchar **err_str); -void gpu_remove_and_free_screen(nvScreenPtr screen); Bool gpu_add_screenless_modes_to_displays(nvGpuPtr gpu); /* Layout functions */ void layout_free(nvLayoutPtr layout); +void layout_add_screen(nvLayoutPtr layout, nvScreenPtr screen); nvLayoutPtr layout_load_from_server(NvCtrlAttributeHandle *handle, gchar **err_str); nvScreenPtr layout_get_a_screen(nvLayoutPtr layout, nvGpuPtr preferred_gpu); - +void layout_remove_and_free_screen(nvScreenPtr screen); diff --git a/src/gtk+-2.x/ctkdisplayconfig.c b/src/gtk+-2.x/ctkdisplayconfig.c index f9e1600..c848bad 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.c +++ b/src/gtk+-2.x/ctkdisplayconfig.c @@ -55,8 +55,7 @@ static void setup_layout_frame(CtkDisplayConfig *ctk_object); static void setup_display_page(CtkDisplayConfig *ctk_object); -static void display_config_clicked(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); static void display_modelname_changed(GtkWidget *widget, gpointer user_data); @@ -138,7 +137,10 @@ 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 /*** G L O B A L S ***********************************************************/ @@ -166,6 +168,10 @@ static const char * __layout_xinerama_button_help = static const char * __dpy_model_help = "The Display drop-down allows you to select a desired display device."; +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 * __dpy_resolution_mnu_help = "The Resolution drop-down allows you to select a desired resolution " "for the currently selected display device."; @@ -322,17 +328,19 @@ static void check_screen_pos_changed(CtkDisplayConfig *ctk_object) /** layout_supports_depth_30() *************************************** * - * Returns TRUE if all the GPUs in the layout that have screens - * support depth 30. + * Returns TRUE if all the screens in the layout are driven by GPUs + * that support depth 30. * **/ static gboolean layout_supports_depth_30(nvLayoutPtr layout) { + nvScreenPtr screen; nvGpuPtr gpu; - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - if ((gpu->num_screens) && (!gpu->allow_depth_30)) { + for (screen = layout->screens; screen; screen = screen->next_in_layout) { + gpu = screen->gpu; + if (!gpu->allow_depth_30) { return FALSE; } } @@ -354,11 +362,10 @@ static void register_layout_events(CtkDisplayConfig *ctk_object) nvLayoutPtr layout = ctk_object->layout; nvScreenPtr screen; nvGpuPtr gpu; - - /* Register all Screen/Gpu events. */ - for (gpu = layout->gpus; gpu; gpu = gpu->next) { + /* Register for GPU events */ + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { if (!gpu->handle) continue; @@ -371,31 +378,32 @@ static void register_layout_events(CtkDisplayConfig *ctk_object) CTK_EVENT_NAME(NV_CTRL_MODE_SET_EVENT), G_CALLBACK(display_config_attribute_changed), (gpointer) ctk_object); + } - for (screen = gpu->screens; screen; screen = screen->next) { + /* Register for X screen events */ + for (screen = layout->screens; screen; screen = screen->next_in_layout) { - if (!screen->handle) continue; - - g_signal_connect(G_OBJECT(screen->ctk_event), - CTK_EVENT_NAME(NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER), - G_CALLBACK(display_config_attribute_changed), - (gpointer) ctk_object); - - g_signal_connect(G_OBJECT(screen->ctk_event), - CTK_EVENT_NAME(NV_CTRL_ASSOCIATED_DISPLAY_DEVICES), - G_CALLBACK(display_config_attribute_changed), - (gpointer) ctk_object); - - g_signal_connect(G_OBJECT(screen->ctk_event), - CTK_EVENT_NAME(NV_CTRL_STRING_MOVE_METAMODE), - G_CALLBACK(display_config_attribute_changed), - (gpointer) ctk_object); - - g_signal_connect(G_OBJECT(screen->ctk_event), - CTK_EVENT_NAME(NV_CTRL_STRING_DELETE_METAMODE), - G_CALLBACK(display_config_attribute_changed), - (gpointer) ctk_object); - } + if (!screen->handle) continue; + + g_signal_connect(G_OBJECT(screen->ctk_event), + CTK_EVENT_NAME(NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER), + G_CALLBACK(display_config_attribute_changed), + (gpointer) ctk_object); + + g_signal_connect(G_OBJECT(screen->ctk_event), + CTK_EVENT_NAME(NV_CTRL_ASSOCIATED_DISPLAY_DEVICES), + G_CALLBACK(display_config_attribute_changed), + (gpointer) ctk_object); + + g_signal_connect(G_OBJECT(screen->ctk_event), + CTK_EVENT_NAME(NV_CTRL_STRING_MOVE_METAMODE), + G_CALLBACK(display_config_attribute_changed), + (gpointer) ctk_object); + + g_signal_connect(G_OBJECT(screen->ctk_event), + CTK_EVENT_NAME(NV_CTRL_STRING_DELETE_METAMODE), + G_CALLBACK(display_config_attribute_changed), + (gpointer) ctk_object); } } /* register_layout_events() */ @@ -416,15 +424,13 @@ static void unregister_layout_events(CtkDisplayConfig *ctk_object) nvLayoutPtr layout = ctk_object->layout; nvScreenPtr screen; nvGpuPtr gpu; - - /* Unregister all Screen/Gpu events. */ - for (gpu = layout->gpus; gpu; gpu = gpu->next) { + /* Unregister GPU events */ + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { if (!gpu->handle) continue; - /* Unregister all GPU events for this GPU */ g_signal_handlers_disconnect_matched(G_OBJECT(gpu->ctk_event), G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, // Signal ID @@ -432,20 +438,20 @@ static void unregister_layout_events(CtkDisplayConfig *ctk_object) NULL, // Closure G_CALLBACK(display_config_attribute_changed), (gpointer) ctk_object); + } - for (screen = gpu->screens; screen; screen = screen->next) { + /* Unregister X screen events */ + for (screen = layout->screens; screen; screen = screen->next_in_layout) { - if (!screen->handle) continue; - - /* Unregister all screen events for this screen */ - g_signal_handlers_disconnect_matched(G_OBJECT(screen->ctk_event), - G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, - 0, // Signal ID - 0, // Signal Detail - NULL, // Closure - G_CALLBACK(display_config_attribute_changed), - (gpointer) ctk_object); - } + if (!screen->handle) continue; + + g_signal_handlers_disconnect_matched(G_OBJECT(screen->ctk_event), + G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, + 0, // Signal ID + 0, // Signal Detail + NULL, // Closure + G_CALLBACK(display_config_attribute_changed), + (gpointer) ctk_object); } } /* unregister_layout_events() */ @@ -463,7 +469,6 @@ static void consolidate_xinerama(CtkDisplayConfig *ctk_object, nvScreenPtr screen) { nvLayoutPtr layout = ctk_object->layout; - nvGpuPtr gpu; nvScreenPtr other; if (!layout->xinerama_enabled) return; @@ -484,11 +489,11 @@ static void consolidate_xinerama(CtkDisplayConfig *ctk_object, } /* If Xinerama is enabled, all screens must have the same depth. */ - for (gpu = screen->gpu->layout->gpus; gpu; gpu = gpu->next) { - for (other = gpu->screens; other; other = other->next) { - if (other == screen) continue; - other->depth = screen->depth; - } + for (other = layout->screens; other; other = other->next_in_layout) { + + if (other == screen) continue; + + other->depth = screen->depth; } } /* consolidate_xinerama() */ @@ -504,21 +509,19 @@ static void consolidate_xinerama(CtkDisplayConfig *ctk_object, void update_btn_apply(CtkDisplayConfig *ctk_object, Bool sensitive) { Bool xrandr_available = FALSE; - nvGpuPtr gpu; + nvLayoutPtr layout = ctk_object->layout; nvScreenPtr screen; if (sensitive) { - /* If XRandR is disabled (for all screens), we can't apply */ - for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { - - for (screen = gpu->screens; screen; screen = screen->next) { - if (NvCtrlGetXrandrEventBase(screen->handle) >= 0) { - xrandr_available = TRUE; - break; - } + /* If none of the screens support XRandR, we can't apply */ + for (screen = layout->screens; + screen; + screen = screen->next_in_layout) { + if (NvCtrlGetXrandrEventBase(screen->handle) >= 0) { + xrandr_available = TRUE; + break; } - if (xrandr_available) break; } if (!xrandr_available && !ctk_object->primary_display_changed) { @@ -754,7 +757,7 @@ static int generate_xconf_metamode_str(CtkDisplayConfig *ctk_object, static void assign_screen_positions(CtkDisplayConfig *ctk_object) { - nvGpuPtr gpu; + nvLayoutPtr layout = ctk_object->layout; nvScreenPtr prev_screen = NULL; nvScreenPtr screen; int xinerama; @@ -770,64 +773,87 @@ static void assign_screen_positions(CtkDisplayConfig *ctk_object) if (ret != NvCtrlSuccess) { initialize = 1; /* Fallback to right-of positioning */ } - /* Setup screen positions */ - for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { - for (screen = gpu->screens; screen; screen = screen->next) { - - screen_info = NULL; - if (screen->handle && !initialize) { - ret = NvCtrlGetStringAttribute - (screen->handle, - NV_CTRL_STRING_XINERAMA_SCREEN_INFO, - &screen_info); - - if (ret != NvCtrlSuccess) { - screen_info = NULL; - } + for (screen = layout->screens; screen; screen = screen->next_in_layout) { + + screen_info = NULL; + if (screen->handle && !initialize) { + ret = NvCtrlGetStringAttribute + (screen->handle, + NV_CTRL_STRING_XINERAMA_SCREEN_INFO, + &screen_info); + + if (ret != NvCtrlSuccess) { + screen_info = NULL; } + } - if (screen_info) { + if (screen_info) { - /* Parse the positioning information */ + /* Parse the positioning information */ - screen_parsed_info.x = -1; - screen_parsed_info.y = -1; - screen_parsed_info.width = -1; - screen_parsed_info.height = -1; + screen_parsed_info.x = -1; + screen_parsed_info.y = -1; + screen_parsed_info.width = -1; + screen_parsed_info.height = -1; - parse_token_value_pairs(screen_info, apply_screen_info_token, - &screen_parsed_info); + parse_token_value_pairs(screen_info, apply_screen_info_token, + &screen_parsed_info); - if (screen_parsed_info.x >= 0 && - screen_parsed_info.y >= 0 && - screen_parsed_info.width >= 0 && - screen_parsed_info.height) { + if (screen_parsed_info.x >= 0 && + screen_parsed_info.y >= 0 && + screen_parsed_info.width >= 0 && + screen_parsed_info.height) { - ctk_display_layout_set_screen_position - (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), - screen, CONF_ADJ_ABSOLUTE, NULL, - screen_parsed_info.x, - screen_parsed_info.y); - } - XFree(screen_info); - - } else if (prev_screen) { - /* Set this screen right of the previous */ ctk_display_layout_set_screen_position (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), - screen, CONF_ADJ_RIGHTOF, prev_screen, 0, 0); + screen, CONF_ADJ_ABSOLUTE, NULL, + screen_parsed_info.x, + screen_parsed_info.y); } + XFree(screen_info); - prev_screen = screen; + } else if (prev_screen) { + /* Set this screen right of the previous */ + ctk_display_layout_set_screen_position + (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), + screen, CONF_ADJ_RIGHTOF, prev_screen, 0, 0); } + + prev_screen = screen; } } /* assign_screen_positions() */ +/** 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 *****************************************/ @@ -1273,41 +1299,22 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, G_CALLBACK(display_modelname_changed), (gpointer) ctk_object); - /* Display configuration (Disabled, TwinView, Separate X screen */ - ctk_object->btn_display_config = - gtk_button_new_with_label("Configure..."); - g_signal_connect(G_OBJECT(ctk_object->btn_display_config), "clicked", - G_CALLBACK(display_config_clicked), + /* 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", + G_CALLBACK(display_config_changed), (gpointer) ctk_object); - ctk_object->txt_display_config = gtk_label_new("Disabled"); - gtk_misc_set_alignment(GTK_MISC(ctk_object->txt_display_config), 0.0f, 0.5f); - - - /* Display configuration dialog */ - ctk_object->dlg_display_config = gtk_dialog_new_with_buttons - ("Configure Display Device", - GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(ctk_object))), - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT - | GTK_DIALOG_NO_SEPARATOR, - GTK_STOCK_OK, - GTK_RESPONSE_ACCEPT, - NULL); - ctk_object->btn_display_config_cancel = - gtk_dialog_add_button(GTK_DIALOG(ctk_object->dlg_display_config), - GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL); - ctk_object->rad_display_config_disabled = - gtk_radio_button_new_with_label(NULL, "Disabled"); - ctk_object->rad_display_config_xscreen = - gtk_radio_button_new_with_label_from_widget - (GTK_RADIO_BUTTON(ctk_object->rad_display_config_disabled), - "Separate X screen"); - ctk_object->rad_display_config_twinview = - gtk_radio_button_new_with_label_from_widget - (GTK_RADIO_BUTTON(ctk_object->rad_display_config_disabled), - "TwinView"); - gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_display_config), - FALSE); /* Display disable dialog */ ctk_object->txt_display_disable = gtk_label_new(""); @@ -1631,8 +1638,6 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, { /* Display page */ - GtkWidget *longest_hbox; - /* Generate the major vbox for the display section */ vbox = gtk_vbox_new(FALSE, 5); ctk_object->display_page = vbox; @@ -1640,16 +1645,15 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, /* Display Configuration */ hbox = gtk_hbox_new(FALSE, 5); - /* XXX Pack widget later. Create it here so we can get its size */ - longest_hbox = hbox; + /* Pack widget into major vbox later. + * Create it here so we can get its size */ label = gtk_label_new("Configuration:"); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_widget_size_request(label, &req); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5); - gtk_box_pack_start(GTK_BOX(hbox), ctk_object->txt_display_config, - FALSE, FALSE, 0); - gtk_box_pack_end(GTK_BOX(hbox), ctk_object->btn_display_config, - FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), ctk_object->mnu_display_config, + TRUE, TRUE, 0); + ctk_object->box_display_config = hbox; /* Display model name */ hbox = gtk_hbox_new(FALSE, 5); @@ -1662,7 +1666,8 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, TRUE, TRUE, 0); /* Pack the display configuration line */ - gtk_box_pack_start(GTK_BOX(vbox), longest_hbox, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), ctk_object->box_display_config, + FALSE, TRUE, 0); /* Display resolution and refresh dropdowns */ hbox = gtk_hbox_new(FALSE, 5); @@ -1851,24 +1856,6 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, { /* Dialogs */ - /* Display Configuration Dialog */ - label = gtk_label_new("How should this display device be configured?"); - hbox = gtk_hbox_new(TRUE, 0); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 20); - gtk_box_pack_start - (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_config)->vbox), - hbox, TRUE, TRUE, 20); - gtk_box_pack_start - (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_config)->vbox), - ctk_object->rad_display_config_disabled, FALSE, FALSE, 0); - gtk_box_pack_start - (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_config)->vbox), - ctk_object->rad_display_config_xscreen, FALSE, FALSE, 0); - gtk_box_pack_start - (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_config)->vbox), - ctk_object->rad_display_config_twinview, FALSE, FALSE, 0); - gtk_widget_show_all(GTK_DIALOG(ctk_object->dlg_display_config)->vbox); - /* Display Disable Dialog */ hbox = gtk_hbox_new(TRUE, 0); gtk_box_pack_start(GTK_BOX(hbox), ctk_object->txt_display_disable, @@ -2059,8 +2046,6 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table, static void setup_layout_frame(CtkDisplayConfig *ctk_object) { nvLayoutPtr layout = ctk_object->layout; - nvGpuPtr gpu; - int num_screens; GdkScreen *s; /* @@ -2071,14 +2056,8 @@ static void setup_layout_frame(CtkDisplayConfig *ctk_object) s = gtk_widget_get_screen(GTK_WIDGET(ctk_object)); screen_size_changed(s, ctk_object); - /* Only allow Xinerama when there are multiple X screens */ - num_screens = 0; - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - num_screens += gpu->num_screens; - } - - /* Unselect Xinerama if only one (or no) X screen */ - if (num_screens <= 1) { + /* Xinerama requires 2 or more X screens */ + if (layout->num_screens < 2) { layout->xinerama_enabled = 0; gtk_widget_hide(ctk_object->chk_xinerama_enabled); return; @@ -2146,20 +2125,68 @@ static void setup_display_config(CtkDisplayConfig *ctk_object) { nvDisplayPtr display = ctk_display_layout_get_selected_display (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); + nvScreenPtr screen = NULL; + int num_screens_on_gpu = 0; if (!display) return; - if (!display->screen) { - gtk_label_set_text(GTK_LABEL(ctk_object->txt_display_config), - "Disabled"); - } else if (display->screen->num_displays == 1) { - gtk_label_set_text(GTK_LABEL(ctk_object->txt_display_config), - "Separate X screen"); + /* 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_label_set_text(GTK_LABEL(ctk_object->txt_display_config), - "TwinView"); + gtk_widget_set_sensitive(ctk_object->mnu_display_config_disabled, + TRUE); + } + + + /* We can only have as many X screens on the GPU as it supports outputs */ + for (screen = ctk_object->layout->screens; + screen; + screen = screen->next_in_layout) { + if (screen->gpu == display->gpu) { + num_screens_on_gpu++; + } } + 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. + */ + if (display->gpu->num_displays == 1 || + !num_screens_on_gpu || + (num_screens_on_gpu == 1 && display->screen) || + (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); + } + + /* 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 { + gtk_option_menu_set_history(GTK_OPTION_MENU(ctk_object->mnu_display_config), + DPY_CFG_SEPARATE_X_SCREEN); // XScreen + } } /* setup_display_config() */ @@ -2570,22 +2597,24 @@ static void setup_display_resolution_dropdown(CtkDisplayConfig *ctk_object) * **/ -static GtkWidget* generate_display_modelname_dropdown - (CtkDisplayConfig *ctk_object, int *cur_idx) +static GtkWidget* generate_display_modelname_dropdown(CtkDisplayConfig *ctk_object, + int *cur_idx) { GtkWidget *menu; GtkWidget *menu_item; + nvLayoutPtr layout = ctk_object->layout; nvGpuPtr gpu; nvDisplayPtr display; int display_count = 0; nvDisplayPtr d = ctk_display_layout_get_selected_display (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); + /* Create the display modelname lookup table for the dropdown */ if (ctk_object->display_model_table) { free(ctk_object->display_model_table); } ctk_object->display_model_table_len = 0; - for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { display_count += gpu->num_displays; } @@ -2601,8 +2630,11 @@ static GtkWidget* generate_display_modelname_dropdown /* Generate the popup menu */ menu = gtk_menu_new(); - for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { - for (display = gpu->displays; display; display = display->next) { + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + for (display = gpu->displays; + display; + display = display->next_on_gpu) { + gchar *str, *type; if (d == display) { *cur_idx = ctk_object->display_model_table_len; @@ -2760,20 +2792,18 @@ static void setup_display_position_relative(CtkDisplayConfig *ctk_object) idx = 0; selected_idx = 0; menu = gtk_menu_new(); - for (relative_to = display->gpu->displays; + for (relative_to = display->screen->displays; relative_to; - relative_to = relative_to->next) { + relative_to = relative_to->next_in_screen) { - if (relative_to == display || relative_to->screen != display->screen) { - continue; - } + if (relative_to == display) continue; if (relative_to == display->cur_mode->relative_to) { selected_idx = idx; } ctk_object->display_position_table[idx] = relative_to; - + menu_item = gtk_menu_item_new_with_label(relative_to->name); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); gtk_widget_show(menu_item); @@ -2883,8 +2913,8 @@ static void setup_display_position(CtkDisplayConfig *ctk_object) (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); - /* Hide the position box if this screen only has one display */ - if (!display || !display->screen || display->screen->num_displays <= 1) { + /* Need at least 2 displays in the X screen to configure position */ + if (!display || !display->screen || (display->screen->num_displays < 2)) { gtk_widget_hide(ctk_object->box_display_position); return; } @@ -3282,9 +3312,9 @@ static void setup_screen_position_type(CtkDisplayConfig *ctk_object) static void setup_screen_position_relative(CtkDisplayConfig *ctk_object) { + nvLayoutPtr layout = ctk_object->layout; nvScreenPtr screen; nvScreenPtr relative_to; - nvGpuPtr gpu; int idx; int selected_idx; GtkWidget *menu; @@ -3299,14 +3329,9 @@ static void setup_screen_position_relative(CtkDisplayConfig *ctk_object) } - /* Count the number of screens */ - ctk_object->screen_position_table_len = 0; - for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { - ctk_object->screen_position_table_len += gpu->num_screens; - } - - /* Don't count the current screen */ - if (ctk_object->screen_position_table_len >= 1) { + /* Count the number of screens, not including the current one */ + ctk_object->screen_position_table_len = layout->num_screens; + if (ctk_object->screen_position_table_len > 0) { ctk_object->screen_position_table_len--; } @@ -3326,29 +3351,28 @@ static void setup_screen_position_relative(CtkDisplayConfig *ctk_object) idx = 0; selected_idx = 0; menu = gtk_menu_new(); - for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { - for (relative_to = gpu->screens; - relative_to; - relative_to = relative_to->next) { - gchar *tmp_str; + for (relative_to = layout->screens; + relative_to; + relative_to = relative_to->next_in_layout) { - if (relative_to == screen) continue; + gchar *tmp_str; - if (relative_to == screen->relative_to) { - selected_idx = idx; - } - - ctk_object->screen_position_table[idx] = relative_to; + if (relative_to == screen) continue; - tmp_str = g_strdup_printf("X screen %d", - relative_to->scrnum); - menu_item = gtk_menu_item_new_with_label(tmp_str); - g_free(tmp_str); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - gtk_widget_show(menu_item); - idx++; + if (relative_to == screen->relative_to) { + selected_idx = idx; } + + ctk_object->screen_position_table[idx] = relative_to; + + tmp_str = g_strdup_printf("X screen %d", + relative_to->scrnum); + menu_item = gtk_menu_item_new_with_label(tmp_str); + g_free(tmp_str); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); + gtk_widget_show(menu_item); + idx++; } @@ -3444,21 +3468,13 @@ static void setup_screen_position_offset(CtkDisplayConfig *ctk_object) static void setup_screen_position(CtkDisplayConfig *ctk_object) { - nvGpuPtr gpu; + nvLayoutPtr layout = ctk_object->layout; nvScreenPtr screen = ctk_display_layout_get_selected_screen (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); - int num_screens; - /* Count the number of screens */ - num_screens = 0; - for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { - num_screens += gpu->num_screens; - } - - - /* Hide the position box if there is only one screen */ - if (!screen || num_screens <= 1) { + /* Need at least 2 X screens to configure position */ + if (!screen || (layout->num_screens < 2)) { gtk_widget_hide(ctk_object->box_screen_position); return; } @@ -3617,7 +3633,7 @@ static gint validation_fix_crowded_metamodes(CtkDisplayConfig *ctk_object, /* Verify each metamode with the metamodes that come before it */ for (i = 0; i < screen->num_metamodes; i++) { - + /* Keep track of the first mode in case we need to assign * a default resolution */ @@ -3629,18 +3645,16 @@ static gint validation_fix_crowded_metamodes(CtkDisplayConfig *ctk_object, * that have a (non NULL) mode set. */ num = 0; - for (display = screen->gpu->displays; + for (display = screen->displays; display; - display = display->next) { - - if (display->screen != screen) continue; + display = display->next_in_screen) { /* Check the mode that corresponds with the metamode */ mode = display->modes; for (j = 0; j < i; j++) { mode = mode->next; } - + if (!first_mode) { first_mode = mode; } @@ -3787,18 +3801,18 @@ static gint validation_auto_fix_screen(CtkDisplayConfig *ctk_object, static gint validation_auto_fix(CtkDisplayConfig *ctk_object) { nvLayoutPtr layout = ctk_object->layout; - nvGpuPtr gpu; nvScreenPtr screen; gint success = 1; /* Auto fix each screen */ - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - for (screen = gpu->screens; screen; screen = screen->next) { - if (!validation_auto_fix_screen(ctk_object, screen)) { - success = 0; - break; - } + for (screen = layout->screens; + screen; + screen = screen->next_in_layout) { + + if (!validation_auto_fix_screen(ctk_object, screen)) { + success = 0; + break; } } @@ -3861,12 +3875,10 @@ static gchar * validate_screen(nvScreenPtr screen) /* Count the number of display devices used in the metamode */ num_displays = 0; - for (display = screen->gpu->displays; + for (display = screen->displays; display; - display = display->next) { + display = display->next_in_screen) { - if (display->screen != screen) continue; - mode = display->modes; for (j = 0; j < i; j++) { mode = mode->next; @@ -3943,7 +3955,6 @@ static gchar * validate_screen(nvScreenPtr screen) static int validate_layout(CtkDisplayConfig *ctk_object, int validation_type) { nvLayoutPtr layout = ctk_object->layout; - nvGpuPtr gpu; nvScreenPtr screen; gchar *err_strs = NULL; gchar *err_str; @@ -3953,18 +3964,16 @@ static int validate_layout(CtkDisplayConfig *ctk_object, int validation_type) /* Validate each screen and count the number of screens using abs. pos. */ - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - for (screen = gpu->screens; screen; screen = screen->next) { - err_str = validate_screen(screen); - if (err_str) { - tmp = g_strconcat((err_strs ? err_strs : ""), err_str, NULL); - g_free(err_strs); - g_free(err_str); - err_strs = tmp; - } - if (screen->position_type == CONF_ADJ_ABSOLUTE) { - num_absolute++; - } + for (screen = layout->screens; screen; screen = screen->next_in_layout) { + err_str = validate_screen(screen); + if (err_str) { + tmp = g_strconcat((err_strs ? err_strs : ""), err_str, NULL); + g_free(err_strs); + g_free(err_str); + err_strs = tmp; + } + if (screen->position_type == CONF_ADJ_ABSOLUTE) { + num_absolute++; } } @@ -4172,28 +4181,11 @@ void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object, nvDisplayPtr display) { nvLayoutPtr layout = ctk_object->layout; - nvGpuPtr gpu; nvScreenPtr screen; nvScreenPtr rightmost = NULL; nvScreenPtr other; nvMetaModePtr metamode; nvModePtr mode; - int scrnum = 0; - - - /* Get the next available screen number and the right-most screen */ - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - for (screen = gpu->screens; screen; screen = screen->next) { - scrnum++; - - /* Compute the right-most screen */ - if (!rightmost || - ((screen->dim[X] + screen->dim[W]) > - (rightmost->dim[X] + rightmost->dim[W]))) { - rightmost = screen; - } - } - } /* Get resources */ @@ -4207,7 +4199,7 @@ void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object, /* Setup the display */ - display->screen = screen; + screen_link_display(screen, display); /* Setup the mode */ @@ -4231,19 +4223,25 @@ void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object, /* Setup the screen */ - screen->scrnum = scrnum; + screen->scrnum = layout->num_screens; screen->gpu = display->gpu; - + other = layout_get_a_screen(layout, display->gpu); screen->depth = other ? other->depth : 24; - screen->displays_mask = display->device_mask; - screen->num_displays = 1; screen->metamodes = metamode; screen->num_metamodes = 1; screen->cur_metamode = metamode; screen->cur_metamode_idx = 0; + /* Compute the right-most screen */ + for (other = layout->screens; other; other = other->next_in_layout) { + if (!rightmost || + ((other->dim[X] + other->dim[W]) > + (rightmost->dim[X] + rightmost->dim[W]))) { + rightmost = other; + } + } /* Make the screen right-of the right-most screen */ if (rightmost) { @@ -4257,15 +4255,11 @@ void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object, screen->relative_to = NULL; screen->dim[X] = mode->dim[X]; screen->dim[Y] = mode->dim[Y]; - } - + } - /* Add the screen at the end of the gpu's screen list */ - gpu = display->gpu; - xconfigAddListItem((GenericListPtr *)(&gpu->screens), - (GenericListPtr)screen); - gpu->num_screens++; + /* Add the screen at the end of the layout's screen list */ + layout_add_screen(layout, screen); /* We can't dynamically add new X screens */ ctk_object->apply_possible = FALSE; @@ -4283,27 +4277,29 @@ void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object, * - Deleting all the implicit metamodes from the X screens that the * GPU is driving. * - * - Making all X screens that are relative to displays on this GPU - * relative to the first X screen instead. XXX This assumes we are - * using the first X screen as the X screen to use for TwinView. + * - 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) + nvGpuPtr gpu, + nvScreenPtr use_screen) { + nvLayoutPtr layout = ctk_object->layout; nvMetaModePtr metamode; nvScreenPtr screen; - nvGpuPtr other; int m; if (!gpu) return; /* Delete implicit metamodes from all screens involved */ - for (screen = gpu->screens; screen; screen = screen->next) { + 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) { @@ -4334,17 +4330,33 @@ static void prepare_gpu_for_twinview(CtkDisplayConfig *ctk_object, } /* Make all other X screens in the layout relative to the GPU's - * first X screen if they are relative to any display driven - * by the GPU. + * '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. */ - for (other = ctk_object->layout->gpus; other; other = other->next) { - - if (other == gpu) continue; + 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; + } - for (screen = other->screens; screen; screen = screen->next) { if (screen->relative_to && screen->relative_to->gpu == gpu) { - screen->relative_to = gpu->screens; + screen->relative_to = use_screen; } } } @@ -4374,7 +4386,7 @@ static void do_enable_display_for_twinview(CtkDisplayConfig *ctk_object, /* Make sure a screen exists */ gpu = display->gpu; - screen = gpu->screens; + screen = find_first_screen_on_gpu(gpu); if (!screen) return; @@ -4435,7 +4447,7 @@ static void do_enable_display_for_twinview(CtkDisplayConfig *ctk_object, } /* Delete implicit metamodes on all X Screens driven by the GPU */ - prepare_gpu_for_twinview(ctk_object, gpu); + prepare_gpu_for_twinview(ctk_object, gpu, screen); /* Fix up the display's metamode list */ display_remove_modes(display); @@ -4445,10 +4457,9 @@ static void do_enable_display_for_twinview(CtkDisplayConfig *ctk_object, nvDisplayPtr other; nvModePtr rightmost = NULL; - + /* Get the right-most mode of the metamode */ - for (other = screen->gpu->displays; other; other = other->next) { - if (other->screen != screen) continue; + for (other = screen->displays; other; other = other->next_in_screen) { for (mode = other->modes; mode; mode = mode->next) { if (!rightmost || ((mode->dim[X] + mode->dim[W]) > @@ -4496,9 +4507,7 @@ static void do_enable_display_for_twinview(CtkDisplayConfig *ctk_object, /* Link the screen and display together */ - screen->displays_mask = new_mask; - screen->num_displays++; - display->screen = screen; + screen_link_display(screen, display); } /* do_enable_display_for_twinview() */ @@ -4525,18 +4534,13 @@ static void do_configure_display_for_xscreen(CtkDisplayConfig *ctk_object, /* Get the next available screen number */ - scrnum = 0; - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - for (screen = gpu->screens; screen; screen = screen->next) { - scrnum++; - } - } + 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) { + for (display = gpu->displays; display; display = display->next_on_gpu) { nvScreenPtr new_screen; @@ -4552,9 +4556,6 @@ static void do_configure_display_for_xscreen(CtkDisplayConfig *ctk_object, new_screen->depth = screen->depth; - new_screen->displays_mask = display->device_mask; - new_screen->num_displays = 1; - /* Create a metamode for each mode on the display */ new_screen->num_metamodes = 0; for (mode = display->modes; mode; mode = mode->next) { @@ -4581,20 +4582,13 @@ static void do_configure_display_for_xscreen(CtkDisplayConfig *ctk_object, } /* Move the display to the new screen */ - screen->num_displays--; - screen->displays_mask &= ~(display->device_mask); - - display->screen = new_screen; + screen_unlink_display(display); + screen_link_display(new_screen, display); if (display == screen->primaryDisplay) { new_screen->primaryDisplay = display; screen->primaryDisplay = NULL; } - - /* Append the screen to the gpu */ - xconfigAddListItem((GenericListPtr *)(&gpu->screens), - (GenericListPtr)new_screen); - gpu->num_screens++; /* Earlier display devices get first dibs on low screen numbers */ new_screen->handle = screen->handle; @@ -4604,14 +4598,17 @@ static void do_configure_display_for_xscreen(CtkDisplayConfig *ctk_object, 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; } /* Translate mode positional relationships to screen relationships */ - for (display = gpu->displays; display; display = display->next) { - + for (display = gpu->displays; display; display = display->next_on_gpu) { + if (!display->screen) continue; for (mode = display->modes; mode; mode = mode->next) { @@ -4631,14 +4628,15 @@ static void do_configure_display_for_xscreen(CtkDisplayConfig *ctk_object, /** do_configure_display_for_twinview() ****************************** * - * Configures the display's GPU for TwinView + * Configures the display's GPU for TwinView. * **/ static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object, nvDisplayPtr display) { - nvScreenPtr screen; + nvLayoutPtr layout = ctk_object->layout; + nvScreenPtr use_screen; /* Screen that inherits all displays */ nvMetaModePtr metamode; nvModePtr mode; nvModePtr last_mode; @@ -4646,33 +4644,39 @@ static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object, int m; - /* We need at least one screen to activate TwinView */ - if (!gpu || !gpu->screens) return; + if (!gpu) return; + /* Find screen on GPU with the lowest screen number */ + use_screen = find_first_screen_on_gpu(gpu); - /* Delete implicit metamodes on all X Screens driven by the GPU */ - prepare_gpu_for_twinview(ctk_object, gpu); + /* Need at least one screen to toggle into TwinView */ + if (!use_screen) return; - /* Make sure the screen has enough metamodes */ - screen = gpu->screens; - for (display = gpu->displays; display; display = display->next) { + /* Delete implicit metamodes on all X screens driven by the GPU */ + prepare_gpu_for_twinview(ctk_object, gpu, use_screen); - /* Only add enabled displays to TwinView setup */ + + /* Make sure the screen has enough metamodes to accomodate 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 - screen->num_metamodes; m > 0; m--) { + 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 *)(&screen->metamodes), + xconfigAddListItem((GenericListPtr *)(&use_screen->metamodes), (GenericListPtr)metamode); - screen->num_metamodes++; + use_screen->num_metamodes++; } } @@ -4680,18 +4684,18 @@ static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object, /* 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) { + 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 = screen->metamodes; + metamode = use_screen->metamodes; mode = display->modes; last_mode = NULL; while (metamode && mode) { - if (metamode == screen->cur_metamode) { + if (metamode == use_screen->cur_metamode) { display->cur_mode = mode; } @@ -4706,7 +4710,9 @@ static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object, nvDisplayPtr other; /* Make the display relative to the other display */ - for (other = gpu->displays; other; other = other->next) { + 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; @@ -4730,7 +4736,7 @@ static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object, mode->dummy = 1; mode->metamode = metamode; - if (metamode == screen->cur_metamode) { + if (metamode == use_screen->cur_metamode) { display->cur_mode = mode; } @@ -4753,66 +4759,36 @@ static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object, } - /* Make the displays part of the screen */ - for (display = gpu->displays; display; display = display->next) { + /* Make the GPU's active displays part of the screen */ + for (display = gpu->displays; display; display = display->next_on_gpu) { - /* Only add enabled displays to TwinView setup */ if (!display->screen) continue; + if (display->screen == use_screen) continue; - if (display->screen != screen) { - display->screen = screen; - screen->displays_mask |= display->device_mask; - screen->num_displays++; - } + screen_unlink_display(display); + screen_link_display(use_screen, display); } /* Delete extra screens on the GPU */ - while (gpu->screens->next) { + { nvScreenPtr other; + nvScreenPtr next; - /* Delete screens that come before 'screen' */ - if (gpu->screens != screen) { - other = gpu->screens; - gpu->screens = other->next; + other = layout->screens; + next = layout->screens; + while (next) { + other = next; + next = other->next_in_layout; - /* Delete screens that comes after 'screen' */ - } else { - other = gpu->screens->next; - gpu->screens->next = other->next; - } - - /* Handle positional relationships going away */ - if (screen->relative_to == other) { - screen->position_type = CONF_ADJ_ABSOLUTE; - screen->relative_to = NULL; - } + if (other->gpu != gpu) continue; + if (other == use_screen) continue; - /* Clean up memory used by the screen */ - while (other->metamodes) { - nvMetaModePtr metamode = other->metamodes; - other->metamodes = metamode->next; - free(metamode); + layout_remove_and_free_screen(other); } - - /* Keep the lowest screen number */ - if (other->scrnum < screen->scrnum) { - if (screen->handle) { - NvCtrlAttributeClose(screen->handle); - } - screen->scrnum = other->scrnum; - screen->handle = other->handle; - screen->ctk_event = other->ctk_event; - } else { - if (other->handle) { - NvCtrlAttributeClose(other->handle); - } - } - - free(other); - gpu->num_screens--; } + /* Make sure screen numbering is consistent */ renumber_xscreens(ctk_object->layout); @@ -4903,139 +4879,31 @@ void do_disable_display(CtkDisplayConfig *ctk_object, nvDisplayPtr display) -/** display_config_clicked() ***************************************** +/** display_config_changed() ***************************************** * - * Called when user clicks on the display configuration button. + * Called when user selects an option in the display configuration menu. * **/ -static void display_config_clicked(GtkWidget *widget, gpointer user_data) +static void display_config_changed(GtkWidget *widget, gpointer user_data) { CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data); + nvLayoutPtr layout = ctk_object->layout; nvDisplayPtr display = ctk_display_layout_get_selected_display - (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); - gint result; + (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); + nvScreenPtr screen; gboolean update = FALSE; - nvGpuPtr gpu; - int num_screens; - - - if (!display) return; - - - /* Don't allow disabling the last display device */ - num_screens = 0; - for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { - num_screens += gpu->num_screens; - } - if (num_screens == 1 && display->screen && - display->screen->num_displays == 1) { - gtk_widget_set_sensitive(ctk_object->rad_display_config_disabled, - FALSE); - } else { - gtk_widget_set_sensitive(ctk_object->rad_display_config_disabled, - TRUE); - } - - - /* We can only enable as many X screens as the GPU supports */ - if (!display->screen && - (display->gpu->num_screens >= display->gpu->max_displays)) { - gtk_widget_set_sensitive(ctk_object->rad_display_config_xscreen, - FALSE); - } else { - gtk_widget_set_sensitive(ctk_object->rad_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. - */ - if (display->gpu->num_displays == 1 || !display->gpu->num_screens || - display->gpu->screens->sli || - (display->gpu->num_screens == 1 && - display->gpu->screens->num_displays == 1 && - display->screen == display->gpu->screens)) { - gtk_widget_set_sensitive(ctk_object->rad_display_config_twinview, - FALSE); - } else { - gtk_widget_set_sensitive(ctk_object->rad_display_config_twinview, - TRUE); - } - - - /* Setup the button state */ - if (!display->screen) { - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_disabled), - TRUE); - gtk_button_set_label - (GTK_BUTTON(ctk_object->rad_display_config_disabled), - "Disabled"); - gtk_button_set_label - (GTK_BUTTON(ctk_object->rad_display_config_xscreen), - "Separate X screen (requires X restart)"); - gtk_button_set_label - (GTK_BUTTON(ctk_object->rad_display_config_twinview), - "TwinView"); - - } else if (display->screen->num_displays > 1) { - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_twinview), - TRUE); - gtk_button_set_label - (GTK_BUTTON(ctk_object->rad_display_config_disabled), - "Disabled"); - gtk_button_set_label - (GTK_BUTTON(ctk_object->rad_display_config_xscreen), - "Separate X screen (requires X restart)"); - gtk_button_set_label - (GTK_BUTTON(ctk_object->rad_display_config_twinview), - "TwinView"); - - } else { - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_xscreen), - TRUE); - gtk_button_set_label - (GTK_BUTTON(ctk_object->rad_display_config_disabled), - "Disabled (requires X restart)"); - gtk_button_set_label - (GTK_BUTTON(ctk_object->rad_display_config_xscreen), - "Separate X screen"); - gtk_button_set_label - (GTK_BUTTON(ctk_object->rad_display_config_twinview), - "TwinView (requires X restart)"); - } - + gint position_idx; - /* Show the display config dialog */ - gtk_window_set_transient_for - (GTK_WINDOW(ctk_object->dlg_display_config), - GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(ctk_object)))); - gtk_widget_show_all(ctk_object->dlg_display_config); - gtk_widget_grab_focus(ctk_object->btn_display_config_cancel); - result = gtk_dialog_run(GTK_DIALOG(ctk_object->dlg_display_config)); - gtk_widget_hide(ctk_object->dlg_display_config); - - switch (result) - { - case GTK_RESPONSE_ACCEPT: - /* OK */ - break; - - case GTK_RESPONSE_CANCEL: - default: - /* Cancel */ + if (!display) { return; } + position_idx = gtk_option_menu_get_history(GTK_OPTION_MENU( + ctk_object->mnu_display_config)); - - if (gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_disabled))) { + /* Disabled was selected. */ + if (position_idx == DPY_CFG_DISABLED) { if (display->screen) { do_disable_display(ctk_object, display); update = TRUE; @@ -5061,15 +4929,14 @@ static void display_config_clicked(GtkWidget *widget, gpointer user_data) if (!display->screen) { /* Enable display as a separate X screen */ - if (gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_xscreen))) { + 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 (gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_twinview))) { + if (position_idx == DPY_CFG_TWINVIEW) { do_enable_display_for_twinview(ctk_object, display); update = TRUE; } @@ -5078,16 +4945,14 @@ static void display_config_clicked(GtkWidget *widget, gpointer user_data) /* Move display to a new X screen */ if (display->screen->num_displays > 1 && - gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_xscreen))) { + 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 && - gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_twinview))) { + position_idx == DPY_CFG_TWINVIEW) { do_configure_display_for_twinview(ctk_object, display); update = TRUE; } @@ -5109,13 +4974,11 @@ static void display_config_clicked(GtkWidget *widget, gpointer user_data) ctk_display_layout_update(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); /* Auto fix all screens on the gpu */ - { - nvGpuPtr gpu = display->gpu; - nvScreenPtr screen; - - for (screen = gpu->screens; screen; screen = screen->next) { - validation_auto_fix_screen(ctk_object, screen); - } + for (screen = layout->screens; + screen; + screen = screen->next_in_layout) { + if (screen->gpu != display->gpu) continue; + validation_auto_fix_screen(ctk_object, screen); } /* Redraw */ @@ -5129,7 +4992,7 @@ static void display_config_clicked(GtkWidget *widget, gpointer user_data) user_changed_attributes(ctk_object); } -} /* display_config_clicked() */ +} /* display_config_changed() */ @@ -5367,7 +5230,7 @@ static void display_position_relative_changed(GtkWidget *widget, /* Get the new display to be relative to */ position_idx = gtk_option_menu_get_history - (GTK_OPTION_MENU(ctk_object->mnu_display_position_type)); + (GTK_OPTION_MENU(ctk_object->mnu_display_position_type)); position_type = __position_table[position_idx]; @@ -6493,7 +6356,7 @@ static int update_screen_metamodes(CtkDisplayConfig *ctk_object, static void apply_clicked(GtkWidget *widget, gpointer user_data) { CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data); - nvGpuPtr gpu; + nvScreenPtr screen; ReturnStatus ret; gboolean clear_apply = TRUE; @@ -6511,58 +6374,55 @@ static void apply_clicked(GtkWidget *widget, gpointer user_data) /* Temporarily unregister events */ unregister_layout_events(ctk_object); - /* Update all GPUs */ - for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { - nvScreenPtr screen; + /* Update all X screens */ + for (screen = ctk_object->layout->screens; + screen; + screen = screen->next_in_layout) { - /* Update all X screens */ - for (screen = gpu->screens; screen; screen = screen->next) { + if (!screen->handle) continue; + if (screen->no_scanout) continue; - if (!screen->handle) continue; - if (screen->no_scanout) continue; + if (!update_screen_metamodes(ctk_object, screen)) { + clear_apply = FALSE; + } else { + ReturnStatus ret; - if (!update_screen_metamodes(ctk_object, screen)) { - clear_apply = FALSE; - } else { - ReturnStatus ret; + ret = NvCtrlSetDisplayAttributeWithReply + (screen->handle, 0, + NV_CTRL_ASSOCIATED_DISPLAY_DEVICES, + screen->displays_mask); - ret = NvCtrlSetDisplayAttributeWithReply - (screen->handle, 0, - NV_CTRL_ASSOCIATED_DISPLAY_DEVICES, - screen->displays_mask); - - if (ret != NvCtrlSuccess) { - nv_error_msg("Failed to set screen %d's association mask " - "to: 0x%08x", - screen->scrnum, screen->displays_mask); - } else { - /* Make sure other parts of nvidia-settings get updated */ - ctk_event_emit(screen->ctk_event, 0, - NV_CTRL_ASSOCIATED_DISPLAY_DEVICES, - screen->displays_mask); - } + if (ret != NvCtrlSuccess) { + nv_error_msg("Failed to set screen %d's association mask " + "to: 0x%08x", + screen->scrnum, screen->displays_mask); + } else { + /* Make sure other parts of nvidia-settings get updated */ + ctk_event_emit(screen->ctk_event, 0, + NV_CTRL_ASSOCIATED_DISPLAY_DEVICES, + screen->displays_mask); } - - if (screen->primaryDisplay && ctk_object->primary_display_changed) { - gchar *primary_str = - display_get_type_str(screen->primaryDisplay->device_mask, - 0); - - ret = NvCtrlSetStringAttribute(screen->handle, - NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER, - primary_str, NULL); - g_free(primary_str); - - if (ret != NvCtrlSuccess) { - nv_error_msg("Failed to set primary display" - "for screen %d (GPU:%s)", screen->scrnum, - screen->gpu->name); - } else { - /* Make sure other parts of nvidia-settings get updated */ - ctk_event_emit_string(screen->ctk_event, 0, - NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER); - ctk_object->primary_display_changed = FALSE; - } + } + + if (screen->primaryDisplay && ctk_object->primary_display_changed) { + gchar *primary_str = + display_get_type_str(screen->primaryDisplay->device_mask, + 0); + + ret = NvCtrlSetStringAttribute(screen->handle, + NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER, + primary_str, NULL); + g_free(primary_str); + + if (ret != NvCtrlSuccess) { + nv_error_msg("Failed to set primary display" + "for screen %d (GPU:%s)", screen->scrnum, + screen->gpu->name); + } else { + /* Make sure other parts of nvidia-settings get updated */ + ctk_event_emit_string(screen->ctk_event, 0, + NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER); + ctk_object->primary_display_changed = FALSE; } } } @@ -6959,18 +6819,15 @@ static int add_screen_to_xconfig(CtkDisplayConfig *ctk_object, /* Configure screen for scanout */ /* Find the first display on the screen */ - for (display = screen->gpu->displays; display; display = display->next) { - if (display->screen == screen) { - break; - } - } + display = screen->displays;; + if (!display) { nv_error_msg("Unable to find a display device for screen %d!", screen->scrnum); goto fail; } - + /* Create the screen's only Monitor section from the first display */ if (!add_monitor_to_xconfig(display, config, screen->scrnum)) { nv_error_msg("Failed to add display device '%s' to screen %d!", @@ -6986,24 +6843,22 @@ static int add_screen_to_xconfig(CtkDisplayConfig *ctk_object, /* Add the modelines of all other connected displays to the monitor */ - for (other = screen->gpu->displays; other; other = other->next) { - if (other->screen != screen) continue; - if (other == display) continue; - - /* Add modelines used by this display */ + for (other = display->next_in_screen; + other; + other = other->next_in_screen) { add_modelines_to_monitor(display->conf_monitor, other->modes); } /* Set the TwinView option */ xconfigAddNewOption(&conf_screen->options, "TwinView", ((screen->num_displays > 1) ? "1" : "0" )); - + /* Set the TwinviewXineramaInfoOrder option */ - + if (screen->primaryDisplay) { gchar *primary_str = display_get_type_str(screen->primaryDisplay->device_mask, 0); - + xconfigAddNewOption(&conf_screen->options, "TwinViewXineramaInfoOrder", primary_str); g_free(primary_str); @@ -7070,34 +6925,40 @@ static int add_screen_to_xconfig(CtkDisplayConfig *ctk_object, */ static int get_device_screen_id(nvGpuPtr gpu, nvScreenPtr screen) { + nvLayoutPtr layout = gpu->layout; nvScreenPtr other; int device_screen_id; + int num_screens_on_gpu; /* Go through the GPU's screens and figure out what the * GPU-relative screen number should be for the given * screen's device section. + * + * This is done by counting the number of screens that + * have a screen number that is lower than the given + * screen, and that's the relative position of this + * screen wrt the GPU. */ - /* If there is one screen, the device section shouldn't - * specify a "Screen #" - */ - - if (gpu->num_screens < 2) return -1; + device_screen_id = 0; + num_screens_on_gpu = 0; + for (other = layout->screens; other; other = other->next_in_layout) { + if (other->gpu != gpu) continue; + num_screens_on_gpu++; - /* Count the number of screens that have a screen number - * that is lower than the given screen, and that's the - * relative position of this screen wrt the GPU. - */ - - device_screen_id = 0; - for (other = gpu->screens; other; other = other->next) { if (other == screen) continue; + if (screen->scrnum > other->scrnum) { device_screen_id++; } } + /* If there is only one screen on the GPU, the device + * section shouldn't specify a "Screen #" + */ + if (num_screens_on_gpu < 2) return -1; + return device_screen_id; } /* get_device_screen_id() */ @@ -7112,7 +6973,6 @@ static int get_device_screen_id(nvGpuPtr gpu, nvScreenPtr screen) static int add_screens_to_xconfig(CtkDisplayConfig *ctk_object, nvLayoutPtr layout, XConfigPtr config) { - nvGpuPtr gpu; nvScreenPtr screen; int device_screen_id; int print_bus_ids; @@ -7127,8 +6987,8 @@ static int add_screens_to_xconfig(CtkDisplayConfig *ctk_object, /* Don't print the bus ID in the case where we have a single * GPU driving a single X screen */ - if (layout->num_gpus == 1 && - layout->gpus->num_screens == 1) { + if ((layout->num_gpus == 1) && + (layout->num_screens == 1)) { print_bus_ids = 0; } else { print_bus_ids = 1; @@ -7136,37 +6996,35 @@ static int add_screens_to_xconfig(CtkDisplayConfig *ctk_object, /* Generate the Device sections and Screen sections */ - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - - for (screen = gpu->screens; screen; screen = screen->next) { + for (screen = layout->screens; screen; screen = screen->next_in_layout) { + nvGpuPtr gpu = screen->gpu; - /* Figure out what screen number to use for the device section. */ - device_screen_id = get_device_screen_id(gpu, screen); + /* Figure out what screen number to use for the device section. */ + device_screen_id = get_device_screen_id(gpu, screen); - /* Each screen needs a unique device section - * - * Note that the device id used to name the - * device section is the same as the screen - * number such that the name of the two sections - * match. - */ - screen->conf_device = add_device_to_xconfig(gpu, config, - screen->scrnum, - device_screen_id, - print_bus_ids); - if (!screen->conf_device) { - nv_error_msg("Failed to add device '%s' to X config.", - gpu->name); - goto fail; - } + /* Each screen needs a unique device section + * + * Note that the device id used to name the + * device section is the same as the screen + * number such that the name of the two sections + * match. + */ + screen->conf_device = add_device_to_xconfig(gpu, config, + screen->scrnum, + device_screen_id, + print_bus_ids); + if (!screen->conf_device) { + nv_error_msg("Failed to add device '%s' to X config.", + gpu->name); + goto fail; + } - ret = add_screen_to_xconfig(ctk_object, screen, config); - if (ret == XCONFIG_GEN_ERROR) { - nv_error_msg("Failed to add X screen %d to X config.", - screen->scrnum); - } - if (ret != XCONFIG_GEN_OK) goto bail; + ret = add_screen_to_xconfig(ctk_object, screen, config); + if (ret == XCONFIG_GEN_ERROR) { + nv_error_msg("Failed to add X screen %d to X config.", + screen->scrnum); } + if (ret != XCONFIG_GEN_OK) goto bail; } return XCONFIG_GEN_OK; @@ -7235,7 +7093,6 @@ static Bool add_adjacency_to_xconfig(nvScreenPtr screen, XConfigPtr config) static Bool add_layout_to_xconfig(nvLayoutPtr layout, XConfigPtr config) { XConfigLayoutPtr conf_layout; - nvGpuPtr gpu; nvScreenPtr screen; int scrnum; @@ -7251,20 +7108,21 @@ static Bool add_layout_to_xconfig(nvLayoutPtr layout, XConfigPtr config) /* Clean up the adjacencies */ xconfigFreeAdjacencyList(&conf_layout->adjacencies); - + /* Assign the adjacencies (in order) */ scrnum = 0; do { + /* Find the next screen to write */ screen = NULL; - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - for (screen = gpu->screens; screen; screen = screen->next) { - if (screen->scrnum == scrnum) break; - } - if (screen) { - if (!add_adjacency_to_xconfig(screen, config)) goto fail; - break; - } + for (screen = layout->screens; + screen; + screen = screen->next_in_layout) { + if (screen->scrnum == scrnum) break; + } + if (screen) { + if (!add_adjacency_to_xconfig(screen, config)) goto fail; } + scrnum++; } while (screen); @@ -7478,6 +7336,7 @@ static void probe_clicked(GtkWidget *widget, gpointer user_data) CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data); unsigned int probed_displays; unsigned int mask; + nvLayoutPtr layout = ctk_object->layout; nvGpuPtr gpu; nvDisplayPtr display; nvDisplayPtr selected_display = ctk_display_layout_get_selected_display @@ -7487,7 +7346,7 @@ static void probe_clicked(GtkWidget *widget, gpointer user_data) gchar *str; /* Probe each GPU for display changes */ - for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { if (!gpu->handle) continue; diff --git a/src/gtk+-2.x/ctkdisplayconfig.h b/src/gtk+-2.x/ctkdisplayconfig.h index 03919ca..c6f88fc 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.h +++ b/src/gtk+-2.x/ctkdisplayconfig.h @@ -83,9 +83,12 @@ typedef struct _CtkDisplayConfig int display_model_table_len; GtkWidget *txt_display_gpu; - GtkWidget *btn_display_config; - GtkWidget *txt_display_config; - + GtkWidget *box_display_config; + GtkWidget *mnu_display_config; + GtkWidget *mnu_display_config_disabled; + GtkWidget *mnu_display_config_xscreen; + GtkWidget *mnu_display_config_twinview; + /* Display - Settings */ GtkWidget *box_display_resolution; GtkWidget *mnu_display_resolution; @@ -138,12 +141,6 @@ typedef struct _CtkDisplayConfig int screen_depth_table_len; /* Dialogs */ - GtkWidget *dlg_display_config; - GtkWidget *rad_display_config_disabled; - GtkWidget *rad_display_config_xscreen; - GtkWidget *rad_display_config_twinview; - GtkWidget *btn_display_config_cancel; - GtkWidget *dlg_display_disable; GtkWidget *txt_display_disable; GtkWidget *btn_display_disable_off; diff --git a/src/gtk+-2.x/ctkdisplaylayout.c b/src/gtk+-2.x/ctkdisplaylayout.c index c116b59..010a559 100644 --- a/src/gtk+-2.x/ctkdisplaylayout.c +++ b/src/gtk+-2.x/ctkdisplaylayout.c @@ -170,7 +170,7 @@ static void zorder_layout(CtkDisplayLayout *ctk_object) nvGpuPtr gpu; nvScreenPtr screen; nvDisplayPtr display; - int i; + int z; /* Clean up */ @@ -183,8 +183,9 @@ static void zorder_layout(CtkDisplayLayout *ctk_object) /* Count the number of Z-orderable elements in the layout */ - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - ctk_object->Zcount += gpu->num_displays + gpu->num_screens; + ctk_object->Zcount = layout->num_screens; + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + ctk_object->Zcount += gpu->num_displays; } @@ -203,31 +204,35 @@ static void zorder_layout(CtkDisplayLayout *ctk_object) /* Populate the Z-order list */ - i = 0; - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - // Add screens - for (screen = gpu->screens; screen; screen = screen->next) { - // Add displays that belong to the screen - for (display = gpu->displays; display; display = display->next) { - if (display->screen == screen) { - ctk_object->Zorder[i].type = ZNODE_TYPE_DISPLAY; - ctk_object->Zorder[i].u.display = display; - i++; - } - } + z = 0; + + /* Add screens */ + for (screen = layout->screens; screen; screen = screen->next_in_layout) { - // Add the screen - ctk_object->Zorder[i].type = ZNODE_TYPE_SCREEN; - ctk_object->Zorder[i].u.screen = screen; - i++; + /* Add displays that belong to the screen */ + for (display = screen->displays; + display; + display = display->next_in_screen) { + ctk_object->Zorder[z].type = ZNODE_TYPE_DISPLAY; + ctk_object->Zorder[z].u.display = display; + z++; } - // Add displays that don't have screens. - for (display = gpu->displays; display; display = display->next) { - if (!display->screen) { - ctk_object->Zorder[i].type = ZNODE_TYPE_DISPLAY; - ctk_object->Zorder[i].u.display = display; - i++; - } + + /* Add the screen */ + ctk_object->Zorder[z].type = ZNODE_TYPE_SCREEN; + ctk_object->Zorder[z].u.screen = screen; + z++; + } + + /* Add displays that don't have screens */ + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + for (display = gpu->displays; + display; + display = display->next_on_gpu) { + if (display->screen) continue; + ctk_object->Zorder[z].type = ZNODE_TYPE_DISPLAY; + ctk_object->Zorder[z].u.display = display; + z++; } } @@ -378,9 +383,9 @@ static Bool get_modify_info(CtkDisplayLayout *ctk_object) * relative positioning. */ use_screen_instead = TRUE; - for (display = info->display->gpu->displays; display; - display = display->next) { - if (display->screen != info->screen) continue; + for (display = info->display->screen->displays; + display; + display = display->next_in_screen) { if (display == info->display) continue; if (!display->cur_mode) continue; if (display->cur_mode->position_type == CONF_ADJ_ABSOLUTE) { @@ -588,15 +593,16 @@ static void offset_layout(nvLayoutPtr layout, int x, int y) layout->dim[X] += x; layout->dim[Y] += y; - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - - /* Offset screens */ - for (screen = gpu->screens; screen; screen = screen->next) { - offset_screen(screen, x, y); - } + /* Offset screens */ + for (screen = layout->screens; screen; screen = screen->next_in_layout) { + offset_screen(screen, x, y); + } - /* Offset displays */ - for (display = gpu->displays; display; display = display->next) { + /* Offset displays */ + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + for (display = gpu->displays; + display; + display = display->next_on_gpu) { offset_display(display, x, y); } } @@ -700,9 +706,9 @@ static void resolve_displays_in_screen(nvScreenPtr screen, } /* Resolve the current mode of each display in the screen */ - for (display = screen->gpu->displays; display; display = display->next) { - - if (display->screen != screen) continue; + for (display = screen->displays; + display; + display = display->next_in_screen) { for (mode_idx = first_idx; mode_idx <= last_idx; mode_idx++) { if (resolve_display(display, mode_idx, pos)) { @@ -808,24 +814,21 @@ static void resolve_screen_in_layout(nvScreenPtr screen) int x, y; int *sdim; - + /* Resolve the current screen location */ if (resolve_screen(screen, pos)) { /* Move the screen and the displays by offsetting */ sdim = get_screen_dim(screen, 0); - + x = pos[X] - sdim[X]; y = pos[Y] - sdim[Y]; offset_screen(screen, x, y); - for (display = screen->gpu->displays; + for (display = screen->displays; display; - display = display->next) { - - if (display->screen != screen) continue; - + display = display->next_in_screen) { offset_mode(display->cur_mode, x, y); } } @@ -843,23 +846,18 @@ static void resolve_screen_in_layout(nvScreenPtr screen) static void resolve_layout(nvLayoutPtr layout) { - nvGpuPtr gpu; nvScreenPtr screen; /* First, resolve TwinView relationships */ - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - for (screen = gpu->screens; screen; screen = screen->next) { - resolve_displays_in_screen(screen, 0); - } + for (screen = layout->screens; screen; screen = screen->next_in_layout) { + resolve_displays_in_screen(screen, 0); } /* Next, resolve X screen relationships */ - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - for (screen = gpu->screens; screen; screen = screen->next) { - resolve_screen_in_layout(screen); - } + for (screen = layout->screens; screen; screen = screen->next_in_layout) { + resolve_screen_in_layout(screen); } - + } /* resolve_layout() */ @@ -896,9 +894,9 @@ static void calc_metamode(nvScreenPtr screen, nvMetaModePtr metamode) dim[H] = edim[H] = 0; /* Calculate its dimensions */ - for (display = screen->gpu->displays; display; display = display->next) { - - if (display->screen != screen) continue; + for (display = screen->displays; + display; + display = display->next_in_screen) { /* Get the display's mode that is part of the metamode. */ for (mode = display->modes; mode; mode = mode->next) { @@ -1001,12 +999,11 @@ static void calc_screen(nvScreenPtr screen) /** calc_layout() **************************************************** * * Calculates the dimensions (width & height) of the layout. This is - * the smallest bounding box that holds all the gpu's X screen's - * display device's (current) modes in the layout. (Bounding box of - * all the current metamodes of all X screens.) - * - * As a side effect, all other screen/metamode dimensions are - * calculated. + * the smallest bounding box that holds all the metamodes of all X + * screens as well as dummy modes for disabled displays. + + * As a side effect, the dimensions of all metamodes for all X + * screens are (re)calculated. * **/ @@ -1030,28 +1027,25 @@ static void calc_layout(nvLayoutPtr layout) dim[W] = 0; dim[H] = 0; - for (gpu = layout->gpus; gpu; gpu = gpu->next) { + for (screen = layout->screens; screen; screen = screen->next_in_layout) { + int *sdim; - for (screen = gpu->screens; screen; screen = screen->next) { - int *sdim; - - calc_screen(screen); - sdim = get_screen_dim(screen, 0); - - if (init) { - dim[X] = sdim[X]; - dim[Y] = sdim[Y]; - dim[W] = sdim[X] +sdim[W]; - dim[H] = sdim[Y] +sdim[H]; - init = 0; - continue; - } - - dim[X] = MIN(dim[X], sdim[X]); - dim[Y] = MIN(dim[Y], sdim[Y]); - dim[W] = MAX(dim[W], sdim[X] +sdim[W]); - dim[H] = MAX(dim[H], sdim[Y] +sdim[H]); + calc_screen(screen); + sdim = get_screen_dim(screen, 0); + + if (init) { + dim[X] = sdim[X]; + dim[Y] = sdim[Y]; + dim[W] = sdim[X] +sdim[W]; + dim[H] = sdim[Y] +sdim[H]; + init = 0; + continue; } + + dim[X] = MIN(dim[X], sdim[X]); + dim[Y] = MIN(dim[Y], sdim[Y]); + dim[W] = MAX(dim[W], sdim[X] +sdim[W]); + dim[H] = MAX(dim[H], sdim[Y] +sdim[H]); } dim[W] = dim[W] - dim[X]; @@ -1061,8 +1055,10 @@ static void calc_layout(nvLayoutPtr layout) /* Position disabled display devices off to the top right */ x = dim[W] + dim[X]; y = dim[Y]; - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - for (display = gpu->displays; display; display = display->next) { + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + for (display = gpu->displays; + display; + display = display->next_on_gpu) { if (display->screen) continue; display->cur_mode->dim[X] = x; @@ -1092,10 +1088,10 @@ static void recenter_screen(nvScreenPtr screen) { nvDisplayPtr display; - for (display = screen->gpu->displays; display; display = display->next) { + for (display = screen->displays; + display; + display = display->next_in_screen) { nvModePtr mode; - - if (display->screen != screen) continue; for (mode = display->modes; mode; mode = mode->next) { int offset_x = (screen->dim[X] - mode->metamode->dim[X]); @@ -1103,7 +1099,7 @@ static void recenter_screen(nvScreenPtr screen) offset_mode(mode, offset_x, offset_y); } } - + /* Recalculate the screen's dimensions */ calc_screen(screen); @@ -1129,10 +1125,9 @@ static void set_screen_metamode(nvLayoutPtr layout, nvScreenPtr screen, screen->cur_metamode = get_metamode(screen, new_metamode_idx); /* Make each display within the screen point to the new mode */ - for (display = screen->gpu->displays; display; display = display->next) { - - if (display->screen != screen) continue; /* Display not in screen */ - + for (display = screen->displays; + display; + display = display->next_in_screen) { display->cur_mode = get_mode(display, new_metamode_idx); } @@ -1154,28 +1149,24 @@ static void set_screen_metamode(nvLayoutPtr layout, nvScreenPtr screen, static void recenter_layout(nvLayoutPtr layout) { - nvGpuPtr gpu; nvScreenPtr screen; int real_metamode_idx; int metamode_idx; - - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - for (screen = gpu->screens; screen; screen = screen->next) { - - real_metamode_idx = screen->cur_metamode_idx; + for (screen = layout->screens; screen; screen = screen->next_in_layout) { - for (metamode_idx = 0; - metamode_idx < screen->num_metamodes; - metamode_idx++) { - - if (metamode_idx == real_metamode_idx) continue; + real_metamode_idx = screen->cur_metamode_idx; - set_screen_metamode(layout, screen, metamode_idx); - } + for (metamode_idx = 0; + metamode_idx < screen->num_metamodes; + metamode_idx++) { + + if (metamode_idx == real_metamode_idx) continue; - set_screen_metamode(layout, screen, real_metamode_idx); + set_screen_metamode(layout, screen, metamode_idx); } + + set_screen_metamode(layout, screen, real_metamode_idx); } } /* recenter_layout() */ @@ -1425,7 +1416,7 @@ static void snap_move(CtkDisplayLayout *ctk_object) int *bh; int i; int dist; - nvGpuPtr gpu; + nvLayoutPtr layout = ctk_object->layout; nvScreenPtr screen; nvDisplayPtr other; int *sdim; @@ -1500,69 +1491,68 @@ static void snap_move(CtkDisplayLayout *ctk_object) } /* Done snapping to other displays */ - /* Snap to other screen dimensions */ - for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { - for (screen = gpu->screens; screen; screen = screen->next) { - if (screen == info->screen) continue; + /* Snap to dimensions of other X screens */ + for (screen = layout->screens; screen; screen = screen->next_in_layout) { - /* NOTE: When the (display devices's) screens are relative to - * each other, we may still want to allow snapping of the - * non-related edges. This is useful, for example, when - * two screens have a right of/left of relationtship and - * one of them is taller. - */ + if (screen == info->screen) continue; - bv = &info->best_snap_v; - bh = &info->best_snap_h; + /* NOTE: When the (display devices's) screens are relative to + * each other, we may still want to allow snapping of the + * non-related edges. This is useful, for example, when + * two screens have a right of/left of relationtship and + * one of them is taller. + */ - if (((screen->position_type == CONF_ADJ_RIGHTOF) || - (screen->position_type == CONF_ADJ_LEFTOF)) && - (screen->relative_to == info->screen)) { - bh = NULL; - } - if (((info->screen->position_type == CONF_ADJ_RIGHTOF) || - (info->screen->position_type == CONF_ADJ_LEFTOF)) && - (info->screen->relative_to == screen)) { - bh = NULL; - } + bv = &info->best_snap_v; + bh = &info->best_snap_h; - /* If we aren't snapping horizontally with the other screen, - * we shouldn't snap vertically either if we are moving the - * top-most display in the screen. - */ - if (!bh && - info->display && - info->display->cur_mode->dim[Y] == info->screen->dim[Y]) { - bv = NULL; - } - - if (((screen->position_type == CONF_ADJ_ABOVE) || - (screen->position_type == CONF_ADJ_BELOW)) && - (screen->relative_to == info->screen)) { - bv = NULL; - } - if (((info->screen->position_type == CONF_ADJ_ABOVE) || - (info->screen->position_type == CONF_ADJ_BELOW)) && - (info->screen->relative_to == screen)) { - bv = NULL; - } + if (((screen->position_type == CONF_ADJ_RIGHTOF) || + (screen->position_type == CONF_ADJ_LEFTOF)) && + (screen->relative_to == info->screen)) { + bh = NULL; + } + if (((info->screen->position_type == CONF_ADJ_RIGHTOF) || + (info->screen->position_type == CONF_ADJ_LEFTOF)) && + (info->screen->relative_to == screen)) { + bh = NULL; + } - /* If we aren't snapping vertically with the other screen, - * we shouldn't snap horizontally either if this is the - * left-most display in the screen. - */ - if (!bv && - info->display && - info->display->cur_mode->dim[X] == info->screen->dim[X]) { - bh = NULL; - } + /* If we aren't snapping horizontally with the other screen, + * we shouldn't snap vertically either if we are moving the + * top-most display in the screen. + */ + if (!bh && + info->display && + info->display->cur_mode->dim[Y] == info->screen->dim[Y]) { + bv = NULL; + } - sdim = get_screen_dim(screen, 0); - snap_dim_to_dim(info->dst_dim, - info->src_dim, - sdim, - ctk_object->snap_strength, bv, bh); + if (((screen->position_type == CONF_ADJ_ABOVE) || + (screen->position_type == CONF_ADJ_BELOW)) && + (screen->relative_to == info->screen)) { + bv = NULL; } + if (((info->screen->position_type == CONF_ADJ_ABOVE) || + (info->screen->position_type == CONF_ADJ_BELOW)) && + (info->screen->relative_to == screen)) { + bv = NULL; + } + + /* If we aren't snapping vertically with the other screen, + * we shouldn't snap horizontally either if this is the + * left-most display in the screen. + */ + if (!bv && + info->display && + info->display->cur_mode->dim[X] == info->screen->dim[X]) { + bh = NULL; + } + + sdim = get_screen_dim(screen, 0); + snap_dim_to_dim(info->dst_dim, + info->src_dim, + sdim, + ctk_object->snap_strength, bv, bh); } /* Snap to the maximum screen dimensions */ @@ -1610,7 +1600,7 @@ static void snap_pan(CtkDisplayLayout *ctk_object) int *bh; int i; int dist; - nvGpuPtr gpu; + nvLayoutPtr layout = ctk_object->layout; nvScreenPtr screen; nvDisplayPtr other; int *sdim; @@ -1729,46 +1719,45 @@ static void snap_pan(CtkDisplayLayout *ctk_object) } - /* Snap to other screen dimensions */ - for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { - for (screen = gpu->screens; screen; screen = screen->next) { - if (screen == info->screen) continue; + /* Snap to dimensions of other X screens */ + for (screen = layout->screens; screen; screen = screen->next_in_layout) { - bv = &info->best_snap_v; - bh = &info->best_snap_h; + if (screen == info->screen) continue; - /* Don't snap horizontally to other screens that are somehow - * related on the right edge of the (display's) screen being - * panned. - */ - if ((screen->position_type == CONF_ADJ_RIGHTOF) && - (screen->relative_to == info->screen)) { - bh = NULL; - } - if ((info->screen->position_type == CONF_ADJ_LEFTOF) && - (info->screen->relative_to == screen)) { - bh = NULL; - } + bv = &info->best_snap_v; + bh = &info->best_snap_h; - /* Don't snap vertically to other screens that are somehow - * related on the bottom edge of the (display's) screen being - * panned. - */ - if ((screen->position_type == CONF_ADJ_BELOW) && - (screen->relative_to == info->screen)) { - bv = NULL; - } - if ((info->screen->position_type == CONF_ADJ_ABOVE) && - (info->screen->relative_to == screen)) { - bv = NULL; - } + /* Don't snap horizontally to other screens that are somehow + * related on the right edge of the (display's) screen being + * panned. + */ + if ((screen->position_type == CONF_ADJ_RIGHTOF) && + (screen->relative_to == info->screen)) { + bh = NULL; + } + if ((info->screen->position_type == CONF_ADJ_LEFTOF) && + (info->screen->relative_to == screen)) { + bh = NULL; + } - sdim = get_screen_dim(screen, 0); - snap_side_to_dim(info->dst_dim, - info->src_dim, - sdim, - bv, bh); + /* Don't snap vertically to other screens that are somehow + * related on the bottom edge of the (display's) screen being + * panned. + */ + if ((screen->position_type == CONF_ADJ_BELOW) && + (screen->relative_to == info->screen)) { + bv = NULL; + } + if ((info->screen->position_type == CONF_ADJ_ABOVE) && + (info->screen->relative_to == screen)) { + bv = NULL; } + + sdim = get_screen_dim(screen, 0); + snap_side_to_dim(info->dst_dim, + info->src_dim, + sdim, + bv, bh); } bh = &(info->best_snap_h); @@ -1962,9 +1951,9 @@ static int move_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap) /* Offset the screen and all its displays */ offset_screen(info->screen, x, y); - for (display = info->gpu->displays; display; - display = display->next) { - if (display->screen != info->screen) continue; + for (display = info->screen->displays; + display; + display = display->next_in_screen) { offset_display(display, x, y); } @@ -1991,23 +1980,22 @@ static int move_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap) calc_metamode(info->screen, info->screen->cur_metamode); x = info->screen->cur_metamode->dim[X] - info->orig_screen_dim[X]; y = info->screen->cur_metamode->dim[Y] - info->orig_screen_dim[Y]; - + if (x || y) { nvDisplayPtr other; nvModePtr mode; - for (other = info->gpu->displays; other; other = other->next) { - - /* Other display must be in the same screen */ - if (other->screen != info->screen) continue; - + for (other = info->screen->displays; + other; + other = other->next_in_screen) { + for (mode = other->modes; mode; mode = mode->next) { - + /* Only move non-current modes */ if (mode == other->cur_mode) continue; - + /* Don't move modes that are relative */ if (mode->position_type != CONF_ADJ_ABSOLUTE) continue; - + offset_mode(mode, x, y); } } @@ -3239,7 +3227,7 @@ static void draw_screen(CtkDisplayLayout *ctk_object, gdk_gc_set_line_attributes(fg_gc, 1, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_ROUND); - /* Show the name of the scree if no-scanout is selected */ + /* Show the name of the screen if no-scanout is selected */ if (screen->no_scanout) { tmp_str = g_strdup_printf("X Screen %d", screen->scrnum); @@ -3656,11 +3644,11 @@ void ctk_display_layout_add_screen_metamode(CtkDisplayLayout *ctk_object, /* Add a mode to each display */ - for (display = screen->gpu->displays; display; display = display->next) { + for (display = screen->displays; + display; + display = display->next_in_screen) { nvModePtr mode; - if (display->screen != screen) continue; /* Display not in screen */ - /* Create the mode */ mode = (nvModePtr)calloc(1, sizeof(nvMode)); if (!mode) goto fail; @@ -3768,10 +3756,10 @@ void ctk_display_layout_delete_screen_metamode(CtkDisplayLayout *ctk_object, /* Delete the mode from each display in the screen */ - for (display = screen->gpu->displays; display; display = display->next) { + for (display = screen->displays; + display; + display = display->next_in_screen) { - if (display->screen != screen) continue; - /* Find the mode */ mode_prev = NULL; mode = display->modes; @@ -3779,7 +3767,7 @@ void ctk_display_layout_delete_screen_metamode(CtkDisplayLayout *ctk_object, mode_prev = mode; mode = mode->next; } - + /* Remove the mode from the list */ if (!mode_prev) { display->modes = display->modes->next; @@ -3823,7 +3811,7 @@ void ctk_display_layout_disable_display(CtkDisplayLayout *ctk_object, /* If the screen is empty, remove it */ if (!screen->num_displays) { - gpu_remove_and_free_screen(screen); + layout_remove_and_free_screen(screen); /* Unselect the screen if it was selected */ if (screen == ctk_object->first_selected_screen) { @@ -3838,7 +3826,7 @@ void ctk_display_layout_disable_display(CtkDisplayLayout *ctk_object, } /* Add the fake mode to the display */ - gpu_add_screenless_modes_to_displays(display->gpu); + gpu_add_screenless_modes_to_displays(display->gpu); } /* ctk_display_layout_disable_display() */ @@ -3955,9 +3943,9 @@ void ctk_display_layout_set_display_position(CtkDisplayLayout *ctk_object, nvDisplayPtr other; nvModePtr mode; - for (other = display->gpu->displays; other; other = other->next) { - - if (other->screen != display->screen) continue; + for (other = display->screen->displays; + other; + other = other->next_in_screen) { if (!resolve_all_modes) { mode = other->cur_mode; @@ -4225,7 +4213,6 @@ void ctk_display_layout_set_screen_position(CtkDisplayLayout *ctk_object, GdkGCValues old_gc_values; int modified = 0; nvLayoutPtr layout = ctk_object->layout; - nvGpuPtr gpu; if (!screen) return; @@ -4247,15 +4234,15 @@ void ctk_display_layout_set_screen_position(CtkDisplayLayout *ctk_object, */ if (position_type != CONF_ADJ_ABSOLUTE) { - + nvScreenPtr other; - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - for (other = gpu->screens; other; other = other->next) { - if (other->relative_to == screen) { - /* Make this screen use absolute positioning */ - switch_screen_to_absolute(other); - } + for (other = layout->screens; + other; + other = other->next_in_layout) { + + if (other->relative_to == screen) { + switch_screen_to_absolute(other); } } } @@ -4275,14 +4262,15 @@ void ctk_display_layout_set_screen_position(CtkDisplayLayout *ctk_object, /* Do the move by offsetting */ offset_screen(screen, x_offset, y_offset); - for (other = screen->gpu->displays; other; other = other->next) { - if (other->screen != screen) continue; + for (other = screen->displays; + other; + other = other->next_in_screen) { offset_display(other, x_offset, y_offset); } - + /* Recalculate the layout */ ctk_display_layout_update(ctk_object); - + /* Report back result of move */ sdim = get_screen_dim(screen, 1); if (x != sdim[X] || y != sdim[Y]) { diff --git a/src/gtk+-2.x/ctkdisplaylayout.h b/src/gtk+-2.x/ctkdisplaylayout.h index 784094a..d6cae85 100644 --- a/src/gtk+-2.x/ctkdisplaylayout.h +++ b/src/gtk+-2.x/ctkdisplaylayout.h @@ -178,7 +178,8 @@ typedef struct nvModeRec { /* Display Device (CRT, DFP, TV, Projector ...) */ typedef struct nvDisplayRec { - struct nvDisplayRec *next; + struct nvDisplayRec *next_on_gpu; + struct nvDisplayRec *next_in_screen; XConfigMonitorPtr conf_monitor; struct nvGpuRec *gpu; /* GPU the display belongs to */ @@ -221,7 +222,8 @@ typedef struct nvMetaModeRec { /* X Screen */ typedef struct nvScreenRec { - struct nvScreenRec *next; + struct nvScreenRec *next_in_layout; + XConfigScreenPtr conf_screen; XConfigDevicePtr conf_device; @@ -237,11 +239,13 @@ typedef struct nvScreenRec { CtkEvent *ctk_event; int scrnum; + struct nvLayoutRec *layout; /* Layout this X screen belongs to */ struct nvGpuRec *gpu; /* GPU driving this X screen */ int depth; /* Depth of the screen */ unsigned int displays_mask; /* Display devices on this X screen */ + nvDisplayPtr displays; /* List of displays using this screen */ int num_displays; /* # of displays using this screen */ nvMetaModePtr metamodes; /* List of metamodes */ @@ -276,11 +280,11 @@ typedef struct GvoModeDataRec { /* GPU (Device) */ typedef struct nvGpuRec { - struct nvGpuRec *next; + struct nvGpuRec *next_in_layout; /* List of all GPUs */ NvCtrlAttributeHandle *handle; /* NV-CONTROL handle to GPU */ CtkEvent *ctk_event; - + struct nvLayoutRec *layout; /* Layout this GPU belongs to */ int max_width; @@ -289,7 +293,7 @@ typedef struct nvGpuRec { Bool allow_depth_30; char *name; /* Name of the GPU */ - + unsigned int connected_displays; /* Bitmask of connected displays */ gchar *pci_bus_id; @@ -297,10 +301,7 @@ typedef struct nvGpuRec { GvoModeData *gvo_mode_data; /* Information about GVO modes available */ unsigned int num_gvo_modes; - nvScreenPtr screens; /* List of screens this GPU drives */ - int num_screens; - - nvDisplayPtr displays; /* List of displays attached to screen */ + nvDisplayPtr displays; /* Linked list of displays connected to GPU */ int num_displays; } nvGpu, *nvGpuPtr; @@ -314,10 +315,13 @@ typedef struct nvLayoutRec { NvCtrlAttributeHandle *handle; - nvGpuPtr gpus; /* List of GPUs in the layout */ + nvGpuPtr gpus; /* Linked list of GPUs (next_in_layout) */ int num_gpus; - // Used for drawing the layout. + nvScreenPtr screens; /* Linked list of X screens (next_in_layout) */ + int num_screens; + + /* Used for drawing the layout */ int dim[4]; /* Bounding box of All X screens (Absolute coords) */ int xinerama_enabled; diff --git a/src/gtk+-2.x/ctkditheringcontrols.c b/src/gtk+-2.x/ctkditheringcontrols.c index 3ff91e0..473a9f4 100644 --- a/src/gtk+-2.x/ctkditheringcontrols.c +++ b/src/gtk+-2.x/ctkditheringcontrols.c @@ -384,18 +384,6 @@ GtkWidget* ctk_dithering_controls_new(NvCtrlAttributeHandle *handle, CTK_EVENT_NAME(NV_CTRL_DITHERING_DEPTH), G_CALLBACK(dithering_update_received), (gpointer) ctk_dithering_controls); - g_signal_connect(G_OBJECT(ctk_event), - CTK_EVENT_NAME(NV_CTRL_CURRENT_DITHERING), - G_CALLBACK(dithering_update_received), - (gpointer) ctk_dithering_controls); - g_signal_connect(G_OBJECT(ctk_event), - CTK_EVENT_NAME(NV_CTRL_CURRENT_DITHERING_MODE), - G_CALLBACK(dithering_update_received), - (gpointer) ctk_dithering_controls); - g_signal_connect(G_OBJECT(ctk_event), - CTK_EVENT_NAME(NV_CTRL_CURRENT_DITHERING_DEPTH), - G_CALLBACK(dithering_update_received), - (gpointer) ctk_dithering_controls); return GTK_WIDGET(object); @@ -603,6 +591,7 @@ void post_dithering_config_update(CtkDitheringControls *ctk_dithering_controls, return; } + gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE); ctk_config_statusbar_message(ctk_dithering_controls->ctk_config, "Dithering set to %s for %s.", dither_config_table[dithering_config], @@ -625,6 +614,7 @@ void post_dithering_mode_update(CtkDitheringControls *ctk_dithering_controls, return; } + gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE); ctk_config_statusbar_message(ctk_dithering_controls->ctk_config, "Dithering mode set to %s for %s.", dither_mode_table[dithering_mode], @@ -646,6 +636,7 @@ void post_dithering_depth_update(CtkDitheringControls *ctk_dithering_controls, return; } + gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE); ctk_config_statusbar_message(ctk_dithering_controls->ctk_config, "Dithering depth set to %s for %s.", dither_depth_table[dithering_depth], @@ -696,7 +687,6 @@ static void dithering_config_menu_changed(GtkOptionMenu *dithering_config_menu, /* reflecting the change in configuration to other widgets & reset button */ ctk_dithering_controls_setup(ctk_dithering_controls); post_dithering_config_update(ctk_dithering_controls, dithering_config); - gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE); } /* dithering_config_menu_changed() */ @@ -736,7 +726,6 @@ static void dithering_mode_menu_changed(GtkOptionMenu *dithering_mode_menu, /* reflecting the change in mode to other widgets & reset button */ ctk_dithering_controls_setup(ctk_dithering_controls); post_dithering_mode_update(ctk_dithering_controls, dithering_mode); - gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE); } /* dithering_mode_menu_changed() */ @@ -784,7 +773,6 @@ static void dithering_depth_menu_changed(GtkOptionMenu *dithering_depth_menu, /* reflecting the change in configuration to other widgets & reset button */ ctk_dithering_controls_setup(ctk_dithering_controls); post_dithering_depth_update(ctk_dithering_controls, dithering_depth); - gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE); } /* dithering_depth_menu_changed() */ @@ -847,6 +835,16 @@ static void dithering_update_received(GtkObject *object, gpointer arg1, } ctk_dithering_controls_setup(ctk_object); + + /* update status bar message */ + switch (event_struct->attribute) { + case NV_CTRL_DITHERING: + post_dithering_config_update(ctk_object, event_struct->value); break; + case NV_CTRL_DITHERING_MODE: + post_dithering_mode_update(ctk_object, event_struct->value); break; + case NV_CTRL_DITHERING_DEPTH: + post_dithering_depth_update(ctk_object, event_struct->value); break; + } } /* dithering_update_received() */ diff --git a/src/gtk+-2.x/ctkevent.c b/src/gtk+-2.x/ctkevent.c index c175a8c..42584cc 100644 --- a/src/gtk+-2.x/ctkevent.c +++ b/src/gtk+-2.x/ctkevent.c @@ -406,10 +406,12 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU); MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN); MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU); + MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_DISPLAY_TARGETS); + MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU); #undef MAKE_BINARY_SIGNAL - -#if NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE != NV_CTRL_BINARY_DATA_GLASSES_PAIRED_TO_3D_VISION_PRO_TRANSCEIVER + +#if NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE != NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU #warning "There are attributes that do not emit signals!" #endif diff --git a/src/gtk+-2.x/ctkimagesliders.c b/src/gtk+-2.x/ctkimagesliders.c index 5450436..10c29a2 100644 --- a/src/gtk+-2.x/ctkimagesliders.c +++ b/src/gtk+-2.x/ctkimagesliders.c @@ -260,8 +260,8 @@ static GtkWidget * add_scale(CtkConfig *ctk_config, */ static void post_scale_value_changed(GtkAdjustment *adjustment, - CtkImageSliders *ctk_image_sliders, - gint value) + CtkImageSliders *ctk_image_sliders, + gint value) { char *name = g_object_get_data(G_OBJECT(adjustment), "attribute name"); @@ -417,6 +417,12 @@ static void scale_value_received(GtkObject *object, gpointer arg1, g_object_set_data(G_OBJECT(CTK_SCALE(scale)->gtk_adjustment), "attribute active", GINT_TO_POINTER(1)); + /* In case of image sharpening slider here we are syncing to the + * recent image sharpening value, so updating status bar message */ + post_scale_value_changed(CTK_SCALE(scale)->gtk_adjustment, + ctk_image_sliders, + gtk_adjustment_get_value( + CTK_SCALE(scale)->gtk_adjustment)); } break; default: diff --git a/src/gtk+-2.x/ctkpowermizer.c b/src/gtk+-2.x/ctkpowermizer.c index 1939795..cf529c9 100644 --- a/src/gtk+-2.x/ctkpowermizer.c +++ b/src/gtk+-2.x/ctkpowermizer.c @@ -91,9 +91,7 @@ static const char *__powermizer_menu_help = "utilization. 'Prefer Maximum Performance' hints to the driver to prefer " "higher GPU clocks, when possible. If a single X server is running, the " "mode selected in nvidia-settings is what the system will be using; if two or " -"more X servers are running, the behavior is undefined. If any CUDA " -"application is running, the system will always be in the 'Prefer Maximum " -"Performance' mode."; +"more X servers are running, the behavior is undefined."; GType ctk_powermizer_get_type(void) { diff --git a/src/gtk+-2.x/ctkslimm.c b/src/gtk+-2.x/ctkslimm.c index 5c7ff84..cb3fac6 100644 --- a/src/gtk+-2.x/ctkslimm.c +++ b/src/gtk+-2.x/ctkslimm.c @@ -1149,8 +1149,8 @@ static Bool other_displays_have_modeline(nvLayoutPtr layout, nvGpuPtr gpu; nvDisplayPtr d; - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - for (d = gpu->displays; d; d = d->next) { + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + for (d = gpu->displays; d; d = d->next_on_gpu) { if (display == d) continue; if (d->modelines == NULL) continue; if (!display_has_modeline(d, modeline)) { @@ -1167,8 +1167,11 @@ static nvDisplayPtr find_active_display(nvLayoutPtr layout) { nvGpuPtr gpu; nvDisplayPtr display; - for (gpu = layout->gpus; gpu; gpu = gpu->next) { - for (display = gpu->displays; display; display = display->next) { + + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + for (display = gpu->displays; + display; + display = display->next_on_gpu) { if (display->modelines) return display; } } @@ -1338,7 +1341,7 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle, GridConfig *grid; int num_valid = 0; - for (gpu = layout->gpus; gpu; gpu = gpu->next) { + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { num_displays += gpu->num_displays; } diff --git a/src/libXNVCtrl/NVCtrl.h b/src/libXNVCtrl/NVCtrl.h index 5ee1b56..f712ec4 100644 --- a/src/libXNVCtrl/NVCtrl.h +++ b/src/libXNVCtrl/NVCtrl.h @@ -47,6 +47,7 @@ #define NV_CTRL_TARGET_TYPE_COOLER 5 /* e.g., fan */ #define NV_CTRL_TARGET_TYPE_THERMAL_SENSOR 6 #define NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER 7 +#define NV_CTRL_TARGET_TYPE_DISPLAY 8 /**************************************************************************/ @@ -78,6 +79,10 @@ * designated with "D" below. For attributes that do not require the * display mask, the argument is ignored. * + * Alternatively, NV-CONTROL versions 1.27 and greater allow these + * attributes to be accessed via display target types, in which case + * the display_mask is ignored. + * * G: The attribute may be queried using an NV_CTRL_TARGET_TYPE_GPU * target type via XNVCTRLQueryTargetAttribute(). * @@ -97,19 +102,18 @@ * Q: The attribute is a 64-bit integer attribute; use the 64-bit versions * of the appropriate query interfaces. * - * * C: The attribute may be queried using an NV_CTRL_TARGET_TYPE_COOLER target * type via XNVCTRLQueryTargetAttribute(). - * + * * S: The attribute may be queried using an NV_CTRL_TARGET_TYPE_THERMAL_SENSOR * target type via XNVCTRLQueryTargetAttribute(). * * T: The attribute may be queried using an * NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER target type * via XNVCTRLQueryTargetAttribute(). - * + * * NOTE: Unless mentioned otherwise, all attributes may be queried using - * an NV_CTRL_TARGET_TYPE_X_SCREEN target type via + * an NV_CTRL_TARGET_TYPE_X_SCREEN target type via * XNVCTRLQueryTargetAttribute(). */ @@ -699,8 +703,7 @@ /* * NV_CTRL_FLIPPING_ALLOWED - when TRUE, OpenGL will swap by flipping - * when possible; when FALSE, OpenGL will alway swap by blitting. XXX - * can this be enabled dynamically? + * when possible; when FALSE, OpenGL will alway swap by blitting. */ #define NV_CTRL_FLIPPING_ALLOWED 40 /* RW-X */ @@ -1340,7 +1343,8 @@ * NV_CTRL_GVO_DATA_FORMAT * NV_CTRL_GVO_FLIP_QUEUE_SIZE * - * XXX This is deprecated, please see NV_CTRL_GVO_LOCK_OWNER + * This attribute is deprecated and may be removed in a future release. Its + * functionality has been replaced by NV_CTRL_GVO_LOCK_OWNER. */ #define NV_CTRL_GVO_GLX_LOCKED 82 /* R-- */ @@ -4120,8 +4124,38 @@ */ #define NV_CTRL_BINARY_DATA_GLASSES_PAIRED_TO_3D_VISION_PRO_TRANSCEIVER 13 /* R--T */ +/* + * NV_CTRL_BINARY_DATA_DISPLAY_TARGETS - Returns all the display devices + * currently connected to any GPU on the X server. + * + * The format of the returned data is: + * + * 4 CARD32 number of display devices + * 4 * n CARD32 display device indices + * + * This attribute can only be queried through XNVCTRLQueryTargetBinaryData(). + */ + +#define NV_CTRL_BINARY_DATA_DISPLAY_TARGETS 14 /* R--- */ + +/* + * NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU - Returns the list of + * display devices that are connected to the GPU target. + * + * The format of the returned data is: + * + * 4 CARD32 number of display devices + * 4 * n CARD32 display device indices + * + * This attribute can only be queried through XNVCTRLQueryTargetBinaryData() + * using a NV_CTRL_TARGET_TYPE_GPU target. + */ + +#define NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU 15 /* R--G */ + + #define NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE \ - NV_CTRL_BINARY_DATA_GLASSES_PAIRED_TO_3D_VISION_PRO_TRANSCEIVER + NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU /**************************************************************************/ @@ -4365,7 +4399,9 @@ * * ATTRIBUTE_TYPE_READ - Attribute may be read (queried.) * ATTRIBUTE_TYPE_WRITE - Attribute may be written to (set.) - * ATTRIBUTE_TYPE_DISPLAY - Attribute requires a display mask. + * ATTRIBUTE_TYPE_DISPLAY - Attribute is valid for display target types + * (requires a display_mask if queried via + * a GPU or X screen.) * ATTRIBUTE_TYPE_GPU - Attribute is valid for GPU target types. * ATTRIBUTE_TYPE_FRAMELOCK - Attribute is valid for Frame Lock target types. * ATTRIBUTE_TYPE_X_SCREEN - Attribute is valid for X Screen target types. @@ -4407,6 +4443,17 @@ #define ATTRIBUTE_TYPE_THERMAL_SENSOR 0x400 #define ATTRIBUTE_TYPE_3D_VISION_PRO_TRANSCEIVER 0x800 +#define ATTRIBUTE_TYPE_ALL_TARGETS \ + ((ATTRIBUTE_TYPE_DISPLAY) | \ + (ATTRIBUTE_TYPE_GPU) | \ + (ATTRIBUTE_TYPE_FRAMELOCK) | \ + (ATTRIBUTE_TYPE_X_SCREEN) | \ + (ATTRIBUTE_TYPE_VCSC) | \ + (ATTRIBUTE_TYPE_GVI) | \ + (ATTRIBUTE_TYPE_COOLER) | \ + (ATTRIBUTE_TYPE_THERMAL_SENSOR) | \ + (ATTRIBUTE_TYPE_3D_VISION_PRO_TRANSCEIVER)) + typedef struct _NVCTRLAttributeValidValues { int type; union { diff --git a/src/libXNVCtrl/nv_control.h b/src/libXNVCtrl/nv_control.h index d944b3c..914d83a 100644 --- a/src/libXNVCtrl/nv_control.h +++ b/src/libXNVCtrl/nv_control.h @@ -52,6 +52,7 @@ * report false positives via the GPU and X screen target types * 1.25 Added 3D_VISION_PRO_TRANSCEIVER TargetType * 1.26 Added XNVCTRLQueryXXXAttributePermissions. + * 1.27 Added DISPLAY TargetType */ #ifndef __NVCONTROL_H @@ -62,7 +63,7 @@ #define NV_CONTROL_NAME "NV-CONTROL" #define NV_CONTROL_MAJOR 1 -#define NV_CONTROL_MINOR 26 +#define NV_CONTROL_MINOR 27 #define X_nvCtrlQueryExtension 0 #define X_nvCtrlIsNv 1 diff --git a/src/parse.c b/src/parse.c index a8fc02e..9b3ae8c 100644 --- a/src/parse.c +++ b/src/parse.c @@ -450,7 +450,15 @@ TargetTypeEntry targetTypeTable[] = { ATTRIBUTE_TYPE_3D_VISION_PRO_TRANSCEIVER, /* permission_bit */ NV_FALSE, /* uses_display_devices */ 1, 25 }, /* required major,minor protocol rev */ - + + { "Display Device", /* name */ + "dpy", /* parsed_name */ + DISPLAY_TARGET, /* target_index */ + NV_CTRL_TARGET_TYPE_DISPLAY, /* nvctrl */ + ATTRIBUTE_TYPE_DISPLAY, /* permission_bit */ + NV_FALSE, /* uses_display_devices */ + 1, 27 }, /* required major,minor protocol rev */ + { NULL, NULL, 0, 0, 0 }, }; diff --git a/src/parse.h b/src/parse.h index 9ba725e..c0dc4dd 100644 --- a/src/parse.h +++ b/src/parse.h @@ -153,7 +153,8 @@ extern AttributeTableEntry attributeTable[]; #define COOLER_TARGET 5 #define THERMAL_SENSOR_TARGET 6 #define NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET 7 -#define MAX_TARGET_TYPES 8 +#define DISPLAY_TARGET 8 +#define MAX_TARGET_TYPES 9 diff --git a/src/query-assign.c b/src/query-assign.c index 0d3e11b..d3d961d 100644 --- a/src/query-assign.c +++ b/src/query-assign.c @@ -104,6 +104,7 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display) NvCtrlAttributeHandle *handle; int target, i, j, val, d, c, len; char *tmp; + int *pData = NULL; /* allocate the CtrlHandles struct */ @@ -176,9 +177,23 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display) ((major == targetTypeTable[j].major) && (minor >= targetTypeTable[j].minor)))) { - status = NvCtrlQueryTargetCount - (pQueryHandle, targetTypeTable[j].nvctrl, - &val); + if (target != DISPLAY_TARGET) { + status = NvCtrlQueryTargetCount + (pQueryHandle, targetTypeTable[j].nvctrl, + &val); + } else { + /* For targets that aren't simply enumerated, + * query the list of valid IDs in pData which + * will be used below + */ + status = + NvCtrlGetBinaryAttribute(pQueryHandle, 0, + NV_CTRL_BINARY_DATA_DISPLAY_TARGETS, + (unsigned char **)(&pData), &len); + if (status == NvCtrlSuccess) { + val = pData[0]; + } + } } else { status = NvCtrlMissingExtension; } @@ -199,8 +214,14 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display) /* if there are no targets of this type, skip */ - if (h->targets[target].n == 0) continue; - + if (h->targets[target].n == 0) { + if (pData) { + XFree(pData); + pData = NULL; + } + continue; + } + /* allocate an array of CtrlHandleTarget's */ h->targets[target].t = @@ -212,11 +233,29 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display) */ for (i = 0; i < h->targets[target].n; i++) { - + int targetId; + + switch (target) { + case DISPLAY_TARGET: + /* Grab the target Id from the pData list */ + targetId = pData[i+1]; + break; + case X_SCREEN_TARGET: + case GPU_TARGET: + case FRAMELOCK_TARGET: + case VCS_TARGET: + case GVI_TARGET: + case COOLER_TARGET: + case THERMAL_SENSOR_TARGET: + case NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET: + default: + targetId = i; + } + /* allocate the handle */ handle = NvCtrlAttributeInit(h->dpy, - targetTypeTable[j].nvctrl, i, + targetTypeTable[j].nvctrl, targetId, NV_CTRL_ATTRIBUTES_ALL_SUBSYSTEMS); h->targets[target].t[i].h = handle; @@ -225,9 +264,15 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display) * silently fail: this might happen if not all X screens * are NVIDIA X screens */ - - if (!handle) continue; - + + if (!handle) { + if (pData) { + XFree(pData); + pData = NULL; + } + continue; + } + /* * get a name for this target; in the case of * X_SCREEN_TARGET targets, just use the string returned @@ -294,6 +339,11 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display) if (!pQueryHandle) pQueryHandle = handle; } + + if (pData) { + XFree(pData); + pData = NULL; + } } return h; @@ -429,6 +479,11 @@ static int process_attribute_queries(int num, char **queries, continue; } + if (nv_strcasecmp(queries[query], "dpys")) { + query_all_targets(display_name, DISPLAY_TARGET); + continue; + } + /* call the parser to parse queries[query] */ ret = nv_parse_attribute_string(queries[query], NV_PARSER_QUERY, &a); @@ -1147,44 +1202,22 @@ static int print_target_display_connections(CtrlHandleTarget *t) /* - * get_vcs_name() Returns the VCS product name of the given - * VCS target. + * get_product_name() Returns the (GPU, X screen, display device or VCS) + * product name of the given target. */ -static char * get_vcs_name(NvCtrlAttributeHandle *h) +static char * get_product_name(NvCtrlAttributeHandle *h, int attr) { char *product_name; ReturnStatus status; - status = NvCtrlGetStringAttribute(h, NV_CTRL_STRING_VCSC_PRODUCT_NAME, - &product_name); - - if (status != NvCtrlSuccess) return strdup("Unknown"); - - return product_name; - -} /* get_vcs_name() */ - - - -/* - * get_gpu_name() Returns the GPU product name of the given - * GPU target. - */ - -static char * get_gpu_name(NvCtrlAttributeHandle *h) -{ - char *product_name; - ReturnStatus status; + status = NvCtrlGetStringAttribute(h, attr, &product_name); - status = NvCtrlGetStringAttribute(h, NV_CTRL_STRING_PRODUCT_NAME, - &product_name); - if (status != NvCtrlSuccess) return strdup("Unknown"); - + return product_name; -} /* get_gpu_name() */ +} /* get_product_name() */ @@ -1240,12 +1273,20 @@ static int print_target_connections(CtrlHandles *h, switch (target_index) { case GPU_TARGET: product_name = - get_gpu_name(h->targets[target_index].t[ pData[i] ].h); + get_product_name(h->targets[target_index].t[ pData[i] ].h, + NV_CTRL_STRING_PRODUCT_NAME); break; case VCS_TARGET: product_name = - get_vcs_name(h->targets[target_index].t[ pData[i] ].h); + get_product_name(h->targets[target_index].t[ pData[i] ].h, + NV_CTRL_STRING_VCSC_PRODUCT_NAME); + break; + + case DISPLAY_TARGET: + product_name = + get_product_name(h->targets[target_index].t[ pData[i] ].h, + NV_CTRL_STRING_DISPLAY_DEVICE_NAME); break; case NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET: @@ -1299,7 +1340,6 @@ static int query_all_targets(const char *display_name, const int target_index) { CtrlHandles *h; CtrlHandleTarget *t; - ReturnStatus status; int i, table_index; char *str, *name, *product_name; @@ -1379,31 +1419,31 @@ static int query_all_targets(const char *display_name, const int target_index) product_name = malloc(32); snprintf(product_name, 32, "G-Sync %d", i); - + } else if (target_index == VCS_TARGET) { - status = NvCtrlGetStringAttribute - (t->h, NV_CTRL_STRING_VCSC_PRODUCT_NAME, &product_name); - - if (status != NvCtrlSuccess) product_name = strdup("Unknown"); - + product_name = get_product_name(t->h, + NV_CTRL_STRING_VCSC_PRODUCT_NAME); + } else if (target_index == GVI_TARGET) { /* for gvi, create the product name */ product_name = malloc(32); snprintf(product_name, 32, "SDI Input %d", i); + + } else if (target_index == DISPLAY_TARGET) { + + product_name = get_product_name(t->h, + NV_CTRL_STRING_DISPLAY_DEVICE_NAME); + } else { /* for X_SCREEN_TARGET or GPU_TARGET, query the product name */ + product_name = get_product_name(t->h, NV_CTRL_STRING_PRODUCT_NAME); - status = NvCtrlGetStringAttribute - (t->h, NV_CTRL_STRING_PRODUCT_NAME, &product_name); - - if (status != NvCtrlSuccess) product_name = strdup("Unknown"); - } - + /* * use the name for the target handle, or "Unknown" if we * don't have a target handle name (this can happen for a @@ -1444,6 +1484,9 @@ static int query_all_targets(const char *display_name, const int target_index) print_target_connections (h, t, NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU, THERMAL_SENSOR_TARGET); + print_target_connections + (h, t, NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU, + GPU_TARGET); break; case X_SCREEN_TARGET: @@ -1469,13 +1512,13 @@ static int query_all_targets(const char *display_name, const int target_index) (h, t, NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU, COOLER_TARGET); break; - + case THERMAL_SENSOR_TARGET: print_target_connections (h, t, NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU, THERMAL_SENSOR_TARGET); break; - + default: break; } @@ -1 +1 @@ -NVIDIA_VERSION = 270.41.19 +NVIDIA_VERSION = 275.09 |