diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2020-10-07 08:53:59 -0700 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2020-10-07 08:53:59 -0700 |
commit | 6d5ab9be83bbb279638a672dedda96cc39174759 (patch) | |
tree | 7eb446d92c83491f14947d5023dd5b77d02854da | |
parent | 3fac2b1bd245e109161a5efa9eac2a0fe811663b (diff) |
455.28455.28
-rw-r--r-- | doc/version.mk | 2 | ||||
-rw-r--r-- | samples/version.mk | 2 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplayconfig.c | 221 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplayconfig.h | 4 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkgridlicense.c | 44 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkgridlicense.h | 1 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkslimm.c | 1110 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkslimm.h | 66 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkwindow.c | 14 | ||||
-rw-r--r-- | src/libXNVCtrl/version.mk | 2 | ||||
-rw-r--r-- | src/nvml.h | 20 | ||||
-rw-r--r-- | src/version.h | 2 | ||||
-rw-r--r-- | src/version.mk | 2 | ||||
-rw-r--r-- | version.mk | 2 |
14 files changed, 837 insertions, 655 deletions
diff --git a/doc/version.mk b/doc/version.mk index 618e84a..14d7f22 100644 --- a/doc/version.mk +++ b/doc/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 455.23.04 +NVIDIA_VERSION = 455.28 diff --git a/samples/version.mk b/samples/version.mk index 618e84a..14d7f22 100644 --- a/samples/version.mk +++ b/samples/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 455.23.04 +NVIDIA_VERSION = 455.28 diff --git a/src/gtk+-2.x/ctkdisplayconfig.c b/src/gtk+-2.x/ctkdisplayconfig.c index 515264e..673e63a 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.c +++ b/src/gtk+-2.x/ctkdisplayconfig.c @@ -22,6 +22,7 @@ #include <string.h> #include <sys/stat.h> #include <assert.h> +#include <math.h> #include <gtk/gtk.h> #include <gdk/gdkx.h> @@ -106,6 +107,7 @@ static void screen_metamode_delete_clicked(GtkWidget *widget, gpointer user_data static void setup_prime_display_page(CtkDisplayConfig *ctk_object); static void xinerama_state_toggled(GtkWidget *widget, gpointer user_data); +static void mosaic_config_clicked(GtkWidget *widget, gpointer user_data); static void apply_clicked(GtkWidget *widget, gpointer user_data); static void save_clicked(GtkWidget *widget, gpointer user_data); static void probe_clicked(GtkWidget *widget, gpointer user_data); @@ -127,6 +129,7 @@ static XConfigPtr xconfig_generate(XConfigPtr xconfCur, Bool *merged, void *callback_data); +static void update_layout(CtkDisplayConfig *ctk_object); @@ -204,6 +207,10 @@ static const char * __layout_base_mosaic_surround_button_help = static const char * __layout_base_mosaic_full_button_help = "The Enable Base Mosaic checkbox enables Base Mosaic."; +static const char * __layout_mosaic_config_button_help = +"The Configure SLI Mosaic Displays button will open a dialog to assist in " +"configuring multiple displays."; + static const char * __dpy_resolution_mnu_help = "The Resolution drop-down allows you to select a desired resolution " "for the currently selected display device. The 'scaled' qualifier indicates " @@ -1913,6 +1920,12 @@ GtkWidget* ctk_display_config_new(CtrlTarget *ctrl_target, xconfig_generate, (void *)ctk_object); + ctk_object->dialog_mosaic = + create_mosaic_dialog(GTK_WIDGET(ctk_object), + ctk_object->ctrl_target, + ctk_object->ctk_config, + ctk_object->layout); + /* Apply button */ ctk_object->btn_apply = gtk_button_new_with_label("Apply"); @@ -1960,7 +1973,17 @@ GtkWidget* ctk_display_config_new(CtrlTarget *ctrl_target, G_CALLBACK(save_clicked), (gpointer) ctk_object); + /* Mosaic/Grid Config button */ + ctk_object->btn_mosaic = gtk_button_new_with_label + ("Configure SLI Mosaic Displays"); + ctk_config_set_tooltip(ctk_config, ctk_object->btn_mosaic, + __layout_mosaic_config_button_help); + g_signal_connect(G_OBJECT(ctk_object->btn_mosaic), "clicked", + G_CALLBACK(mosaic_config_clicked), + (gpointer) ctk_object); + { /* Layout section */ + GtkWidget *vbox2; frame = gtk_frame_new("Layout"); /* main panel */ gtk_box_pack_start(GTK_BOX(ctk_object), frame, FALSE, FALSE, 0); @@ -1973,13 +1996,22 @@ GtkWidget* ctk_display_config_new(CtrlTarget *ctrl_target, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), eventbox, TRUE, TRUE, 0); + hbox = gtk_hbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(vbox), hbox); + vbox2 = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(hbox), vbox2); + /* Mosaic checkbox */ - gtk_box_pack_start(GTK_BOX(vbox), ctk_object->chk_mosaic_enabled, + gtk_box_pack_start(GTK_BOX(vbox2), ctk_object->chk_mosaic_enabled, FALSE, FALSE, 0); /* Xinerama checkbox */ - gtk_box_pack_start(GTK_BOX(vbox), ctk_object->chk_xinerama_enabled, + gtk_box_pack_start(GTK_BOX(vbox2), ctk_object->chk_xinerama_enabled, FALSE, FALSE, 0); + + /* Mosaic configuration dialog button */ + gtk_box_pack_end(GTK_BOX(hbox), ctk_object->btn_mosaic, + FALSE, FALSE, 0); } @@ -2524,6 +2556,8 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table, case MOSAIC_TYPE_SLI_MOSAIC: ctk_help_heading(b, &i, "Enable SLI Mosaic"); ctk_help_para(b, &i, "%s", __layout_sli_mosaic_button_help); + ctk_help_heading(b, &i, "Configure SLI Mosaic"); + ctk_help_para(b, &i, "%s", __layout_mosaic_config_button_help); break; case MOSAIC_TYPE_BASE_MOSAIC: ctk_help_heading(b, &i, "Enable Base Mosaic"); @@ -2667,6 +2701,12 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table, ctk_help_heading(b, &i, "Save to X Configuration File"); ctk_help_para(b, &i, "%s", __save_button_help); + + ctk_help_para(b, &i, ""); + ctk_help_heading(b, &i, "Dialogs"); + + ctk_mmdialog_insert_help(b, &i); + ctk_help_finish(b); return b; @@ -2696,6 +2736,7 @@ static void setup_mosaic_config(CtkDisplayConfig *ctk_object) if (!ctk_object->advanced_mode || (!display_gpu_support_mosaic && !screen_gpu_support_mosaic)) { gtk_widget_hide(ctk_object->chk_mosaic_enabled); + gtk_widget_hide(ctk_object->btn_mosaic); return; } @@ -2707,6 +2748,14 @@ static void setup_mosaic_config(CtkDisplayConfig *ctk_object) gpu = screen->display_owner_gpu; } + /* Only show the Mosaic Config tool with SLI Mosaic and dialog exists */ + if (gpu->mosaic_type == MOSAIC_TYPE_SLI_MOSAIC && + ctk_object->dialog_mosaic) { + gtk_widget_show(ctk_object->btn_mosaic); + } else { + gtk_widget_hide(ctk_object->btn_mosaic); + } + switch (gpu->mosaic_type) { case MOSAIC_TYPE_SLI_MOSAIC: tooltip = __layout_sli_mosaic_button_help; @@ -6156,6 +6205,49 @@ static Bool display_build_modepool(nvDisplayPtr display, Bool *updated) +static nvModeLinePtr +display_find_closest_matching_modeline(nvDisplayPtr display, + nvModeLinePtr input_modeline) +{ + const int target_width = input_modeline->data.hdisplay; + const int target_height = input_modeline->data.vdisplay; + const double target_rr = input_modeline->refresh_rate; + const double tolerance = 0.0001; + + nvModeLinePtr modeline, best_modeline = NULL; + int modeline_idx; + int best_idx = -1; + + modeline_idx = 0; + for (modeline = display->modelines; modeline; modeline = modeline->next) { + if (modeline->data.hdisplay == target_width && + modeline->data.vdisplay == target_height) { + nvModeLinePtr tmp_modeline = modeline; + int tmp_idx = modeline_idx; + + /* + * We already have a match. Let's figure out if the currently + * considered modeline is the closer to what we want. + */ + if (best_modeline) { + if (fabs(best_modeline->refresh_rate - target_rr) < tolerance) { + tmp_modeline = best_modeline; + tmp_idx = best_idx; + } + /* Fallthrough. */ + } + best_modeline = tmp_modeline; + best_idx = tmp_idx; + } + modeline_idx++; + } + + return best_modeline; + +} /* display_find_closest_matching_modeline() */ + + + static void do_enable_mosaic(CtkDisplayConfig *ctk_object) { nvLayoutPtr layout = ctk_object->layout; @@ -6199,6 +6291,76 @@ static void do_enable_mosaic(CtkDisplayConfig *ctk_object) } } } + + /* Enable the Mosaic Config dialog if available */ + gtk_widget_set_sensitive(ctk_object->btn_mosaic, True); +} + + + +static void mosaic_config_clicked(GtkWidget *widget, gpointer user_data) +{ + CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data); + nvLayoutPtr layout = ctk_object->layout; + nvGpuPtr gpu; + gboolean enabled = gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON(ctk_object->chk_mosaic_enabled)); + + if (!enabled) { + return; + } + + // Launch Mosaic Dialog // + if (run_mosaic_dialog(ctk_object->dialog_mosaic, + ctk_get_parent_window(GTK_WIDGET(ctk_object)), + ctk_object->layout)) { + + // apply mosaic options and update screen // + int idx = ctk_object->dialog_mosaic->refresh_idx; + int display_num = 0; + nvModeLinePtr ml = ctk_object->dialog_mosaic->refresh_table[idx]; + + for(gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + nvDisplayPtr display; + + for(display = gpu->displays; + display; + display = display->next_on_gpu) { + nvModeLinePtr modeline; + + if (display->num_selected_modes == 0) { + generate_selected_modes(display); + } + + modeline = display_find_closest_matching_modeline(display, ml); + + if (modeline) { + int x_loc, y_loc, x_pos, y_pos; + + x_loc = display_num % ctk_object->dialog_mosaic->x_displays; + y_loc = display_num / ctk_object->dialog_mosaic->x_displays; + + x_pos = x_loc * ml->data.hdisplay - + x_loc * ctk_object->dialog_mosaic->h_overlap; + y_pos = y_loc * ml->data.vdisplay - + y_loc * ctk_object->dialog_mosaic->v_overlap; + + display_num++; + + display->cur_mode->pan.x = x_pos; + display->cur_mode->pan.y = y_pos; + + ctk_display_layout_set_mode_modeline( + CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), + display->cur_mode, modeline, NULL, NULL); + + } + } + } + + update_layout(ctk_object); + + } } @@ -6246,6 +6408,9 @@ static void do_disable_mosaic(CtkDisplayConfig *ctk_object) */ mosaic_screen->num_gpus = 0; link_screen_to_gpu(mosaic_screen, mosaic_screen->display_owner_gpu); + + /* Disable the Mosaic Config dialog if available */ + gtk_widget_set_sensitive(ctk_object->btn_mosaic, False); } @@ -9016,7 +9181,7 @@ static int add_screen_to_xconfig(CtkDisplayConfig *ctk_object, xconfigAddNewOption(&conf_screen->options, "BaseMosaic", "on"); break; default: - nv_warning_msg("Uknonwn mosaic mode %d", + nv_warning_msg("Unknown mosaic mode %d", screen->display_owner_gpu->mosaic_type); xconfigAddNewOption(&conf_screen->options, "SLI", screen->sli_mode ? screen->sli_mode : "Off"); @@ -9637,6 +9802,39 @@ static gboolean layout_change_is_applyable(const nvLayoutPtr old, return False; } + + +/** update_layout() ************************************************* + * + * Update layout and redraw. + * + **/ + +static void update_layout(CtkDisplayConfig *ctk_object) +{ + ctk_display_layout_set_layout((CtkDisplayLayout *)(ctk_object->obj_layout), + ctk_object->layout); + + /* Make sure X screens have some kind of position */ + assign_screen_positions(ctk_object); + + update_gui(ctk_object); + + /* Get new position */ + get_cur_screen_pos(ctk_object); + + /* Update the apply button */ + ctk_object->apply_possible = TRUE; + update_btn_apply(ctk_object, TRUE); + + ctk_object->forced_reset_allowed = TRUE; /* OK to reset w/o user input */ + ctk_object->notify_user_of_reset = TRUE; /* Notify user of new changes */ + ctk_object->reset_required = FALSE; /* No reset required to apply */ + +} + + + /** reset_layout() ************************************************* * * Load current X server settings. @@ -9693,6 +9891,8 @@ static void reset_layout(CtkDisplayConfig *ctk_object) ctk_object->apply_possible = TRUE; update_btn_apply(ctk_object, allow_apply); + update_mosaic_dialog_ui(ctk_object->dialog_mosaic, ctk_object->layout); + ctk_object->forced_reset_allowed = TRUE; /* OK to reset w/o user input */ ctk_object->notify_user_of_reset = TRUE; /* Notify user of new changes */ ctk_object->reset_required = FALSE; /* No reset required to apply */ @@ -9849,6 +10049,21 @@ static void display_config_attribute_changed(GtkWidget *object, { CtkDisplayConfig *ctk_object = (CtkDisplayConfig *) user_data; + if(ctk_object->dialog_mosaic && ctk_object->dialog_mosaic->is_active) { + GtkWidget *dlg; + GtkWidget *parent = ctk_get_parent_window(GTK_WIDGET(ctk_object)); + dlg = gtk_message_dialog_new (GTK_WINDOW(parent), + GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "A change to the display configuration " + "has been detected. The information " + "shown here may no longer be valid. " + "Please close this dialog."); + gtk_dialog_run(GTK_DIALOG(dlg)); + gtk_widget_destroy (dlg); + } + if (ctk_object->ignore_reset_events) return; ctk_object->ignore_reset_events = TRUE; diff --git a/src/gtk+-2.x/ctkdisplayconfig.h b/src/gtk+-2.x/ctkdisplayconfig.h index c80200b..802ac80 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.h +++ b/src/gtk+-2.x/ctkdisplayconfig.h @@ -25,6 +25,7 @@ #include "ctkconfig.h" #include "ctkdisplaylayout.h" #include "ctkdisplayconfig-utils.h" +#include "ctkslimm.h" @@ -231,6 +232,8 @@ typedef struct _CtkDisplayConfig SaveXConfDlg *save_xconfig_dlg; + CtkMMDialog *dialog_mosaic; + /* Buttons */ GtkWidget *btn_apply; gboolean apply_possible; /* True if all modifications are applicable */ @@ -242,6 +245,7 @@ typedef struct _CtkDisplayConfig GdkPoint cur_screen_pos; /* Keep track of the selected X screen's position */ + GtkWidget *btn_mosaic; GtkWidget *btn_save; GtkWidget *btn_probe; diff --git a/src/gtk+-2.x/ctkgridlicense.c b/src/gtk+-2.x/ctkgridlicense.c index 52cba46..47e2394 100644 --- a/src/gtk+-2.x/ctkgridlicense.c +++ b/src/gtk+-2.x/ctkgridlicense.c @@ -1660,12 +1660,14 @@ GtkWidget* ctk_manage_grid_license_new(CtrlTarget *target, gtk_container_set_border_width(GTK_CONTAINER(vbox3), 5); ctk_manage_grid_license->isvComputeSupported = is_feature_supported(ctk_manage_grid_license, NV_GRID_LICENSE_FEATURE_TYPE_VCOMPUTE); - if (ctk_manage_grid_license->isvComputeSupported) { + ctk_manage_grid_license->isQuadroSupported = is_feature_supported(ctk_manage_grid_license, NV_GRID_LICENSE_FEATURE_TYPE_QDWS); + if (ctk_manage_grid_license->isvComputeSupported && ctk_manage_grid_license->isQuadroSupported) { ctk_manage_grid_license->radio_btn_vcompute = gtk_radio_button_new_with_label(NULL, ctk_manage_grid_license->productNamevCompute); slist = gtk_radio_button_get_group(GTK_RADIO_BUTTON(ctk_manage_grid_license->radio_btn_vcompute)); + gtk_box_pack_start(GTK_BOX(vbox3), ctk_manage_grid_license->radio_btn_vcompute, FALSE, FALSE, 0); g_object_set_data(G_OBJECT(ctk_manage_grid_license->radio_btn_vcompute), "button_id", - GINT_TO_POINTER(NV_GRID_LICENSE_FEATURE_TYPE_VCOMPUTE)); + GINT_TO_POINTER(NV_GRID_LICENSE_FEATURE_TYPE_VCOMPUTE)); g_signal_connect(G_OBJECT(ctk_manage_grid_license->radio_btn_vcompute), "toggled", G_CALLBACK(license_edition_toggled), @@ -1674,24 +1676,44 @@ GtkWidget* ctk_manage_grid_license_new(CtrlTarget *target, ctk_manage_grid_license->radio_btn_qdws = gtk_radio_button_new_with_label(slist, ctk_manage_grid_license->productNameQvDWS); slist = gtk_radio_button_get_group(GTK_RADIO_BUTTON(ctk_manage_grid_license->radio_btn_qdws)); + gtk_box_pack_start(GTK_BOX(vbox3), ctk_manage_grid_license->radio_btn_qdws, FALSE, FALSE, 0); + g_object_set_data(G_OBJECT(ctk_manage_grid_license->radio_btn_qdws), "button_id", + GINT_TO_POINTER(NV_GRID_LICENSE_FEATURE_TYPE_QDWS)); + + g_signal_connect(G_OBJECT(ctk_manage_grid_license->radio_btn_qdws), "toggled", + G_CALLBACK(license_edition_toggled), + (gpointer) ctk_manage_grid_license); + + } + else if (ctk_manage_grid_license->isvComputeSupported) { + ctk_manage_grid_license->radio_btn_vcompute = gtk_radio_button_new_with_label(NULL, ctk_manage_grid_license->productNamevCompute); + slist = gtk_radio_button_get_group(GTK_RADIO_BUTTON(ctk_manage_grid_license->radio_btn_vcompute)); + + gtk_box_pack_start(GTK_BOX(vbox3), ctk_manage_grid_license->radio_btn_vcompute, FALSE, FALSE, 0); + g_object_set_data(G_OBJECT(ctk_manage_grid_license->radio_btn_vcompute), "button_id", + GINT_TO_POINTER(NV_GRID_LICENSE_FEATURE_TYPE_VCOMPUTE)); + + g_signal_connect(G_OBJECT(ctk_manage_grid_license->radio_btn_vcompute), "toggled", + G_CALLBACK(license_edition_toggled), + (gpointer) ctk_manage_grid_license); } - else { + else if (ctk_manage_grid_license->isQuadroSupported) { ctk_manage_grid_license->radio_btn_qdws = gtk_radio_button_new_with_label(NULL, ctk_manage_grid_license->productNameQvDWS); slist = gtk_radio_button_get_group(GTK_RADIO_BUTTON(ctk_manage_grid_license->radio_btn_qdws)); - } - gtk_box_pack_start(GTK_BOX(vbox3), ctk_manage_grid_license->radio_btn_qdws, FALSE, FALSE, 0); - g_object_set_data(G_OBJECT(ctk_manage_grid_license->radio_btn_qdws), "button_id", - GINT_TO_POINTER(NV_GRID_LICENSE_FEATURE_TYPE_QDWS)); + gtk_box_pack_start(GTK_BOX(vbox3), ctk_manage_grid_license->radio_btn_qdws, FALSE, FALSE, 0); + g_object_set_data(G_OBJECT(ctk_manage_grid_license->radio_btn_qdws), "button_id", + GINT_TO_POINTER(NV_GRID_LICENSE_FEATURE_TYPE_QDWS)); - g_signal_connect(G_OBJECT(ctk_manage_grid_license->radio_btn_qdws), "toggled", - G_CALLBACK(license_edition_toggled), - (gpointer) ctk_manage_grid_license); + g_signal_connect(G_OBJECT(ctk_manage_grid_license->radio_btn_qdws), "toggled", + G_CALLBACK(license_edition_toggled), + (gpointer) ctk_manage_grid_license); + } ctk_manage_grid_license->radio_btn_vapp = gtk_radio_button_new_with_label(slist, GRID_VIRTUAL_APPLICATIONS); gtk_box_pack_start(GTK_BOX(vbox3), ctk_manage_grid_license->radio_btn_vapp, FALSE, FALSE, 0); g_object_set_data(G_OBJECT(ctk_manage_grid_license->radio_btn_vapp), "button_id", - GINT_TO_POINTER(NV_GRID_LICENSE_FEATURE_TYPE_VAPP)); + GINT_TO_POINTER(NV_GRID_LICENSE_FEATURE_TYPE_VAPP)); g_signal_connect(G_OBJECT(ctk_manage_grid_license->radio_btn_vapp), "toggled", G_CALLBACK(license_edition_toggled), diff --git a/src/gtk+-2.x/ctkgridlicense.h b/src/gtk+-2.x/ctkgridlicense.h index 9848ea2..404fc35 100644 --- a/src/gtk+-2.x/ctkgridlicense.h +++ b/src/gtk+-2.x/ctkgridlicense.h @@ -78,6 +78,7 @@ struct _CtkManageGridLicense int licenseStatus; // Current license status to be displayed on UI gboolean isvComputeSupported; // Check if 'NVIDIA Virtual Compute Server' feature is supported + gboolean isQuadroSupported; // Check if 'Quadro Virtual Data Center Workstation' feature is supported }; /* diff --git a/src/gtk+-2.x/ctkslimm.c b/src/gtk+-2.x/ctkslimm.c index 67488e8..8464258 100644 --- a/src/gtk+-2.x/ctkslimm.c +++ b/src/gtk+-2.x/ctkslimm.c @@ -38,20 +38,18 @@ /* Static function declarations */ -static void setup_display_refresh_dropdown(CtkSLIMM *ctk_object); -static void setup_display_resolution_dropdown(CtkSLIMM *ctk_object); -static void setup_total_size_label(CtkSLIMM *ctk_object); +static void setup_display_refresh_dropdown(CtkMMDialog *ctk_object); +static void setup_display_resolution_dropdown(CtkMMDialog *ctk_object); +static void setup_total_size_label(CtkMMDialog *ctk_object); static void display_refresh_changed(GtkWidget *widget, gpointer user_data); static void display_resolution_changed(GtkWidget *widget, gpointer user_data); static void display_config_changed(GtkWidget *widget, gpointer user_data); static void txt_overlap_activated(GtkWidget *widget, gpointer user_data); -static void slimm_checkbox_toggled(GtkWidget *widget, gpointer user_data); -static void save_xconfig_button_clicked(GtkWidget *widget, gpointer user_data); -static void add_slimm_options(XConfigPtr xconf, gchar *metamode_str); -static void remove_slimm_options(XConfigPtr xconf); +static void validate_screen_size(CtkMMDialog *ctk_object); static nvDisplayPtr find_active_display(nvLayoutPtr layout); -static nvDisplayPtr intersect_modelines(nvLayoutPtr layout); -static void remove_duplicate_modelines(nvDisplayPtr display); +static nvDisplayPtr intersect_modelines_list(CtkMMDialog *ctk_mmdialog, + nvLayoutPtr layout); +static void remove_duplicate_modelines_from_list(CtkMMDialog *ctk_mmdialog); static Bool other_displays_have_modeline(nvLayoutPtr layout, nvDisplayPtr display, nvModeLinePtr modeline); @@ -65,161 +63,7 @@ typedef struct DpyLocRec { // Display Location - -GType ctk_slimm_get_type() -{ - static GType ctk_slimm_type = 0; - - if (!ctk_slimm_type) { - static const GTypeInfo info_ctk_slimm = { - sizeof (CtkSLIMMClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - NULL, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (CtkSLIMM), - 0, /* n_preallocs */ - NULL, /* instance_init */ - NULL /* value_table */ - }; - - ctk_slimm_type = - g_type_register_static(GTK_TYPE_VBOX, - "CtkSLIMM", &info_ctk_slimm, 0); - } - - return ctk_slimm_type; -} - -static void remove_slimm_options(XConfigPtr xconf) -{ - /* Remove SLI Mosaic Option */ - xconfigRemoveNamedOption(&xconf->layouts->adjacencies->screen->options, - "SLI", NULL); - - /* Remove MetaMode Option */ - xconfigRemoveNamedOption(&xconf->layouts->adjacencies->screen->options, - "MetaModes", NULL); -} - - -static void add_slimm_options(XConfigPtr xconf, gchar *metamode_str) -{ - XConfigAdjacencyPtr adj; - XConfigScreenPtr screen; - - /* Make sure there is only one screen specified in the main layout */ - adj = xconf->layouts->adjacencies; - while (adj->next) { - xconfigRemoveListItem((GenericListPtr *)(&adj), - (GenericListPtr)adj->next); - } - - /* - * Now fix up the screen in the Device section (to prevent failure with - * separate x screen config - * - */ - xconf->layouts->adjacencies->screen->device->screen = -1; - - /* Write out SLI Mosaic Option */ - xconfigAddNewOption(&(xconf->layouts->adjacencies->screen->options), - "SLI", "Mosaic"); - - /* Write out MetaMode Option */ - xconfigAddNewOption(&(xconf->layouts->adjacencies->screen->options), - "MetaModes", metamode_str); - - /* Remove Virtual size specification */ - for (screen = xconf->layouts->adjacencies->screen; screen; - screen = screen->next) { - if ((screen->displays->virtualX) || (screen->displays->virtualY)) { - screen->displays->virtualX = 0; - screen->displays->virtualY = 0; - } - } -} - - - -static XConfigPtr xconfig_generate(XConfigPtr xconfCur, - Bool merge, - Bool *merged, - void *callback_data) -{ - CtkSLIMM *ctk_object = (CtkSLIMM *)callback_data; - CtkDropDownMenu *menu = CTK_DROP_DOWN_MENU(ctk_object->mnu_display_config); - - gint idx; - - gint xctr,yctr; - - gint x_displays,y_displays; - gint h_overlap, v_overlap; - - gchar *metamode_str = NULL; - gchar *tmpstr; - - gint checkbox_state = - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctk_object->cbtn_slimm_enable)); - - - /* Make sure we're being asked to merge */ - if (!xconfCur || !merge) { - *merged = FALSE; - return NULL; - } - - - if (checkbox_state) { - /* SLI MM needs to be enabled */ - idx = ctk_drop_down_menu_get_current_value(menu); - - /* Get grid configuration values from index */ - - if (idx < ctk_object->num_grid_configs) { - x_displays = ctk_object->grid_configs[idx].columns; - y_displays = ctk_object->grid_configs[idx].rows; - } else { - x_displays = y_displays = 0; - } - - h_overlap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ctk_object->spbtn_hedge_overlap)); - v_overlap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ctk_object->spbtn_vedge_overlap)); - - for (yctr = 0; yctr < y_displays;yctr++) { - for (xctr = 0; xctr < x_displays;xctr++) { - tmpstr = g_strdup_printf("%s +%d+%d", - ctk_object->cur_modeline->data.identifier, - ctk_object->cur_modeline->data.hdisplay * xctr - - h_overlap * xctr, - ctk_object->cur_modeline->data.vdisplay * yctr - - v_overlap * yctr); - if (metamode_str) { - metamode_str = g_strconcat(metamode_str, ", ", tmpstr, NULL); - g_free(tmpstr); - } else { - metamode_str = tmpstr; - } - } - } - - add_slimm_options(xconfCur, metamode_str); - } else { - /* SLI MM needs to be disabled */ - - remove_slimm_options(xconfCur); - } - - *merged = TRUE; - - return xconfCur; -} - - - -static void set_overlap_controls_status(CtkSLIMM *ctk_object) +static void set_overlap_controls_status(CtkMMDialog *ctk_object) { CtkDropDownMenu *menu; gint config_idx, x_displays, y_displays; @@ -243,7 +87,7 @@ static void set_overlap_controls_status(CtkSLIMM *ctk_object) -static Bool compute_screen_size(CtkSLIMM *ctk_object, gint *width, +static Bool compute_screen_size(CtkMMDialog *ctk_object, gint *width, gint *height) { gint config_idx; @@ -282,9 +126,8 @@ static Bool compute_screen_size(CtkSLIMM *ctk_object, gint *width, -static void save_xconfig_button_clicked(GtkWidget *widget, gpointer user_data) +static void validate_screen_size(CtkMMDialog *ctk_object) { - CtkSLIMM *ctk_object = CTK_SLIMM(user_data); gint width, height; Bool error = FALSE; gchar *err_msg = NULL; @@ -324,22 +167,13 @@ static void save_xconfig_button_clicked(GtkWidget *widget, gpointer user_data) g_free(err_msg); return; } - - - /* Run the save dialog */ - if (run_save_xconfig_dialog(ctk_object->save_xconfig_dlg)) { - - /* Config file written */ - ctk_object->ctk_config->pending_config &= - ~CTK_CONFIG_PENDING_WRITE_MOSAIC_CONFIG; - } } static void txt_overlap_activated(GtkWidget *widget, gpointer user_data) { - CtkSLIMM *ctk_object = CTK_SLIMM(user_data); + CtkMMDialog *ctk_object = (CtkMMDialog *)(user_data); /* Update total size label */ setup_total_size_label(ctk_object); @@ -349,7 +183,7 @@ static void txt_overlap_activated(GtkWidget *widget, gpointer user_data) static void display_config_changed(GtkWidget *widget, gpointer user_data) { - CtkSLIMM *ctk_object = CTK_SLIMM(user_data); + CtkMMDialog *ctk_object = (CtkMMDialog *)(user_data); /* Update total size label */ setup_total_size_label(ctk_object); @@ -360,7 +194,7 @@ static void display_config_changed(GtkWidget *widget, gpointer user_data) static void display_refresh_changed(GtkWidget *widget, gpointer user_data) { - CtkSLIMM *ctk_object = CTK_SLIMM(user_data); + CtkMMDialog *ctk_object = (CtkMMDialog *)(user_data); CtkDropDownMenu *menu = CTK_DROP_DOWN_MENU(widget); gint idx; @@ -377,7 +211,7 @@ static void display_refresh_changed(GtkWidget *widget, gpointer user_data) static void display_resolution_changed(GtkWidget *widget, gpointer user_data) { - CtkSLIMM *ctk_object = CTK_SLIMM(user_data); + CtkMMDialog *ctk_object = (CtkMMDialog *)(user_data); CtkDropDownMenu *menu = CTK_DROP_DOWN_MENU(widget); gint idx; @@ -418,39 +252,6 @@ static void display_resolution_changed(GtkWidget *widget, gpointer user_data) -static void slimm_checkbox_toggled(GtkWidget *widget, gpointer user_data) -{ - CtkSLIMM *ctk_object = CTK_SLIMM(user_data); - - gint enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - - if (enabled) { - if (ctk_object->mnu_refresh_disabled) { - ctk_object->mnu_refresh_disabled = False; - gtk_widget_set_sensitive(ctk_object->mnu_display_refresh, True); - } - gtk_widget_set_sensitive(ctk_object->mnu_display_resolution, True); - gtk_widget_set_sensitive(ctk_object->mnu_display_config, True); - gtk_widget_set_sensitive(ctk_object->box_total_size, True); - set_overlap_controls_status(ctk_object); - } else { - if (ctk_widget_get_sensitive(ctk_object->mnu_display_refresh)) { - ctk_object->mnu_refresh_disabled = True; - gtk_widget_set_sensitive(ctk_object->mnu_display_refresh, False); - } - gtk_widget_set_sensitive(ctk_object->mnu_display_resolution, False); - gtk_widget_set_sensitive(ctk_object->mnu_display_config, False); - gtk_widget_set_sensitive(ctk_object->spbtn_hedge_overlap, False); - gtk_widget_set_sensitive(ctk_object->spbtn_vedge_overlap, False); - gtk_widget_set_sensitive(ctk_object->box_total_size, False); - } - - ctk_object->ctk_config->pending_config |= - CTK_CONFIG_PENDING_WRITE_MOSAIC_CONFIG; -} - - - /** setup_total_size_label() ********************************* * * Generates and sets the label showing total X Screen size of all displays @@ -458,7 +259,7 @@ static void slimm_checkbox_toggled(GtkWidget *widget, gpointer user_data) * **/ -static void setup_total_size_label(CtkSLIMM *ctk_object) +static void setup_total_size_label(CtkMMDialog *ctk_object) { gint width, height; gchar *xscreen_size; @@ -471,6 +272,8 @@ static void setup_total_size_label(CtkSLIMM *ctk_object) xscreen_size = g_strdup_printf("%d x %d", width, height); gtk_label_set_text(GTK_LABEL(ctk_object->lbl_total_size), xscreen_size); g_free(xscreen_size); + + validate_screen_size(ctk_object); } @@ -482,12 +285,15 @@ static void setup_total_size_label(CtkSLIMM *ctk_object) * **/ -static void setup_display_refresh_dropdown(CtkSLIMM *ctk_object) +static void setup_display_refresh_dropdown(CtkMMDialog *ctk_object) { CtkDropDownMenu *menu; - nvModeLinePtr modeline; + nvModeLinePtr modeline, m; + nvModeLineItemPtr item, i; float cur_rate; /* Refresh Rate */ int cur_idx = 0; /* Currently selected modeline */ + int idx; + int match_cur_modeline; gchar *name; /* Modeline's label for the dropdown menu */ @@ -521,20 +327,40 @@ static void setup_display_refresh_dropdown(CtkSLIMM *ctk_object) ctk_drop_down_menu_reset(menu); + /* Make sure cur_modeline can possibly match resolution table */ + match_cur_modeline = 0; + for (idx = 0; idx < ctk_object->resolution_table_len; idx++) { + m = ctk_object->resolution_table[idx]; + if (m->data.hdisplay == ctk_object->cur_modeline->data.hdisplay && + m->data.vdisplay == ctk_object->cur_modeline->data.vdisplay) { + match_cur_modeline = 1; + break; + } + } + /* Generate the refresh rate dropdown from the modelines list */ - for (modeline = ctk_object->modelines; modeline; modeline = modeline->next) { + for (item = ctk_object->modelines; item; item = item->next) { float modeline_rate; - nvModeLinePtr m; int count_ref; /* # modelines with similar refresh rates */ int num_ref; /* Modeline # in a group of similar refresh rates */ gchar *extra = NULL; gchar *tmp; - /* Ignore modelines of different resolution */ - if (modeline->data.hdisplay != ctk_object->cur_modeline->data.hdisplay || - modeline->data.vdisplay != ctk_object->cur_modeline->data.vdisplay) { + modeline = item->modeline; + + /* Ignore modelines of different resolution than the selected */ + m = NULL; + if (match_cur_modeline) { + m = ctk_object->cur_modeline; + } else { + m = ctk_object->resolution_table[ + ctk_object->cur_resolution_table_idx]; + } + + if (m && (modeline->data.hdisplay != m->data.hdisplay || + modeline->data.vdisplay != m->data.vdisplay)) { continue; } @@ -546,7 +372,8 @@ static void setup_display_refresh_dropdown(CtkSLIMM *ctk_object) /* Get a unique number for this modeline */ count_ref = 0; /* # modelines with similar refresh rates */ num_ref = 0; /* Modeline # in a group of similar refresh rates */ - for (m = ctk_object->modelines; m; m = m->next) { + for (i = ctk_object->modelines; i; i = i->next) { + nvModeLinePtr m = i->modeline; float m_rate = m->refresh_rate; gchar *tmp = g_strdup_printf("%.0f Hz", m_rate); @@ -629,7 +456,6 @@ static void setup_display_refresh_dropdown(CtkSLIMM *ctk_object) } /* Setup the menu and select the current mode */ - ctk_object->cur_modeline = ctk_object->refresh_table[cur_idx]; ctk_drop_down_menu_set_current_value(menu, cur_idx); gtk_widget_set_sensitive(ctk_object->mnu_display_refresh, True); @@ -656,10 +482,11 @@ static void setup_display_refresh_dropdown(CtkSLIMM *ctk_object) * **/ -static void setup_display_resolution_dropdown(CtkSLIMM *ctk_object) +static void setup_display_resolution_dropdown(CtkMMDialog *ctk_object) { CtkDropDownMenu *menu; + nvModeLineItemPtr item; nvModeLinePtr modeline; nvModeLinePtr cur_modeline = ctk_object->cur_modeline; @@ -679,26 +506,34 @@ static void setup_display_resolution_dropdown(CtkSLIMM *ctk_object) /* Start the menu generation */ menu = CTK_DROP_DOWN_MENU(ctk_object->mnu_display_resolution); - modeline = ctk_object->modelines; + + item = ctk_object->modelines; cur_idx = 0; g_signal_handlers_block_by_func (G_OBJECT(ctk_object->mnu_display_resolution), G_CALLBACK(display_resolution_changed), (gpointer) ctk_object); - /* Generate the resolution menu */ - while (modeline) { + ctk_drop_down_menu_reset(menu); + + /* Generate the resolution menu */ + while (item) { + nvModeLineItemPtr i; nvModeLinePtr m; gchar *name; + modeline = item->modeline; + /* Find the first resolution that matches the current res W & H */ - m = ctk_object->modelines; + i = ctk_object->modelines; + m = i->modeline; while (m != modeline) { + m = i->modeline; if (modeline->data.hdisplay == m->data.hdisplay && modeline->data.vdisplay == m->data.vdisplay) { break; } - m = m->next; + i = i->next; } /* Add resolution if it is the first of its kind */ @@ -721,12 +556,13 @@ static void setup_display_resolution_dropdown(CtkSLIMM *ctk_object) ctk_object->resolution_table[ctk_object->resolution_table_len++] = modeline; } - modeline = modeline->next; + item = item->next; } /* Setup the menu and select the current mode */ ctk_drop_down_menu_set_current_value(menu, cur_idx); + ctk_object->cur_resolution_table_idx = cur_idx; /* If dropdown has only one item, disable menu selection */ if (ctk_object->resolution_table_len > 1) { @@ -775,12 +611,14 @@ static Bool add_array_value(int array[][2], int max_len, int *cur_len, int val) return FALSE; } -static Bool parse_slimm_layout(CtkSLIMM *ctk_slimm, + + +static Bool parse_slimm_layout(CtkMMDialog *ctk_mmdialog, nvLayoutPtr layout, int *hoverlap, int *voverlap) { - CtrlTarget *ctrl_target = ctk_slimm->ctrl_target; + CtrlTarget *ctrl_target = ctk_mmdialog->ctrl_target; ReturnStatus ret; char *metamode_str = NULL; char *str; @@ -789,7 +627,7 @@ static Bool parse_slimm_layout(CtkSLIMM *ctk_slimm, char *mode_name = NULL; gchar *err_msg = NULL; - const int max_locs = ctk_slimm->num_displays; + const int max_locs = ctk_mmdialog->num_displays; int row_loc[max_locs][2]; // As position, count int col_loc[max_locs][2]; // As position, count DpyLoc locs[max_locs]; // Location of displays @@ -999,8 +837,8 @@ static Bool parse_slimm_layout(CtkSLIMM *ctk_slimm, *hoverlap += (*cur_modeline)->data.hdisplay; } - ctk_slimm->parsed_rows = rows; - ctk_slimm->parsed_cols = cols; + ctk_mmdialog->parsed_rows = rows; + ctk_mmdialog->parsed_cols = cols; free(metamode_str); return TRUE; @@ -1023,47 +861,42 @@ static Bool parse_slimm_layout(CtkSLIMM *ctk_slimm, -static void remove_duplicate_modelines(nvDisplayPtr display) +static void remove_duplicate_modelines_from_list(CtkMMDialog *ctk_mmdialog) { - nvModeLinePtr m, nextm; - m = display->modelines; - if (!m) { + nvModeLineItemPtr iter = ctk_mmdialog->modelines; + nvModeLineItemPtr tmp; + if (!iter) { return; } /* Remove nvidia-auto-select modeline first */ - if (IS_NVIDIA_DEFAULT_MODE(m)) { - display->modelines = m->next; - if (m == display->cur_mode->modeline) { - display->cur_mode->modeline = m->next; - } - modeline_free(m); - display->num_modelines--; + if (IS_NVIDIA_DEFAULT_MODE(iter->modeline)) { + ctk_mmdialog->modelines = iter->next; + free(iter); + ctk_mmdialog->num_modelines--; } - + /* Remove duplicate modelines in active display - assuming sorted order*/ - for (m = display->modelines; m;) { - nextm = m->next; - if (!nextm) break; - - if (modelines_match(m, nextm)) { - /* nextm is a duplicate - remove it. */ - m->next = nextm->next; - if (nextm == display->cur_mode->modeline) { - display->cur_mode->modeline = m; - } - modeline_free(nextm); - display->num_modelines--; + for (iter = ctk_mmdialog->modelines; iter;) { + if (!iter->next) break; + + if (modelines_match(iter->modeline, iter->next->modeline)) { + /* next is a duplicate - remove it. */ + tmp = iter->next; + iter->next = iter->next->next; + free(tmp); + ctk_mmdialog->num_modelines--; } else { - m = nextm; + iter = iter->next; } } } -static Bool other_displays_have_modeline(nvLayoutPtr layout, + +static Bool other_displays_have_modeline(nvLayoutPtr layout, nvDisplayPtr display, nvModeLinePtr modeline) { @@ -1100,13 +933,61 @@ static nvDisplayPtr find_active_display(nvLayoutPtr layout) } -static nvDisplayPtr intersect_modelines(nvLayoutPtr layout) + +static void add_modeline_to_list(CtkMMDialog *ctk_mmdialog, nvModeLinePtr m) +{ + nvModeLineItemPtr item; + + if (!m) return; + + item = calloc(1,sizeof(nvModeLineItem)); + item->modeline = m; + + if (!ctk_mmdialog->modelines) { + ctk_mmdialog->modelines = item; + ctk_mmdialog->num_modelines = 1; + } else { + nvModeLineItemPtr iter = ctk_mmdialog->modelines; + while (iter->next) { + iter = iter->next; + } + iter->next = item; + ctk_mmdialog->num_modelines++; + } +} + + + +static void delete_modelines_list(CtkMMDialog *ctk_mmdialog) +{ + nvModeLineItemPtr item, next; + + if (ctk_mmdialog->modelines == NULL || ctk_mmdialog->num_modelines == 0) { + return; + } + + item = ctk_mmdialog->modelines; + + while (item) { + next = item->next; + free(item); + item = next; + } + + ctk_mmdialog->num_modelines = 0; + ctk_mmdialog->modelines = NULL; +} + + + +static nvDisplayPtr intersect_modelines_list(CtkMMDialog *ctk_mmdialog, + const nvLayoutPtr layout) { nvDisplayPtr display; - nvModeLinePtr m, prev; + nvModeLinePtr m; - /** - * + /** + * * Only need to go through one active display, and eliminate all modelines * in this display that do not exist in other displays (being driven by * this or any other GPU) @@ -1115,36 +996,17 @@ static nvDisplayPtr intersect_modelines(nvLayoutPtr layout) display = find_active_display(layout); if (display == NULL) return NULL; - prev = NULL; + delete_modelines_list(ctk_mmdialog); + m = display->modelines; while (m) { - if (!other_displays_have_modeline(layout, display, m)) { - if (prev) { - /* Remove past beginning */ - prev->next = m->next; - } else { - /* Remove first entry */ - display->modelines = m->next; - } - - if (m == display->cur_mode->modeline) { - display->cur_mode->modeline = 0; - } - modeline_free(m); - display->num_modelines--; - - if (prev) { - m = prev->next; - } else { - m = display->modelines; - } - } else { - prev = m; - m = m->next; + if (other_displays_have_modeline(layout, display, m)) { + add_modeline_to_list(ctk_mmdialog, m); } + m = m->next; } - remove_duplicate_modelines(display); + remove_duplicate_modelines_from_list(ctk_mmdialog); return display; } @@ -1202,51 +1064,51 @@ static int generate_configs_helper(const int num_displays, -static void generate_configs(CtkSLIMM *ctk_slimm, gboolean only_max) +static void generate_configs(CtkMMDialog *ctk_mmdialog, gboolean only_max) { - int n_configs = generate_configs_helper(ctk_slimm->num_displays, only_max, + int n_configs = generate_configs_helper(ctk_mmdialog->num_displays, only_max, NULL); - ctk_slimm->grid_configs = calloc(n_configs, sizeof(GridConfig)); - ctk_slimm->num_grid_configs = n_configs; + ctk_mmdialog->grid_configs = calloc(n_configs, sizeof(GridConfig)); + ctk_mmdialog->num_grid_configs = n_configs; - generate_configs_helper(ctk_slimm->num_displays, only_max, - ctk_slimm->grid_configs); + generate_configs_helper(ctk_mmdialog->num_displays, only_max, + ctk_mmdialog->grid_configs); } -static void populate_dropdown(CtkSLIMM *ctk_slimm, gboolean only_max) +static void populate_dropdown(CtkMMDialog *ctk_mmdialog, gboolean only_max) { int iter; int rows, cols; int cur_rows, cur_cols; char *tmp; - CtkDropDownMenu *menu = CTK_DROP_DOWN_MENU(ctk_slimm->mnu_display_config); + CtkDropDownMenu *menu = CTK_DROP_DOWN_MENU(ctk_mmdialog->mnu_display_config); int grid_config_id = ctk_drop_down_menu_get_current_value(menu); - if (ctk_slimm->grid_configs && grid_config_id >= 0) { - cur_rows = ctk_slimm->grid_configs[grid_config_id].rows; - cur_cols = ctk_slimm->grid_configs[grid_config_id].columns; + if (ctk_mmdialog->grid_configs && grid_config_id >= 0) { + cur_rows = ctk_mmdialog->grid_configs[grid_config_id].rows; + cur_cols = ctk_mmdialog->grid_configs[grid_config_id].columns; } else { - cur_rows = ctk_slimm->parsed_rows; - cur_cols = ctk_slimm->parsed_cols; + cur_rows = ctk_mmdialog->parsed_rows; + cur_cols = ctk_mmdialog->parsed_cols; } - if (ctk_slimm->grid_configs) { - free(ctk_slimm->grid_configs); - ctk_slimm->num_grid_configs = 0; + if (ctk_mmdialog->grid_configs) { + free(ctk_mmdialog->grid_configs); + ctk_mmdialog->num_grid_configs = 0; } ctk_drop_down_menu_reset(menu); - generate_configs(ctk_slimm, only_max); + generate_configs(ctk_mmdialog, only_max); - for (iter = 0; iter < ctk_slimm->num_grid_configs; iter++) { - rows = ctk_slimm->grid_configs[iter].rows; - cols = ctk_slimm->grid_configs[iter].columns; + for (iter = 0; iter < ctk_mmdialog->num_grid_configs; iter++) { + rows = ctk_mmdialog->grid_configs[iter].rows; + cols = ctk_mmdialog->grid_configs[iter].columns; tmp = g_strdup_printf("%d x %d grid", rows, cols); @@ -1265,36 +1127,203 @@ static void populate_dropdown(CtkSLIMM *ctk_slimm, gboolean only_max) static void restrict_display_config_changed(GtkWidget *widget, gpointer user_data) { - CtkSLIMM *ctk_slimm = CTK_SLIMM(user_data); + CtkMMDialog *ctk_mmdialog = (CtkMMDialog *)(user_data); - populate_dropdown(ctk_slimm, + populate_dropdown(ctk_mmdialog, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))); + + update_mosaic_dialog_ui(ctk_mmdialog, NULL); +} + + + +static void print_error_string(gchar *err_str) +{ + if (!err_str) { + nv_error_msg("Unable to load SLI Mosaic Mode Settings dialog."); + } else { + nv_error_msg("Unable to load SLI Mosaic Mode Settings " + "dialog:\n\n%s", err_str); + } +} + + + +static nvDisplayPtr setup_display(CtkMMDialog *ctk_mmdialog) +{ + nvDisplayPtr display; + nvLayoutPtr layout = ctk_mmdialog->layout; + + display = intersect_modelines_list(ctk_mmdialog, layout); + + if (display == NULL) { + print_error_string("Unable to find active display with " + "intersected modelines."); + free(ctk_mmdialog); + return NULL; + + } else if ((ctk_mmdialog->modelines == NULL)) { + /* The modepool for the active display did not have any modes in + * its modepool matching any of the modes on the modepool of any + * other display in the layout, causing intersect_modelines to + * remove every mode from the list of available modes for SLI mosaic + * mode. + * + * This can happen if one display had its modepool trimmed and modified + * to support 3D vision, while other displays (either on X screens + * without stereo currently enabled, or on screenless GPUs) did not. + * Find if that is the case, and display an informative message if so. + */ + nvGpuPtr gpu; + nvDisplayPtr d; + int stereo = get_display_stereo_mode(display); + + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + for (d = gpu->displays; d; d = d->next_on_gpu) { + int other_stereo; + + if (display == d) { + continue; + } + + other_stereo = get_display_stereo_mode(d); + + if ((STEREO_IS_3D_VISION(stereo) && + !STEREO_IS_3D_VISION(other_stereo)) || + (!STEREO_IS_3D_VISION(stereo) && + STEREO_IS_3D_VISION(other_stereo))) { + + print_error_string("Unable to find common modelines between\n" + "all connected displays due to 3D vision\n" + "being enabled on some displays and not\n" + "others. Please make sure that 3D vision\n" + "is enabled on all connected displays\n" + "before enabling SLI mosaic mode."); + + free(ctk_mmdialog); + return NULL; + } + } + } + + /* The intersected modepool was empty, but not because of a mismatch + * in 3D Vision settings. + */ + print_error_string("Unable to find find common modelines between " + "all connected displays."); + + free(ctk_mmdialog); + return NULL; + } + + if (display) { + + /* Extract modelines and cur_modeline */ + if (display->cur_mode->modeline) { + ctk_mmdialog->cur_modeline = display->cur_mode->modeline; + } else if (ctk_mmdialog->num_modelines > 0) { + ctk_mmdialog->cur_modeline = ctk_mmdialog->modelines->modeline; + } + } + + return display; } +void update_mosaic_dialog_ui(CtkMMDialog *ctk_mmdialog, nvLayoutPtr layout) +{ + GtkWidget *btn; + + if (ctk_mmdialog == NULL) { + return; + } + + btn = ctk_mmdialog->chk_all_displays; + + if (layout) { + ctk_mmdialog->layout = layout; + } + + parse_slimm_layout(ctk_mmdialog, + ctk_mmdialog->layout, + &ctk_mmdialog->h_overlap_parsed, + &ctk_mmdialog->v_overlap_parsed); + + setup_display(ctk_mmdialog); + + populate_dropdown(ctk_mmdialog, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn))); + + setup_display_resolution_dropdown(ctk_mmdialog); + setup_display_refresh_dropdown(ctk_mmdialog); + + gtk_spin_button_set_value(GTK_SPIN_BUTTON(ctk_mmdialog->spbtn_hedge_overlap), + ctk_mmdialog->h_overlap_parsed); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(ctk_mmdialog->spbtn_vedge_overlap), + ctk_mmdialog->v_overlap_parsed); + setup_total_size_label(ctk_mmdialog); +} -GtkWidget* ctk_slimm_new(CtrlTarget *ctrl_target, - CtkEvent *ctk_event, - CtkConfig *ctk_config) + + +static gchar *count_displays_and_parse_layout(CtkMMDialog *ctk_mmdialog) { - GObject *object; - CtkSLIMM *ctk_slimm; + nvLayoutPtr layout = ctk_mmdialog->layout; + gchar *err_str = NULL; + + if (layout) { + + nvGpuPtr gpu; + int num_displays = 0; + + for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { + num_displays += gpu->num_displays; + } + + ctk_mmdialog->num_displays = num_displays; + + + /* Make sure we have enough displays for the minimum config */ + if (num_displays < 2) { + err_str = g_strdup_printf("Not enough display devices to " + "configure SLI Mosaic Mode.\nYou must " + "have at least 2 Displays connected, " + "but only %d Display%s detected.", + num_displays, + (num_displays != 1) ? "s were" : " was"); + } else { + parse_slimm_layout(ctk_mmdialog, + layout, + &ctk_mmdialog->h_overlap_parsed, + &ctk_mmdialog->v_overlap_parsed); + } + } + + return err_str; +} + + + +CtkMMDialog *create_mosaic_dialog(GtkWidget *parent, + CtrlTarget *ctrl_target, + CtkConfig *ctk_config, + const nvLayoutPtr layout) +{ + GtkWidget *dialog_obj; + CtkMMDialog *ctk_mmdialog; + GtkWidget *content; GtkWidget *label; GtkWidget *vbox; GtkWidget *hbox; - GtkWidget *banner; GtkWidget *checkbutton; GtkWidget *hseparator; GtkWidget *table; - GtkWidget *button; GtkWidget *spinbutton; - CtkSLIMM *ctk_object; CtkDropDownMenu *menu; gchar *err_str = NULL; - gchar *str; gchar *tmp; gchar *sli_mode = NULL; ReturnStatus ret; @@ -1302,23 +1331,26 @@ GtkWidget* ctk_slimm_new(CtrlTarget *ctrl_target, int major = 0, minor = 0; gint val; - nvLayoutPtr layout; nvDisplayPtr display; Bool trust_slimm_available = FALSE; Bool only_max; - int hoverlap = 0; - int voverlap = 0; - /* now, create the object */ + /* now, create the dialog */ + + ctk_mmdialog = calloc(1, sizeof(CtkMMDialog)); + if (!ctk_mmdialog) { + return NULL; + } - object = g_object_new(CTK_TYPE_SLIMM, NULL); - ctk_slimm = CTK_SLIMM(object); + ctk_mmdialog->ctrl_target = ctrl_target; + ctk_mmdialog->ctk_config = ctk_config; - ctk_slimm->ctrl_target = ctrl_target; - ctk_slimm->ctk_config = ctk_config; - ctk_object = ctk_slimm; + ctk_mmdialog->parent = parent; + ctk_mmdialog->layout = layout; + + ctk_mmdialog->is_active = FALSE; /* * Check for NV-CONTROL protocol version. @@ -1337,7 +1369,8 @@ GtkWidget* ctk_slimm_new(CtrlTarget *ctrl_target, /* return on old X drivers. */ if (!trust_slimm_available) { - return NULL; + free(ctk_mmdialog); + return NULL; } /* Check if this screen supports SLI Mosaic Mode */ @@ -1346,21 +1379,24 @@ GtkWidget* ctk_slimm_new(CtrlTarget *ctrl_target, if ((ret == NvCtrlSuccess) && (val == NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE_FALSE)) { /* Mosaic not supported */ + free(ctk_mmdialog); return NULL; } /* Query the maximum screen sizes */ ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_MAX_SCREEN_WIDTH, - &ctk_slimm->max_screen_width); + &ctk_mmdialog->max_screen_width); if (ret != NvCtrlSuccess) { + free(ctk_mmdialog); return NULL; } ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_MAX_SCREEN_HEIGHT, - &ctk_slimm->max_screen_height); + &ctk_mmdialog->max_screen_height); if (ret != NvCtrlSuccess) { + free(ctk_mmdialog); return NULL; } @@ -1369,144 +1405,45 @@ GtkWidget* ctk_slimm_new(CtrlTarget *ctrl_target, * */ - /* Load the layout structure from the X server */ - layout = layout_load_from_server(ctrl_target, &err_str); - - if (!err_str && layout) { - nvGpuPtr gpu; - int num_displays = 0; - - for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { - num_displays += gpu->num_displays; - } - - ctk_slimm->num_displays = num_displays; - - - /* Make sure we have enough displays for the minimum config */ - if (num_displays < 2) { - err_str = g_strdup_printf("Not enough display devices to " - "configure SLI Mosaic Mode.\nYou must " - "have at least 2 Displays connected, " - "but only %d Display%s detected.", - num_displays, - (num_displays != 1) ? "s were" : " was"); - layout_free(layout); - layout = NULL; - - } else { - parse_slimm_layout(ctk_slimm, - layout, - &hoverlap, - &voverlap); - } - } + err_str = count_displays_and_parse_layout(ctk_mmdialog); /* If we failed to load, tell the user why */ if (err_str || !layout) { - goto slimm_fail; + print_error_string(err_str); + g_free(err_str); + free(ctk_mmdialog); + return NULL; } - display = intersect_modelines(layout); + display = setup_display(ctk_mmdialog); if (display == NULL) { - err_str = g_strdup("Unable to find active display with " - "intersected modelines."); - goto slimm_fail; - } else if ((display->modelines == NULL) && - (display->cur_mode->modeline == NULL)) { - /* The modepool for the active display did not have any modes in - * its modepool matching any of the modes on the modepool of any - * other display in the layout, causing intersect_modelines to - * remove every mode from the list of available modes for SLI mosaic - * mode. - * - * This can happen if one display had its modepool trimmed and modified - * to support 3D vision, while other displays (either on X screens - * without stereo currently enabled, or on screenless GPUs) did not. - * Find if that is the case, and display an informative message if so. - */ - nvGpuPtr gpu; - nvDisplayPtr d; - int stereo = get_display_stereo_mode(display); - - for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) { - for (d = gpu->displays; d; d = d->next_on_gpu) { - int other_stereo; - - if (display == d) { - continue; - } - - other_stereo = get_display_stereo_mode(d); - - if ((STEREO_IS_3D_VISION(stereo) && - !STEREO_IS_3D_VISION(other_stereo)) || - (!STEREO_IS_3D_VISION(stereo) && - STEREO_IS_3D_VISION(other_stereo))) { - - err_str = g_strdup("Unable to find common modelines between\n" - "all connected displays due to 3D vision\n" - "being enabled on some displays and not\n" - "others. Please make sure that 3D vision\n" - "is enabled on all connected displays\n" - "before enabling SLI mosaic mode."); - - goto slimm_fail; - } - } - } - - /* The intersected modepool was empty, but not because of a mismatch - * in 3D Vision settings. - */ - err_str = g_strdup("Unable to find find common modelines between " - "all connected displays."); - - goto slimm_fail; + return NULL; } + /* Create the dialog */ + dialog_obj = gtk_dialog_new_with_buttons + ("Configure SLI Mosaic Layout", + GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(parent))), + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + "_Apply to Layout", + GTK_RESPONSE_APPLY, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + NULL); + ctk_mmdialog->dialog = dialog_obj; - /* Extract modelines and cur_modeline and free layout structure */ - ctk_object->modelines = display->modelines; - if (display->cur_mode->modeline) { - ctk_object->cur_modeline = display->cur_mode->modeline; - } else { - ctk_object->cur_modeline = ctk_object->modelines; - } - ctk_object->num_modelines = display->num_modelines; + gtk_dialog_set_default_response(GTK_DIALOG(dialog_obj), + GTK_RESPONSE_REJECT); - /* XXX Since we've hijacked the layout's modelines, - * we can stub out the layout's pointer and free it. - */ - display->modelines = NULL; - display->cur_mode->modeline = NULL; - display->num_modelines = 0; - layout_free(layout); - layout = NULL; /* set container properties of the object */ - gtk_box_set_spacing(GTK_BOX(ctk_slimm), 10); - - /* banner */ - - banner = ctk_banner_image_new(BANNER_ARTWORK_SLIMM); - gtk_box_pack_start(GTK_BOX(ctk_slimm), banner, FALSE, FALSE, 0); - + content = ctk_dialog_get_content_area(GTK_DIALOG(dialog_obj)); + gtk_box_set_spacing(GTK_BOX(content), 10); vbox = gtk_vbox_new(FALSE, 5); - gtk_box_pack_start(GTK_BOX(ctk_slimm), vbox, TRUE, TRUE, 0); - - hbox = gtk_hbox_new(FALSE, 0); - checkbutton = gtk_check_button_new_with_label("Use SLI Mosaic Mode"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), TRUE); - ctk_slimm->cbtn_slimm_enable = checkbutton; - g_signal_connect(G_OBJECT(checkbutton), "toggled", - G_CALLBACK(slimm_checkbox_toggled), - (gpointer) ctk_object); - gtk_box_pack_start(GTK_BOX(hbox), checkbutton, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + gtk_container_add(GTK_CONTAINER(content), vbox); hbox = gtk_hbox_new(FALSE, 0); label = gtk_label_new("Display Configuration (rows x columns)"); @@ -1515,30 +1452,31 @@ GtkWidget* ctk_slimm_new(CtrlTarget *ctrl_target, gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10); gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 10); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - + hbox = gtk_hbox_new(FALSE, 0); /* Option menu for Display Grid Configuration */ menu = (CtkDropDownMenu *) ctk_drop_down_menu_new(CTK_DROP_DOWN_MENU_FLAG_READONLY); - ctk_slimm->mnu_display_config = GTK_WIDGET(menu); + ctk_mmdialog->mnu_display_config = GTK_WIDGET(menu); - only_max = (ctk_slimm->parsed_rows * ctk_slimm->parsed_cols == - ctk_slimm->num_displays); + only_max = (ctk_mmdialog->parsed_rows * ctk_mmdialog->parsed_cols == + ctk_mmdialog->num_displays); - populate_dropdown(ctk_slimm, only_max); + populate_dropdown(ctk_mmdialog, only_max); - g_signal_connect(G_OBJECT(ctk_object->mnu_display_config), "changed", + g_signal_connect(G_OBJECT(ctk_mmdialog->mnu_display_config), "changed", G_CALLBACK(display_config_changed), - (gpointer) ctk_object); + (gpointer) ctk_mmdialog); checkbutton = gtk_check_button_new_with_label("Only show configurations " "using all displays"); + ctk_mmdialog->chk_all_displays = checkbutton; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), only_max); g_signal_connect(G_OBJECT(checkbutton), "toggled", G_CALLBACK(restrict_display_config_changed), - (gpointer) ctk_object); + (gpointer) ctk_mmdialog); label = gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); @@ -1574,34 +1512,34 @@ GtkWidget* ctk_slimm_new(CtrlTarget *ctrl_target, /* Option menu for resolutions */ hbox = gtk_hbox_new(FALSE, 0); - ctk_slimm->mnu_display_resolution = + ctk_mmdialog->mnu_display_resolution = ctk_drop_down_menu_new(CTK_DROP_DOWN_MENU_FLAG_READONLY); /* Create a drop down menu */ - setup_display_resolution_dropdown(ctk_object); + setup_display_resolution_dropdown(ctk_mmdialog); label = gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); - gtk_box_pack_end(GTK_BOX(hbox), ctk_slimm->mnu_display_resolution, + gtk_box_pack_end(GTK_BOX(hbox), ctk_mmdialog->mnu_display_resolution, TRUE, TRUE, 0); gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0.5, 0.5); - g_signal_connect(G_OBJECT(ctk_object->mnu_display_resolution), "changed", + g_signal_connect(G_OBJECT(ctk_mmdialog->mnu_display_resolution), "changed", G_CALLBACK(display_resolution_changed), - (gpointer) ctk_object); + (gpointer) ctk_mmdialog); /* Option menu for refresh rates */ hbox = gtk_hbox_new(FALSE, 0); - ctk_slimm->mnu_display_refresh = + ctk_mmdialog->mnu_display_refresh = ctk_drop_down_menu_new(CTK_DROP_DOWN_MENU_FLAG_READONLY); - setup_display_refresh_dropdown(ctk_object); - g_signal_connect(G_OBJECT(ctk_object->mnu_display_refresh), "changed", + setup_display_refresh_dropdown(ctk_mmdialog); + g_signal_connect(G_OBJECT(ctk_mmdialog->mnu_display_refresh), "changed", G_CALLBACK(display_refresh_changed), - (gpointer) ctk_object); + (gpointer) ctk_mmdialog); label = gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); - gtk_box_pack_end(GTK_BOX(hbox), ctk_slimm->mnu_display_refresh, TRUE, TRUE, 0); + gtk_box_pack_end(GTK_BOX(hbox), ctk_mmdialog->mnu_display_refresh, TRUE, TRUE, 0); gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0.5, 0.5); @@ -1631,16 +1569,18 @@ GtkWidget* ctk_slimm_new(CtrlTarget *ctrl_target, label = gtk_label_new("Horizontal:"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10); - spinbutton = gtk_spin_button_new_with_range(-ctk_object->cur_modeline->data.hdisplay, - ctk_object->cur_modeline->data.hdisplay, - 1); + spinbutton = gtk_spin_button_new_with_range( + -ctk_mmdialog->cur_modeline->data.hdisplay, + ctk_mmdialog->cur_modeline->data.hdisplay, + 1); - ctk_slimm->spbtn_hedge_overlap = spinbutton; - gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbutton), hoverlap); + ctk_mmdialog->spbtn_hedge_overlap = spinbutton; + gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbutton), + ctk_mmdialog->h_overlap_parsed); - g_signal_connect(G_OBJECT(ctk_object->spbtn_hedge_overlap), "value-changed", + g_signal_connect(G_OBJECT(ctk_mmdialog->spbtn_hedge_overlap), "value-changed", G_CALLBACK(txt_overlap_activated), - (gpointer) ctk_object); + (gpointer) ctk_mmdialog); gtk_box_pack_start(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 5); @@ -1655,15 +1595,16 @@ GtkWidget* ctk_slimm_new(CtrlTarget *ctrl_target, label = gtk_label_new("Vertical: "); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10); - spinbutton = gtk_spin_button_new_with_range(-ctk_object->cur_modeline->data.vdisplay, - ctk_object->cur_modeline->data.vdisplay, + spinbutton = gtk_spin_button_new_with_range(-ctk_mmdialog->cur_modeline->data.vdisplay, + ctk_mmdialog->cur_modeline->data.vdisplay, 1); - ctk_slimm->spbtn_vedge_overlap = spinbutton; - gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbutton), voverlap); + ctk_mmdialog->spbtn_vedge_overlap = spinbutton; + gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbutton), + ctk_mmdialog->v_overlap_parsed); - g_signal_connect(G_OBJECT(ctk_object->spbtn_vedge_overlap), "value-changed", + g_signal_connect(G_OBJECT(ctk_mmdialog->spbtn_vedge_overlap), "value-changed", G_CALLBACK(txt_overlap_activated), - (gpointer) ctk_object); + (gpointer) ctk_mmdialog); gtk_box_pack_start(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 5); @@ -1674,11 +1615,11 @@ GtkWidget* ctk_slimm_new(CtrlTarget *ctrl_target, GTK_EXPAND | GTK_FILL, 0.5, 0.5); label = gtk_label_new("NULL"); - ctk_slimm->lbl_total_size = label; - setup_total_size_label(ctk_slimm); + ctk_mmdialog->lbl_total_size = label; + setup_total_size_label(ctk_mmdialog); hbox = gtk_hbox_new(FALSE, 0); - ctk_slimm->box_total_size = hbox; + ctk_mmdialog->box_total_size = hbox; gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10); gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 9, 10, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0.5, 0.5); @@ -1692,8 +1633,8 @@ GtkWidget* ctk_slimm_new(CtrlTarget *ctrl_target, gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 10, 11, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0.5, 0.5); - tmp = g_strdup_printf("%dx%d", ctk_slimm->max_screen_width, - ctk_slimm->max_screen_height); + tmp = g_strdup_printf("%dx%d", ctk_mmdialog->max_screen_width, + ctk_mmdialog->max_screen_height); label = gtk_label_new(tmp); g_free(tmp); hbox = gtk_hbox_new(FALSE, 0); @@ -1702,116 +1643,51 @@ GtkWidget* ctk_slimm_new(CtrlTarget *ctrl_target, GTK_EXPAND | GTK_FILL, 0.5, 0.5); - label = gtk_label_new("Save to X Configuration File"); - hbox = gtk_hbox_new(FALSE, 0); - button = gtk_button_new(); - ctk_slimm->btn_save_config = button; - g_signal_connect(G_OBJECT(ctk_object->btn_save_config), "clicked", - G_CALLBACK(save_xconfig_button_clicked), - (gpointer) ctk_object); - - ctk_slimm->save_xconfig_dlg = - create_save_xconfig_dialog(GTK_WIDGET(ctk_slimm), - FALSE, // Merge toggleable - xconfig_generate, - (void *)ctk_slimm); - - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - gtk_container_add(GTK_CONTAINER(button), hbox); - - gtk_table_attach(GTK_TABLE(table), button, 1, 2, 19, 20, GTK_EXPAND | GTK_FILL, - GTK_EXPAND | GTK_FILL, 0, 0); - /* If current SLI Mode != Mosaic, disable UI elements initially */ ret = NvCtrlGetStringAttribute(ctrl_target, NV_CTRL_STRING_SLI_MODE, &sli_mode); - set_overlap_controls_status(ctk_slimm); - - if ((ret != NvCtrlSuccess) || - (ret == NvCtrlSuccess && g_ascii_strcasecmp(sli_mode, "Mosaic"))) { - gtk_toggle_button_set_active( - GTK_TOGGLE_BUTTON(ctk_slimm->cbtn_slimm_enable), FALSE); - slimm_checkbox_toggled(ctk_slimm->cbtn_slimm_enable, - (gpointer) ctk_slimm); - } + set_overlap_controls_status(ctk_mmdialog); - ctk_object->ctk_config->pending_config &= + ctk_mmdialog->ctk_config->pending_config &= ~CTK_CONFIG_PENDING_WRITE_MOSAIC_CONFIG; free(sli_mode); - gtk_widget_show_all(GTK_WIDGET(object)); - - return GTK_WIDGET(object); - -slimm_fail: - - if (layout) { - layout_free(layout); - } - - if (!err_str) { - str = g_strdup("Unable to load SLI Mosaic Mode Settings page."); - } else { - str = g_strdup_printf("Unable to load SLI Mosaic Mode Settings " - "page:\n\n%s", err_str); - g_free(err_str); - } - - label = gtk_label_new(str); - g_free(str); - gtk_label_set_selectable(GTK_LABEL(label), TRUE); - gtk_container_add(GTK_CONTAINER(object), label); - - /* Show the GUI */ - gtk_widget_show_all(GTK_WIDGET(ctk_object)); - - return GTK_WIDGET(ctk_object); + gtk_widget_show_all(content); + return ctk_mmdialog; } - -GtkTextBuffer *ctk_slimm_create_help(GtkTextTagTable *table, - const gchar *slimm_name) -{ - GtkTextIter i; - GtkTextBuffer *b; - - b = gtk_text_buffer_new(table); - - gtk_text_buffer_get_iter_at_offset(b, &i, 0); - ctk_help_title(b, &i, "SLI Mosaic Mode Settings Help"); +void ctk_mmdialog_insert_help(GtkTextBuffer *b, GtkTextIter *i) +{ + ctk_help_heading(b, i, "Configure SLI Mosaic Layout Dialog"); - ctk_help_para(b, &i, "This page allows easy configuration " + ctk_help_para(b, i, "This dialog allows easy configuration " "of SLI Mosaic Mode."); - ctk_help_heading(b, &i, "Use SLI Mosaic Mode"); - ctk_help_para(b, &i, "This checkbox controls whether SLI Mosaic Mode is enabled " - "or disabled."); - - ctk_help_heading(b, &i, "Display Configuration"); - ctk_help_para(b, &i, "This drop down menu allows selection of the display grid " + ctk_help_heading(b, i, "Display Configuration"); + ctk_help_para(b, i, "This drop down menu allows selection of the display grid " "configuration for SLI Mosaic Mode; the possible configurations " "are described as rows x columns."); - ctk_help_heading(b, &i, "Resolution"); - ctk_help_para(b, &i, "This drop down menu allows selection of the resolution to " + ctk_help_heading(b, i, "Resolution"); + ctk_help_para(b, i, "This drop down menu allows selection of the resolution to " "use for each of the displays in SLI Mosaic Mode. Note that only " "the resolutions that are available for each display will be " "shown here."); - ctk_help_heading(b, &i, "Refresh Rate"); - ctk_help_para(b, &i, "This drop down menu allows selection of the refresh rate " + ctk_help_heading(b, i, "Refresh Rate"); + ctk_help_para(b, i, "This drop down menu allows selection of the refresh rate " "to use for each of the displays in SLI Mosaic Mode. By default " "the highest refresh rate each of the displays can achieve at " "the selected resolution is chosen. This combo box gets updated " "when a new resolution is picked."); - ctk_help_heading(b, &i, "Edge Overlap"); - ctk_help_para(b, &i, "These two controls allow the user to specify the " + ctk_help_heading(b, i, "Edge Overlap"); + ctk_help_para(b, i, "These two controls allow the user to specify the " "Horizontal and Vertical Edge Overlap values. The displays " "will overlap by the specified number of pixels when forming " "the grid configuration. For example, 4 flat panel displays " @@ -1820,21 +1696,93 @@ GtkTextBuffer *ctk_slimm_create_help(GtkTextTagTable *table, "will generate the following MetaMode: \"1600x1200+0+0," "1600x1200+1550+0,1600x1200+0+1150,1600x1200+1550+1150\"."); - ctk_help_heading(b, &i, "Total Size"); - ctk_help_para(b, &i, "This is the total size of the X screen formed using all " + ctk_help_heading(b, i, "Total Size"); + ctk_help_para(b, i, "This is the total size of the X screen formed using all " "displays in SLI Mosaic Mode."); - ctk_help_heading(b, &i, "Maximum Size"); - ctk_help_para(b, &i, "This is the maximum allowable size of the X screen " + ctk_help_heading(b, i, "Maximum Size"); + ctk_help_para(b, i, "This is the maximum allowable size of the X screen " "formed using all displays in SLI Mosaic Mode."); - ctk_help_heading(b, &i, "Save to X Configuration File"); - ctk_help_para(b, &i, "Clicking this button saves the selected SLI Mosaic Mode " - "settings into the X Configuration File."); +} + + + +int run_mosaic_dialog(CtkMMDialog *ctk_mmdialog, GtkWidget *parent, + const nvLayoutPtr layout) +{ + gint response; + gint x_displays, y_displays; + CtkDropDownMenu *menu; + gint idx; + gint h_overlap; + gint v_overlap; + + + ctk_mmdialog->layout = layout; + + /* Show the save dialog */ + gtk_window_set_transient_for + (GTK_WINDOW(ctk_mmdialog->dialog), + GTK_WINDOW(gtk_widget_get_toplevel(parent))); + + gtk_window_resize(GTK_WINDOW(ctk_mmdialog->dialog), 350, 1); + gtk_window_set_resizable(GTK_WINDOW(ctk_mmdialog->dialog), FALSE); + gtk_widget_show(ctk_mmdialog->dialog); + + ctk_mmdialog->is_active = TRUE; + response = gtk_dialog_run(GTK_DIALOG(ctk_mmdialog->dialog)); + ctk_mmdialog->is_active = FALSE; + + gtk_widget_hide(ctk_mmdialog->dialog); + + if (response == GTK_RESPONSE_ACCEPT || + response == GTK_RESPONSE_APPLY) { + + + /* Grid width && Grid height */ + + menu = CTK_DROP_DOWN_MENU(ctk_mmdialog->mnu_display_config); + idx = ctk_drop_down_menu_get_current_value(menu); + + if (idx < ctk_mmdialog->num_grid_configs) { + x_displays = ctk_mmdialog->grid_configs[idx].columns; + y_displays = ctk_mmdialog->grid_configs[idx].rows; + } else { + x_displays = y_displays = 0; + } + + ctk_mmdialog->x_displays = x_displays; + ctk_mmdialog->y_displays = y_displays; + + + /* Resolution */ + + menu = CTK_DROP_DOWN_MENU(ctk_mmdialog->mnu_display_resolution); + ctk_mmdialog->resolution_idx = + ctk_drop_down_menu_get_current_value(menu); + + + /* Refresh Rate */ + + menu = CTK_DROP_DOWN_MENU(ctk_mmdialog->mnu_display_refresh); + ctk_mmdialog->refresh_idx = ctk_drop_down_menu_get_current_value(menu); + + + /* Edge Overlap */ + + h_overlap = gtk_spin_button_get_value_as_int( + GTK_SPIN_BUTTON(ctk_mmdialog->spbtn_hedge_overlap)); + v_overlap = gtk_spin_button_get_value_as_int( + GTK_SPIN_BUTTON(ctk_mmdialog->spbtn_vedge_overlap)); + + ctk_mmdialog->h_overlap = h_overlap; + ctk_mmdialog->v_overlap = v_overlap; + + } - ctk_help_finish(b); + return response != GTK_RESPONSE_CANCEL; - return b; } diff --git a/src/gtk+-2.x/ctkslimm.h b/src/gtk+-2.x/ctkslimm.h index 00fd283..277d818 100644 --- a/src/gtk+-2.x/ctkslimm.h +++ b/src/gtk+-2.x/ctkslimm.h @@ -29,40 +29,27 @@ #include "XF86Config-parser/xf86Parser.h" -G_BEGIN_DECLS - -#define CTK_TYPE_SLIMM (ctk_slimm_get_type()) - -#define CTK_SLIMM(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_SLIMM, CtkSLIMM)) - -#define CTK_SLIMM_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_SLIMM, CtkSLIMMClass)) - -#define CTK_IS_SLIMM(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_SLIMM)) - -#define CTK_IS_SLIMM_CLASS(class) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_SLIMM)) - -#define CTK_SLIMM_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_SLIMM, CtkSLIMMClass)) - -typedef struct _CtkSLIMM CtkSLIMM; -typedef struct _CtkSLIMMClass CtkSLIMMClass; - typedef struct GridConfigRec { int rows; int columns; } GridConfig; -struct _CtkSLIMM +typedef struct nvModeLineItemRec { + nvModeLinePtr modeline; + struct nvModeLineItemRec *next; +} nvModeLineItem, *nvModeLineItemPtr; + +typedef struct _CtkMMDialog { - GtkVBox parent; + GtkWidget *parent; + nvLayoutPtr layout; CtrlTarget *ctrl_target; CtkConfig *ctk_config; + GtkWidget *dialog; + gboolean is_active; + GtkWidget *mnu_display_config; GtkWidget *mnu_display_resolution; GtkWidget *mnu_display_refresh; @@ -70,15 +57,15 @@ struct _CtkSLIMM GtkWidget *spbtn_vedge_overlap; GtkWidget *lbl_total_size; GtkWidget *box_total_size; - GtkWidget *btn_save_config; - SaveXConfDlg *save_xconfig_dlg; - GtkWidget *cbtn_slimm_enable; + GtkWidget *chk_all_displays; nvModeLinePtr *resolution_table; nvModeLinePtr *refresh_table; int resolution_table_len; int refresh_table_len; + int cur_resolution_table_idx; + gint h_overlap_parsed, v_overlap_parsed; gboolean mnu_refresh_disabled; - nvModeLinePtr modelines; + nvModeLineItemPtr modelines; nvModeLinePtr cur_modeline; gint num_modelines; int num_displays; @@ -88,6 +75,10 @@ struct _CtkSLIMM int max_screen_width; int max_screen_height; + gint x_displays, y_displays; + gint resolution_idx, refresh_idx; + gint h_overlap, v_overlap; + /** * The grid_configs array enumerates the display grid configurations * that are presently supported. @@ -95,20 +86,15 @@ struct _CtkSLIMM GridConfig *grid_configs; int num_grid_configs; -}; - -struct _CtkSLIMMClass -{ - GtkVBoxClass parent_class; -}; - -GType ctk_slimm_get_type (void) G_GNUC_CONST; -GtkWidget* ctk_slimm_new (CtrlTarget *ctrl_target, - CtkEvent *ctk_event, CtkConfig *ctk_config); +} CtkMMDialog; -GtkTextBuffer *ctk_slimm_create_help(GtkTextTagTable *, const gchar *); +CtkMMDialog *create_mosaic_dialog(GtkWidget *parent, CtrlTarget *ctrl_target, + CtkConfig *ctk_config, nvLayoutPtr layout); +int run_mosaic_dialog(CtkMMDialog *dialog, GtkWidget *parent, + nvLayoutPtr layout); -G_END_DECLS +void ctk_mmdialog_insert_help(GtkTextBuffer *b, GtkTextIter *i); +void update_mosaic_dialog_ui(CtkMMDialog *ctk_mmdialog, nvLayoutPtr layout); #endif /* __CTK_SLIMM_H__ */ diff --git a/src/gtk+-2.x/ctkwindow.c b/src/gtk+-2.x/ctkwindow.c index dd9a8a4..a208055 100644 --- a/src/gtk+-2.x/ctkwindow.c +++ b/src/gtk+-2.x/ctkwindow.c @@ -503,7 +503,6 @@ GtkWidget *ctk_window_new(ParsedAttribute *p, ConfigProperties *conf, CtkConfig *ctk_config; gint column_offset; - gboolean slimm_page_added; /* XXX Kludge to only show one SLIMM page */ /* create the new object */ @@ -697,7 +696,6 @@ GtkWidget *ctk_window_new(ParsedAttribute *p, ConfigProperties *conf, /* add the per-screen entries into the tree model */ - slimm_page_added = FALSE; for (node = system->targets[X_SCREEN_TARGET]; node; node = node->next) { gchar *screen_name; @@ -738,18 +736,6 @@ GtkWidget *ctk_window_new(ParsedAttribute *p, ConfigProperties *conf, CTK_WINDOW_CONFIG_FILE_ATTRIBUTES_FUNC_COLUMN, NULL, -1); - if (!slimm_page_added) { - /* SLI Mosaic Mode information */ - - child = ctk_slimm_new(screen_target, ctk_event, ctk_config); - if (child) { - slimm_page_added = TRUE; - help = ctk_slimm_create_help(tag_table, "SLI Mosaic Mode Settings"); - add_page(child, help, ctk_window, &iter, NULL, - "SLI Mosaic Mode Settings", NULL, NULL, NULL); - } - } - /* * color correction, if RandR per-CRTC color correction is not * available diff --git a/src/libXNVCtrl/version.mk b/src/libXNVCtrl/version.mk index 618e84a..14d7f22 100644 --- a/src/libXNVCtrl/version.mk +++ b/src/libXNVCtrl/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 455.23.04 +NVIDIA_VERSION = 455.28 @@ -904,6 +904,8 @@ typedef enum { #define NVML_GRID_LICENSE_FEATURE_MAX_COUNT 3 +#define INVALID_GPU_INSTANCE_PROFILE_ID 0xFFFFFFFF + /*! * Macros for vGPU instance's virtualization capabilities bitfield. */ @@ -5985,6 +5987,24 @@ nvmlReturn_t DECLDIR nvmlVgpuTypeGetClass(nvmlVgpuTypeId_t vgpuTypeId, char *vgp nvmlReturn_t DECLDIR nvmlVgpuTypeGetName(nvmlVgpuTypeId_t vgpuTypeId, char *vgpuTypeName, unsigned int *size); /** + * Retrieve the GPU Instance Profile ID for the given vGPU type ID. + * The API will return a valid profile ID for MIG backed vGPU types when GPU is configured in MIG mode, else INVALID_GPU_INSTANCE_PROFILE_ID + * is returned. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuTypeId Handle to vGPU type + * @param gpuInstanceProfileId GPU instance Profile ID + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_NOT_SUPPORTED if \a device is not in vGPU Host virtualization mode + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a vgpuTypeId is invalid, or \a gpuInstanceProfileId is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuTypeGetGpuInstanceProfileId(nvmlVgpuTypeId_t vgpuTypeId, unsigned int *gpuInstanceProfileId); + +/** * Retrieve the device ID of a vGPU type. * * For Kepler &tm; or newer fully supported devices. diff --git a/src/version.h b/src/version.h index e9b7758..7f42b14 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define NVIDIA_VERSION "455.23.04" +#define NVIDIA_VERSION "455.28" diff --git a/src/version.mk b/src/version.mk index 618e84a..14d7f22 100644 --- a/src/version.mk +++ b/src/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 455.23.04 +NVIDIA_VERSION = 455.28 @@ -1 +1 @@ -NVIDIA_VERSION = 455.23.04 +NVIDIA_VERSION = 455.28 |