ReturnStatus NvCtrlGetAttribute(NvCtrlAttributeHandle *handle, int attr, int *val) { if (!handle) return NvCtrlBadArgument; return NvCtrlGetDisplayAttribute(handle, 0, attr, val); } /* NvCtrlGetAttribute() */
/* * dfp_info_setup() - * * */ static void dfp_info_setup(CtkDisplayDeviceDfp *ctk_display_device_dfp) { ReturnStatus ret; gint val, signal_type, gpu_scaling, dfp_scaling; char *chip_location, *link, *signal; char *scaling; char tmp[32]; chip_location = link = signal = "Unknown"; scaling = "Unknown"; /* Chip location */ ret = NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle, ctk_display_device_dfp->display_device_mask, NV_CTRL_FLATPANEL_CHIP_LOCATION, &val); if (ret == NvCtrlSuccess) { switch (val) { case NV_CTRL_FLATPANEL_CHIP_LOCATION_INTERNAL: chip_location = "Internal"; break; case NV_CTRL_FLATPANEL_CHIP_LOCATION_EXTERNAL: chip_location = "External"; break; } } gtk_label_set_text (GTK_LABEL(ctk_display_device_dfp->txt_chip_location), chip_location); /* Signal */ ret = NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle, ctk_display_device_dfp->display_device_mask, NV_CTRL_FLATPANEL_SIGNAL, &val); if (ret == NvCtrlSuccess) { switch (val) { case NV_CTRL_FLATPANEL_SIGNAL_LVDS: signal = "LVDS"; break; case NV_CTRL_FLATPANEL_SIGNAL_TMDS: signal = "TMDS"; break; case NV_CTRL_FLATPANEL_SIGNAL_DISPLAYPORT: signal = "DisplayPort"; break; } } gtk_label_set_text (GTK_LABEL(ctk_display_device_dfp->txt_signal), signal); signal_type = val; /* Link */ ret = NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle, ctk_display_device_dfp->display_device_mask, NV_CTRL_FLATPANEL_LINK, &val); if (ret == NvCtrlSuccess) { if (signal_type == NV_CTRL_FLATPANEL_SIGNAL_DISPLAYPORT) { int lanes; lanes = val + 1; ret = NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle, ctk_display_device_dfp->display_device_mask, NV_CTRL_DISPLAYPORT_LINK_RATE, &val); if (ret == NvCtrlSuccess && val == NV_CTRL_DISPLAYPORT_LINK_RATE_DISABLED) { link = "Disabled"; } else { char *bw = "unknown bandwidth"; if (ret == NvCtrlSuccess) { switch (val) { case NV_CTRL_DISPLAYPORT_LINK_RATE_1_62GBPS: bw = "1.62 Gbps"; break; case NV_CTRL_DISPLAYPORT_LINK_RATE_2_70GBPS: bw = "2.70 Gbps"; break; } } snprintf(tmp, 32, "%d lane%s @ %s", lanes, lanes == 1 ? "" : "s", bw); link = tmp; } } else { // LVDS or TMDS switch(val) { case NV_CTRL_FLATPANEL_LINK_SINGLE: link = "Single"; break; case NV_CTRL_FLATPANEL_LINK_DUAL: link = "Dual"; break; } } } gtk_label_set_text (GTK_LABEL(ctk_display_device_dfp->txt_link), link); /* Native Resolution */ ret = NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle, ctk_display_device_dfp->display_device_mask, NV_CTRL_FLATPANEL_NATIVE_RESOLUTION, &val); if (ret == NvCtrlSuccess) { gchar *resolution = g_strdup_printf("%dx%d", (val >> 16), (val & 0xFFFF)); gtk_label_set_text (GTK_LABEL(ctk_display_device_dfp->txt_native_resolution), resolution); g_free(resolution); } else {
GtkWidget* ctk_display_device_dfp_new(NvCtrlAttributeHandle *handle, CtkConfig *ctk_config, CtkEvent *ctk_event, unsigned int display_device_mask, char *name) { GObject *object; CtkDisplayDeviceDfp *ctk_display_device_dfp; GtkWidget *banner; GtkWidget *frame; GtkWidget *hbox, *vbox, *tmpbox; GtkWidget *eventbox; GtkWidget *button; GtkWidget *radio0; GtkWidget *radio1; GtkWidget *radio2; GtkWidget *alignment; GtkWidget *table; ReturnStatus ret1, ret2; gint val_target, val_method; object = g_object_new(CTK_TYPE_DISPLAY_DEVICE_DFP, NULL); if (!object) return NULL; ctk_display_device_dfp = CTK_DISPLAY_DEVICE_DFP(object); ctk_display_device_dfp->handle = handle; ctk_display_device_dfp->ctk_event = ctk_event; ctk_display_device_dfp->ctk_config = ctk_config; ctk_display_device_dfp->display_device_mask = display_device_mask; ctk_display_device_dfp->name = g_strdup(name); /* cache the default scaling target & method values */ ret1 = NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle, ctk_display_device_dfp->display_device_mask, NV_CTRL_GPU_SCALING_DEFAULT_TARGET, &val_target); ret2 = NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle, ctk_display_device_dfp->display_device_mask, NV_CTRL_GPU_SCALING_DEFAULT_METHOD, &val_method); if (ret1 != NvCtrlSuccess || ret2 != NvCtrlSuccess || val_target == NV_CTRL_GPU_SCALING_TARGET_INVALID || val_method == NV_CTRL_GPU_SCALING_METHOD_INVALID) { val_target = NV_CTRL_GPU_SCALING_TARGET_FLATPANEL_BEST_FIT; val_method = NV_CTRL_GPU_SCALING_METHOD_STRETCHED; } ctk_display_device_dfp->default_scaling_target = val_target; ctk_display_device_dfp->default_scaling_method = val_method; gtk_box_set_spacing(GTK_BOX(object), 10); /* banner */ banner = ctk_banner_image_new(BANNER_ARTWORK_DFP); gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0); /* * create the reset button (which we need while creating the * controls in this page so that we can set the button's * sensitivity), though we pack it at the bottom of the page */ ctk_display_device_dfp->reset_button = gtk_button_new_with_label("Reset Hardware Defaults"); alignment = gtk_alignment_new(1, 1, 0, 0); gtk_container_add(GTK_CONTAINER(alignment), ctk_display_device_dfp->reset_button); gtk_box_pack_end(GTK_BOX(object), alignment, TRUE, TRUE, 0); g_signal_connect(G_OBJECT(ctk_display_device_dfp->reset_button), "clicked", G_CALLBACK(reset_button_clicked), (gpointer) ctk_display_device_dfp); ctk_config_set_tooltip(ctk_config, ctk_display_device_dfp->reset_button, "The Reset Hardware Defaults button restores " "the DFP settings to their default values."); /* create the hbox to store dfp info, scaling */ hbox = gtk_hbox_new(FALSE, FRAME_PADDING); gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, FRAME_PADDING); /* DFP info */ frame = gtk_frame_new("Flat Panel Information"); gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 0); /* * insert a vbox between the frame and the widgets, so that the * widgets don't expand to fill all of the space within the * frame */ tmpbox = gtk_vbox_new(FALSE, 5); gtk_container_add(GTK_CONTAINER(frame), tmpbox); /* Make the txt widgets that will get updated */ ctk_display_device_dfp->txt_chip_location = gtk_label_new(""); ctk_display_device_dfp->txt_link = gtk_label_new(""); ctk_display_device_dfp->txt_signal = gtk_label_new(""); ctk_display_device_dfp->txt_native_resolution = gtk_label_new(""); ctk_display_device_dfp->txt_best_fit_resolution = gtk_label_new(""); ctk_display_device_dfp->txt_frontend_resolution = gtk_label_new(""); ctk_display_device_dfp->txt_backend_resolution = gtk_label_new(""); ctk_display_device_dfp->txt_refresh_rate = gtk_label_new(""); /* Add information widget lines */ { typedef struct { GtkWidget *label; GtkWidget *txt; const gchar *tooltip; } TextLineInfo; TextLineInfo lines[] = { { gtk_label_new("Chip location:"), ctk_display_device_dfp->txt_chip_location, NULL }, { gtk_label_new("Connection link:"), ctk_display_device_dfp->txt_link, NULL }, { gtk_label_new("Signal:"), ctk_display_device_dfp->txt_signal, NULL }, { gtk_label_new("Native Resolution:"), ctk_display_device_dfp->txt_native_resolution, __native_res_help, }, { gtk_label_new("Best Fit Resolution:"), ctk_display_device_dfp->txt_best_fit_resolution, __best_fit_res_help, }, { gtk_label_new("Frontend Resolution:"), ctk_display_device_dfp->txt_frontend_resolution, __frontend_res_help, }, { gtk_label_new("Backend Resolution:"), ctk_display_device_dfp->txt_backend_resolution, __backend_res_help, }, { gtk_label_new("Refresh Rate:"), ctk_display_device_dfp->txt_refresh_rate, __refresh_rate_help, }, { NULL, NULL, NULL } }; int i; GtkRequisition req; int max_width; /* Compute max width of lables and setup text alignments */ max_width = 0; for (i = 0; lines[i].label; i++) { gtk_misc_set_alignment(GTK_MISC(lines[i].label), 0.0f, 0.5f); gtk_misc_set_alignment(GTK_MISC(lines[i].txt), 0.0f, 0.5f); gtk_widget_size_request(lines[i].label, &req); if (max_width < req.width) { max_width = req.width; } } /* Pack labels */ for (i = 0; lines[i].label; i++) { GtkWidget *tmphbox; /* Add separators */ if (i == 3 || i == 5 || i == 7) { GtkWidget *separator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(tmpbox), separator, FALSE, FALSE, 0); } /* Set the label's width */ gtk_widget_set_size_request(lines[i].label, max_width, -1); /* add the widgets for this line */ tmphbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(tmphbox), lines[i].label, FALSE, TRUE, 5); gtk_box_pack_start(GTK_BOX(tmphbox), lines[i].txt, FALSE, TRUE, 5); /* Include tooltips */ if (!lines[i].tooltip) { gtk_box_pack_start(GTK_BOX(tmpbox), tmphbox, FALSE, FALSE, 0); } else { eventbox = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(eventbox), tmphbox); ctk_config_set_tooltip(ctk_config, eventbox, lines[i].tooltip); gtk_box_pack_start(GTK_BOX(tmpbox), eventbox, FALSE, FALSE, 0); } } } /* Flat Panel Scaling */ frame = gtk_frame_new("Flat Panel Scaling"); eventbox = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(eventbox), frame); gtk_box_pack_start(GTK_BOX(hbox), eventbox, FALSE, FALSE, 0); ctk_display_device_dfp->scaling_frame = eventbox; ctk_config_set_tooltip(ctk_config, eventbox, __scaling_help); vbox = gtk_vbox_new(FALSE, FRAME_PADDING); gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING); gtk_container_add(GTK_CONTAINER(frame), vbox); button = gtk_check_button_new_with_label("Force Full GPU Scaling"); ctk_display_device_dfp->scaling_gpu_button = button; ctk_config_set_tooltip(ctk_config, button, __force_gpu_scaling_help); gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); table = gtk_table_new(1, 2, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 6); gtk_table_set_col_spacings(GTK_TABLE(table), 15); gtk_container_set_border_width(GTK_CONTAINER(table), 5); ctk_display_device_dfp->txt_scaling = add_table_row(table, 0, 0, 0.5, "Scaling:", 0, 0.5, ""); gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); frame = gtk_frame_new("GPU Scaling Method"); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); vbox = gtk_vbox_new(FALSE, FRAME_PADDING); gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING); gtk_container_add(GTK_CONTAINER(frame), vbox); g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(dfp_scaling_changed), (gpointer) ctk_display_device_dfp); radio0 = make_scaling_radio_button (ctk_display_device_dfp, vbox, NULL, "Stretched", NV_CTRL_GPU_SCALING_METHOD_STRETCHED); radio1 = make_scaling_radio_button (ctk_display_device_dfp, vbox, radio0, "Centered", NV_CTRL_GPU_SCALING_METHOD_CENTERED); radio2 = make_scaling_radio_button (ctk_display_device_dfp, vbox, radio1, "Aspect Ratio Scaled", NV_CTRL_GPU_SCALING_METHOD_ASPECT_SCALED); g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_GPU_SCALING), G_CALLBACK(dfp_update_received), (gpointer) ctk_display_device_dfp); /* pack the color controls */ ctk_display_device_dfp->color_controls = ctk_color_controls_new(handle, ctk_config, ctk_event, ctk_display_device_dfp->reset_button, display_device_mask, name); if (ctk_display_device_dfp->color_controls) { gtk_box_pack_start(GTK_BOX(object), ctk_display_device_dfp->color_controls, FALSE, FALSE, 0); } /* pack the dithering controls */ ctk_display_device_dfp->dithering_controls = ctk_dithering_controls_new(handle, ctk_config, ctk_event, ctk_display_device_dfp->reset_button, display_device_mask, name); if (ctk_display_device_dfp->dithering_controls) { gtk_box_pack_start(GTK_BOX(object), ctk_display_device_dfp->dithering_controls, FALSE, FALSE, 0); } /* pack the image sliders */ ctk_display_device_dfp->image_sliders = ctk_image_sliders_new(handle, ctk_config, ctk_event, ctk_display_device_dfp->reset_button, display_device_mask, name); if (ctk_display_device_dfp->image_sliders) { gtk_box_pack_start(GTK_BOX(object), ctk_display_device_dfp->image_sliders, FALSE, FALSE, 0); } /* pack the EDID button */ hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0); ctk_display_device_dfp->edid_box = hbox; /* show the page */ gtk_widget_show_all(GTK_WIDGET(object)); /* Update the GUI */ update_display_enabled_flag(ctk_display_device_dfp->handle, &ctk_display_device_dfp->display_enabled, ctk_display_device_dfp->display_device_mask); ctk_display_device_dfp_setup(ctk_display_device_dfp); /* handle enable/disable events on the display device */ g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_ENABLED_DISPLAYS), G_CALLBACK(enabled_displays_received), (gpointer) ctk_display_device_dfp); g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_GPU_SCALING_ACTIVE), G_CALLBACK(info_update_received), (gpointer) ctk_display_device_dfp); g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_DFP_SCALING_ACTIVE), G_CALLBACK(info_update_received), (gpointer) ctk_display_device_dfp); g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_FRONTEND_RESOLUTION), G_CALLBACK(info_update_received), (gpointer) ctk_display_device_dfp); g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_FLATPANEL_BEST_FIT_RESOLUTION), G_CALLBACK(info_update_received), (gpointer) ctk_display_device_dfp); g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_BACKEND_RESOLUTION), G_CALLBACK(info_update_received), (gpointer) ctk_display_device_dfp); g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_REFRESH_RATE), G_CALLBACK(info_update_received), (gpointer) ctk_display_device_dfp); return GTK_WIDGET(object); } /* ctk_display_device_dfp_new() */
int nv_write_config_file(const char *filename, CtrlHandles *h, ParsedAttribute *p, ConfigProperties *conf) { int screen, ret, entry, bit, val; FILE *stream; time_t now; AttributeTableEntry *a; ReturnStatus status; NVCTRLAttributeValidValuesRec valid; uint32 mask; CtrlHandleTarget *t; char *tmp_d_str, *prefix, scratch[4]; const char *tmp; char *locale = "C"; if (!filename) { nv_error_msg("Unable to open configuration file for writing."); return NV_FALSE; } stream = fopen(filename, "w"); if (!stream) { nv_error_msg("Unable to open file '%s' for writing.", filename); return NV_FALSE; } /* write header */ now = time(NULL); fprintf(stream, "#\n"); fprintf(stream, "# %s\n", filename); fprintf(stream, "#\n"); fprintf(stream, "# Configuration file for nvidia-settings - the NVIDIA " "X Server Settings utility\n"); /* NOTE: ctime(3) generates a new line */ fprintf(stream, "# Generated on %s", ctime(&now)); fprintf(stream, "#\n"); /* * set the locale to "C" before writing the configuration file to * reduce the risk of locale related parsing problems. Restore * the original locale before exiting this function. */ if (setlocale(LC_NUMERIC, "C") == NULL) { nv_warning_msg("Error writing configuration file '%s': could " "not set the locale 'C'.", filename); locale = conf->locale; } /* write the values in ConfigProperties */ write_config_properties(stream, conf, locale); /* for each screen, query each attribute in the table */ fprintf(stream, "\n"); fprintf(stream, "# Attributes:\n"); fprintf(stream, "\n"); /* * Note: we only save writable attributes addressable by X screen * (i.e., we don't look at other target types, yet). */ for (screen = 0; screen < h->targets[X_SCREEN_TARGET].n; screen++) { t = &h->targets[X_SCREEN_TARGET].t[screen]; /* skip it if we don't have a handle for this screen */ if (!t->h) continue; /* * construct the prefix that will be printed in the config * file infront of each attribute on this screen; this will * either be "[screen]" or "[displayname]". */ if (conf->booleans & CONFIG_PROPERTIES_INCLUDE_DISPLAY_NAME_IN_CONFIG_FILE) { prefix = t->name; } else { snprintf(scratch, 4, "%d", screen); prefix = scratch; } /* loop over all the entries in the table */ for (entry = 0; attributeTable[entry].name; entry++) { a = &attributeTable[entry]; /* * skip all attributes that are not supposed to be written * to the config file */ if (a->flags & NV_PARSER_TYPE_NO_CONFIG_WRITE) continue; /* * special case the color attributes because we want to * print floats */ if (a->flags & NV_PARSER_TYPE_COLOR_ATTRIBUTE) { float c[3], b[3], g[3]; status = NvCtrlGetColorAttributes(t->h, c, b, g); if (status != NvCtrlSuccess) continue; fprintf(stream, "%s%c%s=%f\n", prefix, DISPLAY_NAME_SEPARATOR, a->name, get_color_value(a->attr, c, b, g)); continue; } for (bit = 0; bit < 24; bit++) { mask = 1 << bit; /* * if this bit is not present in the screens's enabled * display device mask (and the X screen has enabled * display devices), skip to the next bit */ if (((t->d & mask) == 0x0) && (t->d)) continue; status = NvCtrlGetValidDisplayAttributeValues (t->h, mask, a->attr, &valid); if (status != NvCtrlSuccess) goto exit_bit_loop; if ((valid.permissions & ATTRIBUTE_TYPE_WRITE) == 0x0) goto exit_bit_loop; status = NvCtrlGetDisplayAttribute(t->h, mask, a->attr, &val); if (status != NvCtrlSuccess) goto exit_bit_loop; if (valid.permissions & ATTRIBUTE_TYPE_DISPLAY) { tmp_d_str = display_device_mask_to_display_device_name(mask); fprintf(stream, "%s%c%s[%s]=%d\n", prefix, DISPLAY_NAME_SEPARATOR, a->name, tmp_d_str, val); free(tmp_d_str); continue; } else { fprintf(stream, "%s%c%s=%d\n", prefix, DISPLAY_NAME_SEPARATOR, a->name, val); /* fall through to exit_bit_loop */ } exit_bit_loop: bit = 25; /* XXX force us out of the display device loop */ } /* bit */ } /* entry */ } /* screen */ /* * loop the ParsedAttribute list, writing the attributes to file. * note that we ignore conf->include_display_name_in_config_file * when writing these parsed attributes; this is because parsed * attributes (like the framelock properties) require a display * name be specified (since there are multiple X servers * involved). */ while (p) { char target_str[64]; if (!p->next) { p = p->next; continue; } tmp = nv_get_attribute_name(p->attr, NV_PARSER_TYPE_STRING_ATTRIBUTE, p->flags); if (!tmp) { nv_error_msg("Failure to save unknown attribute %d.", p->attr); p = p->next; continue; } /* * if the parsed attribute has a target specification, and a * target type other than an X screen, include a target * specification in what we write to the .rc file. */ target_str[0] = '\0'; if ((p->flags & NV_PARSER_HAS_TARGET) && (p->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN)) { int j; /* Find the target name of the target type */ for (j = 0; targetTypeTable[j].name; j++) { if (targetTypeTable[j].nvctrl == p->target_type) { snprintf(target_str, 64, "[%s:%d]", targetTypeTable[j].parsed_name, p->target_id); break; } } } if (p->display_device_mask) { tmp_d_str = display_device_mask_to_display_device_name (p->display_device_mask); fprintf(stream, "%s%s%c%s[%s]=%d\n", p->display, target_str, DISPLAY_NAME_SEPARATOR, tmp, tmp_d_str, p->val); free(tmp_d_str); } else { fprintf(stream, "%s%s%c%s=%d\n", p->display, target_str, DISPLAY_NAME_SEPARATOR, tmp, p->val); } p = p->next; } setlocale(LC_NUMERIC, conf->locale); /* close the configuration file */ ret = fclose(stream); if (ret != 0) { nv_error_msg("Failure while closing file '%s'.", filename); return NV_FALSE; } return NV_TRUE; } /* nv_write_config_file() */