/* * build_dithering_mode_table() - build a table of dithering modes, showing * modes supported by the hardware. */ static gboolean build_dithering_mode_table(CtkDitheringControls *ctk_dithering_controls) { ReturnStatus ret; NVCTRLAttributeValidValuesRec valid; gint i, n = 0, num_of_modes = 0, mask; if (ctk_dithering_controls->dithering_mode_table_size > 0 && ctk_dithering_controls->dithering_mode_table != NULL) { ctk_dithering_controls->dithering_mode_table_size = 0; free(ctk_dithering_controls->dithering_mode_table); } ret = NvCtrlGetValidAttributeValues(ctk_dithering_controls->handle, NV_CTRL_DITHERING_MODE, &valid); if (ret != NvCtrlSuccess || valid.type != ATTRIBUTE_TYPE_INT_BITS) { /* * We do not have valid information to build a mode table * so we need to create default data for the placeholder menu. */ ctk_dithering_controls->dithering_mode_table_size = 1; ctk_dithering_controls->dithering_mode_table = calloc(1, sizeof(ctk_dithering_controls->dithering_mode_table[0])); if (ctk_dithering_controls->dithering_mode_table) { ctk_dithering_controls->dithering_mode_table[0] = NV_CTRL_DITHERING_MODE_AUTO; } else { ctk_dithering_controls->dithering_mode_table_size = 0; } return False; } /* count no. of supported modes */ mask = valid.u.bits.ints; while(mask) { mask = mask & (mask - 1); num_of_modes++; } ctk_dithering_controls->dithering_mode_table_size = num_of_modes; ctk_dithering_controls->dithering_mode_table = calloc(num_of_modes, sizeof(ctk_dithering_controls->dithering_mode_table[0])); if (!ctk_dithering_controls->dithering_mode_table) { ctk_dithering_controls->dithering_mode_table_size = 0; return False; } for (i = 0; i < num_of_modes; i++) { if (valid.u.bits.ints & (1 << i)) { ctk_dithering_controls->dithering_mode_table[n] = i; n++; } } return True; } /* build_dithering_mode_table() */
/**** * * Updates widgets in relation to current overclocking state. * */ static void overclocking_state_update_gui(CtkClocks *ctk_object) { ReturnStatus ret; int value; NVCTRLAttributeValidValuesRec range_detection; gboolean probing_optimal = TRUE; gboolean enabled; /* We need to check the overclocking state status with * the server every time someone tries to change the state * because the set might have failed. */ ret = NvCtrlGetAttribute(ctk_object->handle, NV_CTRL_GPU_OVERCLOCKING_STATE, &value); if ( ret != NvCtrlSuccess ) enabled = False; else enabled = (value==NV_CTRL_GPU_OVERCLOCKING_STATE_MANUAL)?True:False; ctk_object->overclocking_enabled = enabled; /* We need to also make sure the server is not busy probing * for the optimal clocks. */ if ( enabled ) { ret = NvCtrlGetValidAttributeValues(ctk_object->handle, NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION, &range_detection); if ( ret == NvCtrlSuccess ) { ret = NvCtrlGetAttribute(ctk_object->handle, NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE, &value); if ( ret == NvCtrlSuccess ) { probing_optimal = (value == NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE_BUSY); } ctk_object->probing_optimal = probing_optimal; ctk_object->auto_detection_available = TRUE; } } /* Sync the gui to be able to modify the clocks */ sync_gui_to_modify_clocks(ctk_object, ctk_object->clocks_being_modified); /* Update the status bar */ ctk_config_statusbar_message(ctk_object->ctk_config, "GPU overclocking %sabled.", enabled?"en":"dis"); } /* overclocking_state_update_gui() */
static void setup_scale(CtkDisplayDeviceTv *ctk_display_device_tv, int attribute, GtkWidget *scale) { ReturnStatus ret0, ret1; NVCTRLAttributeValidValuesRec valid; NvCtrlAttributeHandle *handle = ctk_display_device_tv->handle; int val; GtkAdjustment *adj = CTK_SCALE(scale)->gtk_adjustment; /* Read settings from X server */ ret0 = NvCtrlGetValidAttributeValues(handle, attribute, &valid); ret1 = NvCtrlGetAttribute(handle, attribute, &val); if ((ret0 == NvCtrlSuccess) && (ret1 == NvCtrlSuccess) && (valid.type == ATTRIBUTE_TYPE_RANGE)) { g_signal_handlers_block_by_func(adj, adjustment_value_changed, ctk_display_device_tv); adj->lower = valid.u.range.min; adj->upper = valid.u.range.max; gtk_adjustment_changed(GTK_ADJUSTMENT(adj)); gtk_adjustment_set_value(GTK_ADJUSTMENT(adj), val); g_signal_handlers_unblock_by_func(adj, adjustment_value_changed, ctk_display_device_tv); g_object_set_data(G_OBJECT(adj), "attribute active", GINT_TO_POINTER(1)); gtk_widget_set_sensitive(scale, TRUE); gtk_widget_show(scale); } else { g_object_set_data(G_OBJECT(adj), "attribute active", GINT_TO_POINTER(0)); gtk_widget_set_sensitive(scale, FALSE); gtk_widget_hide(scale); } } /* setup_scale() */
static void setup_scale(CtkImageSliders *ctk_image_sliders, int attribute, GtkWidget *scale) { ReturnStatus ret0, ret1; NVCTRLAttributeValidValuesRec valid; NvCtrlAttributeHandle *handle = ctk_image_sliders->handle; int val; GtkAdjustment *adj = CTK_SCALE(scale)->gtk_adjustment; /* Read settings from X server */ ret0 = NvCtrlGetValidAttributeValues(handle, attribute, &valid); ret1 = NvCtrlGetAttribute(handle, attribute, &val); if ((ret0 == NvCtrlSuccess) && (ret1 == NvCtrlSuccess) && (valid.type == ATTRIBUTE_TYPE_RANGE)) { g_signal_handlers_block_by_func(adj, scale_value_changed, ctk_image_sliders); adj->lower = valid.u.range.min; adj->upper = valid.u.range.max; gtk_adjustment_changed(GTK_ADJUSTMENT(adj)); gtk_adjustment_set_value(GTK_ADJUSTMENT(adj), val); g_signal_handlers_unblock_by_func(adj, scale_value_changed, ctk_image_sliders); gtk_widget_set_sensitive(scale, TRUE); } else { gtk_widget_set_sensitive(scale, FALSE); } } /* setup_scale() */
static void setup_scale(CtkImageSliders *ctk_image_sliders, int attribute, GtkWidget *scale) { CtrlTarget *ctrl_target = ctk_image_sliders->ctrl_target; ReturnStatus ret0, ret1; CtrlAttributeValidValues valid; int val; GtkAdjustment *adj = CTK_SCALE(scale)->gtk_adjustment; /* Read settings from X server */ ret0 = NvCtrlGetValidAttributeValues(ctrl_target, attribute, &valid); ret1 = NvCtrlGetAttribute(ctrl_target, attribute, &val); if ((ret0 == NvCtrlSuccess) && (ret1 == NvCtrlSuccess) && (valid.valid_type == CTRL_ATTRIBUTE_VALID_TYPE_RANGE)) { g_signal_handlers_block_by_func(adj, scale_value_changed, ctk_image_sliders); ctk_adjustment_set_lower(adj, valid.range.min); ctk_adjustment_set_upper(adj, valid.range.max); gtk_adjustment_changed(GTK_ADJUSTMENT(adj)); gtk_adjustment_set_value(GTK_ADJUSTMENT(adj), val); g_signal_handlers_unblock_by_func(adj, scale_value_changed, ctk_image_sliders); gtk_widget_set_sensitive(scale, TRUE); } else { gtk_widget_set_sensitive(scale, FALSE); } } /* setup_scale() */
GtkWidget* ctk_gvo_sync_new(NvCtrlAttributeHandle *handle, GtkWidget *parent_window, CtkConfig *ctk_config, CtkEvent *ctk_event, CtkGvo *gvo_parent) { GObject *object; CtkGvoSync *ctk_gvo_sync; GtkWidget *frame; GtkWidget *hbox; GtkWidget *label; GtkWidget *alignment; GtkWidget *button; GtkWidget *table, *menu; gint val, i; NVCTRLAttributeValidValuesRec valid; ReturnStatus ret; gint row; const char *help_text; /* make sure we have a handle */ g_return_val_if_fail(handle != NULL, NULL); /* create and initialize the object */ object = g_object_new(CTK_TYPE_GVO_SYNC, NULL); ctk_gvo_sync = CTK_GVO_SYNC(object); ctk_gvo_sync->handle = handle; ctk_gvo_sync->parent_window = parent_window; ctk_gvo_sync->ctk_config = ctk_config; ctk_gvo_sync->ctk_event = ctk_event; ctk_gvo_sync->gvo_parent = gvo_parent; /* Query the current GVO state */ if ( !query_init_gvo_sync_state(ctk_gvo_sync) ) { // Free the object g_object_ref(object); gtk_object_sink(GTK_OBJECT(object)); g_object_unref(object); return NULL; } /* set container properties for the widget */ gtk_box_set_spacing(GTK_BOX(object), 10); /* banner */ hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0); ctk_gvo_sync->banner_box = hbox; /* * Sync options */ frame = gtk_frame_new("Sync Options"); ctk_gvo_sync->frame = frame; gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0); table = gtk_table_new(6, 2, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 0); gtk_table_set_col_spacings(GTK_TABLE(table), 0); gtk_container_add(GTK_CONTAINER(frame), table); /* input video format */ label = gtk_label_new("Input Video Format: "); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, TABLE_PADDING, TABLE_PADDING); hbox = gtk_hbox_new(FALSE, 5); ctk_gvo_sync->input_video_format_text_entry = gtk_entry_new(); ctk_config_set_tooltip(ctk_config, ctk_gvo_sync->input_video_format_text_entry, __input_video_format_help); gtk_entry_set_width_chars (GTK_ENTRY(ctk_gvo_sync->input_video_format_text_entry), max_input_video_format_text_entry_length()); gtk_widget_set_sensitive(ctk_gvo_sync->input_video_format_text_entry, FALSE); update_input_video_format_text_entry(ctk_gvo_sync); gtk_box_pack_start(GTK_BOX(hbox), ctk_gvo_sync->input_video_format_text_entry, TRUE, TRUE, 0); /* Input video format detect button */ button = gtk_toggle_button_new_with_label("Detect"); alignment = gtk_alignment_new(1, 1, 0, 0); gtk_container_add(GTK_CONTAINER(alignment), button); ctk_gvo_sync->input_video_format_detect_button = button; ctk_config_set_tooltip(ctk_config, button, __input_video_format_detect_help); g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(detect_input_toggled), ctk_gvo_sync); gtk_box_pack_start(GTK_BOX(hbox), alignment, FALSE, FALSE, 0); gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL, TABLE_PADDING, TABLE_PADDING); /* Composite Termination */ if (ctk_gvo_sync->caps & NV_CTRL_GVO_CAPABILITIES_COMPOSITE_TERMINATION) { button = gtk_check_button_new_with_label("Enable Composite Termination"); ctk_config_set_tooltip(ctk_config, button, __composite_termination_help); alignment = gtk_alignment_new(1, 1, 0, 0); gtk_container_add(GTK_CONTAINER(alignment), button); gtk_table_attach(GTK_TABLE(table), alignment, 0, 2, 2, 3, GTK_FILL | GTK_EXPAND, GTK_FILL, TABLE_PADDING, TABLE_PADDING); ctk_gvo_sync->composite_termination_button = button; init_composite_termination(ctk_gvo_sync); g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(composite_termination_toggled), ctk_gvo_sync); row = 3; } else { ctk_gvo_sync->composite_termination_button = NULL; row = 2; } /* Sync Mode */ menu = start_menu("Sync Mode: ", table, row); ctk_drop_down_menu_append_item(CTK_DROP_DOWN_MENU(menu), "Free Running", NV_CTRL_GVO_SYNC_MODE_FREE_RUNNING); ctk_drop_down_menu_append_item(CTK_DROP_DOWN_MENU(menu), "GenLock", NV_CTRL_GVO_SYNC_MODE_GENLOCK); ctk_drop_down_menu_append_item(CTK_DROP_DOWN_MENU(menu), "FrameLock", NV_CTRL_GVO_SYNC_MODE_FRAMELOCK); finish_menu(menu, table, row); row++; ctk_gvo_sync->sync_mode_menu = menu; ctk_drop_down_menu_set_tooltip(ctk_config, CTK_DROP_DOWN_MENU(menu), __sync_mode_help); ctk_drop_down_menu_set_current_value (CTK_DROP_DOWN_MENU(ctk_gvo_sync->sync_mode_menu), ctk_gvo_sync->sync_mode); g_signal_connect(G_OBJECT(ctk_gvo_sync->sync_mode_menu), "changed", G_CALLBACK(sync_mode_changed), (gpointer) ctk_gvo_sync); /* Sync Format */ menu = start_menu("Sync Format: ", table, row); for (i = 0; syncFormatNames[i].name; i++) { ctk_drop_down_menu_append_item(CTK_DROP_DOWN_MENU(menu), syncFormatNames[i].name, syncFormatNames[i].format); } finish_menu(menu, table, row); row++; ctk_gvo_sync->sync_format_menu = menu; ctk_drop_down_menu_set_tooltip(ctk_config, CTK_DROP_DOWN_MENU(menu), __sync_format_help); init_sync_format_menu(ctk_gvo_sync); g_signal_connect(G_OBJECT(ctk_gvo_sync->sync_format_menu), "changed", G_CALLBACK(sync_format_changed), (gpointer) ctk_gvo_sync); /* Sync Status */ label = gtk_label_new("Sync Status:"); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_FILL, GTK_FILL, TABLE_PADDING, TABLE_PADDING); ctk_gvo_sync->sync_lock_status_text = gtk_label_new(""); update_sync_lock_status_text(ctk_gvo_sync); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), ctk_gvo_sync->sync_lock_status_text, FALSE, FALSE, 0); gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, row, row+1, GTK_FILL /*| GTK_EXPAND*/, GTK_FILL, TABLE_PADDING, TABLE_PADDING); row++; /* * Synchronization Skew (Delay/Advance) */ /* NV_CTRL_GVO_SYNC_DELAY_PIXELS */ ret = NvCtrlGetValidAttributeValues(handle, NV_CTRL_GVO_SYNC_DELAY_PIXELS, &valid); if ((ret == NvCtrlSuccess) && (valid.type == ATTRIBUTE_TYPE_RANGE)) { ret = NvCtrlGetAttribute(handle, NV_CTRL_GVO_SYNC_DELAY_PIXELS, &val); if (ret != NvCtrlSuccess) val = 0; if (ctk_gvo_sync->caps & NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW) { label = gtk_label_new("HSync Advance:"); help_text = __hsync_advance_help; } else { label = gtk_label_new("HSync Delay:"); help_text = __hsync_delay_help; } gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_FILL, GTK_FILL, TABLE_PADDING, TABLE_PADDING); ctk_gvo_sync->hsync_delay_spin_button = gtk_spin_button_new_with_range(valid.u.range.min, valid.u.range.max, 1); ctk_config_set_tooltip(ctk_config, ctk_gvo_sync->hsync_delay_spin_button, help_text); gtk_spin_button_set_value (GTK_SPIN_BUTTON(ctk_gvo_sync->hsync_delay_spin_button), val); g_signal_connect(G_OBJECT(ctk_gvo_sync->hsync_delay_spin_button), "value-changed", G_CALLBACK(hsync_delay_changed), ctk_gvo_sync); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), ctk_gvo_sync->hsync_delay_spin_button, FALSE, FALSE, 0); label = gtk_label_new("(pixels)"); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, row, row+1, GTK_FILL /*| GTK_EXPAND*/, GTK_FILL, TABLE_PADDING, TABLE_PADDING); row++; } /* NV_CTRL_GVO_SYNC_DELAY_LINES */ ret = NvCtrlGetValidAttributeValues(handle, NV_CTRL_GVO_SYNC_DELAY_LINES, &valid); if ((ret == NvCtrlSuccess) && (valid.type == ATTRIBUTE_TYPE_RANGE)) { ret = NvCtrlGetAttribute(handle, NV_CTRL_GVO_SYNC_DELAY_LINES, &val); if (ret != NvCtrlSuccess) val = 0; if (ctk_gvo_sync->caps & NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW) { label = gtk_label_new("VSync Advance:"); help_text = __vsync_advance_help; } else { label = gtk_label_new("VSync Delay:"); help_text = __vsync_delay_help; } gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_FILL, GTK_FILL, TABLE_PADDING, TABLE_PADDING); ctk_gvo_sync->vsync_delay_spin_button = gtk_spin_button_new_with_range(valid.u.range.min, valid.u.range.max, 1); ctk_config_set_tooltip(ctk_config, ctk_gvo_sync->vsync_delay_spin_button, help_text); gtk_spin_button_set_value (GTK_SPIN_BUTTON(ctk_gvo_sync->vsync_delay_spin_button), val); g_signal_connect(G_OBJECT(ctk_gvo_sync->vsync_delay_spin_button), "value-changed", G_CALLBACK(vsync_delay_changed), ctk_gvo_sync); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), ctk_gvo_sync->vsync_delay_spin_button, FALSE, FALSE, 0); label = gtk_label_new("(lines)"); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, row, row+1, GTK_FILL /*| GTK_EXPAND*/, GTK_FILL, TABLE_PADDING, TABLE_PADDING); row++; } /* create the watch cursor (for use when the "Detect" button is toggled" */ ctk_gvo_sync->wait_cursor = gdk_cursor_new(GDK_WATCH); /* Set UI sensitivity */ update_gvo_sync_sensitivity(ctk_gvo_sync); /* Start listening for events */ register_for_gvo_sync_events(ctk_gvo_sync); /* show the page */ gtk_widget_show_all(GTK_WIDGET(object)); return GTK_WIDGET(object); } /* ctk_gvo_sync_new() */
static GtkWidget *create_slider(CtkXVideo *ctk_xvideo, GtkWidget *vbox, GtkWidget *button, const gchar *name, const char *help, gint attribute, unsigned int bit) { GtkObject *adjustment; GtkWidget *scale, *widget; gint min, max, val, step_incr, page_incr; NVCTRLAttributeValidValuesRec range; ReturnStatus ret; /* get the attribute value */ ret = NvCtrlGetAttribute(ctk_xvideo->handle, attribute, &val); if (ret != NvCtrlSuccess) return NULL; /* get the range for the attribute */ NvCtrlGetValidAttributeValues(ctk_xvideo->handle, attribute, &range); if (range.type != ATTRIBUTE_TYPE_RANGE) return NULL; min = range.u.range.min; max = range.u.range.max; step_incr = ((max) - (min))/250; if (step_incr <= 0) step_incr = 1; page_incr = ((max) - (min))/25; if (page_incr <= 0) page_incr = 1; /* create the slider */ adjustment = gtk_adjustment_new(val, min, max, step_incr, page_incr, 0.0); g_object_set_data(G_OBJECT(adjustment), "xvideo_attribute", GINT_TO_POINTER(attribute)); g_signal_connect(G_OBJECT(adjustment), "value_changed", G_CALLBACK(slider_changed), (gpointer) ctk_xvideo); g_signal_connect_swapped(G_OBJECT(adjustment), "value_changed", G_CALLBACK(set_button_sensitive), (gpointer) button); scale = ctk_scale_new(GTK_ADJUSTMENT(adjustment), name, ctk_xvideo->ctk_config, G_TYPE_INT); gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0); ctk_xvideo->active_attributes |= bit; widget = CTK_SCALE(scale)->gtk_scale; ctk_config_set_tooltip(ctk_xvideo->ctk_config, widget, help); return scale; } /* create_slider() */
/***** * * Syncs the gui to properly display the correct clocks the user wants to * modify, or has modified with another NV_CONTROL client. * */ static void sync_gui_to_modify_clocks(CtkClocks *ctk_object, int which_clocks) { GtkRange *gtk_range; GtkAdjustment *gtk_adjustment_gpu; GtkAdjustment *gtk_adjustment_mem; ReturnStatus ret; int clk_values; int default_clk_values; NVCTRLAttributeValidValuesRec clk_ranges; CtkDropDownMenu *menu; menu = CTK_DROP_DOWN_MENU(ctk_object->clock_menu); /* Obtain the current value and range of the desired clocks */ switch (which_clocks) { case CLOCKS_2D: ret = NvCtrlGetAttribute(ctk_object->handle, NV_CTRL_GPU_2D_CLOCK_FREQS, &clk_values); if ( ret != NvCtrlSuccess ) return; ret = NvCtrlGetValidAttributeValues(ctk_object->handle, NV_CTRL_GPU_2D_CLOCK_FREQS, &clk_ranges); if ( ret != NvCtrlSuccess ) return; break; case CLOCKS_3D: ret = NvCtrlGetAttribute(ctk_object->handle, NV_CTRL_GPU_3D_CLOCK_FREQS, &clk_values); if ( ret != NvCtrlSuccess ) return; ret = NvCtrlGetValidAttributeValues(ctk_object->handle, NV_CTRL_GPU_3D_CLOCK_FREQS, &clk_ranges); if ( ret != NvCtrlSuccess ) return; break; case CLOCKS_NONE: default: return; } /* See if the clocks were modified */ ret = NvCtrlGetAttribute(ctk_object->handle, which_clocks==CLOCKS_2D? NV_CTRL_GPU_DEFAULT_2D_CLOCK_FREQS: NV_CTRL_GPU_DEFAULT_3D_CLOCK_FREQS, &default_clk_values); ctk_object->clocks_modified = ((ret == NvCtrlSuccess) && (default_clk_values != clk_values)); if ( ctk_object->clocks_being_modified != which_clocks ) { ctk_object->clocks_moved = False; } ctk_object->clocks_being_modified = which_clocks; /* Make sure the dropdown reflects the right clock set */ g_signal_handlers_block_by_func(G_OBJECT(ctk_object->clock_menu), G_CALLBACK(clock_menu_changed), (gpointer) ctk_object); ctk_drop_down_menu_set_current_value(menu, (which_clocks==CLOCKS_2D)?0:1); g_signal_handlers_unblock_by_func(G_OBJECT(ctk_object->clock_menu), G_CALLBACK(clock_menu_changed), (gpointer) ctk_object); /* Make GPU and Memory clocks reflect the right range/values */ gtk_range = GTK_RANGE(CTK_SCALE(ctk_object->gpu_clk_scale)->gtk_scale); gtk_adjustment_gpu = GTK_ADJUSTMENT(gtk_range->adjustment); g_signal_handlers_block_by_func(G_OBJECT(gtk_adjustment_gpu), G_CALLBACK(adjustment_value_changed), (gpointer) ctk_object); gtk_range_set_range(gtk_range, GET_GPU_CLOCK(clk_ranges.u.range.min), GET_GPU_CLOCK(clk_ranges.u.range.max)); g_signal_handlers_unblock_by_func(G_OBJECT(gtk_adjustment_gpu), G_CALLBACK(adjustment_value_changed), (gpointer) ctk_object); gtk_range = GTK_RANGE(CTK_SCALE(ctk_object->mem_clk_scale)->gtk_scale); gtk_adjustment_mem = GTK_ADJUSTMENT(gtk_range->adjustment); g_signal_handlers_block_by_func(G_OBJECT(gtk_adjustment_mem), G_CALLBACK(adjustment_value_changed), (gpointer) ctk_object); gtk_range_set_range(gtk_range, GET_MEM_CLOCK(clk_ranges.u.range.min), GET_MEM_CLOCK(clk_ranges.u.range.max)); set_clocks_value(ctk_object, clk_values, which_clocks); g_signal_handlers_unblock_by_func(G_OBJECT(gtk_adjustment_mem), G_CALLBACK(adjustment_value_changed), (gpointer) ctk_object); /* Update the gui sensitivity */ sync_gui_sensitivity(ctk_object); } /* sync_gui_to_modify_clocks() */
/***** * * Main CTK widget creation. * */ GtkWidget* ctk_clocks_new(NvCtrlAttributeHandle *handle, CtkConfig *ctk_config, CtkEvent *ctk_event) { GObject *object; CtkClocks *ctk_object; GtkObject *adjustment; GtkWidget *alignment; GtkWidget *scale; CtkDropDownMenu *menu; GtkWidget *label; GtkWidget *frame; GtkWidget *banner; GtkWidget *hbox; GtkWidget *vbox; ReturnStatus ret; /* NvCtrlxxx function return value */ int value, i = 0; int clocks_2D; NVCTRLAttributeValidValuesRec ranges_2D; NVCTRLAttributeValidValuesRec range_detection; int clocks_3D; NVCTRLAttributeValidValuesRec ranges_3D; Bool overclocking_enabled; Bool auto_detection_available = FALSE; Bool probing_optimal = FALSE; Bool can_access_2d_clocks; Bool can_access_3d_clocks; /* Make sure we have a handle */ g_return_val_if_fail(handle != NULL, NULL); /* If we can't query the overclocking state, don't load the page */ ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_OVERCLOCKING_STATE, &value); if ( ret != NvCtrlSuccess ) return NULL; overclocking_enabled = (value==NV_CTRL_GPU_OVERCLOCKING_STATE_MANUAL)?True:False; /* Check if overclocking is busy */ if ( overclocking_enabled ) { ret = NvCtrlGetValidAttributeValues(handle, NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION, &range_detection); if ( ret == NvCtrlSuccess ) { ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE, &value); if ( ret != NvCtrlSuccess ) return NULL; probing_optimal = (value == NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE_BUSY); auto_detection_available = TRUE; } } /* Can we access the 2D clocks? */ can_access_2d_clocks = True; ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_2D_CLOCK_FREQS, &clocks_2D); if ( ret != NvCtrlSuccess ) can_access_2d_clocks = False; ret = NvCtrlGetValidAttributeValues(handle, NV_CTRL_GPU_2D_CLOCK_FREQS, &ranges_2D); if ( ret != NvCtrlSuccess ) can_access_2d_clocks = False; /* Can we access the 3D clocks? */ can_access_3d_clocks = True; ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_3D_CLOCK_FREQS, &clocks_3D); if ( ret != NvCtrlSuccess ) can_access_3d_clocks = False; ret = NvCtrlGetValidAttributeValues(handle, NV_CTRL_GPU_3D_CLOCK_FREQS, &ranges_3D); if ( ret != NvCtrlSuccess ) can_access_3d_clocks = False; /* If we can't access either of the clocks, don't load the page */ if ( !can_access_2d_clocks && !can_access_3d_clocks ) return NULL; /* Create the ctk object */ object = g_object_new(CTK_TYPE_CLOCKS, NULL); ctk_object = CTK_CLOCKS(object); /* Cache the handle and configuration */ ctk_object->handle = handle; ctk_object->ctk_config = ctk_config; ctk_object->overclocking_enabled = overclocking_enabled; ctk_object->auto_detection_available = auto_detection_available; ctk_object->probing_optimal = probing_optimal; /* Create the Clock menu widget */ menu = (CtkDropDownMenu *) ctk_drop_down_menu_new(CTK_DROP_DOWN_MENU_FLAG_READONLY); i = 0; if ( can_access_2d_clocks ) { ctk_drop_down_menu_append_item(menu, "2D Clock Frequencies", i++); } if ( can_access_3d_clocks ) { ctk_drop_down_menu_append_item(menu, "3D Clock Frequencies", i++); } ctk_object->clock_menu = GTK_WIDGET(menu); g_signal_connect(G_OBJECT(ctk_object->clock_menu), "changed", G_CALLBACK(clock_menu_changed), (gpointer) ctk_object); ctk_config_set_tooltip(ctk_config, ctk_object->clock_menu, __clock_menu_help); gtk_widget_set_sensitive(ctk_object->clock_menu, overclocking_enabled && !probing_optimal); /* Create the Graphics clock frequency slider widget */ if ( can_access_2d_clocks ) { adjustment = gtk_adjustment_new(GET_GPU_CLOCK(clocks_2D), GET_GPU_CLOCK(ranges_2D.u.range.min), GET_GPU_CLOCK(ranges_2D.u.range.max), 1, 5, 0.0); ctk_object->clocks_being_modified = CLOCKS_2D; } else { adjustment = gtk_adjustment_new(GET_GPU_CLOCK(clocks_3D), GET_GPU_CLOCK(ranges_3D.u.range.min), GET_GPU_CLOCK(ranges_3D.u.range.max), 1, 5, 0.0); ctk_object->clocks_being_modified = CLOCKS_3D; } scale = ctk_scale_new(GTK_ADJUSTMENT(adjustment), "GPU (MHz)", ctk_config, G_TYPE_INT); ctk_object->gpu_clk_scale = scale; g_signal_connect(adjustment, "value_changed", G_CALLBACK(adjustment_value_changed), (gpointer) ctk_object); ctk_config_set_tooltip(ctk_config, CTK_SCALE(ctk_object->gpu_clk_scale)->gtk_scale, __graphics_clock_help); gtk_widget_set_sensitive(ctk_object->gpu_clk_scale, overclocking_enabled && !probing_optimal); /* Create the Memory clock frequency slider widget */ if ( can_access_2d_clocks ) { adjustment = gtk_adjustment_new(GET_MEM_CLOCK(clocks_2D), GET_MEM_CLOCK(ranges_2D.u.range.min), GET_MEM_CLOCK(ranges_2D.u.range.max), 1, 5, 0.0); } else { adjustment = gtk_adjustment_new(GET_MEM_CLOCK(clocks_3D), GET_MEM_CLOCK(ranges_3D.u.range.min), GET_MEM_CLOCK(ranges_3D.u.range.max), 1, 5, 0.0); } scale = ctk_scale_new(GTK_ADJUSTMENT(adjustment), "Memory (MHz)", ctk_config, G_TYPE_INT); ctk_object->mem_clk_scale = scale; g_signal_connect(adjustment, "value_changed", G_CALLBACK(adjustment_value_changed), (gpointer) ctk_object); ctk_config_set_tooltip(ctk_config, CTK_SCALE(ctk_object->mem_clk_scale)->gtk_scale, __mem_clock_help); gtk_widget_set_sensitive(ctk_object->mem_clk_scale, overclocking_enabled && !probing_optimal); /* Create the Enable Overclocking checkbox widget */ ctk_object->enable_checkbox = gtk_check_button_new_with_label("Enable Overclocking"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(ctk_object->enable_checkbox), overclocking_enabled); gtk_widget_set_sensitive(ctk_object->enable_checkbox, overclocking_enabled && !probing_optimal); g_signal_connect(G_OBJECT(ctk_object->enable_checkbox), "toggled", G_CALLBACK(overclocking_state_toggled), (gpointer) ctk_object); ctk_config_set_tooltip(ctk_config, ctk_object->enable_checkbox, __enable_button_help); gtk_widget_set_sensitive(ctk_object->enable_checkbox, !probing_optimal); /* Create the Apply button widget */ ctk_object->apply_button = gtk_button_new_with_label("Apply"); g_signal_connect(G_OBJECT(ctk_object->apply_button), "clicked", G_CALLBACK(apply_clocks_clicked), (gpointer) ctk_object); ctk_config_set_tooltip(ctk_config, ctk_object->apply_button, __apply_button_help); gtk_widget_set_sensitive(ctk_object->apply_button, False); /* Create the Auto Detect button widget */ ctk_object->detect_button = gtk_button_new_with_label("Auto Detect"); g_signal_connect(G_OBJECT(ctk_object->detect_button), "clicked", G_CALLBACK(detect_clocks_clicked), (gpointer) ctk_object); ctk_config_set_tooltip(ctk_config, ctk_object->detect_button, __detect_button_help); if ( ctk_object->clocks_being_modified == CLOCKS_2D ) { gtk_widget_set_sensitive(ctk_object->detect_button, False); } else { gtk_widget_set_sensitive(ctk_object->detect_button, overclocking_enabled && auto_detection_available && !probing_optimal); } /* Create the Reset hardware button widget */ ctk_object->reset_button = gtk_button_new_with_label("Reset Hardware Defaults"); g_signal_connect(G_OBJECT(ctk_object->reset_button), "clicked", G_CALLBACK(reset_clocks_clicked), (gpointer) ctk_object); ctk_config_set_tooltip(ctk_config, ctk_object->reset_button, __reset_button_help); gtk_widget_set_sensitive(ctk_object->reset_button, False); /* Create the auto detect dialog */ ctk_object->detect_dialog = gtk_dialog_new_with_buttons("Auto Detect Optimal 3D Clock Frequencies?", GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(ctk_object))), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL ); label = gtk_label_new(__detect_confirm_msg); hbox = gtk_hbox_new(TRUE, 15); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 15); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(ctk_object->detect_dialog)->vbox), hbox, FALSE, FALSE, 15); /* * Now that we've created all the widgets we care about, we're * ready to compose the panel */ /* Set container properties of the ctk object */ gtk_box_set_spacing(GTK_BOX(ctk_object), 10); banner = ctk_banner_image_new(BANNER_ARTWORK_CLOCK); gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0); /* Add Overclocking checkbox */ hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), ctk_object->enable_checkbox, FALSE, FALSE, 0); /* Add Clock frequency frame */ frame = gtk_frame_new("Clock Frequencies"); vbox = gtk_vbox_new(FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING); gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(frame), vbox); gtk_box_pack_start(GTK_BOX(hbox), ctk_object->clock_menu, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), ctk_object->gpu_clk_scale, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), ctk_object->mem_clk_scale, FALSE, FALSE, 5); /* Add the Apply, Auto Detect, and Reset buttons */ hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), ctk_object->apply_button, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(hbox), ctk_object->detect_button); gtk_container_add(GTK_CONTAINER(hbox), ctk_object->reset_button); alignment = gtk_alignment_new(1, 1, 0, 0); gtk_container_add(GTK_CONTAINER(alignment), hbox); gtk_box_pack_start(GTK_BOX(object), alignment, TRUE, TRUE, 0); /* Setup the initial gui state */ sync_gui_to_modify_clocks(ctk_object, ctk_object->clocks_being_modified); /* Handle events from other NV-CONTROL clients */ g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_GPU_OVERCLOCKING_STATE), G_CALLBACK(overclocking_state_received), (gpointer) ctk_object); g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_GPU_2D_CLOCK_FREQS), G_CALLBACK(clocks_received), (gpointer) ctk_object); g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_GPU_3D_CLOCK_FREQS), G_CALLBACK(clocks_received), (gpointer) ctk_object); g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS), G_CALLBACK(clocks_received), (gpointer) ctk_object); g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE), G_CALLBACK(auto_detection_state_received), (gpointer) ctk_object); /* Show the widget */ gtk_widget_show_all(GTK_WIDGET(ctk_object)); return GTK_WIDGET(ctk_object); } /* ctk_clocks_new() */