diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2009-07-22 10:00:35 -0700 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2009-07-22 10:00:35 -0700 |
commit | d6a4e693cb1b75bd45c27a8847da7ab46e1b7d6a (patch) | |
tree | ffd2fe592bb22cc07b6025b5960c990611814c1a /src | |
parent | 37c32510db16c92d802991f0137ded02b8cc8058 (diff) |
190.16190.16
This is a beta release: some of the new NV-CONTROL attributes are prelminary and
may change in the stable release.
Diffstat (limited to 'src')
-rw-r--r-- | src/glxinfo.c | 10 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkcolorcorrection.c | 6 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplayconfig-utils.c | 142 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplayconfig-utils.h | 1 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplayconfig.c | 491 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplayconfig.h | 3 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplaylayout.c | 2368 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplaylayout.h | 88 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkevent.c | 21 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkglx.c | 14 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkgpu.c | 99 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkgvo-banner.c | 24 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkgvo-sync.c | 4 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkgvo-sync.h | 2 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkgvo.c | 184 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkpowermizer.c | 179 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkpowermizer.h | 6 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkscreen.c | 22 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkwindow.c | 2 | ||||
-rw-r--r-- | src/libXNVCtrl/NVCtrl.c | 2 | ||||
-rw-r--r-- | src/libXNVCtrl/NVCtrl.h | 270 | ||||
-rw-r--r-- | src/parse.c | 38 | ||||
-rw-r--r-- | src/parse.h | 3 | ||||
-rw-r--r-- | src/query-assign.c | 19 |
24 files changed, 2673 insertions, 1325 deletions
diff --git a/src/glxinfo.c b/src/glxinfo.c index 23c322b..c6d89e3 100644 --- a/src/glxinfo.c +++ b/src/glxinfo.c @@ -182,11 +182,11 @@ print_fbconfig_attribs(GLXFBConfigAttr *fbca) return; } - printf("--fc- -vi- vt buf lv rgb d s colorbuffer ax dp st " + printf("--fc- --vi- vt buf lv rgb d s colorbuffer ax dp st " "accumbuffer ---ms---- cav -----pbuffer----- ---transparent----\n"); - printf(" id id siz l ci b t r g b a bf th en " + printf(" id id siz l ci b t r g b a bf th en " " r g b a mvs mcs b eat widt hght max-pxs typ r g b a i\n"); - printf("--------------------------------------------------" + printf("---------------------------------------------------" "--------------------------------------------------------------\n"); i = 0; @@ -194,9 +194,9 @@ print_fbconfig_attribs(GLXFBConfigAttr *fbca) printf("0x%03x ", fbca[i].fbconfig_id); if ( fbca[i].visual_id ) { - printf("0x%2.2x ", fbca[i].visual_id); + printf("0x%03x ", fbca[i].visual_id); } else { - printf(" . "); + printf(" . "); } printf("%2.2s %3d %2d %3.3s %1c %1c ", x_visual_type_abbrev(fbca[i].x_visual_type), diff --git a/src/gtk+-2.x/ctkcolorcorrection.c b/src/gtk+-2.x/ctkcolorcorrection.c index 5b2b629..169582d 100644 --- a/src/gtk+-2.x/ctkcolorcorrection.c +++ b/src/gtk+-2.x/ctkcolorcorrection.c @@ -367,7 +367,9 @@ GtkWidget* ctk_color_correction_new(NvCtrlAttributeHandle *handle, gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0); confirm_button = gtk_button_new_with_label("Confirm Current Changes"); - gtk_box_pack_end(GTK_BOX(hbox), confirm_button, FALSE, FALSE, 5); + eventbox = gtk_event_box_new(); + gtk_container_add(GTK_CONTAINER(eventbox), confirm_button); + gtk_box_pack_end(GTK_BOX(hbox), eventbox, FALSE, FALSE, 5); gtk_widget_set_sensitive(confirm_button, FALSE); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(reset_button_clicked), @@ -379,7 +381,7 @@ GtkWidget* ctk_color_correction_new(NvCtrlAttributeHandle *handle, ctk_color_correction->confirm_button = confirm_button; gtk_widget_set_size_request(confirm_button, 160, -1); - ctk_config_set_tooltip(ctk_config, confirm_button, __confirm_button_help); + ctk_config_set_tooltip(ctk_config, eventbox, __confirm_button_help); ctk_config_set_tooltip(ctk_config, button, __resest_button_help); /* diff --git a/src/gtk+-2.x/ctkdisplayconfig-utils.c b/src/gtk+-2.x/ctkdisplayconfig-utils.c index 825d841..e91f9a3 100644 --- a/src/gtk+-2.x/ctkdisplayconfig-utils.c +++ b/src/gtk+-2.x/ctkdisplayconfig-utils.c @@ -1070,6 +1070,45 @@ static void display_free(nvDisplayPtr display) /*****************************************************************************/ +/** renumber_xscreens() ********************************************** + * + * Ensures that the screens are numbered from 0 to (n-1). + * + **/ + +void renumber_xscreens(nvLayoutPtr layout) +{ + nvGpuPtr gpu; + nvScreenPtr screen; + nvScreenPtr lowest; + int scrnum; + + scrnum = 0; + do { + + /* 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; + } + } + } + + if (lowest) { + lowest->scrnum = scrnum; + } + + /* Assign next screen number */ + scrnum++; + } while (lowest); + +} /* renumber_xscreens() */ + + + /** screen_remove_display() ****************************************** * * Removes a display device from the screen @@ -1736,12 +1775,12 @@ static Bool gpu_query_gvo_mode_info(nvGpuPtr gpu, int mode_id, int table_idx) ret1 = NvCtrlGetDisplayAttribute(gpu->handle, mode_id, - NV_CTRL_GVO_VIDEO_FORMAT_REFRESH_RATE, + NV_CTRL_GVIO_VIDEO_FORMAT_REFRESH_RATE, &(rate)); ret2 = NvCtrlGetStringDisplayAttribute(gpu->handle, mode_id, - NV_CTRL_STRING_GVO_VIDEO_FORMAT_NAME, + NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME, &(name)); if ((ret1 == NvCtrlSuccess) && (ret2 == NvCtrlSuccess)) { @@ -1815,7 +1854,7 @@ nvDisplayPtr gpu_add_display_from_server(nvGpuPtr gpu, NVCTRLAttributeValidValuesRec valid; ret = NvCtrlGetValidAttributeValues(gpu->handle, - NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT, + NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT, &valid); if ((ret != NvCtrlSuccess) || (valid.type != ATTRIBUTE_TYPE_INT_BITS)) { @@ -1825,7 +1864,7 @@ nvDisplayPtr gpu_add_display_from_server(nvGpuPtr gpu, } ret = NvCtrlGetValidAttributeValues(gpu->handle, - NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT2, + NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2, &valid); if ((ret != NvCtrlSuccess) || (valid.type != ATTRIBUTE_TYPE_INT_BITS)) { @@ -2037,16 +2076,41 @@ static int gpu_add_screen_from_server(nvGpuPtr gpu, int screen_id, } - /* Make sure this screen supports dynamic twinview */ - ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_DYNAMIC_TWINVIEW, - &val); - if (ret != NvCtrlSuccess || !val) { - *err_str = g_strdup_printf("Dynamic TwinView is disabled on " + /* 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 ? TRUE : FALSE; + + + /* 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) ? TRUE : FALSE; + + + /* 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) */ @@ -2071,38 +2135,46 @@ static int gpu_add_screen_from_server(nvGpuPtr gpu, int screen_id, /* 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); + /* Parse the screen's metamodes (ties displays on the gpu to the screen) */ - 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; - } + 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; + /* 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; + } } } } + + /* Add the screen at the end of the gpu's screen list */ xconfigAddListItem((GenericListPtr *)(&gpu->screens), (GenericListPtr)screen); diff --git a/src/gtk+-2.x/ctkdisplayconfig-utils.h b/src/gtk+-2.x/ctkdisplayconfig-utils.h index 205c2d2..fc62337 100644 --- a/src/gtk+-2.x/ctkdisplayconfig-utils.h +++ b/src/gtk+-2.x/ctkdisplayconfig-utils.h @@ -77,6 +77,7 @@ void display_remove_modes(nvDisplayPtr display); /* Screen functions */ +void renumber_xscreens(nvLayoutPtr layout); void screen_remove_display(nvDisplayPtr display); gchar * screen_get_metamode_str(nvScreenPtr screen, int metamode_idx, int be_generic); diff --git a/src/gtk+-2.x/ctkdisplayconfig.c b/src/gtk+-2.x/ctkdisplayconfig.c index 744de7d..37763aa 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.c +++ b/src/gtk+-2.x/ctkdisplayconfig.c @@ -70,6 +70,10 @@ static gboolean display_panning_focus_out(GtkWidget *widget, GdkEvent *event, static void setup_screen_page(CtkDisplayConfig *ctk_object); +static void screen_virtual_size_activate(GtkWidget *widget, gpointer user_data); +static gboolean screen_virtual_size_focus_out(GtkWidget *widget, GdkEvent *event, + gpointer user_data); + static void screen_depth_changed(GtkWidget *widget, gpointer user_data); static void screen_position_type_changed(GtkWidget *widget, gpointer user_data); @@ -199,6 +203,11 @@ static const char * __dpy_primary_help = /* Screen tooltips */ +static const char * __screen_virtual_size_help = +"The Virtual Size allows setting the size of the resulting X screen. " +"The virtual size must be at least large enough to hold all the display " +"devices that are currently enabled for scanout."; + static const char * __screen_depth_help = "The Depth drop-down allows setting of the color quality for the selected " "screen; changing this option will require restarting your X server."; @@ -272,13 +281,13 @@ static const char * __save_button_help = static void get_cur_screen_pos(CtkDisplayConfig *ctk_object) { - nvDisplayPtr display = ctk_display_layout_get_selected_display + nvScreenPtr screen = ctk_display_layout_get_selected_screen (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); - if (!display || !display->screen) return; + if (!screen) return; - ctk_object->cur_screen_pos[X] = display->screen->dim[X]; - ctk_object->cur_screen_pos[Y] = display->screen->dim[Y]; + ctk_object->cur_screen_pos[X] = screen->dim[X]; + ctk_object->cur_screen_pos[Y] = screen->dim[Y]; } /* get_cur_screen_pos() */ @@ -994,16 +1003,30 @@ GtkWidget * create_validation_apply_dialog(CtkDisplayConfig *ctk_object) +/** user_changed_attributes() ************************************* + * + * Turns off forced reset (of the layout config when the current + * X server configuration changes). + * + **/ + static void user_changed_attributes(CtkDisplayConfig *ctk_object) { if (ctk_object->forced_reset_allowed) { gtk_widget_set_sensitive(ctk_object->btn_apply, True); ctk_object->forced_reset_allowed = FALSE; } + } /* user_changed_attributes() */ +/** screen_primary_display_toggled() ****************************** + * + * Sets the primary display for a screen. + * + **/ + static void screen_primary_display_toggled(GtkWidget *widget, gpointer user_data) { @@ -1018,6 +1041,7 @@ static void screen_primary_display_toggled(GtkWidget *widget, } user_changed_attributes(ctk_object); + } /* screen_primary_display_toggled() */ @@ -1348,6 +1372,18 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, gtk_label_set_selectable(GTK_LABEL(ctk_object->txt_screen_num), TRUE); gtk_misc_set_alignment(GTK_MISC(ctk_object->txt_screen_num), 0.0f, 0.5f); + /* X screen virtual size */ + ctk_object->txt_screen_virtual_size = gtk_entry_new(); + ctk_config_set_tooltip(ctk_config, ctk_object->txt_screen_virtual_size, + __screen_virtual_size_help); + g_signal_connect(G_OBJECT(ctk_object->txt_screen_virtual_size), "activate", + G_CALLBACK(screen_virtual_size_activate), + (gpointer) ctk_object); + g_signal_connect(G_OBJECT(ctk_object->txt_screen_virtual_size), + "focus-out-event", + G_CALLBACK(screen_virtual_size_focus_out), + (gpointer) ctk_object); + /* X screen depth */ ctk_object->mnu_screen_depth = gtk_option_menu_new(); ctk_config_set_tooltip(ctk_config, ctk_object->mnu_screen_depth, @@ -1693,6 +1729,17 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, gtk_box_pack_start(GTK_BOX(hbox), ctk_object->txt_screen_num, TRUE, TRUE, 0); + /* X screen virtual size */ + hbox = gtk_hbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + label = gtk_label_new("Virtual Size:"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_widget_set_size_request(label, req.width, -1); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5); + gtk_box_pack_start(GTK_BOX(hbox), ctk_object->txt_screen_virtual_size, + TRUE, TRUE, 0); + ctk_object->box_screen_virtual_size = hbox; + /* X screen depth dropdown */ hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); @@ -1859,7 +1906,7 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table, ctk_help_para(b, &i, "This section shows information and configuration " "settings for the X server layout."); ctk_help_heading(b, &i, "Layout Image"); - ctk_help_para(b, &i, "The layout image shows the geomertic relationship " + ctk_help_para(b, &i, "The layout image shows the geometric relationship " "that display devices and X screens have to each other. " "You may drag display devices around to reposition them. " "When in advanced view, the display's panning domain may " @@ -1867,7 +1914,7 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table, ctk_help_heading(b, &i, "Layout Hidden Label"); ctk_help_para(b, &i, __layout_hidden_label_help); ctk_help_heading(b, &i, "Enable Xinerama"); - ctk_help_para(b, &i, "%s. This setting is only available when multiple " + ctk_help_para(b, &i, "%s This setting is only available when multiple " "X screens are present.", __layout_xinerama_button_help); @@ -1887,7 +1934,7 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table, ctk_help_heading(b, &i, "Mode Name"); ctk_help_para(b, &i, "The Mode name is the name of the modeline that is " "currently chosen for the selected display device. " - "(Advanced view only.)"); + "This is only available when advanced view is enabled."); ctk_help_heading(b, &i, "Position Type"); ctk_help_para(b, &i, __dpy_position_type_help); ctk_help_heading(b, &i, "Position Relative"); @@ -1895,7 +1942,8 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table, ctk_help_heading(b, &i, "Position Offset"); ctk_help_para(b, &i, __dpy_position_offset_help); ctk_help_heading(b, &i, "Panning"); - ctk_help_para(b, &i, "%s (Advanced view only.)", __dpy_panning_help); + ctk_help_para(b, &i, "%s This is only available when advanced " + "view is enabled.", __dpy_panning_help); ctk_help_heading(b, &i, "Primary Display"); ctk_help_para(b, &i, __dpy_primary_help); @@ -1904,6 +1952,10 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table, ctk_help_heading(b, &i, "X Screen Section"); ctk_help_para(b, &i, "This section shows information and configuration " "settings for the currently selected X screen."); + ctk_help_heading(b, &i, "Virtual Size"); + ctk_help_para(b, &i, "%s The Virtual screen size must be at least " + "304x200, and the width must be a multiple of 8.", + __screen_virtual_size_help); ctk_help_heading(b, &i, "Color Depth"); ctk_help_para(b, &i, __screen_depth_help); ctk_help_heading(b, &i, "Position Type"); @@ -1913,17 +1965,18 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table, ctk_help_heading(b, &i, "Position Offset"); ctk_help_para(b, &i, __screen_position_offset_help); ctk_help_heading(b, &i, "MetaMode Selection"); - ctk_help_para(b, &i, "%s (Advanced view only.)", __screen_metamode_help); + ctk_help_para(b, &i, "%s This is only available when advanced view " + "is enabled.", __screen_metamode_help); ctk_help_heading(b, &i, "Add Metamode"); - ctk_help_para(b, &i, "%s (Advanced view only.)", - __screen_metamode_add_button_help); + ctk_help_para(b, &i, "%s This is only available when advanced view " + "is enabled.", __screen_metamode_add_button_help); ctk_help_heading(b, &i, "Delete Metamode"); - ctk_help_para(b, &i, "%s (Advanced view only.)", - __screen_metamode_delete_button_help); + ctk_help_para(b, &i, "%s This is only available when advanced view " + "is enabled.", __screen_metamode_delete_button_help); ctk_help_para(b, &i, ""); - ctk_help_heading(b, &i, "Buttons"); + ctk_help_heading(b, &i, "Buttons"); ctk_help_heading(b, &i, "Apply"); ctk_help_para(b, &i, "%s Note that not all settings can be applied to an " "active X server; these require restarting the X server " @@ -1935,7 +1988,7 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table, ctk_help_para(b, &i, __detect_displays_button_help); ctk_help_heading(b, &i, "Advanced/Basic..."); ctk_help_para(b, &i, "%s The Basic view modifies the currently active " - "MetaMode for an X screen, while the Advanced view exposes " + "MetaMode for an X screen, while the advanced view exposes " "all the MetaModes available on an X screen, and lets you " "modify each of them.", __advanced_button_help); ctk_help_heading(b, &i, "Reset"); @@ -2641,8 +2694,10 @@ static void setup_display_position_relative(CtkDisplayConfig *ctk_object) display = ctk_display_layout_get_selected_display (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); + + /* No need to show dropdown if display position is absolute */ if (!display || !display->screen || !display->cur_mode || !display->gpu) { - return; + goto fail; } @@ -2659,9 +2714,7 @@ static void setup_display_position_relative(CtkDisplayConfig *ctk_object) sizeof(nvDisplayPtr)); if (!ctk_object->display_position_table) { - ctk_object->display_position_table_len = 0; - gtk_widget_hide(ctk_object->mnu_display_position_relative); - return; + goto fail; } @@ -2713,13 +2766,24 @@ static void setup_display_position_relative(CtkDisplayConfig *ctk_object) (idx > 1)); - /* Handle cases where the position relative dropdown should be hidden */ + /* Hide the dropdown if the display position is absolute */ if (display->cur_mode->position_type == CONF_ADJ_ABSOLUTE) { gtk_widget_hide(ctk_object->mnu_display_position_relative); return; } + gtk_widget_show(ctk_object->mnu_display_position_relative); + return; + + fail: + if (ctk_object->display_position_table) { + free(ctk_object->display_position_table); + ctk_object->display_position_table = NULL; + } + ctk_object->display_position_table_len = 0; + gtk_widget_hide(ctk_object->mnu_display_position_relative); + } /* setup_display_position_relative() */ @@ -2807,6 +2871,13 @@ static void setup_display_position(CtkDisplayConfig *ctk_object) } /* setup_display_position */ + +/** setup_primary_display() ****************************************** + * + * Sets up the primary display device for an X screen. + * + **/ + static void setup_primary_display(CtkDisplayConfig *ctk_object) { nvDisplayPtr display = ctk_display_layout_get_selected_display @@ -2964,6 +3035,41 @@ static void setup_display_page(CtkDisplayConfig *ctk_object) +/** setup_screen_virtual_size() ************************************** + * + * Sets up the UI for configuring the virtual width/height of the + * currently selected X screen. + * + **/ + +static void setup_screen_virtual_size(CtkDisplayConfig *ctk_object) +{ + char *tmp_str; + nvScreenPtr screen; + + screen = ctk_display_layout_get_selected_screen + (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); + + + /* Only show this box for no-scannout screens */ + if (!screen || !screen->no_scanout) { + gtk_widget_hide(ctk_object->box_screen_virtual_size); + return; + } + gtk_widget_show(ctk_object->box_screen_virtual_size); + + + /* Update the virtual size text */ + tmp_str = g_strdup_printf("%dx%d", screen->dim[W], screen->dim[H]); + + gtk_entry_set_text(GTK_ENTRY(ctk_object->txt_screen_virtual_size), + tmp_str); + g_free(tmp_str); + +} /* setup_screen_virtual_size() */ + + + /** setup_screen_depth_dropdown() ************************************ * * Generates the color depth dropdown based on the currently selected @@ -2978,10 +3084,10 @@ static void setup_screen_depth_dropdown(CtkDisplayConfig *ctk_object) int cur_idx; int screen_depth_table_len = 0; gboolean add_depth_30_option; - nvDisplayPtr display = ctk_display_layout_get_selected_display + nvScreenPtr screen = ctk_display_layout_get_selected_screen (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); - if (!display || !display->screen) { + if (!screen) { gtk_widget_hide(ctk_object->box_screen_depth); return; } @@ -2998,9 +3104,9 @@ static void setup_screen_depth_dropdown(CtkDisplayConfig *ctk_object) */ if (ctk_object->layout->xinerama_enabled) { - add_depth_30_option = layout_supports_depth_30(display->gpu->layout); + add_depth_30_option = layout_supports_depth_30(screen->gpu->layout); } else { - add_depth_30_option = display->gpu->allow_depth_30; + add_depth_30_option = screen->gpu->allow_depth_30; } if (add_depth_30_option) { @@ -3038,7 +3144,7 @@ static void setup_screen_depth_dropdown(CtkDisplayConfig *ctk_object) (GTK_OPTION_MENU(ctk_object->mnu_screen_depth), menu); for (cur_idx = 0; cur_idx < SCREEN_DEPTH_COUNT; cur_idx++) { - if (display->screen->depth == ctk_object->screen_depth_table[cur_idx]) { + if (screen->depth == ctk_object->screen_depth_table[cur_idx]) { gtk_option_menu_set_history (GTK_OPTION_MENU(ctk_object->mnu_screen_depth), cur_idx); } @@ -3065,12 +3171,12 @@ static void setup_screen_depth_dropdown(CtkDisplayConfig *ctk_object) static void setup_screen_position_type(CtkDisplayConfig *ctk_object) { - nvDisplayPtr display = ctk_display_layout_get_selected_display + nvScreenPtr screen = ctk_display_layout_get_selected_screen (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); /* Handle cases where the position type should be hidden */ - if (!display || !display->screen) { + if (!screen) { gtk_widget_hide(ctk_object->mnu_screen_position_type); return; } @@ -3084,7 +3190,7 @@ static void setup_screen_position_type(CtkDisplayConfig *ctk_object) gtk_option_menu_set_history (GTK_OPTION_MENU(ctk_object->mnu_screen_position_type), - display->screen->position_type); + screen->position_type); g_signal_handlers_unblock_by_func (G_OBJECT(ctk_object->mnu_screen_position_type), @@ -3102,7 +3208,6 @@ static void setup_screen_position_type(CtkDisplayConfig *ctk_object) static void setup_screen_position_relative(CtkDisplayConfig *ctk_object) { - nvDisplayPtr display; nvScreenPtr screen; nvScreenPtr relative_to; nvGpuPtr gpu; @@ -3111,21 +3216,15 @@ static void setup_screen_position_relative(CtkDisplayConfig *ctk_object) GtkWidget *menu; GtkWidget *menu_item; - display = ctk_display_layout_get_selected_display + screen = ctk_display_layout_get_selected_screen (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); - if (!display || !display->cur_mode || !display->gpu || !display->screen) { - return; - } - - screen = display->screen; - - /* Allocate the screen lookup table for the dropdown */ - if (ctk_object->screen_position_table) { - free(ctk_object->screen_position_table); + if (!screen) { + goto fail; } + /* Count the number of screens */ ctk_object->screen_position_table_len = 0; for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { @@ -3137,14 +3236,16 @@ static void setup_screen_position_relative(CtkDisplayConfig *ctk_object) ctk_object->screen_position_table_len--; } + /* Allocate the screen lookup table for the dropdown */ + if (ctk_object->screen_position_table) { + free(ctk_object->screen_position_table); + } ctk_object->screen_position_table = (nvScreenPtr *)calloc(1, ctk_object->screen_position_table_len * sizeof(nvScreenPtr)); if (!ctk_object->screen_position_table) { - ctk_object->screen_position_table_len = 0; - gtk_widget_hide(ctk_object->mnu_screen_position_relative); - return; + goto fail; } @@ -3201,12 +3302,23 @@ static void setup_screen_position_relative(CtkDisplayConfig *ctk_object) (idx > 1)); - /* Handle cases where the position relative dropdown should be hidden */ - if (display->screen->position_type == CONF_ADJ_ABSOLUTE) { + /* Hide the dropdown if the screen position is absolute */ + if (screen->position_type == CONF_ADJ_ABSOLUTE) { gtk_widget_hide(ctk_object->mnu_screen_position_relative); return; } + gtk_widget_show(ctk_object->mnu_screen_position_relative); + return; + + + fail: + if (ctk_object->screen_position_table) { + free(ctk_object->screen_position_table); + ctk_object->screen_position_table = NULL; + } + ctk_object->screen_position_table_len = 0; + gtk_widget_hide(ctk_object->mnu_screen_position_relative); } /* setup_screen_position_relative() */ @@ -3222,17 +3334,16 @@ static void setup_screen_position_relative(CtkDisplayConfig *ctk_object) static void setup_screen_position_offset(CtkDisplayConfig *ctk_object) { char *tmp_str; - nvDisplayPtr display; nvScreenPtr screen; - display = ctk_display_layout_get_selected_display + screen = ctk_display_layout_get_selected_screen (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); /* Handle cases where the position offset should be hidden */ - if (!display || !display->screen || - (display->screen->position_type != CONF_ADJ_ABSOLUTE && - display->screen->position_type != CONF_ADJ_RELATIVE)) { + if (!screen || + (screen->position_type != CONF_ADJ_ABSOLUTE && + screen->position_type != CONF_ADJ_RELATIVE)) { gtk_widget_hide(ctk_object->txt_screen_position_offset); return; } @@ -3240,8 +3351,6 @@ static void setup_screen_position_offset(CtkDisplayConfig *ctk_object) /* Update the position text */ - screen = display->screen; - tmp_str = g_strdup_printf("%+d%+d", screen->dim[X], screen->dim[Y]); gtk_entry_set_text(GTK_ENTRY(ctk_object->txt_screen_position_offset), @@ -3263,7 +3372,7 @@ static void setup_screen_position_offset(CtkDisplayConfig *ctk_object) static void setup_screen_position(CtkDisplayConfig *ctk_object) { nvGpuPtr gpu; - nvDisplayPtr display = ctk_display_layout_get_selected_display + nvScreenPtr screen = ctk_display_layout_get_selected_screen (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); int num_screens; @@ -3276,7 +3385,7 @@ static void setup_screen_position(CtkDisplayConfig *ctk_object) /* Hide the position box if there is only one screen */ - if (!display || !display->screen || num_screens <= 1) { + if (!screen || num_screens <= 1) { gtk_widget_hide(ctk_object->box_screen_position); return; } @@ -3308,7 +3417,10 @@ static void setup_screen_metamode(CtkDisplayConfig *ctk_object) gchar *str; - if (!screen || !layout->advanced_mode) { + /* Only show the metamodes in advanced mode for screens + * that support scanout. + */ + if (!screen || screen->no_scanout || !layout->advanced_mode) { gtk_widget_hide(ctk_object->box_screen_metamode); return; } @@ -3337,7 +3449,7 @@ static void setup_screen_metamode(CtkDisplayConfig *ctk_object) static void setup_screen_page(CtkDisplayConfig *ctk_object) { - nvDisplayPtr display = ctk_display_layout_get_selected_display + nvScreenPtr screen = ctk_display_layout_get_selected_screen (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); gchar *tmp; gint page_num; @@ -3349,7 +3461,7 @@ static void setup_screen_page(CtkDisplayConfig *ctk_object) /* If there is no display or no screen selected, remove the screen page */ - if (!display || !display->screen) { + if (!screen) { gtk_widget_set_sensitive(ctk_object->screen_page, False); if (page_num >= 0) { gtk_notebook_remove_page(GTK_NOTEBOOK(ctk_object->notebook), @@ -3364,11 +3476,15 @@ static void setup_screen_page(CtkDisplayConfig *ctk_object) /* Setup the screen number */ - tmp = g_strdup_printf("%d", display->screen->scrnum); + tmp = g_strdup_printf("%d", screen->scrnum); gtk_label_set_text(GTK_LABEL(ctk_object->txt_screen_num), tmp); g_free(tmp); + /* Setup screen (virtual) size */ + setup_screen_virtual_size(ctk_object); + + /* Setup depth menu */ setup_screen_depth_dropdown(ctk_object); @@ -3931,7 +4047,7 @@ void layout_modified_callback(nvLayoutPtr layout, void *data) /* Sync the information displayed by the GUI to match the settings * of the currently selected display device. */ - + /* Setup position */ setup_display_position(ctk_object); @@ -3941,6 +4057,9 @@ void layout_modified_callback(nvLayoutPtr layout, void *data) setup_screen_position(ctk_object); + /* Setup screen virtual size */ + setup_screen_virtual_size(ctk_object); + /* If the positioning of the X screen changes, we cannot apply */ check_screen_pos_changed(ctk_object); @@ -3953,45 +4072,6 @@ void layout_modified_callback(nvLayoutPtr layout, void *data) /* Widget signal handlers ********************************************/ -/** renumber_xscreens() ********************************************** - * - * Ensures that the screens are numbered from 0 to (n-1). - * - **/ - -static void renumber_xscreens(nvLayoutPtr layout) -{ - nvGpuPtr gpu; - nvScreenPtr screen; - nvScreenPtr lowest; - int scrnum; - - scrnum = 0; - do { - - /* 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; - } - } - } - - if (lowest) { - lowest->scrnum = scrnum; - } - - /* Assign next screen number */ - scrnum++; - } while (lowest); - -} /* renumber_xscreens() */ - - - /** do_enable_display_for_xscreen() ********************************** * * Adds the display device to a separate X screen in the layout. @@ -4084,6 +4164,7 @@ void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object, } else { screen->position_type = CONF_ADJ_ABSOLUTE; + screen->relative_to = NULL; screen->dim[X] = mode->dim[X]; screen->dim[Y] = mode->dim[Y]; } @@ -4296,6 +4377,7 @@ static void do_enable_display_for_twinview(CtkDisplayConfig *ctk_object, mode->pan[Y] = mode->dim[Y]; } else { mode->position_type = CONF_ADJ_ABSOLUTE; + mode->relative_to = NULL; mode->dim[X] = metamode->dim[X] + metamode->dim[W]; mode->dim[Y] = metamode->dim[Y]; mode->pan[X] = mode->dim[X]; @@ -4683,7 +4765,6 @@ void do_disable_display(CtkDisplayConfig *ctk_object, nvDisplayPtr display) { nvLayoutPtr layout = ctk_object->layout; nvGpuPtr gpu = display->gpu; - nvScreenPtr screen = display->screen; gchar *str; gchar *type = display_get_type_str(display->device_mask, 0); @@ -4710,22 +4791,10 @@ void do_disable_display(CtkDisplayConfig *ctk_object, nvDisplayPtr display) "Cancel"); - /* Ask user what to do */ + /* Confirm with user before disabling */ if (do_query_remove_display(ctk_object, display)) { - - /* Remove display from the X screen */ - screen_remove_display(display); - - /* If the screen is empty, remove it */ - if (!screen->num_displays) { - gpu_remove_and_free_screen(screen); - - /* Make sure screen numbers are consistent */ - renumber_xscreens(ctk_object->layout); - } - - /* Add the fake mode to the display */ - gpu_add_screenless_modes_to_displays(display->gpu); + ctk_display_layout_disable_display(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), + display); } } /* do_disable_display() */ @@ -4927,8 +4996,15 @@ static void display_config_clicked(GtkWidget *widget, gpointer user_data) /* Sync the GUI */ if (update) { - /* Recaltulate */ - ctk_display_layout_redraw(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); + /* Update the z-order */ + ctk_display_layout_update_zorder(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); + + /* Make sure the display is still selected */ + ctk_display_layout_select_display(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), + display); + + /* Recalculate */ + ctk_display_layout_update(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); /* Auto fix all screens on the gpu */ { @@ -5164,6 +5240,7 @@ static void display_position_type_changed(GtkWidget *widget, setup_display_position_offset(ctk_object); user_changed_attributes(ctk_object); + } /* display_position_type_changed() */ @@ -5314,6 +5391,58 @@ static gboolean display_panning_focus_out(GtkWidget *widget, GdkEvent *event, +/** screen_virtual_size_activate() *********************************** + * + * Called when user modifies the screen virtual size text entry. + * + **/ + +static void screen_virtual_size_activate(GtkWidget *widget, gpointer user_data) +{ + CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data); + const gchar *str = gtk_entry_get_text(GTK_ENTRY(widget)); + int x, y; + nvScreenPtr screen = ctk_display_layout_get_selected_screen + (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout)); + + + if (!screen || !screen->no_scanout) { + return; + } + + str = parse_read_integer_pair(str, 'x', &x, &y); + if (!str) { + /* Reset the display panning */ + setup_screen_virtual_size(ctk_object); + return; + } + + ctk_display_layout_set_screen_virtual_size + (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), screen, x, y); + + setup_screen_virtual_size(ctk_object); + +} /* screen_virtual_size_activate() */ + + + +/** screen_virtual_size_focus_out() ********************************** + * + * Called when user leaves the screen virtual size entry + * + **/ + +static gboolean screen_virtual_size_focus_out(GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + screen_virtual_size_activate(widget, user_data); + + return FALSE; + +} /* screen_virtual_size_focus_out() */ + + /** screen_depth_changed() ******************************************* * @@ -6283,6 +6412,7 @@ static void apply_clicked(GtkWidget *widget, gpointer user_data) for (screen = gpu->screens; screen; screen = screen->next) { if (!screen->handle) continue; + if (screen->no_scanout) continue; if (!update_screen_metamodes(ctk_object, screen)) { clear_apply = FALSE; @@ -6649,6 +6779,8 @@ static XConfigDevicePtr add_device_to_xconfig(nvGpuPtr gpu, XConfigPtr config, static Bool add_display_to_screen(nvScreenPtr screen, XConfigScreenPtr conf_screen) { + XConfigDisplayPtr conf_display; + /* Clear the display list */ xconfigFreeDisplayList(&conf_screen->displays); @@ -6657,6 +6789,13 @@ static Bool add_display_to_screen(nvScreenPtr screen, xconfigAddDisplay(&conf_screen->displays, conf_screen->defaultdepth); if (!conf_screen->displays) goto fail; + /* Configure the virtual screen size */ + if (screen->no_scanout) { + conf_display = conf_screen->displays; + + conf_display->virtualX = screen->dim[W]; + conf_display->virtualY = screen->dim[H]; + } /* XXX Don't do any further tweaking to the display subsection. * All mode configuration should be done through the 'MetaModes" @@ -6704,72 +6843,82 @@ static int add_screen_to_xconfig(CtkDisplayConfig *ctk_object, conf_screen->device = screen->conf_device; - /* Find the first display on the screen */ - for (display = screen->gpu->displays; display; display = display->next) { - if (display->screen == screen) { - break; - } - } - 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!", - display->name, screen->scrnum); - goto fail; - } - + if (screen->no_scanout) { + /* Configure screen for no scanout */ - /* Tie the screen to the monitor section */ - conf_screen->monitor_name = - xconfigStrdup(display->conf_monitor->identifier); - conf_screen->monitor = display->conf_monitor; + /* Set the UseDisplayDevice option to "none" */ + xconfigAddNewOption(&conf_screen->options, "UseDisplayDevice", "none"); + } else { + /* Configure screen for scanout */ - /* 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 */ - add_modelines_to_monitor(display->conf_monitor, other->modes); - } + /* Find the first display on the screen */ + for (display = screen->gpu->displays; display; display = display->next) { + if (display->screen == screen) { + break; + } + } + if (!display) { + nv_error_msg("Unable to find a display device for screen %d!", + screen->scrnum); + goto fail; + } - /* Set the TwinView option */ - xconfigAddNewOption(&conf_screen->options, "TwinView", - ((screen->num_displays > 1) ? "1" : "0" )); + + /* 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!", + display->name, screen->scrnum); + goto fail; + } - /* Set the TwinviewXineramaInfoOrder option */ - if (screen->primaryDisplay) { - gchar *primary_str = - display_get_type_str(screen->primaryDisplay->device_mask, 0); + /* Tie the screen to the monitor section */ + conf_screen->monitor_name = + xconfigStrdup(display->conf_monitor->identifier); + conf_screen->monitor = display->conf_monitor; - xconfigAddNewOption(&conf_screen->options, "TwinViewXineramaInfoOrder", - primary_str); - g_free(primary_str); - } - /* Create the "metamode" option string. */ - ret = generate_xconf_metamode_str(ctk_object, screen, &metamode_strs); - if (ret != XCONFIG_GEN_OK) goto bail; + /* 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 */ + add_modelines_to_monitor(display->conf_monitor, other->modes); + } - /* If no user specified metamodes were found, add - * whatever the currently selected metamode is - */ - if (!metamode_strs) { - metamode_strs = screen_get_metamode_str(screen, - screen->cur_metamode_idx, 1); - } + /* 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); + } - if (metamode_strs) { - xconfigAddNewOption(&conf_screen->options, "metamodes", metamode_strs); - free(metamode_strs); + /* Create the "metamode" option string. */ + ret = generate_xconf_metamode_str(ctk_object, screen, &metamode_strs); + if (ret != XCONFIG_GEN_OK) goto bail; + + /* If no user specified metamodes were found, add + * whatever the currently selected metamode is + */ + if (!metamode_strs) { + metamode_strs = screen_get_metamode_str(screen, + screen->cur_metamode_idx, 1); + } + + if (metamode_strs) { + xconfigAddNewOption(&conf_screen->options, "metamodes", metamode_strs); + free(metamode_strs); + } } diff --git a/src/gtk+-2.x/ctkdisplayconfig.h b/src/gtk+-2.x/ctkdisplayconfig.h index 32a41a0..3c03224 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.h +++ b/src/gtk+-2.x/ctkdisplayconfig.h @@ -115,6 +115,9 @@ typedef struct _CtkDisplayConfig GtkWidget *txt_screen_num; /* X Screen - Settings */ + GtkWidget *box_screen_virtual_size; + GtkWidget *txt_screen_virtual_size; + GtkWidget *box_screen_depth; GtkWidget *mnu_screen_depth; diff --git a/src/gtk+-2.x/ctkdisplaylayout.c b/src/gtk+-2.x/ctkdisplaylayout.c index 62a2125..b572a4d 100644 --- a/src/gtk+-2.x/ctkdisplaylayout.c +++ b/src/gtk+-2.x/ctkdisplaylayout.c @@ -34,6 +34,7 @@ #include "ctkevent.h" #include "ctkhelp.h" #include "ctkdisplaylayout.h" +#include "ctkdisplayconfig-utils.h" @@ -167,45 +168,66 @@ static void zorder_layout(CtkDisplayLayout *ctk_object) { nvLayoutPtr layout = ctk_object->layout; nvGpuPtr gpu; + nvScreenPtr screen; + nvDisplayPtr display; int i; - - /* Clear the list */ + + /* Clean up */ if (ctk_object->Zorder) { free(ctk_object->Zorder); ctk_object->Zorder = NULL; } ctk_object->Zcount = 0; - ctk_object->Zselected = 0; + ctk_object->selected_display = NULL; - /* Count the number of displays in the layout */ + /* Count the number of Z-orderable elements in the layout */ for (gpu = layout->gpus; gpu; gpu = gpu->next) { - ctk_object->Zcount += gpu->num_displays; + ctk_object->Zcount += gpu->num_displays + gpu->num_screens; } - /* If there are no displays, we're done */ + /* If there is nothing Z-orderable, we're done */ if (!ctk_object->Zcount) { return; } - /* Create the Z order list buffer */ - ctk_object->Zorder = - (nvDisplayPtr *)calloc(1, ctk_object->Zcount *sizeof(nvDisplayPtr)); + /* Create the Z-order buffer */ + ctk_object->Zorder = (ZNode *)calloc(ctk_object->Zcount, sizeof(ZNode)); if (!ctk_object->Zorder) { ctk_object->Zcount = 0; return; } - /* Populate the Z order list */ + /* Populate the Z-order list */ i = 0; for (gpu = layout->gpus; gpu; gpu = gpu->next) { - nvDisplayPtr display; + // 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++; + } + } + + // Add the screen + ctk_object->Zorder[i].type = ZNODE_TYPE_SCREEN; + ctk_object->Zorder[i].u.screen = screen; + i++; + } + // Add displays that don't have screens. for (display = gpu->displays; display; display = display->next) { - ctk_object->Zorder[i++] = display; + if (!display->screen) { + ctk_object->Zorder[i].type = ZNODE_TYPE_DISPLAY; + ctk_object->Zorder[i].u.display = display; + i++; + } } } @@ -215,18 +237,23 @@ static void zorder_layout(CtkDisplayLayout *ctk_object) /** get_selected() *************************************************** * - * Returns the currently selected display. The selected display - * device should always be at the top of the Z-order. + * Returns the currently selected display and/or screen. This + * function is only useful for keeping track of when something new + * has been selected. * **/ -static nvDisplayPtr get_selected(CtkDisplayLayout *ctk_object) +static void * get_selected(CtkDisplayLayout *ctk_object) { - if (!(ctk_object->Zselected) || !(ctk_object->Zcount)) { - return NULL; + if (ctk_object->selected_display) { + return ctk_object->selected_display; } - return ctk_object->Zorder[0]; + if (ctk_object->selected_screen) { + return ctk_object->selected_screen; + } + + return NULL; } /* get_selected() */ @@ -275,29 +302,143 @@ static nvModePtr get_mode(nvDisplayPtr display, int mode_idx) -/** sync_modify() **************************************************** +/** get_screen_dim *************************************************** + * + * Returns the dimension array to use as the screen's dimensions. + * + **/ + +static int *get_screen_dim(nvScreenPtr screen, Bool edim) +{ + if (!screen) return NULL; + + if (screen->no_scanout || !screen->cur_metamode) { + return screen->dim; + } + + return edim ? screen->cur_metamode->edim : screen->cur_metamode->dim; + +} /* get_screen_dim() */ + + + +/** get_modify_info() ************************************************ * - * When the user is moving/panning a display device around, a - * temporary dimension buffer is used to allow for snapping to other - * displays. + * Gather information prior to moving/panning. * - * This function sets up the temporary buffer by copying the actual - * dimensions of the selected display device to the temporary buffer. + * Returns TRUE if something is selected and movable. * **/ -static void sync_modify(CtkDisplayLayout *ctk_object) +static Bool get_modify_info(CtkDisplayLayout *ctk_object) { - nvDisplayPtr display = get_selected(ctk_object); + ModifyInfo *info = &(ctk_object->modify_info); + Bool use_screen_instead; + int *sdim; + + + info->screen = ctk_object->selected_screen; + info->display = ctk_object->selected_display; + + + /* There must be an associated screen to move */ + if (!info->screen) { + info->display = NULL; + return FALSE; + } + + /* Don't allow modifying displays without modes */ + if (info->display && !info->display->cur_mode) { + info->screen = NULL; + info->display = NULL; + return FALSE; + } + + + /* Gather the initial screen dimensions */ + sdim = get_screen_dim(info->screen, 0); + info->orig_screen_dim[X] = sdim[X]; + info->orig_screen_dim[Y] = sdim[Y]; + info->orig_screen_dim[W] = sdim[W]; + info->orig_screen_dim[H] = sdim[H]; + + + /* If a display device is being moved (not panned) and + * it is the only display device in the screen to use + * absolute positioning, then really we want to move + * its associated screen. + */ + if (!ctk_object->modify_info.modify_panning && + info->display && + info->display->cur_mode->position_type == CONF_ADJ_ABSOLUTE) { + + nvDisplayPtr display; + + /* Make sure all other displays in the screen use + * relative positioning. + */ + use_screen_instead = TRUE; + for (display = info->display->gpu->displays; display; + display = display->next) { + if (display->screen != info->screen) continue; + if (display == info->display) continue; + if (!display->cur_mode) continue; + if (display->cur_mode->position_type == CONF_ADJ_ABSOLUTE) { + use_screen_instead = FALSE; + } + } + if (use_screen_instead) { + info->display = NULL; + } + } + + + /* Gather the initial state of what is being moved */ + if (info->display) { + info->target_position_type = + &(info->display->cur_mode->position_type); + if (ctk_object->modify_info.modify_panning) { + info->target_dim = info->display->cur_mode->pan; + } else { + info->target_dim = info->display->cur_mode->dim; + } + info->gpu = info->display->gpu; + } else { + info->target_position_type = &(info->screen->position_type); + info->target_dim = sdim; + info->gpu = info->screen->gpu; + } + info->orig_position_type = *(info->target_position_type); + info->orig_dim[X] = info->target_dim[X]; + info->orig_dim[Y] = info->target_dim[Y]; + info->orig_dim[W] = info->target_dim[W]; + info->orig_dim[H] = info->target_dim[H]; + - if (display && display->cur_mode) { - ctk_object->modify_dim[X] = display->cur_mode->pan[X]; - ctk_object->modify_dim[Y] = display->cur_mode->pan[Y]; - ctk_object->modify_dim[W] = display->cur_mode->pan[W]; - ctk_object->modify_dim[H] = display->cur_mode->pan[H]; + /* Initialize where we moved to */ + info->dst_dim[X] = info->orig_dim[X]; + info->dst_dim[Y] = info->orig_dim[Y]; + info->dst_dim[W] = info->orig_dim[W]; + info->dst_dim[H] = info->orig_dim[H]; + + + /* Initialize snapping */ + info->best_snap_v = ctk_object->snap_strength +1; + info->best_snap_h = ctk_object->snap_strength +1; + + + /* Make sure the modify dim is up to date */ + if (info->modify_dirty) { + info->modify_dim[X] = info->orig_dim[X]; + info->modify_dim[Y] = info->orig_dim[Y]; + info->modify_dim[W] = info->orig_dim[W]; + info->modify_dim[H] = info->orig_dim[H]; + info->modify_dirty = 0; } -} /* sync_modify() */ + return TRUE; + +} /* get_modify_info() */ @@ -459,6 +600,7 @@ static void offset_layout(nvLayoutPtr layout, int x, int y) offset_display(display, x, y); } } + } /* offset functions */ @@ -592,22 +734,23 @@ static void resolve_displays_in_screen(nvScreenPtr screen, int all_modes) static int resolve_screen(nvScreenPtr screen, int pos[4]) { - nvMetaModePtr metamode = screen->cur_metamode; + int *sdim = get_screen_dim(screen, 0); int relative_pos[4]; - if (!metamode) return 0; + + if (!sdim) return 0; /* Set the dimensions */ - pos[W] = metamode->dim[W]; - pos[H] = metamode->dim[H]; + pos[W] = sdim[W]; + pos[H] = sdim[H]; /* Find the position */ switch (screen->position_type) { case CONF_ADJ_ABSOLUTE: - pos[X] = metamode->dim[X]; - pos[Y] = metamode->dim[Y]; + pos[X] = sdim[X]; + pos[Y] = sdim[Y]; break; case CONF_ADJ_RIGHTOF: @@ -662,15 +805,17 @@ static void resolve_screen_in_layout(nvScreenPtr screen) nvDisplayPtr display; int pos[4]; 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] - screen->cur_metamode->dim[X]; - y = pos[Y] - screen->cur_metamode->dim[Y]; + x = pos[X] - sdim[X]; + y = pos[Y] - sdim[Y]; offset_screen(screen, x, y); @@ -815,7 +960,7 @@ static void calc_screen(nvScreenPtr screen) int *dim; - if (!screen) return; + if (!screen || screen->no_scanout) return; dim = screen->dim; metamode = screen->metamodes; @@ -890,7 +1035,7 @@ static void calc_layout(nvLayoutPtr layout) int *sdim; calc_screen(screen); - sdim = screen->cur_metamode->dim; + sdim = get_screen_dim(screen, 0); if (init) { dim[X] = sdim[X]; @@ -1115,28 +1260,28 @@ static void snap_dim_to_dim(int *dst, int *src, int *snap, int snap_strength, /* Snap top side to top side */ dist = abs(snap[Y] - src[Y]); - if (dist <= snap_strength && dist < *best_vert) { + if (dist < *best_vert) { dst[Y] = snap[Y]; *best_vert = dist; } /* Snap top side to bottom side */ dist = abs((snap[Y] + snap[H]) - src[Y]); - if (dist <= snap_strength && dist < *best_vert) { + if (dist < *best_vert) { dst[Y] = snap[Y] + snap[H]; *best_vert = dist; } /* Snap bottom side to top side */ dist = abs(snap[Y] - (src[Y] + src[H])); - if (dist <= snap_strength && dist < *best_vert) { + if (dist < *best_vert) { dst[Y] = snap[Y] - src[H]; *best_vert = dist; } /* Snap bottom side to bottom side */ dist = abs((snap[Y] + snap[H]) - (src[Y] + src[H])); - if (dist <= snap_strength && dist < *best_vert) { + if (dist < *best_vert) { dst[Y] = snap[Y] + snap[H] - src[H]; *best_vert = dist; } @@ -1149,7 +1294,7 @@ static void snap_dim_to_dim(int *dst, int *src, int *snap, int snap_strength, /* Snap vertically */ dist = abs((snap[Y] + snap[H]/2) - (src[Y]+src[H]/2)); - if (dist <= snap_strength && dist < *best_vert) { + if (dist < *best_vert) { dst[Y] = snap[Y] + snap[H]/2 - src[H]/2; *best_vert = dist; } @@ -1162,28 +1307,28 @@ static void snap_dim_to_dim(int *dst, int *src, int *snap, int snap_strength, /* Snap left side to left side */ dist = abs(snap[X] - src[X]); - if (dist <= snap_strength && dist < *best_horz) { + if (dist < *best_horz) { dst[X] = snap[X]; *best_horz = dist; } /* Snap left side to right side */ dist = abs((snap[X] + snap[W]) - src[X]); - if (dist <= snap_strength && dist < *best_horz) { + if (dist < *best_horz) { dst[X] = snap[X] + snap[W]; *best_horz = dist; } /* Snap right side to left side */ dist = abs(snap[X] - (src[X] + src[W])); - if (dist <= snap_strength && dist < *best_horz) { + if (dist < *best_horz) { dst[X] = snap[X] - src[W]; *best_horz = dist; } /* Snap right side to right side */ dist = abs((snap[X] + snap[W]) - (src[X]+src[W])); - if (dist <= snap_strength && dist < *best_horz) { + if (dist < *best_horz) { dst[X] = snap[X] + snap[W] - src[W]; *best_horz = dist; } @@ -1196,7 +1341,7 @@ static void snap_dim_to_dim(int *dst, int *src, int *snap, int snap_strength, /* Snap vertically */ dist = abs((snap[X] + snap[W]/2) - (src[X]+src[W]/2)); - if (dist <= snap_strength && dist < *best_horz) { + if (dist < *best_horz) { dst[X] = snap[X] + snap[W]/2 - src[W]/2; *best_horz = dist; } @@ -1215,7 +1360,7 @@ static void snap_dim_to_dim(int *dst, int *src, int *snap, int snap_strength, * **/ -static void snap_side_to_dim(int *dst, int *src, int *snap, int snap_strength, +static void snap_side_to_dim(int *dst, int *src, int *snap, int *best_vert, int *best_horz) { int dist; @@ -1226,14 +1371,14 @@ static void snap_side_to_dim(int *dst, int *src, int *snap, int snap_strength, /* Snap side to top side */ dist = abs(snap[Y] - (src[Y] + src[H])); - if (dist <= snap_strength && dist < *best_vert) { + if (dist < *best_vert) { dst[H] = snap[Y] - src[Y]; *best_vert = dist; } /* Snap side to bottom side */ dist = abs((snap[Y] + snap[H]) - (src[Y] + src[H])); - if (dist <= snap_strength && dist < *best_vert) { + if (dist < *best_vert) { dst[H] = snap[Y] + snap[H] - src[Y]; *best_vert = dist; } @@ -1245,14 +1390,14 @@ static void snap_side_to_dim(int *dst, int *src, int *snap, int snap_strength, /* Snap side to left side */ dist = abs(snap[X] - (src[X] + src[W])); - if (dist <= snap_strength && dist < *best_horz) { + if (dist < *best_horz) { dst[W] = snap[X] - src[X]; *best_horz = dist; } /* Snap side to right side */ dist = abs((snap[X] + snap[W]) - (src[X] + src[W])); - if (dist <= snap_strength && dist < *best_horz) { + if (dist < *best_horz) { dst[W] = snap[X] + snap[W] - src[X]; *best_horz = dist; } @@ -1264,328 +1409,387 @@ static void snap_side_to_dim(int *dst, int *src, int *snap, int snap_strength, /** snap_move() ***************************************************** * - * Snaps the given dimensions 'dim' (viewport or panning domain of - * a dislay) to other display devices' viewport and/or panning - * domains in the layout due to a move. - * - * Returns 1 if a snap occured, 0 if not. + * Snaps the modify info's source dimensions (src_dim) to other + * displays/screens by moving the top left coord of the src_dim + * such that one or two of the edges of the src_dim line up + * with the closest other screen/display's dimensions. The results + * of the snap are placed into the destination dimensions (dst_dim). * **/ -static int snap_move(CtkDisplayLayout *ctk_object, int *dim) +static void snap_move(CtkDisplayLayout *ctk_object) { - int dim_orig[4]; - int best_vert; - int best_horz; + ModifyInfo *info = &(ctk_object->modify_info); int *bv; int *bh; - int z; + int i; int dist; - nvDisplayPtr display; - nvDisplayPtr other; nvGpuPtr gpu; nvScreenPtr screen; - - - display = get_selected(ctk_object); - gpu = display->gpu; - screen = display->screen; - - - /* We will know that a snap occured if - * 'best_xxxx' <= ctk_object->snap_strength, so we - * initialize both directions to not having snapped here. - */ - best_vert = ctk_object->snap_strength +1; - best_horz = ctk_object->snap_strength +1; - - - /* Copy the original dimensions (Always snap from this reference) */ - dim_orig[X] = dim[X]; - dim_orig[Y] = dim[Y]; - dim_orig[W] = dim[W]; - dim_orig[H] = dim[H]; + nvDisplayPtr other; + int *sdim; /* Snap to other display's modes */ - for (z = 1; z < ctk_object->Zcount; z++) { - - other = ctk_object->Zorder[z]; - - /* Other display must have a mode */ - if (!other || !other->cur_mode || !other->screen) continue; - - - bv = &best_vert; - bh = &best_horz; + if (info->display) { + for (i = 0; i < ctk_object->Zcount; i++) { + + if (ctk_object->Zorder[i].type != ZNODE_TYPE_DISPLAY) continue; + + other = ctk_object->Zorder[i].u.display; + + /* Other display must have a mode */ + if (!other || !other->cur_mode || !other->screen || + other == info->display) continue; + + /* Don't snap to displays that are somehow related. + * XXX Check for nested relations. + */ + if (((other->cur_mode->position_type != CONF_ADJ_ABSOLUTE) && + (other->cur_mode->relative_to == info->display)) || + ((info->display->cur_mode->position_type != CONF_ADJ_ABSOLUTE) && + (info->display->cur_mode->relative_to == other))) { + continue; + } - /* We shouldn't snap horizontally to the other display if - * we are in a right-of/left-of relative relationship with - * the other display/display's screen. - */ - if (((other->cur_mode->position_type == CONF_ADJ_RIGHTOF) || - (other->cur_mode->position_type == CONF_ADJ_LEFTOF)) && - (other->cur_mode->relative_to == display)) { - bh = NULL; - } - if (((display->cur_mode->position_type == CONF_ADJ_RIGHTOF) || - (display->cur_mode->position_type == CONF_ADJ_LEFTOF)) && - (display->cur_mode->relative_to == other)) { - bh = NULL; - } - if (display->screen && other->screen && - ((other->screen->position_type == CONF_ADJ_RIGHTOF) || - (other->screen->position_type == CONF_ADJ_LEFTOF)) && - (other->screen->relative_to == display->screen)) { - bh = NULL; - } - if (display->screen && other->screen && - ((display->screen->position_type == CONF_ADJ_RIGHTOF) || - (display->screen->position_type == CONF_ADJ_LEFTOF)) && - (display->screen->relative_to == other->screen)) { - bh = NULL; - } + /* 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. + */ + bv = &info->best_snap_v; + bh = &info->best_snap_h; + + if (((other->screen->position_type == CONF_ADJ_RIGHTOF) || + (other->screen->position_type == CONF_ADJ_LEFTOF)) && + (other->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 == other->screen)) { + bh = NULL; + } - /* If we aren't snapping horizontally with the other display, - * we shouldn't snap vertically either if this is the top-most - * display in the screen. - */ - if (!bh && display->cur_mode->dim[Y] == display->screen->dim[Y]) { - bv = NULL; + if (((other->screen->position_type == CONF_ADJ_ABOVE) || + (other->screen->position_type == CONF_ADJ_BELOW)) && + (other->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 == other->screen)) { + bv = NULL; + } + + /* Snap to other display's panning dimensions */ + snap_dim_to_dim(info->dst_dim, + info->src_dim, + other->cur_mode->pan, + ctk_object->snap_strength, bv, bh); + + /* Snap to other display's dimensions */ + snap_dim_to_dim(info->dst_dim, + info->src_dim, + other->cur_mode->dim, + ctk_object->snap_strength, bv, bh); } + } /* Done snapping to other displays */ - /* We shouldn't snap vertically to the other display if - * we are in a above/below relative relationship with - * the other display/display's screen. - */ - if (((other->cur_mode->position_type == CONF_ADJ_ABOVE) || - (other->cur_mode->position_type == CONF_ADJ_BELOW)) && - (other->cur_mode->relative_to == display)) { - bv = NULL; - } - if (((display->cur_mode->position_type == CONF_ADJ_ABOVE) || - (display->cur_mode->position_type == CONF_ADJ_BELOW)) && - (display->cur_mode->relative_to == other)) { - bv = NULL; - } - - if (display->screen && other->screen && - ((other->screen->position_type == CONF_ADJ_ABOVE) || - (other->screen->position_type == CONF_ADJ_BELOW)) && - (other->screen->relative_to == display->screen)) { - bv = NULL; - } - if (display->screen && other->screen && - ((display->screen->position_type == CONF_ADJ_ABOVE) || - (display->screen->position_type == CONF_ADJ_BELOW)) && - (display->screen->relative_to == other->screen)) { - bv = NULL; - } - /* If we aren't snapping vertically with the other display, - * we shouldn't snap horizontally either if this is the left-most - * display in the screen. - */ - if (!bv && display->cur_mode->dim[X] == display->screen->dim[X]) { - bh = NULL; - } + /* 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; + + /* 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. + */ + + bv = &info->best_snap_v; + bh = &info->best_snap_h; + + 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 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; + } - /* Snap to other display's panning dimensions */ - snap_dim_to_dim(dim, - dim_orig, - ctk_object->Zorder[z]->cur_mode->pan, - ctk_object->snap_strength, - bv, bh); + /* 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; + } - /* Snap to other display's dimensions */ - snap_dim_to_dim(dim, - dim_orig, - ctk_object->Zorder[z]->cur_mode->dim, - ctk_object->snap_strength, - bv, bh); + 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 */ - dist = abs(screen->dim[X] + gpu->max_width - dim_orig[W] - dim_orig[X]); - if (dist <= ctk_object->snap_strength && dist < best_horz) { - dim[X] = screen->dim[X] + gpu->max_width - dim_orig[W]; - best_horz = dist; - } - dist = abs(screen->dim[Y] + gpu->max_height - dim_orig[H] - dim_orig[Y]); - if (dist <= ctk_object->snap_strength && dist < best_vert) { - dim[Y] = screen->dim[Y] + gpu->max_height - dim_orig[H]; - best_vert = dist; + bv = &info->best_snap_v; + bh = &info->best_snap_h; + + if (info->display) { + dist = abs( (info->screen->dim[X] + info->gpu->max_width) + -(info->src_dim[X] + info->src_dim[W])); + if (dist < *bh) { + info->dst_dim[X] = + info->screen->dim[X] + info->gpu->max_width - info->src_dim[W]; + *bh = dist; + } + dist = abs( (info->screen->dim[Y] + info->gpu->max_height) + -(info->src_dim[Y] + info->src_dim[H])); + if (dist < *bv) { + info->dst_dim[Y] = + info->screen->dim[Y] + info->gpu->max_height - info->src_dim[H]; + *bv = dist; + } } - - return (best_vert <= ctk_object->snap_strength || - best_horz <= ctk_object->snap_strength); - } /* snap_move() */ /** snap_pan() ****************************************************** * - * Snaps the bottom right of the panning domain given 'pan' of the - * currently selected display to other display devices' viewport - * and/or panning domains in the layout due to a panning domain - * resize. + * Snaps the modify info's source dimensions (src_dim) bottom right + * edge(s) to other displays/screens by growing/shrinking the + * size of the src_dim such that the edge(s) of the src_dim line up + * with the closest other screen/display's dimensions. The results + * of the snap are placed into the destination dimensions (dst_dim). * - * Returns 1 if a snap happened, 0 if not. + * This is used for changing both the panning domain of a display + * device as well as setting a (no-scannout) screen's virtual size. * **/ -static int snap_pan(CtkDisplayLayout *ctk_object, int *pan, int *dim) +static void snap_pan(CtkDisplayLayout *ctk_object) { - int pan_orig[4]; - int best_vert; - int best_horz; + ModifyInfo *info = &(ctk_object->modify_info); int *bv; int *bh; - int z; + int i; int dist; - nvDisplayPtr display; - nvDisplayPtr other; nvGpuPtr gpu; nvScreenPtr screen; + nvDisplayPtr other; + int *sdim; - display = get_selected(ctk_object); - gpu = display->gpu; - screen = display->screen; - + if (info->display) { + /* Snap to multiples of the display's dimensions */ + bh = &(info->best_snap_h); + bv = &(info->best_snap_v); - /* We will know that a snap occured if - * 'best_xxxx' <= ctk_object->snap_strength, so we - * initialize both directions to not having snapped here. - */ - best_vert = ctk_object->snap_strength +1; - best_horz = ctk_object->snap_strength +1; + dist = info->src_dim[W] % info->display->cur_mode->dim[W]; + if (dist < *bh) { + info->dst_dim[W] = info->display->cur_mode->dim[W] * + (int)(info->src_dim[W] / info->display->cur_mode->dim[W]); + *bh = dist; + } + dist = info->display->cur_mode->dim[W] - + (info->src_dim[W] % info->display->cur_mode->dim[W]); + if (dist < *bh) { + info->dst_dim[W] = info->display->cur_mode->dim[W] * + (1 + (int)(info->src_dim[W] / info->display->cur_mode->dim[W])); + *bh = dist; + } + dist = abs(info->src_dim[H] % info->display->cur_mode->dim[H]); + if (dist < *bv) { + info->dst_dim[H] = info->display->cur_mode->dim[H] * + (int)(info->src_dim[H] / info->display->cur_mode->dim[H]); + *bv = dist; + } + dist = info->display->cur_mode->dim[H] - + (info->src_dim[H] % info->display->cur_mode->dim[H]); + if (dist < *bv) { + info->dst_dim[H] = info->display->cur_mode->dim[H] * + (1 + (int)(info->src_dim[H] / info->display->cur_mode->dim[H])); + *bv = dist; + } + } - /* Copy the original dimensions (Always snap from this reference) */ - pan_orig[X] = pan[X]; - pan_orig[Y] = pan[Y]; - pan_orig[W] = pan[W]; - pan_orig[H] = pan[H]; + /* Snap to other display's modes */ + for (i = 0; i < ctk_object->Zcount; i++) { + if (ctk_object->Zorder[i].type != ZNODE_TYPE_DISPLAY) continue; - /* Snap to other display's modes */ - for (z = 1; z < ctk_object->Zcount; z++) { + other = ctk_object->Zorder[i].u.display; - other = ctk_object->Zorder[z]; - /* Other display must have a mode */ - if (!other || !other->cur_mode || !other->screen) continue; + if (!other || !other->cur_mode || !other->screen || + other == info->display) continue; - bv = &best_vert; - bh = &best_horz; + /* NOTE: When display devices are relative to each other, + * we may still want to allow snapping of the non-related + * edges. This is useful, for example, when two + * displays have a right of/left of relationtship and + * one of the displays is taller. + */ + bv = &info->best_snap_v; + bh = &info->best_snap_h; - /* Don't snap to other displays that are positioned right of - * the display being panned. + /* Don't snap horizontally to other displays that are somehow + * related on the right edge of the display being panned. */ - if ((other->cur_mode->position_type == CONF_ADJ_RIGHTOF) && - other->cur_mode->relative_to == display) { - bh = NULL; - } - if ((display->cur_mode->position_type == CONF_ADJ_LEFTOF) && - display->cur_mode->relative_to == other) { - bh = NULL; + if (info->display) { + if ((other->cur_mode->position_type == CONF_ADJ_RIGHTOF) && + other->cur_mode->relative_to == info->display) { + bh = NULL; + } + if ((info->display->cur_mode->position_type == CONF_ADJ_LEFTOF) && + info->display->cur_mode->relative_to == other) { + bh = NULL; + } } - if (display->screen && other->screen && - (other->screen->position_type == CONF_ADJ_RIGHTOF) && - (other->screen->relative_to == display->screen)) { + if ((other->screen->position_type == CONF_ADJ_RIGHTOF) && + other->screen->relative_to == info->screen) { bh = NULL; } - if (display->screen && other->screen && - (display->screen->position_type == CONF_ADJ_LEFTOF) && - (display->screen->relative_to == other->screen)) { + if ((info->screen->position_type == CONF_ADJ_LEFTOF) && + info->screen->relative_to == other->screen) { bh = NULL; } - /* Don't snap to other displays that are positioned below of - * the display being panned. + /* Don't snap vertically to other displays that are somehow + * related on the bottom edge of the display being panned. */ - if ((other->cur_mode->position_type == CONF_ADJ_BELOW) && - other->cur_mode->relative_to == display) { - bv = NULL; - } - if ((display->cur_mode->position_type == CONF_ADJ_ABOVE) && - display->cur_mode->relative_to == other) { - bv = NULL; + if (info->display) { + if ((other->cur_mode->position_type == CONF_ADJ_BELOW) && + other->cur_mode->relative_to == info->display) { + bv = NULL; + } + if ((info->display->cur_mode->position_type == CONF_ADJ_ABOVE) && + info->display->cur_mode->relative_to == other) { + bv = NULL; + } } - if (display->screen && other->screen && - (other->screen->position_type == CONF_ADJ_BELOW) && - (other->screen->relative_to == display->screen)) { + if ((other->screen->position_type == CONF_ADJ_BELOW) && + other->screen->relative_to == info->screen) { bv = NULL; } - if (display->screen && other->screen && - (display->screen->position_type == CONF_ADJ_ABOVE) && - (display->screen->relative_to == other->screen)) { + if ((info->screen->position_type == CONF_ADJ_ABOVE) && + info->screen->relative_to == other->screen) { bv = NULL; } - /* Snap to other screen panning dimensions */ - snap_side_to_dim(pan, - pan_orig, - ctk_object->Zorder[z]->cur_mode->pan, - ctk_object->snap_strength, + /* Snap to other display panning dimensions */ + snap_side_to_dim(info->dst_dim, + info->src_dim, + other->cur_mode->pan, bv, bh); - - /* Snap to other screen dimensions */ - snap_side_to_dim(pan, - pan_orig, - ctk_object->Zorder[z]->cur_mode->dim, - ctk_object->snap_strength, + + /* Snap to other display dimensions */ + snap_side_to_dim(info->dst_dim, + info->src_dim, + other->cur_mode->dim, bv, bh); } - /* Snap to multiples of the display's dimensions */ - dist = pan_orig[W] % dim[W]; - if (dist <= ctk_object->snap_strength && dist < best_horz) { - pan[W] = dim[W] * (int)(pan_orig[W] / dim[W]); - best_horz = dist; - } - dist = dim[W] - (pan_orig[W] % dim[W]); - if (dist <= ctk_object->snap_strength && dist < best_horz) { - pan[W] = dim[W] * (1 + (int)(pan_orig[W] / dim[W])); - best_horz = dist; - } - dist = abs(pan_orig[H] % dim[H]); - if (dist <= ctk_object->snap_strength && dist < best_vert) { - pan[H] = dim[H] * (int)(pan_orig[H] / dim[H]); - best_vert = dist; - } - dist = dim[H] - (pan_orig[H] % dim[H]); - if (dist <= ctk_object->snap_strength && dist < best_vert) { - pan[H] = dim[H] * (1 + (int)(pan_orig[H] / dim[H])); - best_vert = dist; - } + /* 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; + + bv = &info->best_snap_v; + bh = &info->best_snap_h; + + /* 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; + } + /* 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; + } - /* Snap to the maximum screen dimensions */ - dist = abs((screen->dim[X] + gpu->max_width) - -(pan_orig[X] + pan_orig[W])); - if (dist <= ctk_object->snap_strength && dist < best_horz) { - pan[W] = screen->dim[X] + gpu->max_width - pan_orig[X]; - best_horz = dist; - } - dist = abs((screen->dim[Y] + gpu->max_height) - -(pan_orig[Y] + pan_orig[H])); - if (dist <= ctk_object->snap_strength && dist < best_vert) { - pan[H] = screen->dim[Y] + gpu->max_height - pan_orig[Y]; - best_vert = dist; + sdim = get_screen_dim(screen, 0); + snap_side_to_dim(info->dst_dim, + info->src_dim, + sdim, + bv, bh); + } } + bh = &(info->best_snap_h); + bv = &(info->best_snap_v); - return (best_vert <= ctk_object->snap_strength || - best_horz <= ctk_object->snap_strength); + /* Snap to the maximum screen width */ + dist = abs((info->screen->dim[X] + info->gpu->max_width) + -(info->src_dim[X] + info->src_dim[W])); + if (dist < *bh) { + info->dst_dim[W] = info->screen->dim[X] + info->gpu->max_width - + info->src_dim[X]; + *bh = dist; + } + + /* Snap to the maximum screen height */ + dist = abs((info->screen->dim[Y] + info->gpu->max_height) + -(info->src_dim[Y] + info->src_dim[H])); + if (dist < *bv) { + info->dst_dim[H] = info->screen->dim[Y] + info->gpu->max_height - + info->src_dim[Y]; + *bv = dist; + } } /* snap_pan() */ @@ -1593,240 +1797,225 @@ static int snap_pan(CtkDisplayLayout *ctk_object, int *pan, int *dim) /** move_selected() ************************************************** * - * Moves the selected display device by the given offset, optionally - * snapping to other displays. + * Moves whatever is selected by the given x and y offsets. This + * function handles movement of relative and absolute positions as + * well as snapping. * - * If something actually moved, this function returns 1. Otherwise - * 0 is returned. + * Returns 1 if a move occured. * **/ static int move_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap) { nvLayoutPtr layout = ctk_object->layout; - nvDisplayPtr display; - nvGpuPtr gpu; - nvScreenPtr screen; - int *pan; - int *dim; - int orig_display_position_type; - int orig_display_pos[2] = { 0, 0 }; - int orig_screen_position_type; - int orig_metamode_dim[4] = { 0, 0, 0, 0 }; - int post_snap_display_pos[2]; - int snap_dim[4]; - - - /* Get the dimensions of the display to move */ - display = get_selected(ctk_object); - if (!display || !display->screen || !display->cur_mode || - !display->screen->cur_metamode) { - return 0; - } + ModifyInfo *info = &(ctk_object->modify_info); + int *dim; /* Temp dimensions */ + int *sdim; /* Temp screen dimensions */ - /* Keep track of original state to report changes */ - gpu = display->gpu; - screen = display->screen; - orig_display_position_type = display->cur_mode->position_type; - dim = display->cur_mode->dim; - pan = display->cur_mode->pan; - orig_display_pos[X] = dim[X]; - orig_display_pos[Y] = dim[Y]; + info->modify_panning = 0; + if (!get_modify_info(ctk_object)) return 0; - orig_screen_position_type = screen->position_type; - orig_metamode_dim[X] = screen->cur_metamode->dim[X]; - orig_metamode_dim[Y] = screen->cur_metamode->dim[Y]; - orig_metamode_dim[W] = screen->cur_metamode->dim[W]; - orig_metamode_dim[H] = screen->cur_metamode->dim[H]; + /* Should we snap */ + info->snap = snap; - /* Process TwinView relative position moves */ - if (display->cur_mode->position_type != CONF_ADJ_ABSOLUTE) { - nvDisplayPtr other = display->cur_mode->relative_to; - int p_x; - int p_y; - if (!other) return 0; // Oops? - - p_x = (ctk_object->mouse_x - ctk_object->img_dim[X]) / + /* Moving something that is using relative positioning can be done + * fairly cleanly with common code, so do that here. + */ + if (info->orig_position_type != CONF_ADJ_ABSOLUTE) { + int p_x = (ctk_object->mouse_x - ctk_object->img_dim[X]) / ctk_object->scale; - - p_y = (ctk_object->mouse_y - ctk_object->img_dim[Y]) / + int p_y = (ctk_object->mouse_y - ctk_object->img_dim[Y]) / ctk_object->scale; - display->cur_mode->position_type = - get_point_relative_position(other->cur_mode->dim, p_x, p_y); + if (info->display) { + dim = info->display->cur_mode->relative_to->cur_mode->dim; + } else { + dim = get_screen_dim(info->screen->relative_to, 0); + } - /* In basic mode, make the position apply to all metamodes */ - if (!ctk_object->advanced_mode) { - nvModePtr mode; - for (mode = display->modes; mode; mode = mode->next) { - mode->position_type = display->cur_mode->position_type; + if (dim) { + /* Compute the new orientation based on the mouse position */ + *(info->target_position_type) = + get_point_relative_position(dim, p_x, p_y); + + /* For displays, while in basic mode, make sure that the + * relative position applies to all metamodes. + */ + if (info->display) { + + if (!ctk_object->advanced_mode) { + nvModePtr mode; + for (mode = info->display->modes; mode; + mode = mode->next) { + mode->position_type = *(info->target_position_type); + } + } + + /* Make sure the screen position does not change */ + reposition_screen(info->screen, ctk_object->advanced_mode); + /* Always update the modify dim for relative positioning */ + info->modify_dirty = 1; } } - post_snap_display_pos[X] = dim[X]; - post_snap_display_pos[Y] = dim[Y]; + } else { + /* Move via absolute positioning */ - /* Make sure the screen position does not change */ - reposition_screen(display->screen, ctk_object->advanced_mode); + /* Compute pre-snap dimensions */ + info->modify_dim[X] += x; + info->modify_dim[Y] += y; - goto finish; - } + info->dst_dim[X] = info->modify_dim[X]; + info->dst_dim[Y] = info->modify_dim[Y]; + info->dst_dim[W] = info->modify_dim[W]; + info->dst_dim[H] = info->modify_dim[H]; - /* Move the display */ - ctk_object->modify_dim[X] += x; - ctk_object->modify_dim[Y] += y; - snap_dim[X] = ctk_object->modify_dim[X]; /* Snap from move dim */ - snap_dim[Y] = ctk_object->modify_dim[Y]; - snap_dim[W] = dim[W]; - snap_dim[H] = dim[H]; + /* Snap to other screens and displays */ + if (snap && ctk_object->snap_strength) { + info->src_dim[X] = info->dst_dim[X]; + info->src_dim[Y] = info->dst_dim[Y]; + info->src_dim[W] = info->dst_dim[W]; + info->src_dim[H] = info->dst_dim[H]; - /* Snap */ - if (snap && ctk_object->snap_strength) { + snap_move(ctk_object); - /* Snap our viewport to other screens */ - snap_move(ctk_object, snap_dim); + if (info->display) { - /* Snap our panning domain to other screens */ - snap_dim[W] = pan[W]; - snap_dim[H] = pan[H]; - snap_move(ctk_object, snap_dim); - } - dim[X] = snap_dim[X]; - dim[Y] = snap_dim[Y]; - pan[X] = dim[X]; - pan[Y] = dim[Y]; + /* Also snap display's panning box to other screens/displays */ + info->src_dim[W] = info->display->cur_mode->pan[W]; + info->src_dim[H] = info->display->cur_mode->pan[H]; + info->dst_dim[W] = info->src_dim[W]; + info->dst_dim[H] = info->src_dim[H]; + snap_move(ctk_object); + } + } - /* Prevent layout from growing too big */ - x = MAX_LAYOUT_WIDTH - pan[W]; - if (dim[X] > x) { - ctk_object->modify_dim[X] += x - dim[X]; - dim[X] = x; - } - y = MAX_LAYOUT_HEIGHT - pan[H]; - if (dim[Y] > y) { - ctk_object->modify_dim[Y] += y - dim[Y]; - dim[Y] = y; - } - x = layout->dim[W] - MAX_LAYOUT_WIDTH; - if (dim[X] < x) { - ctk_object->modify_dim[X] += x - dim[X]; - dim[X] = x; - } - y = layout->dim[H] - MAX_LAYOUT_HEIGHT; - if (dim[Y] < y) { - ctk_object->modify_dim[Y] += y - dim[Y]; - dim[Y] = y; - } + /* Get the bounding dimensions of what is being moved */ + if (info->display) { + dim = info->display->cur_mode->pan; + } else { + dim = info->target_dim; + } + sdim = get_screen_dim(info->screen, 1); + + /* Prevent moving out of the max layout bounds */ + x = MAX_LAYOUT_WIDTH - dim[W]; + if (info->dst_dim[X] > x) { + info->modify_dim[X] += x - info->dst_dim[X]; + info->dst_dim[X] = x; + } + y = MAX_LAYOUT_HEIGHT - dim[H]; + if (info->dst_dim[Y] > y) { + info->modify_dim[Y] += y - info->dst_dim[Y]; + info->dst_dim[Y] = y; + } + x = layout->dim[W] - MAX_LAYOUT_WIDTH; + if (info->dst_dim[X] < x) { + info->modify_dim[X] += x - info->dst_dim[X]; + info->dst_dim[X] = x; + } + y = layout->dim[H] - MAX_LAYOUT_HEIGHT; + if (info->dst_dim[Y] < y) { + info->modify_dim[Y] += y - info->dst_dim[Y]; + info->dst_dim[Y] = y; + } - /* Prevent screen from growing too big */ - x = screen->cur_metamode->edim[X] + gpu->max_width - pan[W]; - if (dim[X] > x) { - ctk_object->modify_dim[X] += x - dim[X]; - dim[X] = x; - } - y = screen->cur_metamode->edim[Y] + gpu->max_height -pan[H]; - if (dim[Y] > y) { - ctk_object->modify_dim[Y] += y - dim[Y]; - dim[Y] = y; - } - x = screen->cur_metamode->edim[X] + screen->cur_metamode->edim[W] - - gpu->max_width; - if (dim[X] < x) { - ctk_object->modify_dim[X] += x - dim[X]; - dim[X] = x; - } - y = screen->cur_metamode->edim[Y] + screen->cur_metamode->edim[H] - - gpu->max_height; - if (dim[Y] < y) { - ctk_object->modify_dim[Y] += y - dim[Y]; - dim[Y] = y; - } + /* Prevent screen from growing too big */ + x = sdim[X] + info->gpu->max_width - dim[W]; + if (info->dst_dim[X] > x) { + info->modify_dim[X] += x - info->dst_dim[X]; + info->dst_dim[X] = x; + } + y = sdim[Y] + info->gpu->max_height - dim[H]; + if (info->dst_dim[Y] > y) { + info->modify_dim[Y] += y - info->dst_dim[Y]; + info->dst_dim[Y] = y; + } + x = sdim[X] + sdim[W] - info->gpu->max_width; + if (info->dst_dim[X] < x) { + info->modify_dim[X] += x - info->dst_dim[X]; + info->dst_dim[X] = x; + } + y = sdim[Y] + sdim[H] - info->gpu->max_height; + if (info->dst_dim[Y] < y) { + info->modify_dim[Y] += y - info->dst_dim[Y]; + info->dst_dim[Y] = y; + } - /* Sync panning position */ - pan[X] = dim[X]; - pan[Y] = dim[Y]; + /* Apply the move */ + if (!info->display) { + /* Move the screen */ + nvDisplayPtr display; + x = info->dst_dim[X] - info->orig_dim[X]; + y = info->dst_dim[Y] - info->orig_dim[Y]; - /* Get the post-snap display position. If calculating the - * layout changes the display's position, the modify dim - * (used to mode the display) should be offset as well. - */ - post_snap_display_pos[X] = dim[X]; - post_snap_display_pos[Y] = dim[Y]; + /* 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; + offset_display(display, x, y); + } - - /* If the display's screen is using absolute positioning, we should - * check to see if the position of the metamode has changed and if - * so, offset other metamodes on the screen (hence moving the screen's - * position.) - * - * If the screen is using relative positioning, don't offset - * metamodes since the screen's position is based on another - * screen. - */ - if (screen->position_type == CONF_ADJ_ABSOLUTE) { - resolve_displays_in_screen(screen, 0); - calc_metamode(screen, screen->cur_metamode); - x = screen->cur_metamode->dim[X] - orig_metamode_dim[X]; - y = screen->cur_metamode->dim[Y] - orig_metamode_dim[Y]; - - if (x || y) { - nvDisplayPtr other; - nvModePtr mode; - - for (other = display->gpu->displays; other; other = other->next) { + } else { + /* Move the display to its destination */ + info->display->cur_mode->dim[X] = info->dst_dim[X]; + info->display->cur_mode->dim[Y] = info->dst_dim[Y]; + info->display->cur_mode->pan[X] = info->dst_dim[X]; + info->display->cur_mode->pan[Y] = info->dst_dim[Y]; + + /* If the screen of the display that was moved is using absolute + * positioning, we should check to see if the position of the + * metamode has changed and if so, offset other metamodes on the + * screen (hence moving the screen's position.) + * + * If the screen is using relative positioning, don't offset + * metamodes since the screen's position is based on another + * screen which will get resolved later. + */ + if (info->screen->position_type == CONF_ADJ_ABSOLUTE && + info->screen->cur_metamode) { + + resolve_displays_in_screen(info->screen, 0); + 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]; - /* Other display must be in the same screen */ - if (other->screen != screen) continue; - - 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; - - mode->dim[X] += x; - mode->dim[Y] += y; - mode->pan[X] = mode->dim[X]; - mode->pan[Y] = mode->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 (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); + } + } } } } - - - /* Process X Screen Relative screen position moves */ - } else if (screen->num_displays == 1) { - nvScreenPtr other = screen->relative_to; - int p_x; - int p_y; - int type; - - p_x = (ctk_object->mouse_x - ctk_object->img_dim[X]) / - ctk_object->scale; - - p_y = (ctk_object->mouse_y - ctk_object->img_dim[Y]) / - ctk_object->scale; - - type = get_point_relative_position(other->cur_metamode->dim, p_x, p_y); - if (type != CONF_ADJ_RELATIVE) { - screen->position_type = type; - } } - finish: - /* Recalculate layout dimensions and scaling */ calc_layout(layout); offset_layout(layout, -layout->dim[X], -layout->dim[Y]); @@ -1834,26 +2023,25 @@ static int move_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap) sync_scaling(ctk_object); - /* Update the modify dim if the position of the selected display changed */ - if ((post_snap_display_pos[X] != dim[X] || - post_snap_display_pos[Y] != dim[Y])) { - ctk_object->modify_dim[X] += dim[X] - post_snap_display_pos[X]; - ctk_object->modify_dim[Y] += dim[Y] - post_snap_display_pos[Y]; + /* If what we moved required the layout to be shifted, offset + * the modify dim (used for snapping) by the same displacement. + */ + x = info->target_dim[X] - info->dst_dim[X]; + y = info->target_dim[Y] - info->dst_dim[Y]; + if (x || y ) { + info->modify_dim[X] += x; + info->modify_dim[Y] += y; } - - /* Did the actual position of the display device change? */ - if ((orig_display_position_type != display->cur_mode->position_type || - orig_display_pos[X] != dim[X] || - orig_display_pos[Y] != dim[Y] || - orig_screen_position_type != screen->position_type || - orig_metamode_dim[X] != screen->cur_metamode->dim[X] || - orig_metamode_dim[Y] != screen->cur_metamode->dim[Y] || - orig_metamode_dim[W] != screen->cur_metamode->dim[W] || - orig_metamode_dim[H] != screen->cur_metamode->dim[H])) { + /* Report if anything changed */ + if (*(info->target_position_type) != info->orig_position_type || + info->target_dim[X] != info->orig_dim[X] || + info->target_dim[Y] != info->orig_dim[Y]) { return 1; } + // XXX Screen could have changed position due to display moving. + return 0; } /* move_selected() */ @@ -1869,84 +2057,115 @@ static int move_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap) static int pan_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap) { nvLayoutPtr layout = ctk_object->layout; - nvDisplayPtr display; - nvScreenPtr screen; - nvGpuPtr gpu; + ModifyInfo *info = &(ctk_object->modify_info); + int *dim; - int *pan; - int orig_dim[4]; + int extra; + + info->modify_panning = 1; + if (!get_modify_info(ctk_object)) return 0; - /* Get the dimensions of the display to pan */ - display = get_selected(ctk_object); - if (!display || !display->screen || !display->cur_mode) { - return 0; - } - gpu = display->gpu; - screen = display->screen; - dim = display->cur_mode->dim; - pan = display->cur_mode->pan; - orig_dim[W] = pan[W]; - orig_dim[H] = pan[H]; + /* Only allow changing the panning of displays and the size + * of no-scanout screens. + */ + if (!info->display && !info->screen->no_scanout) return 0; + info->snap = snap; - /* Resize the panning */ - ctk_object->modify_dim[W] += x; - ctk_object->modify_dim[H] += y; + /* Compute pre-snap dimensions */ + info->modify_dim[W] += x; + info->modify_dim[H] += y; - /* Panning can never be smaller then the display viewport */ - if (ctk_object->modify_dim[W] < dim[W]) { - ctk_object->modify_dim[W] = dim[W]; - } - if (ctk_object->modify_dim[H] < dim[H]) { - ctk_object->modify_dim[H] = dim[H]; + /* Don't allow the panning domain to get too small */ + if (info->display) { + dim = info->display->cur_mode->dim; + if (info->modify_dim[W] < dim[W]) { + info->modify_dim[W] = dim[W]; + } + if (info->modify_dim[H] < dim[H]) { + info->modify_dim[H] = dim[H]; + } + } else if (info->screen->no_scanout) { + if (info->modify_dim[W] < 304) { + info->modify_dim[W] = 304; + } + if (info->modify_dim[H] < 200) { + info->modify_dim[H] = 200; + } } - pan[W] = ctk_object->modify_dim[W]; /* Snap from panning dimensions */ - pan[H] = ctk_object->modify_dim[H]; + info->dst_dim[W] = info->modify_dim[W]; + info->dst_dim[H] = info->modify_dim[H]; /* Snap to other screens and dimensions */ if (snap && ctk_object->snap_strength) { - snap_pan(ctk_object, pan, dim); + + info->src_dim[X] = info->dst_dim[X]; + info->src_dim[Y] = info->dst_dim[Y]; + info->src_dim[W] = info->dst_dim[W]; + info->src_dim[H] = info->dst_dim[H]; + + snap_pan(ctk_object); } + /* Make sure no-scanout virtual screen width is at least a multiple of 8 */ + if (info->screen->no_scanout) { + extra = (info->dst_dim[W] % 8); + if (extra > 0) { + info->dst_dim[W] += (8 - extra); + } + } /* Panning should not cause us to exceed the maximum layout dimensions */ - x = MAX_LAYOUT_WIDTH - pan[X]; - if (pan[W] > x) { - ctk_object->modify_dim[W] += x - pan[W]; - pan[W] = x; + x = MAX_LAYOUT_WIDTH - info->dst_dim[X]; + if (info->dst_dim[W] > x) { + info->modify_dim[W] += x - info->dst_dim[W]; + info->dst_dim[W] = x; } - y = MAX_LAYOUT_HEIGHT - pan[Y]; - if (pan[H] > y) { - ctk_object->modify_dim[H] += y - pan[H]; - pan[H] = y; + y = MAX_LAYOUT_HEIGHT - info->dst_dim[Y]; + if (info->dst_dim[H] > y) { + info->modify_dim[H] += y - info->dst_dim[H]; + info->dst_dim[H] = y; } - /* Panning should not cause us to exceed the maximum screen dimensions */ - x = screen->cur_metamode->edim[X] + gpu->max_width - pan[X]; - if (pan[W] > x) { - ctk_object->modify_dim[W] += x - pan[W]; - pan[W] = x; - } - y = screen->cur_metamode->edim[Y] + gpu->max_height - pan[Y]; - if (pan[H] > y) { - ctk_object->modify_dim[H] += y - pan[H]; - pan[H] = y; + dim = get_screen_dim(info->screen, 1); + x = dim[X] + info->gpu->max_width - info->dst_dim[X]; + if (info->dst_dim[W] > x) { + info->modify_dim[W] += x - info->dst_dim[W]; + info->dst_dim[W] = x; + } + y = dim[Y] + info->gpu->max_height - info->dst_dim[Y]; + if (info->dst_dim[H] > y) { + info->modify_dim[H] += y - info->dst_dim[H]; + info->dst_dim[H] = y; + } + + /* Panning domain can never be smaller then the display viewport */ + if (info->display) { + dim = info->display->cur_mode->dim; + if (info->dst_dim[W] < dim[W]) { + info->dst_dim[W] = dim[W]; + } + if (info->dst_dim[H] < dim[H]) { + info->dst_dim[H] = dim[H]; + } + } else if (info->screen->no_scanout) { + if (info->dst_dim[W] < 304) { + info->dst_dim[W] = 304; + } + if (info->dst_dim[H] < 200) { + info->dst_dim[H] = 200; + } } - - /* Panning can never be smaller then the display viewport */ - if (pan[W] < dim[W]) { - pan[W] = dim[W]; - } - if (pan[H] < dim[H]) { - pan[H] = dim[H]; - } + /* Assign the new size */ + info->target_dim[W] = info->dst_dim[W]; + info->target_dim[H] = info->dst_dim[H]; /* Recalculate layout dimensions and scaling */ @@ -1956,7 +2175,9 @@ static int pan_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap) sync_scaling(ctk_object); - if (orig_dim[W] != pan[W] || orig_dim[H] != pan[H]) { + /* Report if anything changed */ + if (info->target_dim[W] != info->orig_dim[W] || + info->target_dim[H] != info->orig_dim[H]) { return 1; } @@ -1965,95 +2186,250 @@ static int pan_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap) } /* pan_selected() */ +/** get_screen_zorder_move_data() ************************************ + * + * Looks for the screen in the Z order, and if the position given + * where the screen is to be moved to is different than there the + * screen currently is, returns a backup buffer of the zorder of + * the screen and its displays (also also returns the current zorder + * position of the screen). + * + **/ + +ZNode *get_screen_zorder_move_data(CtkDisplayLayout *ctk_object, + nvScreenPtr screen, + int move_to, + int *screen_at) +{ + ZNode *tmpzo; + int i; + + if (!screen) return NULL; + + for (i = 0; i < ctk_object->Zcount; i++) { + + if (ctk_object->Zorder[i].type == ZNODE_TYPE_SCREEN && + ctk_object->Zorder[i].u.screen == screen) { + + /* Only move screen if it is not moving to the same location */ + if (move_to != i) { + + tmpzo = (ZNode *)malloc((1 + screen->num_displays) * + sizeof(ZNode)); + if (!tmpzo) return NULL; + + memcpy(tmpzo, + ctk_object->Zorder + i - screen->num_displays, + (1 + screen->num_displays)*sizeof(ZNode)); + + if (screen_at) { + *screen_at = i; + } + return tmpzo; + } + break; + } + } + + return NULL; + +} /* get_screen_zorder_move_data() */ + + +/** select_screen() ************************************************** + * + * Selects the given screen (by moving it and all of its displays + * to the top of the zorder). + * + **/ + +static void select_screen(CtkDisplayLayout *ctk_object, nvScreenPtr screen) +{ + int move_to = 0; + int screen_at; + ZNode *tmpzo; + + if (!screen) return; + + + /* Move the screen and its displays to the top */ + move_to = 0 + screen->num_displays; + + + tmpzo = get_screen_zorder_move_data(ctk_object, screen, move_to, + &screen_at); + if (!tmpzo) { + goto done; + } + + /* Move other nodes down to make room at the top */ + memmove(ctk_object->Zorder + 1 + screen->num_displays, + ctk_object->Zorder, + (screen_at - screen->num_displays)*sizeof(ZNode)); + + /* Copy the screen and its displays to the top */ + memcpy(ctk_object->Zorder, tmpzo, + (1 + screen->num_displays)*sizeof(ZNode)); + + free(tmpzo); + + done: + ctk_object->selected_screen = screen; + +} /* select_screen() */ + + /** select_display() ************************************************* * - * Moves the specified display to the top of the Zorder. + * Moves the specified display to the top of the Z-order. * **/ static void select_display(CtkDisplayLayout *ctk_object, nvDisplayPtr display) { - int z; + int i; - for (z = 0; z < ctk_object->Zcount; z++) { + if (!display) { + return; + } - /* Find the display in question */ - if (ctk_object->Zorder[z] == display) { - - /* Bubble it to the top */ - while (z > 0) { - ctk_object->Zorder[z] = ctk_object->Zorder[z-1]; - z--; + /* Move the screen and its displays to the top of the Z order */ + select_screen(ctk_object, display->screen); + + + /* Move the display to the top of the Z order */ + for (i = 0; i < ctk_object->Zcount; i++) { + + /* Find the display */ + if (ctk_object->Zorder[i].type == ZNODE_TYPE_DISPLAY && + ctk_object->Zorder[i].u.display == display) { + + /* Move all nodes above this one down by one location */ + if (i > 0) { + memmove(ctk_object->Zorder + 1, ctk_object->Zorder, + i*sizeof(ZNode)); + + /* Place the display at the top */ + ctk_object->Zorder[0].type = ZNODE_TYPE_DISPLAY; + ctk_object->Zorder[0].u.display = display; } - ctk_object->Zorder[0] = display; - ctk_object->Zselected = 1; break; } } + ctk_object->selected_display = display; + } /* select_display() */ -/** select_default_display() ***************************************** +/** select_default_item() ******************************************** * - * Select the top left most display + * Select the top left most element (display/screen). * */ #define DIST_SQR(D) (((D)[X] * (D)[X]) + ((D)[Y] * (D)[Y])) -static void select_default_display(CtkDisplayLayout *ctk_object) +static void select_default_item(CtkDisplayLayout *ctk_object) { - nvDisplayPtr display = NULL; - int z; + nvDisplayPtr sel_display = NULL; + nvScreenPtr sel_screen = NULL; + nvScreenPtr screen; + nvDisplayPtr display; + int i; + int best_dst = -1; // Distance squared to element. + int dst; + - for (z = 0; z < ctk_object->Zcount; z++) { + for (i = 0; i < ctk_object->Zcount; i++) { + + if (ctk_object->Zorder[i].type == ZNODE_TYPE_DISPLAY) { + display = ctk_object->Zorder[i].u.display; + + /* Ignore disabled displays */ + if (!display->cur_mode) continue; - if (!ctk_object->Zorder[z]->cur_mode) continue; + dst = DIST_SQR(display->cur_mode->dim); + if (best_dst < 0 || dst < best_dst) { + best_dst = dst; + sel_display = display; + sel_screen = NULL; + } + + } else if (ctk_object->Zorder[i].type == ZNODE_TYPE_SCREEN) { + screen = ctk_object->Zorder[i].u.screen; + + /* Only select no-scanout screens */ + if (screen->num_displays > 0) continue; - if (!display || - (DIST_SQR(display->cur_mode->dim) > - DIST_SQR(ctk_object->Zorder[z]->cur_mode->dim))) { - display = ctk_object->Zorder[z]; + dst = DIST_SQR(screen->dim); + if (best_dst < 0 || dst < best_dst) { + best_dst = dst; + sel_display = NULL; + sel_screen = screen; + } } } - if (display) { - select_display(ctk_object, display); + if (sel_display) { + select_display(ctk_object, sel_display); + } else if (sel_screen) { + select_screen(ctk_object, sel_screen); } -} /* select_default_display() */ +} /* select_default_item() */ /** pushback_display() *********************************************** * - * Moves the specified display to the end of the Zorder + * Moves the specified display to the end of the Z-order. * **/ static void pushback_display(CtkDisplayLayout *ctk_object, nvDisplayPtr display) { - int z; - - if (!ctk_object->Zcount) { - return; - } + int i; + int move_to; - for (z = 0; z < ctk_object->Zcount; z++) { + for (i = 0; i < ctk_object->Zcount; i++) { /* Find the display */ - if (ctk_object->Zorder[z] == display) { + if (ctk_object->Zorder[i].type == ZNODE_TYPE_DISPLAY && + ctk_object->Zorder[i].u.display == display) { + + if (!display->screen) { + /* Move display to the end of the list. */ + move_to = ctk_object->Zcount - 1; + } else { + /* Move display prior to its X screen */ + for (move_to = i+1; + move_to < ctk_object->Zcount; + move_to++) { + if (ctk_object->Zorder[move_to].type == + ZNODE_TYPE_SCREEN && + ctk_object->Zorder[move_to].u.screen == + display->screen) { + break; + } + } + move_to--; + } - /* Bubble it down */ - while (z < ctk_object->Zcount -1) { - ctk_object->Zorder[z] = ctk_object->Zorder[z+1]; - z++; + // Now move dispay from i to move_to + if (i != move_to) { + memmove(ctk_object->Zorder + i, + ctk_object->Zorder + i + 1, + (move_to - i)*sizeof(ZNode)); + + /* Place the display at the top */ + ctk_object->Zorder[move_to].type = ZNODE_TYPE_DISPLAY; + ctk_object->Zorder[move_to].u.display = display; } - ctk_object->Zorder[ctk_object->Zcount -1] = display; + break; } } @@ -2062,6 +2438,64 @@ static void pushback_display(CtkDisplayLayout *ctk_object, +/** pushback_screen() ************************************************ + * + * Moves the specified screen to the end of the Z-order. + * + **/ + +static void pushback_screen(CtkDisplayLayout *ctk_object, + nvScreenPtr screen) +{ + int move_to = ctk_object->Zcount -1; + int screen_at; + ZNode *tmpzo; + + /* Get a copy of the zorder buffer for the screen */ + tmpzo = get_screen_zorder_move_data(ctk_object, screen, move_to, + &screen_at); + if (!tmpzo) return; + + /* Move other nodes up to make room at the bottom */ + memmove(ctk_object->Zorder + screen_at - screen->num_displays, + ctk_object->Zorder + screen_at + 1, + (move_to - screen_at)*sizeof(ZNode)); + + /* Copy the screen and its displays to the bottom */ + memcpy(ctk_object->Zorder + move_to - screen->num_displays, + tmpzo, + (1 + screen->num_displays)*sizeof(ZNode)); + + free(tmpzo); + +} /* pushback_screen() */ + + + +/** pushback_selected() ********************************************** + * + * Moves the specified display or screen to the end of the Z-order. + * + **/ + +static void pushback_selected(CtkDisplayLayout *ctk_object) +{ + /* Pushback the selected display if it has no screen or + * is part of twinview to avoid selecting the screen of + * single-display screens. + */ + if (ctk_object->selected_display && + (!ctk_object->selected_screen || + ctk_object->selected_screen->num_displays > 1)) { + pushback_display(ctk_object, ctk_object->selected_display); + } else if (ctk_object->selected_screen) { + pushback_screen(ctk_object, ctk_object->selected_screen); + } + +} /* pushback_selected() */ + + + /** get_display_tooltip() ******************************************** * * Returns the text to use for displaying a tooltip from the given @@ -2073,8 +2507,7 @@ static void pushback_display(CtkDisplayLayout *ctk_object, * **/ -static char *get_display_tooltip(CtkDisplayLayout *ctk_object, - nvDisplayPtr display) +static char *get_display_tooltip(nvDisplayPtr display, Bool advanced) { char *tip; @@ -2092,7 +2525,7 @@ static char *get_display_tooltip(CtkDisplayLayout *ctk_object, /* Basic view */ - } else if (!ctk_object->advanced_mode) { + } else if (!advanced) { /* Display has no mode */ if (!display->cur_mode) { @@ -2122,14 +2555,14 @@ static char *get_display_tooltip(CtkDisplayLayout *ctk_object, /* Display has no mode */ if (!display->cur_mode) { - tip = g_strdup_printf("%s : (Screen: %d) (GPU: %s)", + tip = g_strdup_printf("%s\n(X Screen %d)\n(GPU: %s)", display->name, display->screen->scrnum, display->gpu->name); /* Display does not have a current modeline (Off) */ } else if (!(display->cur_mode->modeline)) { - tip = g_strdup_printf("%s : Off (Screen: %d) (GPU: %s)", + tip = g_strdup_printf("%s : Off\n(X Screen %d)\n(GPU: %s)", display->name, display->screen->scrnum, display->gpu->name); @@ -2137,7 +2570,7 @@ static char *get_display_tooltip(CtkDisplayLayout *ctk_object, /* Display has mode/modeline */ } else { float ref = display->cur_mode->modeline->refresh_rate; - tip = g_strdup_printf("%s : %dx%d @ %.*f Hz (Screen: %d) " + tip = g_strdup_printf("%s : %dx%d @ %.*f Hz\n(X Screen %d)\n" "(GPU: %s)", display->name, display->cur_mode->modeline->data.hdisplay, @@ -2155,20 +2588,69 @@ static char *get_display_tooltip(CtkDisplayLayout *ctk_object, -/** get_display_tooltip_under_mouse() ******************************** +/** get_screen_tooltip() ********************************************* + * + * Returns the text to use for displaying a tooltip from the given + * screen: + * + * SCREEN NUMBER (GPU NAME) + * + * The caller should free the string that is returned. + * + **/ + +static char *get_screen_tooltip(nvScreenPtr screen, Bool advanced) +{ + char *tip; + + + /* No display given */ + if (!screen) { + return NULL; + } + + + /* Basic view */ + if (!advanced) { + + tip = g_strdup_printf("X Screen %d%s", screen->scrnum, + screen->no_scanout ? " : No Scanout" : "" + ); + + /* Advanced view */ + } else { + + tip = g_strdup_printf("X Screen %d%s\n(GPU: %s)", + screen->scrnum, + screen->no_scanout ? " : No Scanout" : "", + screen->gpu->name); + } + + return tip; + +} /* get_screen_tooltip() */ + + + +/** get_tooltip_under_mouse() **************************************** * * Returns the tooltip text that should be used to give information - * about the display under the mouse at x, y. + * about the item under the mouse at x, y. * * The caller should free the string that is returned. * **/ -static char *get_display_tooltip_under_mouse(CtkDisplayLayout *ctk_object, +static char *get_tooltip_under_mouse(CtkDisplayLayout *ctk_object, int x, int y) { - int z; static nvDisplayPtr last_display = NULL; + static nvScreenPtr last_screen = NULL; + int i; + nvDisplayPtr display = NULL; + nvScreenPtr screen = NULL; + char *tip = NULL; + int *sdim; /* Scale and offset x & y so they reside in clickable area */ @@ -2176,43 +2658,50 @@ static char *get_display_tooltip_under_mouse(CtkDisplayLayout *ctk_object, y = (y -ctk_object->img_dim[Y]) / ctk_object->scale; - /* Find the first display under the cursor */ - z = 0; - while (z < ctk_object->Zcount) { - if (ctk_object->Zorder[z]->cur_mode && - point_in_dim(ctk_object->Zorder[z]->cur_mode->dim, x, y)) { - if (ctk_object->Zorder[z] == last_display) { - return NULL; + /* Go through the Z-order looking for what we are under */ + for (i = 0; i < ctk_object->Zcount; i++) { + + if (ctk_object->Zorder[i].type == ZNODE_TYPE_DISPLAY) { + display = ctk_object->Zorder[i].u.display; + if (display->cur_mode && + point_in_dim(display->cur_mode->pan, x, y)) { + screen = NULL; + if (display == last_display) { + goto found; + } + tip = get_display_tooltip(display, ctk_object->advanced_mode); + goto found; } - last_display = ctk_object->Zorder[z]; - return get_display_tooltip(ctk_object, ctk_object->Zorder[z]); - } - z++; - } - /* Check display pannings as a last resort */ - z = 0; - while (z < ctk_object->Zcount) { - if (ctk_object->Zorder[z]->cur_mode && - point_in_dim(ctk_object->Zorder[z]->cur_mode->pan, x, y)) { - if (ctk_object->Zorder[z] == last_display) { - return NULL; + } else if (ctk_object->Zorder[i].type == ZNODE_TYPE_SCREEN) { + screen = ctk_object->Zorder[i].u.screen; + sdim = get_screen_dim(screen, 1); + if (point_in_dim(sdim, x, y)) { + display = NULL; + if (screen == last_screen) { + goto found; + } + tip = get_screen_tooltip(screen, ctk_object->advanced_mode); + goto found; } - last_display = ctk_object->Zorder[z]; - return get_display_tooltip(ctk_object, ctk_object->Zorder[z]); } - z++; } - - if (last_display) { + /* Handle mouse over nothing for the first time */ + if (last_display || last_screen) { last_display = NULL; - return g_strdup("*** No Display ***"); + last_screen = NULL; + return g_strdup("No Display"); } return NULL; -} /* get_display_tooltip_under_mouse() */ + found: + last_display = display; + last_screen = screen; + return tip; + +} /* get_tooltip_under_mouse() */ @@ -2222,63 +2711,65 @@ static char *get_display_tooltip_under_mouse(CtkDisplayLayout *ctk_object, * **/ -static int click_layout(CtkDisplayLayout *ctk_object, int x, int y) +static int click_layout(CtkDisplayLayout *ctk_object, int x, int y, + nvScreenPtr reselect_screen) { - int z; - nvDisplayPtr cur_selected; - - - /* Make sure there is something to click */ - if (!ctk_object->Zcount) { - return 0; - } - + int i; + nvDisplayPtr cur_selected_display = ctk_object->selected_display; + nvScreenPtr cur_selected_screen = ctk_object->selected_screen; + nvDisplayPtr display; + nvScreenPtr screen; + int *sdim; - /* Keep track of the currently selected display */ - cur_selected = ctk_object->Zorder[0]; /* Assume user didn't actually click inside a display for now */ ctk_object->clicked_outside = 1; + ctk_object->selected_display = NULL; + ctk_object->selected_screen = NULL; + - /* Push selected screen to the back of Z order */ - ctk_object->Zselected = 0; - if (ctk_object->select_next) { - pushback_display(ctk_object, ctk_object->Zorder[0]); - } - - /* Find the first display under the cursor */ - z = 0; - while (z < ctk_object->Zcount) { - if (ctk_object->Zorder[z]->cur_mode && - point_in_dim(ctk_object->Zorder[z]->cur_mode->dim, x, y)) { - select_display(ctk_object, ctk_object->Zorder[z]); - ctk_object->clicked_outside = 0; - break; - } - z++; - } - - /* Check if we clicked on a panning domain */ - if (!(ctk_object->Zselected)) { - z = 0; - while (z < ctk_object->Zcount) { - if (ctk_object->Zorder[z]->cur_mode && - point_in_dim(ctk_object->Zorder[z]->cur_mode->pan, x, y)) { - select_display(ctk_object, ctk_object->Zorder[z]); + /* Look through the Z-order for the next element */ + for (i = 0; i < ctk_object->Zcount; i++) { + if (ctk_object->Zorder[i].type == ZNODE_TYPE_DISPLAY) { + display = ctk_object->Zorder[i].u.display; + if (display->cur_mode && + point_in_dim(display->cur_mode->pan, x, y)) { + + /* Re-select the screen instead of the display + * (after a move) + */ + if (display->screen && + (reselect_screen == display->screen)) { + select_screen(ctk_object, display->screen); + } else { + select_display(ctk_object, display); + } + ctk_object->clicked_outside = 0; + break; + } + + } else if (ctk_object->Zorder[i].type == ZNODE_TYPE_SCREEN) { + screen = ctk_object->Zorder[i].u.screen; + sdim = get_screen_dim(screen, 1); + if (point_in_dim(sdim, x, y)) { + select_screen(ctk_object, screen); ctk_object->clicked_outside = 0; break; } - z++; } } - /* Reselect the last display */ - if (ctk_object->clicked_outside && cur_selected) { - select_display(ctk_object, cur_selected); - } - /* Sync modify dimensions to the newly selected display */ - sync_modify(ctk_object); + /* Don't allow clicking outside - reselect what was last selected */ + if (ctk_object->clicked_outside) { + ctk_object->selected_display = cur_selected_display; + ctk_object->selected_screen = cur_selected_screen; + + } else { + + /* Sync modify dimensions to what was newly selected */ + ctk_object->modify_info.modify_dirty = 1; + } return 1; @@ -2361,7 +2852,7 @@ GtkWidget* ctk_display_layout_new(NvCtrlAttributeHandle *handle, calc_layout(layout); sync_scaling(ctk_object); zorder_layout(ctk_object); - select_default_display(ctk_object); + select_default_item(ctk_object); /* Setup Pango layout/font */ @@ -2394,8 +2885,9 @@ GtkWidget* ctk_display_layout_new(NvCtrlAttributeHandle *handle, /* Setup the layout state variables */ ctk_object->snap_strength = DEFAULT_SNAP_STRENGTH; - ctk_object->need_swap = 0; - ctk_object->select_next = 0; + ctk_object->need_swap = 0; + ctk_object->first_selected_display = NULL; + ctk_object->first_selected_screen = NULL; /* Make the drawing area */ @@ -2713,58 +3205,107 @@ static void draw_display(CtkDisplayLayout *ctk_object, -/** draw_layout() **************************************************** +/** draw_screen() **************************************************** * - * Draws a layout. + * Draws a screen to scale within the layout. * **/ -static void draw_layout(CtkDisplayLayout *ctk_object) +static void draw_screen(CtkDisplayLayout *ctk_object, + nvScreenPtr screen) { GtkWidget *drawing_area = ctk_object->drawing_area; GdkGC *fg_gc = get_widget_fg_gc(drawing_area); - + + int *sdim; /* Screen dimensions */ GdkColor bg_color; /* Background color */ GdkColor bd_color; /* Border color */ - nvGpuPtr gpu; - nvScreenPtr screen; - int z; + char *tmp_str; + + + if (!screen) return; - /* Draw the metamode's effective size */ + /* Draw the screen effective size */ gdk_color_parse("#888888", &bg_color); gdk_color_parse("#777777", &bd_color); + sdim = get_screen_dim(screen, 1); + + /* Draw the screen background */ + draw_rect(ctk_object, sdim, &bg_color, 1); + + /* Draw the screen border with dashed lines */ gdk_gc_set_line_attributes(fg_gc, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_NOT_LAST, GDK_JOIN_ROUND); - for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { - for (screen = gpu->screens; screen; screen = screen->next) { - draw_rect(ctk_object, screen->cur_metamode->edim, &bg_color, 1); - draw_rect(ctk_object, screen->cur_metamode->edim, - &(ctk_object->fg_color), 0); - } + draw_rect(ctk_object, sdim, &(ctk_object->fg_color), 0); + + 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 */ + if (screen->no_scanout) { + tmp_str = g_strdup_printf("X Screen %d", screen->scrnum); + + draw_rect_strs(ctk_object, + screen->dim, + &(ctk_object->fg_color), + tmp_str, + "(No Scanout)"); + g_free(tmp_str); } - gdk_gc_set_line_attributes(fg_gc, 1, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, - GDK_JOIN_ROUND); +} /* draw_screen() */ - /* Draw display devices from back to front */ - for (z = ctk_object->Zcount - 1; z >= 0; z--) { - draw_display(ctk_object, ctk_object->Zorder[z]); - ctk_object->need_swap = 1; + +/** draw_layout() **************************************************** + * + * Draws a layout. + * + **/ + +static void draw_layout(CtkDisplayLayout *ctk_object) +{ + GtkWidget *drawing_area = ctk_object->drawing_area; + GdkGC *fg_gc = get_widget_fg_gc(drawing_area); + + GdkColor bg_color; /* Background color */ + GdkColor bd_color; /* Border color */ + int i; + + + gdk_color_parse("#888888", &bg_color); + gdk_color_parse("#777777", &bd_color); + + + /* Draw the Z-order back to front */ + for (i = ctk_object->Zcount - 1; i >= 0; i--) { + if (ctk_object->Zorder[i].type == ZNODE_TYPE_DISPLAY) { + draw_display(ctk_object, ctk_object->Zorder[i].u.display); + ctk_object->need_swap = 1; + } else if (ctk_object->Zorder[i].type == ZNODE_TYPE_SCREEN) { + draw_screen(ctk_object, ctk_object->Zorder[i].u.screen); + ctk_object->need_swap = 1; + } } - /* Hilite the selected display device */ - if (ctk_object->Zselected && ctk_object->Zcount) { + /* Hilite the selected item */ + if (ctk_object->selected_display || + ctk_object->selected_screen) { + int w, h; int size; /* Hilite line size */ int offset; /* Hilite box offset */ int *dim; - dim = ctk_object->Zorder[0]->cur_mode->dim; + if (ctk_object->selected_display) { + dim = ctk_object->selected_display->cur_mode->dim; + } else { + dim = get_screen_dim(ctk_object->selected_screen, 0); + } /* Draw red selection border */ w = (int)(ctk_object->scale * (dim[X] + dim[W])) - (int)(ctk_object->scale * (dim[X])); @@ -2800,33 +3341,47 @@ static void draw_layout(CtkDisplayLayout *ctk_object) /* Uncomment to show bounding box of selected screen's metamodes */ /* - if (ctk_object->Zorder[0]->screen) { + if (ctk_object->selected_screen) { // Shows the screen dimensions used to write to the X config file gdk_color_parse("#00FF00", &bg_color); draw_rect(ctk_object, - ctk_object->Zorder[0]->screen->dim, + ctk_object->selected_screen->dim, &(bg_color), 0); - // Shows the effective screen dimensions used in conjunction with - // display devices that are "off" - gdk_color_parse("#0000FF", &bg_color); - draw_rect(ctk_object, - ctk_object->Zorder[0]->screen->cur_metamode->dim, - &(bg_color), 0); - - // Shows the current screen dimensions used for relative - // positioning of the screen (w/o displays that are "off") - gdk_color_parse("#FF00FF", &bg_color); - draw_rect(ctk_object, - ctk_object->Zorder[0]->screen->cur_metamode->edim, - &(bg_color), 0); + if (ctk_object->selected_screen->cur_metamode) { + // Shows the effective screen dimensions used in conjunction + // with display devices that are "off" + gdk_color_parse("#0000FF", &bg_color); + draw_rect(ctk_object, + ctk_object->selected_screen->cur_metamode->dim, + &(bg_color), 0); + + // Shows the current screen dimensions used for relative + // positioning of the screen (w/o displays that are "off") + gdk_color_parse("#FF00FF", &bg_color); + draw_rect(ctk_object, + ctk_object->selected_screen->cur_metamode->edim, + &(bg_color), 0); + } } - */ + //*/ /* Uncomment to show unsnapped dimensions */ - //gdk_color_parse("#DD4444", &bg_color); - //draw_rect(ctk_object, ctk_object->modify_dim, &bg_color, 0); + /* + { + gdk_color_parse("#DD4444", &bg_color); + if (ctk_object->modify_info.modify_dirty) { + gdk_gc_set_line_attributes(fg_gc, 1, GDK_LINE_ON_OFF_DASH, + GDK_CAP_NOT_LAST, GDK_JOIN_ROUND); + } + draw_rect(ctk_object, ctk_object->modify_info.modify_dim, &bg_color, 0); + if (ctk_object->modify_info.modify_dirty) { + gdk_gc_set_line_attributes(fg_gc, 1, GDK_LINE_SOLID, + GDK_CAP_NOT_LAST, GDK_JOIN_ROUND); + } + } + //*/ ctk_object->need_swap = 1; } @@ -2915,14 +3470,13 @@ static void draw_all(CtkDisplayLayout *ctk_object) -/** ctk_display_layout_redraw() ************************************** +/** ctk_display_layout_update() ************************************** * - * Redraw everything in the layout and makes sure the widget is - * updated. + * Causes a recalculation of the layout. * **/ -void ctk_display_layout_redraw(CtkDisplayLayout *ctk_object) +void ctk_display_layout_update(CtkDisplayLayout *ctk_object) { nvLayoutPtr layout = ctk_object->layout; @@ -2931,12 +3485,28 @@ void ctk_display_layout_redraw(CtkDisplayLayout *ctk_object) offset_layout(layout, -layout->dim[X], -layout->dim[Y]); recenter_layout(layout); sync_scaling(ctk_object); - sync_modify(ctk_object); + ctk_object->modify_info.modify_dirty = 1; - /* Redraw */ - draw_all(ctk_object); + /* Make sure the selected display/screen is up to date */ + if (ctk_object->selected_display) { + ctk_object->selected_screen = ctk_object->selected_display->screen; + } - /* Refresh GUI */ +} /* ctk_display_layout_update() */ + + + +/** ctk_display_layout_redraw() ************************************** + * + * Redraw everything in the layout and makes sure the widget is + * updated. + * + **/ + +void ctk_display_layout_redraw(CtkDisplayLayout *ctk_object) +{ + ctk_display_layout_update(ctk_object); + draw_all(ctk_object); do_swap(ctk_object); } /* ctk_display_layout_redraw() */ @@ -2955,23 +3525,29 @@ void ctk_display_layout_set_layout(CtkDisplayLayout *ctk_object, /* Setup for the new layout */ ctk_object->layout = layout; zorder_layout(ctk_object); - select_default_display(ctk_object); - calc_layout(layout); - offset_layout(layout, -layout->dim[X], -layout->dim[Y]); - recenter_layout(layout); - sync_scaling(ctk_object); - sync_modify(ctk_object); + select_default_item(ctk_object); /* Redraw */ - draw_all(ctk_object); - - /* Refresh GUI */ - do_swap(ctk_object); + ctk_display_layout_redraw(ctk_object); } /* ctk_display_layout_set_layout() */ +/** ctk_display_layout_update_zorder() ******************************* + * + * Updates the layout by re-building the Z-order list. + * + **/ + +void ctk_display_layout_update_zorder(CtkDisplayLayout *ctk_object) +{ + zorder_layout(ctk_object); + +} /* ctk_display_layout_update_zorder() */ + + + /** ctk_display_layout_get_selected_display() ************************ * * Returns the selected display. @@ -2980,7 +3556,7 @@ void ctk_display_layout_set_layout(CtkDisplayLayout *ctk_object, nvDisplayPtr ctk_display_layout_get_selected_display(CtkDisplayLayout *ctk_object) { - return get_selected(ctk_object); + return ctk_object->selected_display; } /* ctk_display_layout_get_selected_display() */ @@ -2994,11 +3570,7 @@ nvDisplayPtr ctk_display_layout_get_selected_display(CtkDisplayLayout *ctk_objec nvScreenPtr ctk_display_layout_get_selected_screen(CtkDisplayLayout *ctk_object) { - nvDisplayPtr display = get_selected(ctk_object); - if (display) { - return display->screen; - } - return NULL; + return ctk_object->selected_screen; } /* ctk_display_layout_get_selected_screen() */ @@ -3012,10 +3584,14 @@ nvScreenPtr ctk_display_layout_get_selected_screen(CtkDisplayLayout *ctk_object) nvGpuPtr ctk_display_layout_get_selected_gpu(CtkDisplayLayout *ctk_object) { - nvDisplayPtr display = get_selected(ctk_object); - if (display) { - return display->gpu; + if (ctk_object->selected_display) { + return ctk_object->selected_display->gpu; + } + + if (ctk_object->selected_screen) { + return ctk_object->selected_screen->gpu; } + return NULL; } /* ctk_display_layout_get_selected_gpu() */ @@ -3045,7 +3621,7 @@ void ctk_display_layout_set_screen_metamode(CtkDisplayLayout *ctk_object, set_screen_metamode(ctk_object->layout, screen, new_metamode_idx); recenter_layout(ctk_object->layout); sync_scaling(ctk_object); - sync_modify(ctk_object); + ctk_object->modify_info.modify_dirty = 1; /* Redraw the layout */ ctk_display_layout_redraw(ctk_object); @@ -3063,7 +3639,7 @@ void ctk_display_layout_set_screen_metamode(CtkDisplayLayout *ctk_object, void ctk_display_layout_add_screen_metamode(CtkDisplayLayout *ctk_object, nvScreenPtr screen) { - nvDisplayPtr display = get_selected(ctk_object); + nvDisplayPtr display; nvMetaModePtr metamode; @@ -3233,6 +3809,43 @@ void ctk_display_layout_delete_screen_metamode(CtkDisplayLayout *ctk_object, +/** ctk_display_layout_disable_display() ***************************** + * + * Disables a display (removes it from its X screen. + * + **/ + +void ctk_display_layout_disable_display(CtkDisplayLayout *ctk_object, + nvDisplayPtr display) +{ + nvScreenPtr screen = display->screen; + + /* Remove display from the X screen */ + screen_remove_display(display); + + /* If the screen is empty, remove it */ + if (!screen->num_displays) { + gpu_remove_and_free_screen(screen); + + /* Unselect the screen if it was selected */ + if (screen == ctk_object->first_selected_screen) { + ctk_object->first_selected_screen = NULL; + } + if (screen == ctk_object->selected_screen) { + ctk_object->selected_screen = NULL; + } + + /* Make sure screen numbers are consistent */ + renumber_xscreens(ctk_object->layout); + } + + /* Add the fake mode to the display */ + gpu_add_screenless_modes_to_displays(display->gpu); + +} /* ctk_display_layout_disable_display() */ + + + /** ctk_display_layout_set_mode_modeline() *************************** * * Sets which modeline the mode should use. @@ -3243,7 +3856,6 @@ void ctk_display_layout_set_mode_modeline(CtkDisplayLayout *ctk_object, nvModePtr mode, nvModeLinePtr modeline) { - nvLayoutPtr layout = ctk_object->layout; nvModeLinePtr old_modeline; if (!mode) { @@ -3292,13 +3904,6 @@ void ctk_display_layout_set_mode_modeline(CtkDisplayLayout *ctk_object, mode->metamode->source = METAMODE_SOURCE_NVCONTROL; } - /* Recalculate layout dimensions and scaling */ - calc_layout(layout); - offset_layout(layout, -layout->dim[X], -layout->dim[Y]); - recenter_layout(layout); - sync_scaling(ctk_object); - sync_modify(ctk_object); - /* Redraw the layout */ ctk_display_layout_redraw(ctk_object); @@ -3323,7 +3928,6 @@ void ctk_display_layout_set_display_position(CtkDisplayLayout *ctk_object, GdkGC *fg_gc = get_widget_fg_gc(drawing_area); GdkGCValues old_gc_values; int modified = 0; - nvLayoutPtr layout = ctk_object->layout; if (!display) return; @@ -3381,7 +3985,7 @@ void ctk_display_layout_set_display_position(CtkDisplayLayout *ctk_object, switch (position_type) { case CONF_ADJ_ABSOLUTE: /* Do the move by offsetting */ - sync_modify(ctk_object); + ctk_object->modify_info.modify_dirty = 1; modified = move_selected(ctk_object, x - display->cur_mode->dim[X], y - display->cur_mode->dim[Y], @@ -3402,11 +4006,7 @@ void ctk_display_layout_set_display_position(CtkDisplayLayout *ctk_object, reposition_screen(display->screen, ctk_object->advanced_mode); /* Recalculate the layout */ - calc_layout(layout); - offset_layout(layout, -layout->dim[X], -layout->dim[Y]); - recenter_layout(layout); - sync_scaling(ctk_object); - sync_modify(ctk_object); + ctk_display_layout_update(ctk_object); break; } @@ -3452,7 +4052,7 @@ void ctk_display_layout_set_display_panning(CtkDisplayLayout *ctk_object, /* Change the panning */ - sync_modify(ctk_object); + ctk_object->modify_info.modify_dirty = 1; modified = pan_selected(ctk_object, width - display->cur_mode->pan[W], height - display->cur_mode->pan[H], @@ -3491,13 +4091,8 @@ void ctk_display_layout_set_display_panning(CtkDisplayLayout *ctk_object, void ctk_display_layout_select_display(CtkDisplayLayout *ctk_object, nvDisplayPtr display) { - if (display) { - /* Select the new display */ - select_display(ctk_object, display); - } else if (ctk_object->Zcount) { - /* Select the new topmost display */ - select_display(ctk_object, ctk_object->Zorder[0]); - } + /* Select the new display */ + select_display(ctk_object, display); } /* ctk_display_layout_select_display() */ @@ -3506,7 +4101,7 @@ void ctk_display_layout_select_display(CtkDisplayLayout *ctk_object, /** ctk_display_layout_update_display_count() ************************ * * Updates the number of displays shown in the layout by re-building - * the Zorder list. + * the Z-order list. * **/ @@ -3517,12 +4112,71 @@ void ctk_display_layout_update_display_count(CtkDisplayLayout *ctk_object, zorder_layout(ctk_object); /* Select the previously selected display */ - ctk_display_layout_select_display(ctk_object, display); + if (display) { + ctk_display_layout_select_display(ctk_object, display); + } } /* ctk_display_layout_update_display_count() */ +/** ctk_display_layout_set_screen_virtual_size() ********************* + * + * Sets the virtual size of the screen + * + **/ + +void ctk_display_layout_set_screen_virtual_size(CtkDisplayLayout *ctk_object, + nvScreenPtr screen, + int width, int height) +{ + GtkWidget *drawing_area = ctk_object->drawing_area; + GdkGC *fg_gc = get_widget_fg_gc(drawing_area); + GdkGCValues old_gc_values; + int modified; + + if (!screen || !screen->no_scanout) return; + + /* Backup the foreground color */ + if (fg_gc) { + gdk_gc_get_values(fg_gc, &old_gc_values); + + clear_layout(ctk_object); + } + + /* Do the panning by offsetting */ + + // XXX May want to pan non-selected screen, + // though right now this just works out + // since what we want to pan is always + // what is selected. + ctk_object->modify_info.modify_dirty = 1; + modified = pan_selected(ctk_object, + width - screen->dim[W], + height - screen->dim[H], + 0); + + if (ctk_object->modified_callback && + (modified || + width != screen->dim[W] || + height != screen->dim[H])) { + ctk_object->modified_callback(ctk_object->layout, + ctk_object->modified_callback_data); + } + + /* Redraw layout and reset the foreground color */ + if (fg_gc) { + draw_layout(ctk_object); + + gdk_gc_set_values(fg_gc, &old_gc_values, GDK_GC_FOREGROUND); + + do_swap(ctk_object); + } + +} /* ctk_display_layout_set_screen_virtual_size() */ + + + /** ctk_display_layout_set_screen_depth() **************************** * * Sets which modeline the screen should use. @@ -3602,6 +4256,7 @@ void ctk_display_layout_set_screen_position(CtkDisplayLayout *ctk_object, nvDisplayPtr other; int x_offset = x - screen->dim[X]; int y_offset = y - screen->dim[Y]; + int *sdim; /* Make sure this screen use absolute positioning */ switch_screen_to_absolute(screen); @@ -3614,17 +4269,15 @@ void ctk_display_layout_set_screen_position(CtkDisplayLayout *ctk_object, } /* Recalculate the layout */ - calc_layout(layout); - offset_layout(layout, -layout->dim[X], -layout->dim[Y]); - recenter_layout(layout); - sync_scaling(ctk_object); - sync_modify(ctk_object); + ctk_display_layout_update(ctk_object); /* Report back result of move */ - if (ctk_object->modified_callback && - (modified || - x != screen->cur_metamode->edim[X] || - y != screen->cur_metamode->edim[Y])) { + sdim = get_screen_dim(screen, 1); + if (x != sdim[X] || y != sdim[Y]) { + modified = 1; + } + + if (ctk_object->modified_callback && modified) { ctk_object->modified_callback (ctk_object->layout, ctk_object->modified_callback_data); } @@ -3659,11 +4312,7 @@ void ctk_display_layout_set_screen_position(CtkDisplayLayout *ctk_object, */ /* Recalculate the layout */ - calc_layout(layout); - offset_layout(layout, -layout->dim[X], -layout->dim[Y]); - recenter_layout(layout); - sync_scaling(ctk_object); - sync_modify(ctk_object); + ctk_display_layout_update(ctk_object); break; } @@ -3780,14 +4429,21 @@ motion_event_callback(GtkWidget *widget, GdkEventMotion *event, gpointer data) GdkGCValues old_gc_values; static int init = 1; - static int __modify_panning; + int modify_panning; - if (init) { + + /* Swap between panning and moving */ + if (ctk_object->advanced_mode && (event->state & ShiftMask)) { + modify_panning = 1; + } else { + modify_panning = 0; + } + if ((ctk_object->modify_info.modify_panning != modify_panning) || init) { init = 0; - __modify_panning = (event->state & ShiftMask) ? 1 : 0; + ctk_object->modify_info.modify_dirty = 1; } - + /* Nothing to do if mouse didn't move */ if (ctk_object->last_mouse_x == event->x && ctk_object->last_mouse_y == event->y) { return TRUE; @@ -3797,8 +4453,9 @@ motion_event_callback(GtkWidget *widget, GdkEventMotion *event, gpointer data) ctk_object->mouse_y = event->y; - /* Mouse moved, allow user to reselect the current display */ - ctk_object->select_next = 0; + /* If mouse moved, allow user to reselect the current display/screen */ + ctk_object->first_selected_display = NULL; + ctk_object->first_selected_screen = NULL; /* Backup the foreground color */ @@ -3816,12 +4473,7 @@ motion_event_callback(GtkWidget *widget, GdkEventMotion *event, gpointer data) clear_layout(ctk_object); - /* Swap between panning and moving */ - if (__modify_panning != ((event->state & ShiftMask) ? 1 : 0)) { - __modify_panning = ((event->state & ShiftMask) ? 1 : 0); - sync_modify(ctk_object); - } - if (!(event->state & ShiftMask) || !ctk_object->advanced_mode) { + if (!modify_panning) { modified = move_selected(ctk_object, delta_x, delta_y, 1); } else { modified = pan_selected(ctk_object, delta_x, delta_y, 1); @@ -3838,7 +4490,7 @@ motion_event_callback(GtkWidget *widget, GdkEventMotion *event, gpointer data) /* Update the tooltip under the mouse */ } else { char *tip = - get_display_tooltip_under_mouse(ctk_object, event->x, event->y); + get_tooltip_under_mouse(ctk_object, event->x, event->y); if (tip) { gtk_tooltips_set_tip(ctk_object->tooltip_group, @@ -3879,20 +4531,43 @@ button_press_event_callback(GtkWidget *widget, GdkEventButton *event, gpointer data) { CtkDisplayLayout *ctk_object = CTK_DISPLAY_LAYOUT(data); - nvDisplayPtr last_selected; /* Last display selected */ - nvDisplayPtr new_selected; + void *last_selected; /* Last thing selected */ + void *new_selected; /* Scale and offset x & y so they reside in the clickable area */ int x = (event->x -ctk_object->img_dim[X]) / ctk_object->scale; int y = (event->y -ctk_object->img_dim[Y]) / ctk_object->scale; - static Time time = 0; + GdkEvent *next_event; + nvScreenPtr reselect_screen = NULL; ctk_object->last_mouse_x = event->x; ctk_object->last_mouse_y = event->y; + /* Check to see if a double click event is pending + * and ignore this click if that is the case. + */ + next_event = gdk_event_peek(); + if (next_event) { + if (next_event->type == GDK_2BUTTON_PRESS) { + /* Double click event detected, ignore the + * preceding GDK_BUTTON_PRESS + */ + return TRUE; + } + } + + /* Handle double clicks */ + if (event->type == GDK_2BUTTON_PRESS) { + /* XXX Flash the display or screen */ + return TRUE; + } + + /* XXX Ignore tripple clicks */ + if (event->type != GDK_BUTTON_PRESS) return TRUE; + switch (event->button) { /* Select a display device */ @@ -3900,35 +4575,74 @@ button_press_event_callback(GtkWidget *widget, GdkEventButton *event, ctk_object->button1 = 1; last_selected = get_selected(ctk_object); + /* If the user had a screen selected + * and is not cycling through overlapping + * elements (screens/displays), try to + * re-select the screen instead of the display. + */ + if (!ctk_object->first_selected_display && + !ctk_object->first_selected_screen && + !ctk_object->selected_display && + ctk_object->selected_screen + ) { + reselect_screen = ctk_object->selected_screen; + } + + /* If user clicked on the same spot twice, push last + * selection back in the Z-order. + */ + if (ctk_object->first_selected_display || + ctk_object->first_selected_screen) { + pushback_selected(ctk_object); + } /* Do the click */ - click_layout(ctk_object, x, y); + click_layout(ctk_object, x, y, reselect_screen); + /* Keep track of what is first selected to properly handle + * cycling through displays and screens when user keeps + * clicks on same spot. + */ new_selected = get_selected(ctk_object); - - /* If the user just clicked on the currently selected display, - * the next time they click here, we should instead select - * the next display in the Z order. + + /* If the user clicks a second time on a display that has a + * screen (or has cycled/clicked through all the displays + * on that screen), select the screen instead of the first + * display that was originally clicked. */ - ctk_object->select_next = - (last_selected == new_selected)?1:0; - - if (ctk_object->selected_callback) { - ctk_object->selected_callback(ctk_object->layout, - ctk_object->selected_callback_data); + if (ctk_object->first_selected_display && + ctk_object->first_selected_screen && + (ctk_object->first_selected_display == + ctk_object->selected_display) + ) { + ctk_object->first_selected_display = NULL; + ctk_object->selected_display = NULL; + new_selected = ctk_object->first_selected_screen; + } else { + /* Keep track of the first display the user + * clicked on wrt the screen the display + * belongs to. (ie, if the user clicked + * and we cycled to the next display in a + * TwinView screen, don't reset the first + * selected display. + */ + if (!ctk_object->first_selected_display || + (ctk_object->first_selected_screen!= + ctk_object->selected_screen)) { + ctk_object->first_selected_display = + ctk_object->selected_display; + } } - if (last_selected != new_selected) { - /* Selected new display - Redraw */ - time = event->time; + /* Keep track of the selected screen */ + ctk_object->first_selected_screen = + ctk_object->selected_screen; - } else if (new_selected && time && (event->time - time < 500)) { - /* Double clicked on display - XXX Could flash display here */ - time = 0; - } else { - /* Selected same display - Do noting */ - time = event->time; + /* Report back selection event */ + if (ctk_object->selected_callback) { + ctk_object->selected_callback(ctk_object->layout, + ctk_object->selected_callback_data); } /* Redraw everything */ diff --git a/src/gtk+-2.x/ctkdisplaylayout.h b/src/gtk+-2.x/ctkdisplaylayout.h index 79d8894..6634bf0 100644 --- a/src/gtk+-2.x/ctkdisplaylayout.h +++ b/src/gtk+-2.x/ctkdisplaylayout.h @@ -207,7 +207,7 @@ typedef struct nvMetaModeRec { int source; /* Source of the metamode */ Bool switchable; /* Can the metamode be accessed through Ctrl Alt +- */ - // Used for drawing metamode boxes + // Used for drawing & moving metamode boxes int dim[4]; /* Bounding box of all modes */ // Used for applying and generating metamodes (effective dimensions) @@ -228,19 +228,18 @@ typedef struct nvScreenRec { /* An X screen may have one or more displays connected to it * if TwinView is on. * - * Fathers all displays (and their modes). From this - * Structure a metamodes string can be generated: - * - * "AAA,BBB,CCC ; DDD,EEE,FFF ; GGG,HHH,III" + * If NoScanout is enabled, the X screen will not make use + * of display device(s). + * */ NvCtrlAttributeHandle *handle; /* NV-CONTROL handle to X screen */ CtkEvent *ctk_event; int scrnum; - struct nvGpuRec *gpu; /* GPU driving this X screen */ + struct nvGpuRec *gpu; /* GPU driving this X screen */ - int depth; /* Depth of the screen */ + int depth; /* Depth of the screen */ unsigned int displays_mask; /* Display devices on this X screen */ int num_displays; /* # of displays using this screen */ @@ -259,6 +258,8 @@ typedef struct nvScreenRec { int y_offset; Bool sli; + Bool dynamic_twinview; /* This screen supports dynamic twinview */ + Bool no_scanout; /* This screen has no display devices */ } nvScreen, *nvScreenPtr; @@ -335,6 +336,56 @@ typedef void (* ctk_display_layout_modified_callback) (nvLayoutPtr, void *); +/* Stores information about a screen or display that + * is being moved/panned. + */ +typedef struct ModifyInfoRec { + + /* What to move */ + nvDisplayPtr display; + nvScreenPtr screen; + int orig_screen_dim[4]; // Used when moding display = moding screen. + nvGpuPtr gpu; + + int orig_position_type; // Original values of what is being + int orig_dim[4]; // modified. + + int *target_position_type; // Pointers to values of thing that + int *target_dim; // is being modified. + + + /* Snapping */ + int snap; // Should we snap or not? + int best_snap_v; + int best_snap_h; + + int modify_dirty; // Sync the modify_dim before moving/panning. + int modify_panning; // Modifying panning (instead of position) + int modify_dim[4]; // Dimensions to snap from + + int src_dim[4]; // Pre-snap (To allow snapping of pan box on move) + int dst_dim[4]; // Post-snap position + +} ModifyInfo; + + + +// Something selectable/visible. +typedef struct _ZNode +{ + enum { + ZNODE_TYPE_DISPLAY, + ZNODE_TYPE_SCREEN, + } type; + + union { + nvDisplayPtr display; + nvScreenPtr screen; + } u; + +} ZNode; + + typedef struct _CtkDisplayLayout { GtkVBox parent; @@ -369,10 +420,12 @@ typedef struct _CtkDisplayLayout PangoLayout *pango_layout; - /* Display Z-Order */ - nvDisplayPtr *Zorder; /* Z ordering of dispays in layout */ - int Zcount; /* Number of displays in Z order list */ - int Zselected; /* Is first item selected? */ + /* List of visible elements in the layout */ + ZNode *Zorder; /* Z ordering of visible elements in layout */ + int Zcount; /* Count of visible elements in the z order */ + + nvDisplayPtr selected_display; /* Currently selected display */ + nvScreenPtr selected_screen; /* Selected screen */ /* Settings */ int snap_strength; @@ -381,9 +434,10 @@ typedef struct _CtkDisplayLayout /* - multiple modes */ /* State */ - int select_next; /* On click, select next screen in Z order. */ - int modify_dim[4]; /* Used to snap when moving/panning */ + void *first_selected_display; /* First thing clicked on (used to cycle) */ + void *first_selected_screen; int clicked_outside; /* User clicked outside displays, don't move */ + ModifyInfo modify_info; /* Used to move/pan screens/displays */ int button1; int button2; @@ -421,11 +475,14 @@ GtkWidget* ctk_display_layout_new (NvCtrlAttributeHandle *, void *modified_callback_data ); +void ctk_display_layout_update (CtkDisplayLayout *); + void ctk_display_layout_redraw (CtkDisplayLayout *); void ctk_display_layout_set_layout (CtkDisplayLayout *, nvLayoutPtr); +void ctk_display_layout_update_zorder(CtkDisplayLayout *ctk_object); nvDisplayPtr ctk_display_layout_get_selected_display (CtkDisplayLayout *); nvScreenPtr ctk_display_layout_get_selected_screen (CtkDisplayLayout *); @@ -449,6 +506,9 @@ void ctk_display_layout_select_display (CtkDisplayLayout *ctk_object, void ctk_display_layout_update_display_count (CtkDisplayLayout *, nvDisplayPtr); +void ctk_display_layout_set_screen_virtual_size (CtkDisplayLayout *ctk_object, + nvScreenPtr screen, + int width, int height); void ctk_display_layout_set_screen_depth (CtkDisplayLayout *ctk_object, nvScreenPtr screen, int depth); void ctk_display_layout_set_screen_position (CtkDisplayLayout *ctk_object, @@ -464,6 +524,8 @@ void ctk_display_layout_delete_screen_metamode (CtkDisplayLayout *, nvScreenPtr, int metamode_idx); +void ctk_display_layout_disable_display (CtkDisplayLayout *ctk_object, + nvDisplayPtr display); void ctk_display_layout_set_advanced_mode (CtkDisplayLayout *ctk_object, int advanced_mode); diff --git a/src/gtk+-2.x/ctkevent.c b/src/gtk+-2.x/ctkevent.c index 3c12a30..f7ce526 100644 --- a/src/gtk+-2.x/ctkevent.c +++ b/src/gtk+-2.x/ctkevent.c @@ -187,8 +187,8 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_SIGNAL(NV_CTRL_GVO_SUPPORTED); MAKE_SIGNAL(NV_CTRL_GVO_SYNC_MODE); MAKE_SIGNAL(NV_CTRL_GVO_SYNC_SOURCE); - MAKE_SIGNAL(NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT); - MAKE_SIGNAL(NV_CTRL_GVO_INPUT_VIDEO_FORMAT); + MAKE_SIGNAL(NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT); + MAKE_SIGNAL(NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT); MAKE_SIGNAL(NV_CTRL_GVO_DATA_FORMAT); MAKE_SIGNAL(NV_CTRL_GVO_DISPLAY_X_SCREEN); MAKE_SIGNAL(NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED); @@ -200,9 +200,9 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_SIGNAL(NV_CTRL_GVO_SYNC_DELAY_LINES); MAKE_SIGNAL(NV_CTRL_GVO_INPUT_VIDEO_FORMAT_REACQUIRE); MAKE_SIGNAL(NV_CTRL_GVO_GLX_LOCKED); - MAKE_SIGNAL(NV_CTRL_GVO_VIDEO_FORMAT_WIDTH); - MAKE_SIGNAL(NV_CTRL_GVO_VIDEO_FORMAT_HEIGHT); - MAKE_SIGNAL(NV_CTRL_GVO_VIDEO_FORMAT_REFRESH_RATE); + MAKE_SIGNAL(NV_CTRL_GVIO_VIDEO_FORMAT_WIDTH); + MAKE_SIGNAL(NV_CTRL_GVIO_VIDEO_FORMAT_HEIGHT); + MAKE_SIGNAL(NV_CTRL_GVIO_VIDEO_FORMAT_REFRESH_RATE); MAKE_SIGNAL(NV_CTRL_GVO_X_SCREEN_PAN_X); MAKE_SIGNAL(NV_CTRL_GVO_X_SCREEN_PAN_Y); MAKE_SIGNAL(NV_CTRL_GPU_OVERCLOCKING_STATE); @@ -270,7 +270,9 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_SIGNAL(NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE); MAKE_SIGNAL(NV_CTRL_GVO_ENABLE_RGB_DATA); MAKE_SIGNAL(NV_CTRL_IMAGE_SHARPENING_DEFAULT); + MAKE_SIGNAL(NV_CTRL_GVI_NUM_PORTS); MAKE_SIGNAL(NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION); + MAKE_SIGNAL(NV_CTRL_GPU_POWER_MIZER_MODE); #undef MAKE_SIGNAL @@ -281,7 +283,7 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) * knows about. */ -#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION +#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_GPU_POWER_MIZER_MODE #warning "There are attributes that do not emit signals!" #endif @@ -300,7 +302,7 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_STRING_SIGNAL(NV_CTRL_STRING_NVIDIA_DRIVER_VERSION); MAKE_STRING_SIGNAL(NV_CTRL_STRING_DISPLAY_DEVICE_NAME); MAKE_STRING_SIGNAL(NV_CTRL_STRING_TV_ENCODER_NAME); - MAKE_STRING_SIGNAL(NV_CTRL_STRING_GVO_FIRMWARE_VERSION); + MAKE_STRING_SIGNAL(NV_CTRL_STRING_GVIO_FIRMWARE_VERSION); MAKE_STRING_SIGNAL(NV_CTRL_STRING_CURRENT_MODELINE); MAKE_STRING_SIGNAL(NV_CTRL_STRING_ADD_MODELINE); MAKE_STRING_SIGNAL(NV_CTRL_STRING_DELETE_MODELINE); @@ -322,7 +324,7 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_STRING_SIGNAL(NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER); MAKE_STRING_SIGNAL(NV_CTRL_STRING_SLI_MODE); MAKE_STRING_SIGNAL(NV_CTRL_STRING_PERFORMANCE_MODES); - MAKE_STRING_SIGNAL(NV_CTRL_STRING_GVO_VIDEO_FORMAT_NAME); + MAKE_STRING_SIGNAL(NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME); #undef MAKE_STRING_SIGNAL #if NV_CTRL_STRING_LAST_ATTRIBUTE != NV_CTRL_STRING_GVO_VIDEO_FORMAT_NAME @@ -348,10 +350,11 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_FRAMELOCKS_USED_BY_GPU); MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_GPUS_USING_VCSC); MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_VCSCS_USED_BY_GPU); + MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN); #undef MAKE_BINARY_SIGNAL -#if NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE != NV_CTRL_BINARY_DATA_VCSCS_USED_BY_GPU +#if NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE != NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN #warning "There are attributes that do not emit signals!" #endif diff --git a/src/gtk+-2.x/ctkglx.c b/src/gtk+-2.x/ctkglx.c index 1ef3c96..4369564 100644 --- a/src/gtk+-2.x/ctkglx.c +++ b/src/gtk+-2.x/ctkglx.c @@ -50,8 +50,8 @@ static const char * __vid_help = "vid (XVisual ID) - ID of the associated X Visual."; static const char * __vt_help = "vt (XVisual Type) - Type of the associated X Visual. " - "Possible X visual types are 'tc', 'dc', 'pc', 'sc', 'gs', 'sg', '.' " - "which means TrueColor, DirectColor, PseudoColor, StaticColor, GrayScale, " + "Possible X visual types are 'tc', 'dc', 'pc', 'sc', 'gs', 'sg' and '.' " + "which mean TrueColor, DirectColor, PseudoColor, StaticColor, GrayScale, " "StaticGray and None, respectively."; static const char * __bfs_help = "bfs (buffer size) - Number of bits per color in the color buffer."; @@ -73,16 +73,16 @@ static const char * __st_help = "buffers that are rendered to in stereo. '-' if this is not supported."; static const char * __rs_help = "rs (Red size) - Number of bits per color used for red. " - "(Undefined for configurations that use color indexing.)"; + "Undefined for configurations that use color indexing."; static const char * __gs_help = "gs (Green size) - Number of bits per color used for green. " - "(Undefined for configurations that use color indexing.)"; + "Undefined for configurations that use color indexing."; static const char * __bs_help = "bs (Blue size) - Number of bits per color used for blue. " - "(Undefined for configurations that use color indexing.)"; + "Undefined for configurations that use color indexing."; static const char * __as_help = "as (Alpha size) - Number of bits per color used for alpha. " - "(Undefined for configurations that use color indexing.)"; + "Undefined for configurations that use color indexing."; static const char * __aux_help = "aux (Auxiliary buffers) - Number of available auxiliary color buffers."; static const char * __dpt_help = @@ -826,7 +826,7 @@ GtkTextBuffer *ctk_glx_create_help(GtkTextTagTable *table, ctk_help_para(b, &i, "This is the list of GLX extensions that are supported by " "both the client (libraries) and server (GLX extension to " - "the X Server.)" + "the X Server)." ); ctk_help_heading(b, &i, "Server GLX Vendor String"); diff --git a/src/gtk+-2.x/ctkgpu.c b/src/gtk+-2.x/ctkgpu.c index d3ad614..ea10438 100644 --- a/src/gtk+-2.x/ctkgpu.c +++ b/src/gtk+-2.x/ctkgpu.c @@ -139,21 +139,20 @@ GtkWidget* ctk_gpu_new( char *product_name, *vbios_version, *video_ram, *irq; gchar *bus_type, *bus_rate, *bus; - int pci_bus; - int pci_device; - int pci_func; + int pci_domain, pci_bus, pci_device, pci_func; gchar *pci_bus_id; gchar pci_device_id[ARRAY_ELEMENTS]; gchar pci_vendor_id[ARRAY_ELEMENTS]; int pci_id; - gchar *__pci_bus_id_unknown = "?:?:?"; + gchar *__pci_bus_id_unknown = "?@?:?:?"; int tmp; ReturnStatus ret; gchar *screens; gchar *displays; + gchar *tmp_str; unsigned int display_devices; int xinerama_enabled; @@ -211,9 +210,14 @@ GtkWidget* ctk_gpu_new( bus = g_strdup(bus_type); } - /* NV_CTRL_PCI_BUS & NV_CTRL_PCI_DEVICE & NV__CTRL_PCI_FUNCTION */ + /* NV_CTRL_PCI_DOMAIN & NV_CTRL_PCI_BUS & + * NV_CTRL_PCI_DEVICE & NV__CTRL_PCI_FUNCTION + */ pci_bus_id = NULL; + ret = NvCtrlGetAttribute(handle, NV_CTRL_PCI_DOMAIN, &pci_domain); + if (ret != NvCtrlSuccess) pci_bus_id = __pci_bus_id_unknown; + ret = NvCtrlGetAttribute(handle, NV_CTRL_PCI_BUS, &pci_bus); if (ret != NvCtrlSuccess) pci_bus_id = __pci_bus_id_unknown; @@ -224,8 +228,13 @@ GtkWidget* ctk_gpu_new( if (ret != NvCtrlSuccess) pci_bus_id = __pci_bus_id_unknown; if (!pci_bus_id) { - pci_bus_id = g_strdup_printf("%d:%d:%d", - pci_bus, pci_device, pci_func); + if (pci_domain == 0) { + pci_bus_id = g_strdup_printf("%d:%d:%d", pci_bus, pci_device, + pci_func); + } else { + pci_bus_id = g_strdup_printf("%d@%d:%d:%d", pci_bus, pci_domain, + pci_device, pci_func); + } } else { pci_bus_id = g_strdup(__pci_bus_id_unknown); } @@ -269,52 +278,46 @@ GtkWidget* ctk_gpu_new( irq = g_strdup_printf("%d", tmp); } - /* List of X Screens using GPU */ - - if (xinerama_enabled) { - - /* In Xinerama, there is only one logical X screen */ - - screens = g_strdup("Screen 0 (Xinerama)"); - - } else { - gchar *tmp_str; - screens = NULL; - - ret = NvCtrlGetBinaryAttribute(handle, - 0, - NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU, - (unsigned char **)(&pData), - &len); - if (ret == NvCtrlSuccess) { - for (i = 1; i <= pData[0]; i++) { - - if (screens) { - tmp_str = g_strdup_printf("%s,\nScreen %d", - screens, pData[i]); - } else { - tmp_str = g_strdup_printf("Screen %d", pData[i]); - } - g_free(screens); - screens = tmp_str; - } - if (!screens) { - screens = g_strdup("None"); - - } else if (pData[0] > 0) { - - ret = NvCtrlGetAttribute(t[pData[1]].h, - NV_CTRL_SHOW_SLI_HUD, - &tmp); - - if (ret == NvCtrlSuccess) { - tmp_str = g_strdup_printf("%s (SLI)", screens); + /* List of X Screens using the GPU */ + + screens = NULL; + ret = NvCtrlGetBinaryAttribute(handle, + 0, + NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU, + (unsigned char **)(&pData), + &len); + if (ret == NvCtrlSuccess) { + if (pData[0] == 0) { + screens = g_strdup("None"); + } else { + if (xinerama_enabled) { + screens = g_strdup("Screen 0 (Xinerama)"); + } else { + for (i = 1; i <= pData[0]; i++) { + if (screens) { + tmp_str = g_strdup_printf("%s,\nScreen %d", + screens, pData[i]); + } else { + tmp_str = g_strdup_printf("Screen %d", pData[i]); + } g_free(screens); screens = tmp_str; } } - XFree(pData); + + ret = NvCtrlGetAttribute(t[pData[1]].h, + NV_CTRL_SHOW_SLI_HUD, + &tmp); + if (ret == NvCtrlSuccess) { + tmp_str = g_strdup_printf("%s (SLI)", screens); + g_free(screens); + screens = tmp_str; + } } + XFree(pData); + } + if (!screens) { + screens = g_strdup("Unknown"); } /* List of Display Device connected on GPU */ diff --git a/src/gtk+-2.x/ctkgvo-banner.c b/src/gtk+-2.x/ctkgvo-banner.c index 581cc88..9e13c04 100644 --- a/src/gtk+-2.x/ctkgvo-banner.c +++ b/src/gtk+-2.x/ctkgvo-banner.c @@ -232,9 +232,9 @@ GtkWidget* ctk_gvo_banner_new(NvCtrlAttributeHandle *handle, } ctk_gvo_banner->sync_source = val; - ret = NvCtrlGetAttribute(handle, NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT, &val); + ret = NvCtrlGetAttribute(handle, NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT, &val); if (ret != NvCtrlSuccess) { - val = NV_CTRL_GVO_VIDEO_FORMAT_NONE; + val = NV_CTRL_GVIO_VIDEO_FORMAT_NONE; } ctk_gvo_banner->output_video_format = val; @@ -289,7 +289,7 @@ GtkWidget* ctk_gvo_banner_new(NvCtrlAttributeHandle *handle, (gpointer) ctk_gvo_banner); g_signal_connect(G_OBJECT(ctk_gvo_banner->ctk_event), - CTK_EVENT_NAME(NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT), + CTK_EVENT_NAME(NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT), G_CALLBACK(gvo_event_received), (gpointer) ctk_gvo_banner); @@ -575,7 +575,7 @@ static gboolean update_gvo_banner_led_images_shared_sync_bnc(gpointer data) ((banner->sync_source == NV_CTRL_GVO_SYNC_SOURCE_SDI) && banner->state[GVO_BANNER_SDI] != GVO_LED_SDI_SYNC_NONE))) { - if (banner->input_video_format != NV_CTRL_GVO_VIDEO_FORMAT_NONE) { + if (banner->input_video_format != NV_CTRL_GVIO_VIDEO_FORMAT_NONE) { /* LED blinks if video format is detected */ new = banner->flash ? LED_GREEN : LED_GREY; } else { @@ -607,13 +607,13 @@ static void update_video_output_state(CtkGvoBanner *banner, gint output_video_format, gint output_data_format) { - if (output_video_format == NV_CTRL_GVO_VIDEO_FORMAT_NONE) { + if (output_video_format == NV_CTRL_GVIO_VIDEO_FORMAT_NONE) { banner->state[GVO_BANNER_VID1] = GVO_LED_VID_OUT_NOT_IN_USE; banner->state[GVO_BANNER_VID2] = GVO_LED_VID_OUT_NOT_IN_USE; } else if ((output_video_format == - NV_CTRL_GVO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC) || + NV_CTRL_GVIO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC) || (output_video_format == - NV_CTRL_GVO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL)) { + NV_CTRL_GVIO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL)) { banner->state[GVO_BANNER_VID1] = GVO_LED_VID_OUT_SD_MODE; banner->state[GVO_BANNER_VID2] = GVO_LED_VID_OUT_SD_MODE; } else { @@ -675,7 +675,7 @@ static void update_gvo_banner_led_state(CtkGvoBanner *ctk_gvo_banner) ctk_gvo_banner->output_data_format); } else { update_video_output_state(ctk_gvo_banner, - NV_CTRL_GVO_VIDEO_FORMAT_NONE, + NV_CTRL_GVIO_VIDEO_FORMAT_NONE, ctk_gvo_banner->output_data_format); } @@ -725,13 +725,13 @@ gint ctk_gvo_banner_probe(gpointer data) ctk_gvo_banner->sync_source = val; - /* query NV_CTRL_GVO_INPUT_VIDEO_FORMAT */ + /* query NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT */ ret = NvCtrlGetAttribute(ctk_gvo_banner->handle, - NV_CTRL_GVO_INPUT_VIDEO_FORMAT, &val); + NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT, &val); if (ret != NvCtrlSuccess) { - val = NV_CTRL_GVO_VIDEO_FORMAT_NONE; + val = NV_CTRL_GVIO_VIDEO_FORMAT_NONE; } ctk_gvo_banner->input_video_format = val; @@ -813,7 +813,7 @@ static void gvo_event_received(GtkObject *object, ctk_gvo_banner->sync_source = value; break; - case NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT: + case NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT: ctk_gvo_banner->output_video_format = value; break; diff --git a/src/gtk+-2.x/ctkgvo-sync.c b/src/gtk+-2.x/ctkgvo-sync.c index 8082329..f58d61e 100644 --- a/src/gtk+-2.x/ctkgvo-sync.c +++ b/src/gtk+-2.x/ctkgvo-sync.c @@ -753,9 +753,9 @@ static gboolean query_init_gvo_sync_state(CtkGvoSync *ctk_gvo_sync) /* Query the current input video formats */ ret = NvCtrlGetAttribute(ctk_gvo_sync->handle, - NV_CTRL_GVO_INPUT_VIDEO_FORMAT, &val); + NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT, &val); if (ret != NvCtrlSuccess) { - val = NV_CTRL_GVO_VIDEO_FORMAT_NONE; + val = NV_CTRL_GVIO_VIDEO_FORMAT_NONE; } ctk_gvo_sync->input_video_format = val; diff --git a/src/gtk+-2.x/ctkgvo-sync.h b/src/gtk+-2.x/ctkgvo-sync.h index 7480bb7..db4b97b 100644 --- a/src/gtk+-2.x/ctkgvo-sync.h +++ b/src/gtk+-2.x/ctkgvo-sync.h @@ -71,7 +71,7 @@ struct _CtkGvoSync gint caps; // SDI device capabilities gint sync_mode; // NV_CTRL_GVO_SYNC_MODE - gint input_video_format; // NV_CTRL_GVO_INPUT_VIDEO_FORMAT + gint input_video_format; // NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT gint sync_source; // NV_CTRL_ SDI and COMP sync formats... gint sdi_sync_input_detected; diff --git a/src/gtk+-2.x/ctkgvo.c b/src/gtk+-2.x/ctkgvo.c index 8e31f40..f98d4e1 100644 --- a/src/gtk+-2.x/ctkgvo.c +++ b/src/gtk+-2.x/ctkgvo.c @@ -48,7 +48,7 @@ /* Some defaults */ #define DEFAULT_OUTPUT_VIDEO_FORMAT \ - NV_CTRL_GVO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC + NV_CTRL_GVIO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC #define DEFAULT_OUTPUT_DATA_FORMAT \ NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_YCRCB444 @@ -145,87 +145,87 @@ static void screen_changed_handler(GtkWidget *widget, */ const GvoFormatName videoFormatNames[] = { - { NV_CTRL_GVO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC, "720 x 487i 59.94 Hz (SMPTE259) NTSC"}, - { NV_CTRL_GVO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL, "720 x 576i 50.00 Hz (SMPTE259) PAL"}, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_23_98_SMPTE296, "1280 x 720p 23.98 Hz (SMPTE296)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_24_00_SMPTE296, "1280 x 720p 24.00 Hz (SMPTE296)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_25_00_SMPTE296, "1280 x 720p 25.00 Hz (SMPTE296)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_29_97_SMPTE296, "1280 x 720p 29.97 Hz (SMPTE296)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_30_00_SMPTE296, "1280 x 720p 30.00 Hz (SMPTE296)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_50_00_SMPTE296, "1280 x 720p 50.00 Hz (SMPTE296)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_59_94_SMPTE296, "1280 x 720p 59.94 Hz (SMPTE296)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_60_00_SMPTE296, "1280 x 720p 60.00 Hz (SMPTE296)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1035I_59_94_SMPTE260, "1920 x 1035i 59.94 Hz (SMPTE260)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1035I_60_00_SMPTE260, "1920 x 1035i 60.00 Hz (SMPTE260)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080I_47_96_SMPTE274, "1920 x 1080i 47.96 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080I_48_00_SMPTE274, "1920 x 1080i 48.00 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE295, "1920 x 1080i 50.00 Hz (SMPTE295)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE274, "1920 x 1080i 50.00 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080I_59_94_SMPTE274, "1920 x 1080i 59.94 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080I_60_00_SMPTE274, "1920 x 1080i 60.00 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080P_23_976_SMPTE274, "1920 x 1080p 23.976 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080P_24_00_SMPTE274, "1920 x 1080p 24.00 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080P_25_00_SMPTE274, "1920 x 1080p 25.00 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080P_29_97_SMPTE274, "1920 x 1080p 29.97 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080P_30_00_SMPTE274, "1920 x 1080p 30.00 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_23_98_SMPTE274, "1920 x 1080PsF 23.98 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_24_00_SMPTE274, "1920 x 1080PsF 24.00 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_25_00_SMPTE274, "1920 x 1080PsF 25.00 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_29_97_SMPTE274, "1920 x 1080PsF 29.97 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274, "1920 x 1080PsF 30.00 Hz (SMPTE274)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048I_47_96_SMPTE372, "2048 x 1080i 47.96 Hz (SMPTE372)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048I_48_00_SMPTE372, "2048 x 1080i 48.00 Hz (SMPTE372)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048I_50_00_SMPTE372, "2048 x 1080i 50.00 Hz (SMPTE372)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048I_59_94_SMPTE372, "2048 x 1080i 59.94 Hz (SMPTE372)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048I_60_00_SMPTE372, "2048 x 1080i 60.00 Hz (SMPTE372)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048P_23_98_SMPTE372, "2048 x 1080p 23.98 Hz (SMPTE372)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048P_24_00_SMPTE372, "2048 x 1080p 24.00 Hz (SMPTE372)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048P_25_00_SMPTE372, "2048 x 1080p 25.00 Hz (SMPTE372)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048P_29_97_SMPTE372, "2048 x 1080p 29.97 Hz (SMPTE372)" }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048P_30_00_SMPTE372, "2048 x 1080p 30.00 Hz (SMPTE372)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC, "720 x 487i 59.94 Hz (SMPTE259) NTSC"}, + { NV_CTRL_GVIO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL, "720 x 576i 50.00 Hz (SMPTE259) PAL"}, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_23_98_SMPTE296, "1280 x 720p 23.98 Hz (SMPTE296)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_24_00_SMPTE296, "1280 x 720p 24.00 Hz (SMPTE296)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_25_00_SMPTE296, "1280 x 720p 25.00 Hz (SMPTE296)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_29_97_SMPTE296, "1280 x 720p 29.97 Hz (SMPTE296)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_30_00_SMPTE296, "1280 x 720p 30.00 Hz (SMPTE296)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_50_00_SMPTE296, "1280 x 720p 50.00 Hz (SMPTE296)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_59_94_SMPTE296, "1280 x 720p 59.94 Hz (SMPTE296)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_60_00_SMPTE296, "1280 x 720p 60.00 Hz (SMPTE296)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1035I_59_94_SMPTE260, "1920 x 1035i 59.94 Hz (SMPTE260)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1035I_60_00_SMPTE260, "1920 x 1035i 60.00 Hz (SMPTE260)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080I_47_96_SMPTE274, "1920 x 1080i 47.96 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080I_48_00_SMPTE274, "1920 x 1080i 48.00 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_SMPTE295, "1920 x 1080i 50.00 Hz (SMPTE295)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_SMPTE274, "1920 x 1080i 50.00 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080I_59_94_SMPTE274, "1920 x 1080i 59.94 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080I_60_00_SMPTE274, "1920 x 1080i 60.00 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080P_23_976_SMPTE274, "1920 x 1080p 23.976 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080P_24_00_SMPTE274, "1920 x 1080p 24.00 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080P_25_00_SMPTE274, "1920 x 1080p 25.00 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080P_29_97_SMPTE274, "1920 x 1080p 29.97 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080P_30_00_SMPTE274, "1920 x 1080p 30.00 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_23_98_SMPTE274, "1920 x 1080PsF 23.98 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_24_00_SMPTE274, "1920 x 1080PsF 24.00 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_25_00_SMPTE274, "1920 x 1080PsF 25.00 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_29_97_SMPTE274, "1920 x 1080PsF 29.97 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274, "1920 x 1080PsF 30.00 Hz (SMPTE274)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048I_47_96_SMPTE372, "2048 x 1080i 47.96 Hz (SMPTE372)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048I_48_00_SMPTE372, "2048 x 1080i 48.00 Hz (SMPTE372)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048I_50_00_SMPTE372, "2048 x 1080i 50.00 Hz (SMPTE372)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048I_59_94_SMPTE372, "2048 x 1080i 59.94 Hz (SMPTE372)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048I_60_00_SMPTE372, "2048 x 1080i 60.00 Hz (SMPTE372)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048P_23_98_SMPTE372, "2048 x 1080p 23.98 Hz (SMPTE372)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048P_24_00_SMPTE372, "2048 x 1080p 24.00 Hz (SMPTE372)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048P_25_00_SMPTE372, "2048 x 1080p 25.00 Hz (SMPTE372)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048P_29_97_SMPTE372, "2048 x 1080p 29.97 Hz (SMPTE372)" }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048P_30_00_SMPTE372, "2048 x 1080p 30.00 Hz (SMPTE372)" }, { -1, NULL }, }; static GvoFormatDetails videoFormatDetails[] = { - { NV_CTRL_GVO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_23_98_SMPTE296, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_24_00_SMPTE296, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_25_00_SMPTE296, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_29_97_SMPTE296, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_30_00_SMPTE296, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_50_00_SMPTE296, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_59_94_SMPTE296, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_720P_60_00_SMPTE296, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1035I_59_94_SMPTE260, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1035I_60_00_SMPTE260, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080I_47_96_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080I_48_00_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE295, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080I_59_94_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080I_60_00_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080P_23_976_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080P_24_00_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080P_25_00_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080P_29_97_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080P_30_00_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_23_98_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_24_00_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_25_00_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_29_97_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048I_47_96_SMPTE372, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048I_48_00_SMPTE372, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048I_50_00_SMPTE372, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048I_59_94_SMPTE372, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048I_60_00_SMPTE372, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048P_23_98_SMPTE372, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048P_24_00_SMPTE372, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048P_25_00_SMPTE372, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048P_29_97_SMPTE372, 0, 0, 0 }, - { NV_CTRL_GVO_VIDEO_FORMAT_2048P_30_00_SMPTE372, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_23_98_SMPTE296, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_24_00_SMPTE296, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_25_00_SMPTE296, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_29_97_SMPTE296, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_30_00_SMPTE296, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_50_00_SMPTE296, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_59_94_SMPTE296, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_720P_60_00_SMPTE296, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1035I_59_94_SMPTE260, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1035I_60_00_SMPTE260, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080I_47_96_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080I_48_00_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_SMPTE295, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080I_59_94_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080I_60_00_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080P_23_976_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080P_24_00_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080P_25_00_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080P_29_97_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080P_30_00_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_23_98_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_24_00_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_25_00_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_29_97_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048I_47_96_SMPTE372, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048I_48_00_SMPTE372, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048I_50_00_SMPTE372, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048I_59_94_SMPTE372, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048I_60_00_SMPTE372, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048P_23_98_SMPTE372, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048P_24_00_SMPTE372, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048P_25_00_SMPTE372, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048P_29_97_SMPTE372, 0, 0, 0 }, + { NV_CTRL_GVIO_VIDEO_FORMAT_2048P_30_00_SMPTE372, 0, 0, 0 }, { -1, -1, -1, -1 }, }; @@ -380,7 +380,7 @@ guint ctk_gvo_video_format_valid(CtkGvo *ctk_gvo, const gint format) /* Check that formats match if Genlock is enabled */ else if ((ctk_gvo->sync_mode == NV_CTRL_GVO_SYNC_MODE_GENLOCK) && - (ctk_gvo->input_video_format != NV_CTRL_GVO_VIDEO_FORMAT_NONE) && + (ctk_gvo->input_video_format != NV_CTRL_GVIO_VIDEO_FORMAT_NONE) && (ctk_gvo->input_video_format != format)) { valid &= ~(GVO_VIDEO_FORMAT_REFRESH_VALID); } @@ -388,7 +388,7 @@ guint ctk_gvo_video_format_valid(CtkGvo *ctk_gvo, const gint format) /* Check that format refresh rates match if Frame Lock is enabled */ else if ((ctk_gvo->sync_mode == NV_CTRL_GVO_SYNC_MODE_FRAMELOCK) && - (ctk_gvo->input_video_format != NV_CTRL_GVO_VIDEO_FORMAT_NONE)) { + (ctk_gvo->input_video_format != NV_CTRL_GVIO_VIDEO_FORMAT_NONE)) { /* Get the refresh rate */ ctk_gvo_get_video_format_refresh(format, &refresh_rate); @@ -572,7 +572,7 @@ GtkWidget* ctk_gvo_new(NvCtrlAttributeHandle *handle, string = NULL; ret = NvCtrlGetStringAttribute(handle, - NV_CTRL_STRING_GVO_FIRMWARE_VERSION, + NV_CTRL_STRING_GVIO_FIRMWARE_VERSION, &string); if ((ret == NvCtrlSuccess) && (string)) { @@ -1179,14 +1179,14 @@ static gboolean query_init_gvo_state(CtkGvo *ctk_gvo) /* Query the current input/output video formats */ - ret = NvCtrlGetAttribute(ctk_gvo->handle, NV_CTRL_GVO_INPUT_VIDEO_FORMAT, + ret = NvCtrlGetAttribute(ctk_gvo->handle, NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT, &val); if (ret != NvCtrlSuccess) { - val = NV_CTRL_GVO_VIDEO_FORMAT_NONE; + val = NV_CTRL_GVIO_VIDEO_FORMAT_NONE; } ctk_gvo->input_video_format = val; - ret = NvCtrlGetAttribute(ctk_gvo->handle, NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT, + ret = NvCtrlGetAttribute(ctk_gvo->handle, NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT, &val); if (ret != NvCtrlSuccess) { val = DEFAULT_OUTPUT_VIDEO_FORMAT; @@ -1196,7 +1196,7 @@ static gboolean query_init_gvo_state(CtkGvo *ctk_gvo) /* Valid output video formats */ ret = NvCtrlGetValidAttributeValues(ctk_gvo->handle, - NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT, + NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT, &valid); if ((ret != NvCtrlSuccess) || (valid.type != ATTRIBUTE_TYPE_INT_BITS)) { ctk_gvo->valid_output_video_format_mask[0] = 0; @@ -1205,7 +1205,7 @@ static gboolean query_init_gvo_state(CtkGvo *ctk_gvo) } ret = NvCtrlGetValidAttributeValues(ctk_gvo->handle, - NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT2, + NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2, &valid); if ((ret != NvCtrlSuccess) || (valid.type != ATTRIBUTE_TYPE_INT_BITS)) { @@ -1248,7 +1248,7 @@ static void query_video_format_details(CtkGvo *ctk_gvo) ret = NvCtrlGetDisplayAttribute(ctk_gvo->handle, videoFormatDetails[i].format, - NV_CTRL_GVO_VIDEO_FORMAT_REFRESH_RATE, + NV_CTRL_GVIO_VIDEO_FORMAT_REFRESH_RATE, &val); if (ret != NvCtrlSuccess) val = 0; @@ -1257,7 +1257,7 @@ static void query_video_format_details(CtkGvo *ctk_gvo) ret = NvCtrlGetDisplayAttribute(ctk_gvo->handle, videoFormatDetails[i].format, - NV_CTRL_GVO_VIDEO_FORMAT_WIDTH, + NV_CTRL_GVIO_VIDEO_FORMAT_WIDTH, &val); if (ret != NvCtrlSuccess) val = 0; @@ -1266,7 +1266,7 @@ static void query_video_format_details(CtkGvo *ctk_gvo) ret = NvCtrlGetDisplayAttribute(ctk_gvo->handle, videoFormatDetails[i].format, - NV_CTRL_GVO_VIDEO_FORMAT_HEIGHT, + NV_CTRL_GVIO_VIDEO_FORMAT_HEIGHT, &val); if (ret != NvCtrlSuccess) val = 0; @@ -1286,7 +1286,7 @@ static void query_video_format_details(CtkGvo *ctk_gvo) static void register_for_gvo_events(CtkGvo *ctk_gvo) { g_signal_connect(G_OBJECT(ctk_gvo->ctk_event), - CTK_EVENT_NAME(NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT), + CTK_EVENT_NAME(NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT), G_CALLBACK(gvo_event_received), (gpointer) ctk_gvo); @@ -1349,7 +1349,7 @@ static void output_video_format_ui_changed(CtkDropDownMenu *menu, } NvCtrlSetAttribute(ctk_gvo->handle, - NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT, + NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT, ctk_gvo->output_video_format); /* Rebuild menu to remove previously invalid entry */ @@ -1742,7 +1742,7 @@ static void gvo_event_received(GtkObject *object, switch (attribute) { - case NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT: + case NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT: widget = ctk_gvo->output_video_format_menu; ctk_gvo->output_video_format = value; @@ -1858,7 +1858,7 @@ static void screen_changed_handler(GtkWidget *widget, * * - NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED * - NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED - * - NV_CTRL_GVO_INPUT_VIDEO_FORMAT + * - NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT * */ diff --git a/src/gtk+-2.x/ctkpowermizer.c b/src/gtk+-2.x/ctkpowermizer.c index 83f64b8..cf5ef40 100644 --- a/src/gtk+-2.x/ctkpowermizer.c +++ b/src/gtk+-2.x/ctkpowermizer.c @@ -41,6 +41,11 @@ #define DEFAULT_UPDATE_POWERMIZER_INFO_TIME_INTERVAL 1000 static gboolean update_powermizer_info(gpointer); +static void update_powermizer_menu_info(gpointer); +static void powermizer_menu_changed(GtkOptionMenu*, gpointer); +static void update_powermizer_menu_event(GtkObject *object, + gpointer arg1, + gpointer user_data); static const char *__adaptive_clock_help = "The Adaptive Clocking status describes if this feature " @@ -77,6 +82,17 @@ static const char *__performance_levels_table_help = "level is shown in regular text. All other performance levels are shown in " "gray."; +static const char *__powermizer_menu_help = +"The Preferred Mode menu allows you to choose the preferred Performance " +"State for the GPU, provided the GPU has multiple Performance Levels. " +"'Adaptive' mode allows the GPU clocks to be adjusted based on GPU " +"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."; + GType ctk_powermizer_get_type(void) { static GType ctk_powermizer_type = 0; @@ -353,12 +369,13 @@ static gboolean update_powermizer_info(gpointer user_data) } GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, - CtkConfig *ctk_config) + CtkConfig *ctk_config, + CtkEvent *ctk_event) { GObject *object; CtkPowermizer *ctk_powermizer; - GtkWidget *hbox, *hbox2, *vbox, *hsep, *table; - GtkWidget *banner, *label; + GtkWidget *hbox, *hbox2, *vbox, *vbox2, *hsep, *table; + GtkWidget *banner, *label, *menu, *menu_item; GtkWidget *eventbox; ReturnStatus ret; gchar *s; @@ -583,14 +600,165 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, (gpointer) ctk_powermizer); g_free(s); + /* PowerMizer Settings */ + + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + + vbox2 = gtk_vbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0); + ctk_powermizer->box_powermizer_menu = vbox2; + + /* H-separator */ + + hbox2 = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, 0); + + label = gtk_label_new("PowerMizer Settings"); + gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); + + hsep = gtk_hseparator_new(); + gtk_box_pack_start(GTK_BOX(hbox2), hsep, TRUE, TRUE, 5); + + /* Specifying drop down list */ + + menu = gtk_menu_new(); + + menu_item = gtk_menu_item_new_with_label("Adaptive"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); + gtk_widget_show(menu_item); + + menu_item = gtk_menu_item_new_with_label("Prefer Maximum Performance"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); + gtk_widget_show(menu_item); + + ctk_powermizer->powermizer_menu = gtk_option_menu_new(); + gtk_option_menu_set_menu(GTK_OPTION_MENU(ctk_powermizer->powermizer_menu), + menu); + + g_signal_connect(G_OBJECT(ctk_powermizer->powermizer_menu), "changed", + G_CALLBACK(powermizer_menu_changed), + (gpointer) ctk_powermizer); + + ctk_config_set_tooltip(ctk_config, + ctk_powermizer->powermizer_menu, + __powermizer_menu_help); + + /* Packing the drop down list */ + + table = gtk_table_new(1, 2, FALSE); + gtk_box_pack_start(GTK_BOX(vbox2), table, FALSE, FALSE, 0); + gtk_table_set_row_spacings(GTK_TABLE(table), 3); + gtk_table_set_col_spacings(GTK_TABLE(table), 15); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + + hbox2 = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox2, 0, 1, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Preferred Mode:"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); + + hbox2 = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox2, 1, 2, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + gtk_box_pack_start(GTK_BOX(hbox2), + ctk_powermizer->powermizer_menu, + FALSE, FALSE, 0); + + /* Updating the powermizer page */ + update_powermizer_info(ctk_powermizer); gtk_widget_show_all(GTK_WIDGET(ctk_powermizer)); + update_powermizer_menu_info(ctk_powermizer); + g_signal_connect(G_OBJECT(ctk_event), + CTK_EVENT_NAME(NV_CTRL_GPU_POWER_MIZER_MODE), + G_CALLBACK(update_powermizer_menu_event), + (gpointer) ctk_powermizer); + return GTK_WIDGET(ctk_powermizer); } +static void update_powermizer_menu_event(GtkObject *object, + gpointer arg1, + gpointer user_data) +{ + update_powermizer_menu_info(user_data); +} + +static void update_powermizer_menu_info(gpointer user_data) +{ + CtkPowermizer *ctk_powermizer = CTK_POWERMIZER(user_data); + gint powerMizerMode = NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE; + NVCTRLAttributeValidValuesRec valid; + ReturnStatus ret0, ret1; + + ret0 = NvCtrlGetValidAttributeValues(ctk_powermizer->attribute_handle, + NV_CTRL_GPU_POWER_MIZER_MODE, + &valid); + + ret1 = NvCtrlGetAttribute(ctk_powermizer->attribute_handle, + NV_CTRL_GPU_POWER_MIZER_MODE, + &powerMizerMode); + + if ((ret0 != NvCtrlSuccess) || (ret1 != NvCtrlSuccess)) { + gtk_widget_hide(ctk_powermizer->box_powermizer_menu); + } else { + g_signal_handlers_block_by_func(G_OBJECT(ctk_powermizer->powermizer_menu), + G_CALLBACK(powermizer_menu_changed), + (gpointer) ctk_powermizer); + + gtk_option_menu_set_history(GTK_OPTION_MENU(ctk_powermizer->powermizer_menu), + powerMizerMode); + + g_signal_handlers_unblock_by_func(G_OBJECT(ctk_powermizer->powermizer_menu), + G_CALLBACK(powermizer_menu_changed), + (gpointer) ctk_powermizer); + + gtk_widget_show(ctk_powermizer->box_powermizer_menu); + } +} + +static void powermizer_menu_changed(GtkOptionMenu *powermizer_menu, + gpointer user_data) +{ + CtkPowermizer *ctk_powermizer; + gint history, powerMizerMode = NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE; + + ctk_powermizer = CTK_POWERMIZER(user_data); + + history = gtk_option_menu_get_history(powermizer_menu); + + switch (history) { + case 1: + powerMizerMode = NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_MAXIMUM_PERFORMANCE; + break; + case 0: + default: + powerMizerMode = NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE; + } + + if (NvCtrlSuccess != NvCtrlSetAttribute(ctk_powermizer->attribute_handle, + NV_CTRL_GPU_POWER_MIZER_MODE, + powerMizerMode)) { + return; + } + + g_signal_handlers_block_by_func(G_OBJECT(ctk_powermizer->powermizer_menu), + G_CALLBACK(powermizer_menu_changed), + (gpointer) ctk_powermizer); + + gtk_option_menu_set_history(GTK_OPTION_MENU(ctk_powermizer->powermizer_menu), + powerMizerMode); + + g_signal_handlers_unblock_by_func(G_OBJECT(ctk_powermizer->powermizer_menu), + G_CALLBACK(powermizer_menu_changed), + (gpointer) ctk_powermizer); +} + GtkTextBuffer *ctk_powermizer_create_help(GtkTextTagTable *table, - CtkPowermizer *ctk_powermizer) + CtkPowermizer *ctk_powermizer) { GtkTextIter i; GtkTextBuffer *b; @@ -619,6 +787,9 @@ GtkTextBuffer *ctk_powermizer_create_help(GtkTextTagTable *table, ctk_help_heading(b, &i, "Performance Levels (Table)"); ctk_help_para(b, &i, __performance_levels_table_help); + + ctk_help_heading(b, &i, "PowerMizer Settings"); + ctk_help_para(b, &i, __powermizer_menu_help); ctk_help_finish(b); return b; diff --git a/src/gtk+-2.x/ctkpowermizer.h b/src/gtk+-2.x/ctkpowermizer.h index fd25df1..316d94a 100644 --- a/src/gtk+-2.x/ctkpowermizer.h +++ b/src/gtk+-2.x/ctkpowermizer.h @@ -27,6 +27,7 @@ #include "NvCtrlAttributes.h" #include "ctkconfig.h" +#include "ctkevent.h" G_BEGIN_DECLS @@ -65,6 +66,8 @@ struct _CtkPowermizer GtkWidget *performance_level; GtkWidget *performance_mode; GtkWidget *performance_table_hbox; + GtkWidget *powermizer_menu; + GtkWidget *box_powermizer_menu; }; struct _CtkPowermizerClass @@ -73,7 +76,8 @@ struct _CtkPowermizerClass }; GType ctk_powermizer_get_type (void) G_GNUC_CONST; -GtkWidget* ctk_powermizer_new (NvCtrlAttributeHandle *, CtkConfig *); +GtkWidget* ctk_powermizer_new (NvCtrlAttributeHandle *, + CtkConfig *, CtkEvent *); GtkTextBuffer* ctk_powermizer_create_help (GtkTextTagTable *, CtkPowermizer *); void ctk_powermizer_start_timer (GtkWidget *); diff --git a/src/gtk+-2.x/ctkscreen.c b/src/gtk+-2.x/ctkscreen.c index b807f79..8e84807 100644 --- a/src/gtk+-2.x/ctkscreen.c +++ b/src/gtk+-2.x/ctkscreen.c @@ -24,6 +24,7 @@ #include <gtk/gtk.h> #include "NvCtrlAttributes.h" +#include "NVCtrlLib.h" #include <stdio.h> #include <stdlib.h> @@ -237,23 +238,28 @@ GtkWidget* ctk_screen_new(NvCtrlAttributeHandle *handle, depth = g_strdup_printf("%d", NvCtrlGetScreenPlanes(handle)); - /* get the list of GPUs driving this X screen */ + /* get the list of GPUs driving this (logical) X screen */ gpus = NULL; ret = NvCtrlGetBinaryAttribute(handle, 0, - NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN, + NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN, (unsigned char **)(&pData), &len); if (ret == NvCtrlSuccess) { for (i = 1; i <= pData[0]; i++) { gchar *tmp_str; gchar *gpu_name; - - ret = NvCtrlGetStringAttribute(handle, - NV_CTRL_STRING_PRODUCT_NAME, - &gpu_name); - if (ret != NvCtrlSuccess) { + Bool valid; + + valid = + XNVCTRLQueryTargetStringAttribute(NvCtrlGetDisplayPtr(handle), + NV_CTRL_TARGET_TYPE_GPU, + pData[i], + 0, + NV_CTRL_STRING_PRODUCT_NAME, + &gpu_name); + if (!valid) { gpu_name = "Unknown"; } if (gpus) { @@ -262,7 +268,7 @@ GtkWidget* ctk_screen_new(NvCtrlAttributeHandle *handle, } else { tmp_str = g_strdup_printf("%s (GPU %d)", gpu_name, pData[i]); } - if (ret == NvCtrlSuccess) { + if (valid) { XFree(gpu_name); } g_free(gpus); diff --git a/src/gtk+-2.x/ctkwindow.c b/src/gtk+-2.x/ctkwindow.c index 29addf0..26620f8 100644 --- a/src/gtk+-2.x/ctkwindow.c +++ b/src/gtk+-2.x/ctkwindow.c @@ -822,7 +822,7 @@ GtkWidget *ctk_window_new(ParsedAttribute *p, ConfigProperties *conf, } /* Powermizer information */ - child = ctk_powermizer_new(gpu_handle, ctk_config); + child = ctk_powermizer_new(gpu_handle, ctk_config, ctk_event); if (child) { help = ctk_powermizer_create_help(tag_table, CTK_POWERMIZER(child)); add_page(child, help, ctk_window, &iter, NULL, "PowerMizer", diff --git a/src/libXNVCtrl/NVCtrl.c b/src/libXNVCtrl/NVCtrl.c index abdedb2..f2cabf6 100644 --- a/src/libXNVCtrl/NVCtrl.c +++ b/src/libXNVCtrl/NVCtrl.c @@ -705,7 +705,7 @@ Bool XNVCTRLQueryTargetBinaryData ( length = rep.length; numbytes = rep.n; slop = numbytes & 3; - *ptr = (char *) Xmalloc(numbytes); + *ptr = (unsigned char *) Xmalloc(numbytes); if (! *ptr) { _XEatData(dpy, length); UnlockDisplay (dpy); diff --git a/src/libXNVCtrl/NVCtrl.h b/src/libXNVCtrl/NVCtrl.h index 32798e6..a6a97a8 100644 --- a/src/libXNVCtrl/NVCtrl.h +++ b/src/libXNVCtrl/NVCtrl.h @@ -42,6 +42,7 @@ #define NV_CTRL_TARGET_TYPE_GPU 1 #define NV_CTRL_TARGET_TYPE_FRAMELOCK 2 #define NV_CTRL_TARGET_TYPE_VCSC 3 /* Visual Computing System */ +#define NV_CTRL_TARGET_TYPE_GVI 4 /**************************************************************************/ @@ -85,7 +86,10 @@ * broadcast by the NVIDIA X Driver to all X Screens. * * V: The attribute may be queried using an NV_CTRL_TARGET_TYPE_VCSC - * target type via XNVCTRLQueryTargetXXXAttribute(). + * target type via XNVCTRLQueryTargetAttribute(). + * + * I: The attribute may be queried using an NV_CTRL_TARGET_TYPE_GVI target type + * via XNVCTRLQueryTargetAttribute(). * * NOTE: Unless mentioned otherwise, all attributes may be queried using * an NV_CTRL_TARGET_TYPE_X_SCREEN target type via @@ -161,11 +165,13 @@ /* - * NV_CTRL_BUS_TYPE - returns the Bus type through which the GPU - * driving the specified X screen is connected to the computer. + * NV_CTRL_BUS_TYPE - returns the bus type through which the specified device + * is connected to the computer. + * When this attribute is queried on an X screen target, the bus type of the + * GPU driving the X screen is returned. */ -#define NV_CTRL_BUS_TYPE 5 /* R--G */ +#define NV_CTRL_BUS_TYPE 5 /* R--GI */ #define NV_CTRL_BUS_TYPE_AGP 0 #define NV_CTRL_BUS_TYPE_PCI 1 #define NV_CTRL_BUS_TYPE_PCI_EXPRESS 2 @@ -186,11 +192,13 @@ /* - * NV_CTRL_IRQ - returns the interrupt request line used by the GPU - * driving the specified X screen. + * NV_CTRL_IRQ - returns the interrupt request line used by the specified + * device. + * When this attribute is queried on an X screen target, the IRQ of the GPU + * driving the X screen is returned. */ -#define NV_CTRL_IRQ 7 /* R--G */ +#define NV_CTRL_IRQ 7 /* R--GI */ /* @@ -878,10 +886,10 @@ * retest with NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED). * * - if syncing to input sync, query the - * NV_CTRL_GVO_INPUT_VIDEO_FORMAT attribute; note that Input video + * NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT attribute; note that Input video * format can only be queried after SYNC_SOURCE is specified. * - * - specify the NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT + * - specify the NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT * * - specify the NV_CTRL_GVO_DATA_FORMAT * @@ -962,8 +970,10 @@ /* - * NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT - specifies the output video - * format. Note that the valid video formats will vary depending on + * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT - specifies the desired output video + * format for GVO devices or the desired input video format for GVI devices. + * + * Note that for GVO, the valid video formats may vary depending on * the NV_CTRL_GVO_SYNC_MODE and the incoming sync video format. See * the definition of NV_CTRL_GVO_SYNC_MODE. * @@ -971,16 +981,61 @@ * values are reported as bits within a bitmask * (ATTRIBUTE_TYPE_INT_BITS); unfortunately, there are more valid * value bits than will fit in a single 32-bit value. To solve this, - * query the ValidValues for NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT to check + * query the ValidValues for NV_CTRL_GVIO_OUTPUT_VIDEO_FORMAT to check * which of the first 31 VIDEO_FORMATS are valid, then query the - * ValidValues for NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT2 to check which of + * ValidValues for NV_CTRL_GVIO_OUTPUT_VIDEO_FORMAT2 to check which of * the VIDEO_FORMATS with value 32 and higher are valid. */ +#define NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT 70 /* RW--I */ + +#define NV_CTRL_GVIO_VIDEO_FORMAT_NONE 0 +#define NV_CTRL_GVIO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC 1 +#define NV_CTRL_GVIO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL 2 +#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_59_94_SMPTE296 3 +#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_60_00_SMPTE296 4 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1035I_59_94_SMPTE260 5 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1035I_60_00_SMPTE260 6 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_SMPTE295 7 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_SMPTE274 8 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_59_94_SMPTE274 9 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_60_00_SMPTE274 10 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_23_976_SMPTE274 11 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_24_00_SMPTE274 12 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_25_00_SMPTE274 13 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_29_97_SMPTE274 14 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_30_00_SMPTE274 15 +#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_50_00_SMPTE296 16 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_48_00_SMPTE274 17 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_47_96_SMPTE274 18 +#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_30_00_SMPTE296 19 +#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_29_97_SMPTE296 20 +#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_25_00_SMPTE296 21 +#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_24_00_SMPTE296 22 +#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_23_98_SMPTE296 23 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_25_00_SMPTE274 24 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_29_97_SMPTE274 25 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274 26 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_24_00_SMPTE274 27 +#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_23_98_SMPTE274 28 +#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_30_00_SMPTE372 29 +#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_29_97_SMPTE372 30 +#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_60_00_SMPTE372 31 +#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_59_94_SMPTE372 32 +#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_25_00_SMPTE372 33 +#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_50_00_SMPTE372 34 +#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_24_00_SMPTE372 35 +#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_23_98_SMPTE372 36 +#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_48_00_SMPTE372 37 +#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_47_96_SMPTE372 38 + +/* + * The following are deprecated; NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT and the + * corresponding NV_CTRL_GVIO_* formats should be used instead. + */ #define NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT 70 /* RW- */ #define NV_CTRL_GVO_VIDEO_FORMAT_NONE 0 -#define NV_CTRL_GVO_VIDEO_FORMAT_480I_59_94_SMPTE259_NTSC 1 //deprecated #define NV_CTRL_GVO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC 1 #define NV_CTRL_GVO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL 2 #define NV_CTRL_GVO_VIDEO_FORMAT_720P_59_94_SMPTE296 3 @@ -997,9 +1052,7 @@ #define NV_CTRL_GVO_VIDEO_FORMAT_1080P_29_97_SMPTE274 14 #define NV_CTRL_GVO_VIDEO_FORMAT_1080P_30_00_SMPTE274 15 #define NV_CTRL_GVO_VIDEO_FORMAT_720P_50_00_SMPTE296 16 -#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_24_00_SMPTE274 17 //deprecated #define NV_CTRL_GVO_VIDEO_FORMAT_1080I_48_00_SMPTE274 17 -#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_23_98_SMPTE274 18 //deprecated #define NV_CTRL_GVO_VIDEO_FORMAT_1080I_47_96_SMPTE274 18 #define NV_CTRL_GVO_VIDEO_FORMAT_720P_30_00_SMPTE296 19 #define NV_CTRL_GVO_VIDEO_FORMAT_720P_29_97_SMPTE296 20 @@ -1023,13 +1076,20 @@ #define NV_CTRL_GVO_VIDEO_FORMAT_2048I_47_96_SMPTE372 38 /* - * NV_CTRL_GVO_INPUT_VIDEO_FORMAT - indicates the input video format - * detected; the possible values are the NV_CTRL_GVO_VIDEO_FORMAT - * constants. + * NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT - indicates the input video format + * detected for GVO or GVI devices; the possible values are the + * NV_CTRL_GVIO_VIDEO_FORMAT constants. + * For GVI devices, the port number should be specified in the "display_mask" + * parameter. */ -#define NV_CTRL_GVO_INPUT_VIDEO_FORMAT 71 /* R-- */ +#define NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT 71 /* R--I */ +/* + * The following is deprecated. Use NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT, + * instead. + */ +#define NV_CTRL_GVO_INPUT_VIDEO_FORMAT 71 /* R-- */ /* * NV_CTRL_GVO_DATA_FORMAT - This controls how the data in the source @@ -1153,7 +1213,7 @@ /* * NV_CTRL_GVO_FPGA_VERSION - indicates the version of the Firmware on * the GVO device. Deprecated; use - * NV_CTRL_STRING_GVO_FIRMWARE_VERSION instead. + * NV_CTRL_STRING_GVIO_FIRMWARE_VERSION instead. */ #define NV_CTRL_GVO_FIRMWARE_VERSION 78 /* R-- */ @@ -1208,7 +1268,7 @@ * not happen immediately and will instead be cached. The GVO resource will * need to be disabled/released and re-enabled/claimed for the values to be * flushed. These attributes are: - * NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT + * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT * NV_CTRL_GVO_DATA_FORMAT * NV_CTRL_GVO_FLIP_QUEUE_SIZE * @@ -1221,21 +1281,26 @@ /* - * NV_CTRL_GVO_VIDEO_FORMAT_{WIDTH,HEIGHT,REFRESH_RATE} - query the + * NV_CTRL_GVIO_VIDEO_FORMAT_{WIDTH,HEIGHT,REFRESH_RATE} - query the * width, height, and refresh rate for the specified - * NV_CTRL_GVO_VIDEO_FORMAT_*. So that this can be queried with + * NV_CTRL_GVIO_VIDEO_FORMAT_*. So that this can be queried with * existing interfaces, XNVCTRLQueryAttribute() should be used, and * the video format specified in the display_mask field; eg: * * XNVCTRLQueryAttribute (dpy, * screen, - * NV_CTRL_GVO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC, - * NV_CTRL_GVO_VIDEO_FORMAT_WIDTH, + * NV_CTRL_GVIO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC, + * NV_CTRL_GVIO_VIDEO_FORMAT_WIDTH, * &value); * - * Note that Refresh Rate is in 1/1000 Hertz values + * Note that Refresh Rate is in milliHertz values */ +#define NV_CTRL_GVIO_VIDEO_FORMAT_WIDTH 83 /* R--I */ +#define NV_CTRL_GVIO_VIDEO_FORMAT_HEIGHT 84 /* R--I */ +#define NV_CTRL_GVIO_VIDEO_FORMAT_REFRESH_RATE 85 /* R--I */ + +/* The following are deprecated; use the NV_CTRL_GVIO_* versions, instead */ #define NV_CTRL_GVO_VIDEO_FORMAT_WIDTH 83 /* R-- */ #define NV_CTRL_GVO_VIDEO_FORMAT_HEIGHT 84 /* R-- */ #define NV_CTRL_GVO_VIDEO_FORMAT_REFRESH_RATE 85 /* R-- */ @@ -1476,13 +1541,14 @@ #define NV_CTRL_XINERAMA_STEREO_TRUE 1 /* - * NV_CTRL_BUS_RATE - if the bus type of the GPU driving the specified - * screen is AGP, then NV_CTRL_BUS_RATE returns the configured AGP - * transfer rate. If the bus type is PCI Express, then this attribute - * returns the width of the physical link. + * NV_CTRL_BUS_RATE - if the bus type of the specified device is AGP, then + * NV_CTRL_BUS_RATE returns the configured AGP transfer rate. If the bus type + * is PCI Express, then this attribute returns the width of the physical link. + * When this attribute is queried on an X screen target, the bus rate of the + * GPU driving the X screen is returned. */ -#define NV_CTRL_BUS_RATE 224 /* R--G */ +#define NV_CTRL_BUS_RATE 224 /* R--GI */ /* * NV_CTRL_SHOW_SLI_HUD - when TRUE, OpenGL will draw information about the @@ -1502,14 +1568,21 @@ #define NV_CTRL_XV_SYNC_TO_DISPLAY 226 /* RW- */ /* - * NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT2 - this attribute is only intended + * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2 - this attribute is only intended * to be used to query the ValidValues for - * NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT above the first 31 VIDEO_FORMATS. - * See NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT for details. + * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT above the first 31 VIDEO_FORMATS. + * See NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT for details. */ +#define NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2 227 /* ---GI */ + +/* + * The following is deprecated; use NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2, + * instead + */ #define NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT2 227 /* --- */ + /* * NV_CTRL_GVO_OVERRIDE_HW_CSC - Override the SDI hardware's Color Space * Conversion with the values controlled through @@ -1591,10 +1664,9 @@ #define NV_CTRL_FRAMELOCK_SLAVES 232 /* RW-G */ /* - * NV_CTRL_FRAMELOCK_MASTERABLE - Can this Display Device be set - * as the master of the frame lock group. Returns MASTERABLE_TRUE if - * the GPU driving the display device is connected to the "primary" - * connector on the frame lock board. + * NV_CTRL_FRAMELOCK_MASTERABLE - Can any of the given display devices + * be set as master of the frame lock group. Returns a bitmask of the + * corresponding display devices that can be set as master. * * This attribute can only be queried through XNVCTRLQueryTargetAttribute() * using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be @@ -1602,9 +1674,6 @@ */ #define NV_CTRL_FRAMELOCK_MASTERABLE 233 /* R-DG */ -#define NV_CTRL_FRAMELOCK_MASTERABLE_FALSE 0 -#define NV_CTRL_FRAMELOCK_MASTERABLE_TRUE 1 - /* * NV_CTRL_PROBE_DISPLAYS - re-probes the hardware to detect what @@ -1676,24 +1745,26 @@ /* - * NV_CTRL_PCI_BUS - Returns the PCI bus number the GPU is using. + * NV_CTRL_PCI_BUS - Returns the PCI bus number the specified device is using. */ -#define NV_CTRL_PCI_BUS 239 /* R--G */ +#define NV_CTRL_PCI_BUS 239 /* R--GI */ /* - * NV_CTRL_PCI_DEVICE - Returns the PCI device number the GPU is using. + * NV_CTRL_PCI_DEVICE - Returns the PCI device number the specified device is + * using. */ -#define NV_CTRL_PCI_DEVICE 240 /* R--G */ +#define NV_CTRL_PCI_DEVICE 240 /* R--GI */ /* - * NV_CTRL_PCI_FUNCTION - Returns the PCI function number the GPU is using. + * NV_CTRL_PCI_FUNCTION - Returns the PCI function number the specified device + * is using. */ -#define NV_CTRL_PCI_FUNCTION 241 /* R--G */ +#define NV_CTRL_PCI_FUNCTION 241 /* R--GI */ /* @@ -1910,7 +1981,7 @@ * GVO resource will need to be disabled/released and re-enabled/claimed for * the values to be flushed. These attributes are: * - * NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT + * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT * NV_CTRL_GVO_DATA_FORMAT * NV_CTRL_GVO_FLIP_QUEUE_SIZE */ @@ -2296,14 +2367,15 @@ #define NV_CTRL_IS_GVO_DISPLAY_TRUE 1 /* - * NV_CTRL_PCI_ID - Returns the PCI vendor and device ID of the GPU. + * NV_CTRL_PCI_ID - Returns the PCI vendor and device ID of the specified + * device. * * NV_CTRL_PCI_ID is a "packed" integer attribute; the PCI vendor ID is stored * in the upper 16 bits of the integer, and the PCI device ID is stored in the * lower 16 bits of the integer. */ -#define NV_CTRL_PCI_ID 301 /* R--G */ +#define NV_CTRL_PCI_ID 301 /* R--GI */ /* * NV_CTRL_GVO_FULL_RANGE_COLOR - Allow full range color data [4-1019] @@ -2315,7 +2387,7 @@ #define NV_CTRL_GVO_FULL_RANGE_COLOR_ENABLED 1 /* - * NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE - returns whether or not + * NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE - Returns whether or not * SLI Mosaic Mode supported. */ @@ -2333,7 +2405,7 @@ #define NV_CTRL_GVO_ENABLE_RGB_DATA_DISABLE 0 #define NV_CTRL_GVO_ENABLE_RGB_DATA_ENABLE 1 -/* +/* * NV_CTRL_IMAGE_SHARPENING_DEFAULT - Returns default value of * Image Sharpening. */ @@ -2341,13 +2413,41 @@ #define NV_CTRL_IMAGE_SHARPENING_DEFAULT 305 /* R-- */ /* + * NV_CTRL_PCI_DOMAIN - Returns the PCI domain number the specified device is + * using. + */ + +#define NV_CTRL_PCI_DOMAIN 306 /* R--GI */ + +/* + * NV_CTRL_GVI_NUM_PORTS - Returns the number of input ports available on a GVI + * device. + */ + +#define NV_CTRL_GVI_NUM_PORTS 307 /* R--I */ + +/* * NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION - Returns the number of nanoseconds * that one unit of NV_CTRL_FRAMELOCK_SYNC_DELAY corresponds to. */ #define NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION 318 /* R-- */ -#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION +/* + * NV_CTRL_GPU_POWER_MIZER_MODE - Provides a hint to the driver + * as to how to manage the performance of the GPU. + * + * ADAPTIVE - adjust GPU clocks based on GPU + * utilization + * PREFER_MAXIMUM_PERFORMANCE - raise GPU clocks to favor + * maximum performance, to the extent + * that thermal and other constraints + * allow + */ +#define NV_CTRL_GPU_POWER_MIZER_MODE 334 /* RW-G */ +#define NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE 0 +#define NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_MAXIMUM_PERFORMANCE 1 +#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_GPU_POWER_MIZER_MODE /**************************************************************************/ @@ -2416,10 +2516,16 @@ /* - * NV_CTRL_STRING_GVO_FIRMWARE_VERSION - indicates the version of the - * Firmware on the GVO device. + * NV_CTRL_STRING_GVIO_FIRMWARE_VERSION - indicates the version of the + * Firmware on the GVIO device. */ +#define NV_CTRL_STRING_GVIO_FIRMWARE_VERSION 8 /* R--I */ + +/* + * The following is deprecated; use NV_CTRL_STRING_GVIO_FIRMWARE_VERSION, + * instead + */ #define NV_CTRL_STRING_GVO_FIRMWARE_VERSION 8 /* R-- */ @@ -2824,22 +2930,28 @@ /* - * NV_CTRL_STRING_GVO_VIDEO_FORMAT_NAME - query the name for the specified - * NV_CTRL_GVO_VIDEO_FORMAT_*. So that this can be queried with existing + * NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME - query the name for the specified + * NV_CTRL_GVIO_VIDEO_FORMAT_*. So that this can be queried with existing * interfaces, XNVCTRLQueryStringAttribute() should be used, and the video * format specified in the display_mask field; eg: * * XNVCTRLQueryStringAttribute(dpy, * screen, - * NV_CTRL_GVO_VIDEO_FORMAT_720P_60_00_SMPTE296, - * NV_CTRL_GVO_VIDEO_FORMAT_NAME, + * NV_CTRL_GVIO_VIDEO_FORMAT_720P_60_00_SMPTE296, + * NV_CTRL_GVIO_VIDEO_FORMAT_NAME, * &name); */ +#define NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME 33 /* R--GI */ + +/* + * The following is deprecated; use NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME, + * instead + */ #define NV_CTRL_STRING_GVO_VIDEO_FORMAT_NAME 33 /* R--- */ #define NV_CTRL_STRING_LAST_ATTRIBUTE \ - NV_CTRL_STRING_GVO_VIDEO_FORMAT_NAME + NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME /**************************************************************************/ @@ -3075,8 +3187,21 @@ #define NV_CTRL_BINARY_DATA_VCSCS_USED_BY_GPU 9 /* R-DG */ +/* + * NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN - Returns the list of + * GPUs currently driving the given X screen. If Xinerama is enabled, this + * will return all GPUs that are driving any X screen. + * + * The format of the returned data is: + * + * 4 CARD32 number of GPUs + * 4 * n CARD32 GPU indices + */ + +#define NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN 11 /* R--- */ + #define NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE \ - NV_CTRL_BINARY_DATA_VCSCS_USED_BY_GPU + NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN /**************************************************************************/ @@ -3249,6 +3374,10 @@ * ATTRIBUTE_TYPE_X_SCREEN - Attribute is valid for X Screen target types. * ATTRIBUTE_TYPE_XINERAMA - Attribute will be made consistent for all * X Screens when the Xinerama extension is enabled. + * ATTRIBUTE_TYPE_VCSC - Attribute is valid for Visual Computing System + * target types. + * ATTRIBUTE_TYPE_GVI - Attribute is valid for Graphics Video In target + * types. * * * See 'Key to Integer Attribute "Permissions"' at the top of this @@ -3262,14 +3391,15 @@ #define ATTRIBUTE_TYPE_RANGE 4 #define ATTRIBUTE_TYPE_INT_BITS 5 -#define ATTRIBUTE_TYPE_READ 0x01 -#define ATTRIBUTE_TYPE_WRITE 0x02 -#define ATTRIBUTE_TYPE_DISPLAY 0x04 -#define ATTRIBUTE_TYPE_GPU 0x08 -#define ATTRIBUTE_TYPE_FRAMELOCK 0x10 -#define ATTRIBUTE_TYPE_X_SCREEN 0x20 -#define ATTRIBUTE_TYPE_XINERAMA 0x40 -#define ATTRIBUTE_TYPE_VCSC 0x80 +#define ATTRIBUTE_TYPE_READ 0x001 +#define ATTRIBUTE_TYPE_WRITE 0x002 +#define ATTRIBUTE_TYPE_DISPLAY 0x004 +#define ATTRIBUTE_TYPE_GPU 0x008 +#define ATTRIBUTE_TYPE_FRAMELOCK 0x010 +#define ATTRIBUTE_TYPE_X_SCREEN 0x020 +#define ATTRIBUTE_TYPE_XINERAMA 0x040 +#define ATTRIBUTE_TYPE_VCSC 0x080 +#define ATTRIBUTE_TYPE_GVI 0x100 typedef struct _NVCTRLAttributeValidValues { int type; diff --git a/src/parse.c b/src/parse.c index 612a467..2ea372a 100644 --- a/src/parse.c +++ b/src/parse.c @@ -133,9 +133,9 @@ AttributeTableEntry attributeTable[] = { { "SliMosaicModeAvailable", NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE, N, "Returns whether or not SLI Mosaic Mode is supported." }, /* GPU */ - { "BusType", NV_CTRL_BUS_TYPE, 0, "Returns the type of bus connecting the GPU driving the specified X screen to the computer." }, + { "BusType", NV_CTRL_BUS_TYPE, 0, "Returns the type of bus connecting the specified device to the computer. If the target is an X screen, then it uses the GPU driving the X screen as the device." }, { "VideoRam", NV_CTRL_VIDEO_RAM, 0, "Returns the total amount of memory available to the specified GPU (or the GPU driving the specified X screen). Note: if the GPU supports TurboCache(TM), the value reported may exceed the amount of video memory installed on the GPU. The value reported for integrated GPUs may likewise exceed the amount of dedicated system memory set aside by the system BIOS for use by the integrated GPU." }, - { "Irq", NV_CTRL_IRQ, 0, "Returns the interrupt request line used by the GPU driving the specified X screen." }, + { "Irq", NV_CTRL_IRQ, 0, "Returns the interrupt request line used by the specified device. If the target is an X screen, then it uses the GPU driving the X screen as the device." }, { "GPUCoreTemp", NV_CTRL_GPU_CORE_TEMPERATURE, N, "Reports the current core temperature in Celsius of the GPU driving the X screen." }, { "GPUAmbientTemp", NV_CTRL_AMBIENT_TEMPERATURE, N, "Reports the current temperature in Celsius of the immediate neighborhood of the GPU driving the X screen." }, { "GPUOverclockingState", NV_CTRL_GPU_OVERCLOCKING_STATE, N, "The current overclocking state; the value of this attribute controls the availability of additional overclocking attributes. Note that this attribute is unavailable unless overclocking support has been enabled by the system administrator." }, @@ -144,17 +144,19 @@ AttributeTableEntry attributeTable[] = { { "GPUDefault2DClockFreqs", NV_CTRL_GPU_DEFAULT_2D_CLOCK_FREQS, N|P, "Returns the default memory and GPU core clocks when operating in 2D mode." }, { "GPUDefault3DClockFreqs", NV_CTRL_GPU_DEFAULT_3D_CLOCK_FREQS, N|P, "Returns the default memory and GPU core clocks when operating in 3D mode." }, { "GPUCurrentClockFreqs", NV_CTRL_GPU_CURRENT_CLOCK_FREQS, N|P, "Returns the current GPU and memory clocks of the graphics device driving the X screen." }, - { "BusRate", NV_CTRL_BUS_RATE, 0, "If the GPU is on an AGP bus, then BusRate returns the configured AGP rate. If the GPU is on a PCI Express bus, then this attribute returns the width of the physical link." }, - { "PCIBus", NV_CTRL_PCI_BUS, N, "Returns the PCI bus number the GPU is using." }, - { "PCIDevice", NV_CTRL_PCI_DEVICE, N, "Returns the PCI device number the GPU is using." }, - { "PCIFunc", NV_CTRL_PCI_FUNCTION, N, "Returns the PCI function number the GPU is using." }, - { "PCIID", NV_CTRL_PCI_ID, N|P, "Returns the PCI vendor and device ID of the GPU." }, + { "BusRate", NV_CTRL_BUS_RATE, 0, "If the device is on an AGP bus, then BusRate returns the configured AGP rate. If the device is on a PCI Express bus, then this attribute returns the width of the physical link." }, + { "PCIDomain", NV_CTRL_PCI_DOMAIN, N, "Returns the PCI domain number for the specified device." }, + { "PCIBus", NV_CTRL_PCI_BUS, N, "Returns the PCI bus number for the specified device." }, + { "PCIDevice", NV_CTRL_PCI_DEVICE, N, "Returns the PCI device number for the specified device." }, + { "PCIFunc", NV_CTRL_PCI_FUNCTION, N, "Returns the PCI function number for the specified device." }, + { "PCIID", NV_CTRL_PCI_ID, N|P, "Returns the PCI vendor and device ID of the specified device." }, { "GPUErrors", NV_CTRL_NUM_GPU_ERRORS_RECOVERED, N, "Returns the number of GPU errors occurred." }, { "GPUPowerSource", NV_CTRL_GPU_POWER_SOURCE, N, "Reports the type of power source of the GPU." }, { "GPUCurrentPerfMode", NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE, N, "Reports the current performance mode of the GPU driving the X screen. Running a 3D app, for example, will change this performance mode if Adaptive Clocking is enabled." }, { "GPUCurrentPerfLevel", NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL, N, "Reports the current Performance level of the GPU driving the X screen. Each Performance level has associated NVClock and Mem Clock values." }, { "GPUAdaptiveClockState", NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE, N, "Reports if Adaptive Clocking is Enabled on the GPU driving the X screen." }, { "GPUPerfModes", NV_CTRL_STRING_PERFORMANCE_MODES, S|N, "Returns a string with all the performance modes defined for this GPU along with their associated NV Clock and Memory Clock values." }, + { "GPUPowerMizerMode", NV_CTRL_GPU_POWER_MIZER_MODE, 0, "Allows setting different GPU powermizer modes." }, /* Framelock */ { "FrameLockAvailable", NV_CTRL_FRAMELOCK, N|F|G, "Returns whether the underlying GPU supports Frame Lock. All of the other frame lock attributes are only applicable if this attribute is enabled (Supported)." }, @@ -175,7 +177,7 @@ AttributeTableEntry attributeTable[] = { { "FrameLockTiming", NV_CTRL_FRAMELOCK_TIMING, N|F|G, "This is 1 when the GPU is both receiving and locked to an input timing signal. Timing information may come from the following places: Another frame lock device that is set to master, the house sync signal, or the GPU's internal timing from a display device." }, { "FramelockUseHouseSync", NV_CTRL_USE_HOUSE_SYNC, N|F|G, "When 1, the server (master) frame lock device will propagate the incoming house sync signal as the outgoing frame lock sync signal. If the frame lock device cannot detect a frame lock sync signal, it will default to using the internal timings from the GPU connected to the primary connector." }, { "FrameLockSlaves", NV_CTRL_FRAMELOCK_SLAVES, N|F|G|D, "Get/set whether the display device(s) given should listen or ignore the master's sync signal." }, - { "FrameLockMasterable", NV_CTRL_FRAMELOCK_MASTERABLE, N|F|G, "Returns whether the display device(s) can be set as the master of the frame lock group. Returns 1 if the GPU driving the display device is connected to the \"primary\" connector on the frame lock board." }, + { "FrameLockMasterable", NV_CTRL_FRAMELOCK_MASTERABLE, N|F|G|D, "Returns whether the display device(s) can be set as the master of the frame lock group. Returns a bitmask indicating which of the given display devices can be set as a frame lock master." }, { "FrameLockSlaveable", NV_CTRL_FRAMELOCK_SLAVEABLE, N|F|G|D, "Returns whether the display device(s) can be set as slave(s) of the frame lock group." }, { "FrameLockFPGARevision", NV_CTRL_FRAMELOCK_FPGA_REVISION, N|F|G, "Returns the FPGA revision of the Frame Lock device." }, { "FrameLockSyncRate4", NV_CTRL_FRAMELOCK_SYNC_RATE_4, N|F|G, "Returns the refresh rate that the frame lock board is sending to the GPU in 1/10000 Hz (i.e. to get the refresh rate in Hz, divide the returned value by 10000.)" }, @@ -185,8 +187,10 @@ AttributeTableEntry attributeTable[] = { { "GvoSupported", NV_CTRL_GVO_SUPPORTED, I|N, "Returns whether this X screen supports GVO; if this screen does not support GVO output, then all other GVO attributes are unavailable." }, { "GvoSyncMode", NV_CTRL_GVO_SYNC_MODE, I, "Selects the GVO sync mode; possible values are: FREE_RUNNING - GVO does not sync to any external signal. GENLOCK - the GVO output is genlocked to an incoming sync signal; genlocking locks at hsync. This requires that the output video format exactly match the incoming sync video format. FRAMELOCK - the GVO output is frame locked to an incoming sync signal; frame locking locks at vsync. This requires that the output video format have the same refresh rate as the incoming sync video format." }, { "GvoSyncSource", NV_CTRL_GVO_SYNC_SOURCE, I, "If the GVO sync mode is set to either GENLOCK or FRAMELOCK, this controls which sync source is used as the incoming sync signal (either Composite or SDI). If the GVO sync mode is FREE_RUNNING, this attribute has no effect." }, - { "GvoOutputVideoFormat", NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT, I, "Specifies the output video format coming out of the GVO device." }, - { "GvoInputVideoFormat", NV_CTRL_GVO_INPUT_VIDEO_FORMAT, I|N, "Returns the input video format detected by the GVO device." }, + { "GvioRequestedVideoFormat", NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT, I, "Specifies the requested output video format for a GVO device, or the requested capture format for a GVI device." }, + { "GvoOutputVideoFormat", NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT, I|A, "DEPRECATED: use \"GvioRequestedVideoFormat\" instead." }, + { "GvioDetectedVideoFormat", NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT, I|N, "Returns the input video format detected by the GVO or GVI device." }, + { "GvoInputVideoFormat", NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT, I|N|A, "DEPRECATED: use \"GvioDetectedVideoFormat\" instead." }, { "GvoDataFormat", NV_CTRL_GVO_DATA_FORMAT, I, "Configures how the data in the source (either the X screen or the GLX pbuffer) is interpreted and displayed by the GVO device." }, { "GvoDisplayXScreen", NV_CTRL_GVO_DISPLAY_X_SCREEN, I|N, "Enable/disable GVO output of the X screen (in Clone mode)." }, { "GvoCompositeSyncInputDetected", NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED, I|N, "Indicates whether Composite Sync input is detected." }, @@ -210,11 +214,13 @@ AttributeTableEntry attributeTable[] = { { "GvoComposite", NV_CTRL_GVO_COMPOSITE, I, "Enables/Disables SDI compositing. This attribute is only available when an SDI input source is detected and is in genlock mode." }, { "GvoCompositeAlphaKey", NV_CTRL_GVO_COMPOSITE_ALPHA_KEY, I, "When SDI compositing is enabled, this enables/disables alpha blending." }, { "GvoCompositeNumKeyRanges", NV_CTRL_GVO_COMPOSITE_NUM_KEY_RANGES, I|N, "Returns the number of ranges available for each channel (Y/Luma, Cr, and Cb) that are used SDI compositing through color keying." }, - { "GvoFirmwareVersion", NV_CTRL_STRING_GVO_FIRMWARE_VERSION, I|S|N, "Indicates the version of the firmware on the GVO device." }, + { "GvioFirmwareVersion", NV_CTRL_STRING_GVIO_FIRMWARE_VERSION, I|S|N, "Indicates the version of the firmware on the GVO or GVI device." }, + { "GvoFirmwareVersion", NV_CTRL_STRING_GVIO_FIRMWARE_VERSION, I|S|N|A,"DEPRECATED: use \"GvioFirmwareVersion\" instead." }, { "GvoSyncToDisplay", NV_CTRL_GVO_SYNC_TO_DISPLAY, I|N, "Controls synchronization of the non-SDI display to the SDI display when both are active." }, { "GvoFullRangeColor", NV_CTRL_GVO_FULL_RANGE_COLOR, I, "Allow full range color data [4-1019]. If disabled, color data is clamped to [64-940]." }, { "IsGvoDisplay", NV_CTRL_IS_GVO_DISPLAY, N|D, "Returns whether or not the given display device is driven by the GVO device." }, { "GvoEnableRGBData", NV_CTRL_GVO_ENABLE_RGB_DATA, I, "Indicates that RGB data is being sent via a PASSTHU mode." }, + { "GviNumPorts", NV_CTRL_GVI_NUM_PORTS, N|A, "Returns the number of ports on a GVI device." }, /* Display */ { "Brightness", BRIGHTNESS_VALUE|ALL_CHANNELS, N|C|G, "Controls the overall brightness of the display." }, @@ -290,7 +296,7 @@ AttributeTableEntry attributeTable[] = { * about. */ -#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION +#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_GPU_POWER_MIZER_MODE #warning "Have you forgotten to add a new integer attribute to attributeTable?" #endif @@ -335,6 +341,14 @@ TargetTypeEntry targetTypeTable[] = { NV_FALSE, /* uses_display_devices */ 1, 12 }, /* required major,minor protocol rev */ + { "SDI Input Device", /* name */ + "gvi", /* parsed_name */ + GVI_TARGET, /* target_index */ + NV_CTRL_TARGET_TYPE_GVI, /* nvctrl */ + ATTRIBUTE_TYPE_GVI, /* permission_bit */ + NV_FALSE, /* uses_display_devices */ + 1, 18 }, /* required major,minor protocol rev */ + { NULL, NULL, 0, 0, 0 }, }; diff --git a/src/parse.h b/src/parse.h index 8a5830c..be511ac 100644 --- a/src/parse.h +++ b/src/parse.h @@ -146,7 +146,8 @@ extern AttributeTableEntry attributeTable[]; #define GPU_TARGET 1 #define FRAMELOCK_TARGET 2 #define VCS_TARGET 3 -#define MAX_TARGET_TYPES 4 +#define GVI_TARGET 4 +#define MAX_TARGET_TYPES 5 diff --git a/src/query-assign.c b/src/query-assign.c index 87a8878..8fab5e7 100644 --- a/src/query-assign.c +++ b/src/query-assign.c @@ -408,6 +408,11 @@ static int process_attribute_queries(int num, char **queries, continue; } + if (nv_strcasecmp(queries[query], "gvis")) { + query_all_targets(display_name, GVI_TARGET); + continue; + } + /* call the parser to parse queries[query] */ @@ -731,8 +736,8 @@ static void print_valid_values(char *name, int attr, uint32 flags, } if (flags & NV_PARSER_TYPE_PACKED_ATTRIBUTE) { - nv_msg(INDENT, "Valid values for '%s' are: [%s], [%s].", name, str, - str2); + nv_msg(INDENT, "Valid values for '%s' are: [%s], [%s].", name, str2, + str); } else { nv_msg(INDENT, "Valid values for '%s' are: %s.", name, str); } @@ -1217,6 +1222,7 @@ static int print_target_connections(CtrlHandles *h, break; case FRAMELOCK_TARGET: + case GVI_TARGET: case X_SCREEN_TARGET: default: product_name = NULL; @@ -1333,6 +1339,12 @@ static int query_all_targets(const char *display_name, const int target_index) if (status != NvCtrlSuccess) product_name = strdup("Unknown"); + } 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 { /* for X_SCREEN_TARGET or GPU_TARGET, query the product name */ @@ -1928,7 +1940,8 @@ int nv_process_parsed_attribute(ParsedAttribute *a, CtrlHandles *h, * sure that GVO is supported by the handle. */ - if (a->flags & NV_PARSER_TYPE_SDI) { + if (a->flags & NV_PARSER_TYPE_SDI && + target != NV_CTRL_TARGET_TYPE_GVI) { int available; status = NvCtrlGetAttribute(t->h, NV_CTRL_GVO_SUPPORTED, |