diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2012-08-27 10:55:04 -0700 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2012-08-27 10:55:04 -0700 |
commit | cc58d9323aa331f16121c2e157611189cee92293 (patch) | |
tree | 69ecfece24b9aece1b200195483d8b91379189c2 | |
parent | 9adcc9c3cde50ef28b734a036cdc336f70c94597 (diff) |
304.43304.43
-rw-r--r-- | doc/version.mk | 2 | ||||
-rw-r--r-- | samples/version.mk | 2 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkcolorcorrection.c | 43 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkcolorcorrection.h | 5 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplayconfig.c | 105 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplayconfig.h | 2 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplaydevice.c | 72 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkdisplaylayout.c | 55 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkevent.c | 3 | ||||
-rw-r--r-- | src/gtk+-2.x/ctkwindow.c | 37 | ||||
-rw-r--r-- | src/libXNVCtrl/NVCtrl.h | 10 | ||||
-rw-r--r-- | src/libXNVCtrlAttributes/NvCtrlAttributes.c | 233 | ||||
-rw-r--r-- | src/libXNVCtrlAttributes/NvCtrlAttributes.h | 15 | ||||
-rw-r--r-- | src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h | 70 | ||||
-rw-r--r-- | src/libXNVCtrlAttributes/NvCtrlAttributesVidMode.c | 371 | ||||
-rw-r--r-- | src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c | 269 | ||||
-rw-r--r-- | src/parse.c | 3 | ||||
-rw-r--r-- | src/src.mk | 2 | ||||
-rw-r--r-- | src/version.mk | 2 | ||||
-rw-r--r-- | version.mk | 2 |
20 files changed, 836 insertions, 467 deletions
diff --git a/doc/version.mk b/doc/version.mk index c7ccc7a..7753329 100644 --- a/doc/version.mk +++ b/doc/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 304.37 +NVIDIA_VERSION = 304.43 diff --git a/samples/version.mk b/samples/version.mk index c7ccc7a..7753329 100644 --- a/samples/version.mk +++ b/samples/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 304.37 +NVIDIA_VERSION = 304.43 diff --git a/src/gtk+-2.x/ctkcolorcorrection.c b/src/gtk+-2.x/ctkcolorcorrection.c index a283ddf..9c2fe1f 100644 --- a/src/gtk+-2.x/ctkcolorcorrection.c +++ b/src/gtk+-2.x/ctkcolorcorrection.c @@ -25,7 +25,6 @@ #include "red_xpm.h" #include "green_xpm.h" #include "blue_xpm.h" -#include "ctkbanner.h" #include "ctkcurve.h" #include "ctkscale.h" @@ -186,7 +185,6 @@ GtkWidget* ctk_color_correction_new(NvCtrlAttributeHandle *handle, GtkWidget *menu; GtkWidget *image; - GtkWidget *banner; GtkWidget *label; GtkWidget *scale; GtkWidget *curve; @@ -201,20 +199,7 @@ GtkWidget* ctk_color_correction_new(NvCtrlAttributeHandle *handle, GtkWidget *widget; GtkWidget *hsep; GtkWidget *eventbox; - ReturnStatus ret; - gint val; - /* check if the VidMode extension is present */ - - ret = NvCtrlGetAttribute(handle, NV_CTRL_ATTR_EXT_VM_PRESENT, &val); - if ((ret != NvCtrlSuccess) || (val == FALSE)) return NULL; - - /* check if the noScanout mode enabled */ - - ret = NvCtrlGetAttribute(handle, NV_CTRL_NO_SCANOUT, &val); - if ((ret == NvCtrlSuccess) && (val == NV_CTRL_NO_SCANOUT_ENABLED)) - return NULL; - object = g_object_new(CTK_TYPE_COLOR_CORRECTION, NULL); ctk_color_correction = CTK_COLOR_CORRECTION(object); @@ -227,16 +212,6 @@ GtkWidget* ctk_color_correction_new(NvCtrlAttributeHandle *handle, gtk_box_set_spacing(GTK_BOX(ctk_color_correction), 10); - /* - * Banner: TOP - LEFT -> RIGHT - * - * This image serves as a visual reference for basic color_box correction - * purposes. - */ - - banner = ctk_banner_image_new(BANNER_ARTWORK_COLOR); - gtk_box_pack_start(GTK_BOX(ctk_color_correction), banner, FALSE, FALSE, 0); - /* create the main hbox and the two main vboxes*/ mainhbox = gtk_hbox_new(FALSE, 10); @@ -1039,7 +1014,9 @@ static gboolean do_confirm_countdown(gpointer data) } /* do_confirm_countdown() */ -GtkTextBuffer *ctk_color_correction_create_help(GtkTextTagTable *table) +GtkTextBuffer *ctk_color_correction_create_help(GtkTextTagTable *table, + const gchar *title, + gboolean randr) { GtkTextIter i; GtkTextBuffer *b; @@ -1048,7 +1025,7 @@ GtkTextBuffer *ctk_color_correction_create_help(GtkTextTagTable *table) gtk_text_buffer_get_iter_at_offset(b, &i, 0); - ctk_help_title(b, &i, "X Server Color Correction Help"); + ctk_help_title(b, &i, "%s Help", title); ctk_help_heading(b, &i, "Active Color Channel"); ctk_help_para(b, &i, __active_color_help); @@ -1072,10 +1049,14 @@ GtkTextBuffer *ctk_color_correction_create_help(GtkTextTagTable *table) ctk_help_para(b, &i, __color_curve_help); - ctk_help_para(b, &i, "Note that the X Server Color Correction page uses " - "the XF86VidMode extension to manipulate the X screen's " - "color ramps."); - + if (randr) { + ctk_help_para(b, &i, "The %s tab uses the RandR extension to " + "manipulate an RandR CRTC's gamma ramp.", title); + } else { + ctk_help_para(b, &i, "The %s page uses the XF86VidMode extension " + "to manipulate the X screen's gamma ramps", title); + } + ctk_help_heading(b, &i, "Confirm Current Changes"); ctk_help_para(b, &i, __confirm_button_help); diff --git a/src/gtk+-2.x/ctkcolorcorrection.h b/src/gtk+-2.x/ctkcolorcorrection.h index 5bbc251..53cb36e 100644 --- a/src/gtk+-2.x/ctkcolorcorrection.h +++ b/src/gtk+-2.x/ctkcolorcorrection.h @@ -79,8 +79,9 @@ GType ctk_color_correction_get_type (void) G_GNUC_CONST; GtkWidget* ctk_color_correction_new (NvCtrlAttributeHandle *, CtkConfig *, ParsedAttribute *, CtkEvent *); -GtkTextBuffer *ctk_color_correction_create_help(GtkTextTagTable *); - +GtkTextBuffer *ctk_color_correction_create_help(GtkTextTagTable *, + const gchar *title, + gboolean randr); G_END_DECLS #endif /* __CTK_COLOR_CORRECTION_H__ */ diff --git a/src/gtk+-2.x/ctkdisplayconfig.c b/src/gtk+-2.x/ctkdisplayconfig.c index 813aef8..9cb4e93 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.c +++ b/src/gtk+-2.x/ctkdisplayconfig.c @@ -1807,6 +1807,18 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, gtk_box_pack_start(GTK_BOX(ctk_object), vbox, FALSE, FALSE, 0); ctk_object->screen_page = vbox; + /* Info on how to drag X screens around */ + hbox = gtk_hbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); + + label = gtk_label_new(""); + labels = g_slist_append(labels, label); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5); + + label = gtk_label_new("(CTRL-Click + Drag to move X screens)"); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5); + ctk_object->box_screen_drag_info = hbox; + /* X screen virtual size */ label = gtk_label_new("Virtual Size:"); labels = g_slist_append(labels, label); @@ -2011,7 +2023,10 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table, "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 " - "be resized by holding shift while dragging."); + "be resized by holding SHIFT while dragging. Also, The " + "X screen a display belongs to may be selected by holding " + "down the CONTROL key while clicking on the display, and can " + "be moved by holding CONTROL-Click and dragging."); ctk_help_heading(b, &i, "Layout Hidden Label"); ctk_help_para(b, &i, __layout_hidden_label_help); ctk_help_heading(b, &i, "Enable Xinerama"); @@ -3752,6 +3767,12 @@ static void setup_screen_page(CtkDisplayConfig *ctk_object) /* Enable display widgets and setup widget information */ gtk_widget_set_sensitive(ctk_object->screen_page, True); + if (screen->layout->num_screens > 1) { + gtk_widget_show(ctk_object->box_screen_drag_info); + } else { + gtk_widget_hide(ctk_object->box_screen_drag_info); + } + setup_screen_virtual_size(ctk_object); setup_screen_depth_dropdown(ctk_object); setup_screen_stereo_dropdown(ctk_object); @@ -3765,8 +3786,8 @@ static void setup_screen_page(CtkDisplayConfig *ctk_object) /** validation_fix_crowded_metamodes() ******************************* * * Goes through each screen's metamodes and ensures that at most - * two display devices are active (have a modeline set) per metamode. - * This function also checks to make sure that there is at least + * (max supported) display devices are active (have a modeline set) per + * metamode. This function also checks to make sure that there is at least * one display device active for each metamode. * **/ @@ -3872,54 +3893,6 @@ static gint validation_fix_crowded_metamodes(CtkDisplayConfig *ctk_object, -/** validation_fix_crowded_metamodes() ******************************* - * - * Goes through each screen's metamodes and ensures that each - * metamode string is unique. If a metamode string is not unique, - * the duplicate metamode is removed. - * - **/ - -static gint validation_remove_dupe_metamodes(CtkDisplayConfig *ctk_object, - nvScreenPtr screen) -{ - int i, j; - char *metamode_str; - - /* Verify each metamode with the metamodes that come before it */ - for (i = 1; i < screen->num_metamodes; i++) { - - metamode_str = screen_get_metamode_str(screen, i, 0); - for (j = 0; j < i; j++) { - char *tmp; - tmp = screen_get_metamode_str(screen, j, 0); - - /* Remove duplicates */ - if (!strcmp(metamode_str, tmp)) { - - /* Delete the metamode */ - ctk_display_layout_delete_screen_metamode - (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), screen, i, - TRUE); - - nv_info_msg(TAB, "Removed MetaMode %d on Screen %d (Is " - "Duplicate of MetaMode %d)\n", i+1, screen->scrnum, - j+1); - g_free(tmp); - i--; /* Check the new metamode in i'th position */ - break; - } - g_free(tmp); - } - g_free(metamode_str); - } - - return 1; - -} /* validation_remove_dupe_metamodes() */ - - - /** validation_auto_fix_screen() ************************************* * * Do what we can to make this screen conform to validation. @@ -3932,7 +3905,6 @@ static gint validation_auto_fix_screen(CtkDisplayConfig *ctk_object, gint status = 1; status &= validation_fix_crowded_metamodes(ctk_object, screen); - status &= validation_remove_dupe_metamodes(ctk_object, screen); return status; @@ -3988,9 +3960,8 @@ static gint validation_auto_fix(CtkDisplayConfig *ctk_object) * * - Have at least 1 display device activated for all metamodes. * - * - Have at most 2 display devices activated for all metamodes. - * - * - All metamodes must be unique. + * - Have at most (max supported) display devices activated for all + * metamodes. * * - All metamodes must have a coherent offset (The top left corner * of the bounding box of all the metamodes must be the same.) @@ -4007,7 +3978,6 @@ static gchar * validate_screen(nvScreenPtr screen) nvModePtr mode; int i, j; int num_displays; - char *metamode_str; gchar *err_str = NULL; gchar *tmp; gchar *tmp2; @@ -4063,29 +4033,6 @@ static gchar * validate_screen(nvScreenPtr screen) g_free(tmp); err_str = tmp2; } - - - /* Verify that the metamode is unique */ - metamode_str = screen_get_metamode_str(screen, i, 0); - for (j = 0; j < i; j++) { - char *tmp = screen_get_metamode_str(screen, j, 0); - - /* Make sure the metamode is unique */ - if (!strcmp(metamode_str, tmp)) { - g_free(tmp); - tmp = g_strdup_printf("%s MetaMode %d of Screen %d is the " - "same as MetaMode %d. All MetaModes " - "must be unique.\n\n", - bullet, i+1, screen->scrnum, j+1); - tmp2 = g_strconcat((err_str ? err_str : ""), tmp, NULL); - g_free(err_str); - err_str = tmp2; - g_free(tmp); - break; - } - g_free(tmp); - } - g_free(metamode_str); } return err_str; diff --git a/src/gtk+-2.x/ctkdisplayconfig.h b/src/gtk+-2.x/ctkdisplayconfig.h index 7e415e8..c90c0d5 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.h +++ b/src/gtk+-2.x/ctkdisplayconfig.h @@ -130,6 +130,8 @@ typedef struct _CtkDisplayConfig GtkWidget *screen_page; /* X Screen - Settings */ + GtkWidget *box_screen_drag_info; + GtkWidget *box_screen_virtual_size; GtkWidget *txt_screen_virtual_size; diff --git a/src/gtk+-2.x/ctkdisplaydevice.c b/src/gtk+-2.x/ctkdisplaydevice.c index b74dfb2..3a7e2fa 100644 --- a/src/gtk+-2.x/ctkdisplaydevice.c +++ b/src/gtk+-2.x/ctkdisplaydevice.c @@ -33,6 +33,7 @@ #include "ctkcolorcontrols.h" #include "ctkimagesliders.h" #include "ctkedid.h" +#include "ctkcolorcorrection.h" #include "ctkconfig.h" #include "ctkhelp.h" #include "ctkutils.h" @@ -66,6 +67,10 @@ static void unregister_link_events(InfoEntry *entry); static void register_refresh_rate_events(InfoEntry *entry); static void unregister_refresh_rate_events(InfoEntry *entry); +static void add_color_correction_tab(CtkDisplayDevice *ctk_object, + CtkConfig *ctk_config, + CtkEvent *ctk_event, + GtkWidget *notebook); #define FRAME_PADDING 5 @@ -253,19 +258,6 @@ GtkWidget* ctk_display_device_new(NvCtrlAttributeHandle *handle, } gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0); - /* Reset button */ - - button = gtk_button_new_with_label("Reset Hardware Defaults"); - str = ctk_help_create_reset_hardware_defaults_text(typeBaseName, - name); - ctk_config_set_tooltip(ctk_config, button, str); - ctk_object->reset_button = button; - - alignment = gtk_alignment_new(1, 1, 0, 0); - gtk_container_add(GTK_CONTAINER(alignment), button); - gtk_box_pack_end(GTK_BOX(object), alignment, FALSE, FALSE, 0); - - /* Create tabbed notebook for widget */ notebook = gtk_notebook_new(); @@ -400,6 +392,18 @@ GtkWidget* ctk_display_device_new(NvCtrlAttributeHandle *handle, FALSE, FALSE, 0); } + /* pack the reset button */ + + button = gtk_button_new_with_label("Reset Hardware Defaults"); + str = ctk_help_create_reset_hardware_defaults_text(typeBaseName, + name); + ctk_config_set_tooltip(ctk_config, button, str); + ctk_object->reset_button = button; + + alignment = gtk_alignment_new(1, 1, 0, 0); + gtk_container_add(GTK_CONTAINER(alignment), button); + gtk_box_pack_end(GTK_BOX(nbox), alignment, FALSE, FALSE, 0); + /* If no controls are created, don't add a controls tab */ if (ctk_object->color_controls || @@ -409,6 +413,10 @@ GtkWidget* ctk_display_device_new(NvCtrlAttributeHandle *handle, gtk_label_new("Controls")); } + /* add the color correction tab if RandR is available */ + + add_color_correction_tab(ctk_object, ctk_config, ctk_event, notebook); + /* Update the GUI */ gtk_widget_show_all(GTK_WIDGET(object)); @@ -851,3 +859,41 @@ static void callback_refresh_rate_changed(GtkObject *object, gpointer arg1, update_refresh_rate(entry); } + + +static void add_color_correction_tab(CtkDisplayDevice *ctk_object, + CtkConfig *ctk_config, + CtkEvent *ctk_event, + GtkWidget *notebook) +{ + ReturnStatus ret; + gint val; + GtkWidget *ctk_color_correction; + GtkWidget *box; + + ret = NvCtrlGetAttribute(ctk_object->handle, + NV_CTRL_ATTR_RANDR_GAMMA_AVAILABLE, &val); + + if (ret != NvCtrlSuccess) { + return; + } + + if (val != 1) { + return; + } + + ctk_color_correction = ctk_color_correction_new(ctk_object->handle, + ctk_config, + NULL /* ParsedAttribute*/, + ctk_event); + if (ctk_color_correction == NULL) { + return; + } + + box = gtk_hbox_new(FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(box), FRAME_PADDING); + gtk_box_pack_start(GTK_BOX(box), ctk_color_correction, TRUE, TRUE, 0); + + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), box, + gtk_label_new("Color Correction")); +} diff --git a/src/gtk+-2.x/ctkdisplaylayout.c b/src/gtk+-2.x/ctkdisplaylayout.c index f2a18ec..7226ae8 100644 --- a/src/gtk+-2.x/ctkdisplaylayout.c +++ b/src/gtk+-2.x/ctkdisplaylayout.c @@ -30,6 +30,7 @@ #include "ctkhelp.h" #include "ctkdisplaylayout.h" #include "ctkdisplayconfig-utils.h" +#include "ctkutils.h" @@ -455,11 +456,12 @@ static Bool get_modify_info(CtkDisplayLayout *ctk_object) * **/ -static void sync_scaling(CtkDisplayLayout *ctk_object) +static Bool sync_scaling(CtkDisplayLayout *ctk_object) { int *dim = ctk_object->layout->dim; float wscale; float hscale; + float prev_scale = ctk_object->scale; wscale = (float)(ctk_object->img_dim[W]) / (float)(dim[W]); hscale = (float)(ctk_object->img_dim[H]) / (float)(dim[H]); @@ -470,6 +472,8 @@ static void sync_scaling(CtkDisplayLayout *ctk_object) ctk_object->scale = wscale; } + return (prev_scale != ctk_object->scale); + } /* sync_scaling() */ @@ -1116,7 +1120,7 @@ static void recenter_screen(nvScreenPtr screen) * **/ -static void set_screen_metamode(nvLayoutPtr layout, nvScreenPtr screen, +static Bool set_screen_metamode(nvLayoutPtr layout, nvScreenPtr screen, int new_metamode_idx) { nvDisplayPtr display; @@ -1135,7 +1139,12 @@ static void set_screen_metamode(nvLayoutPtr layout, nvScreenPtr screen, /* Recalculate the layout dimensions */ calc_layout(layout); - offset_layout(layout, -layout->dim[X], -layout->dim[Y]); + if (layout->dim[X] || layout->dim[Y]) { + offset_layout(layout, -layout->dim[X], -layout->dim[Y]); + return TRUE; + } + + return FALSE; } /* set_screen_metamode() */ @@ -1149,11 +1158,12 @@ static void set_screen_metamode(nvLayoutPtr layout, nvScreenPtr screen, * **/ -static void recenter_layout(nvLayoutPtr layout) +static Bool recenter_layout(nvLayoutPtr layout) { nvScreenPtr screen; int real_metamode_idx; int metamode_idx; + Bool modified = FALSE; for (screen = layout->screens; screen; screen = screen->next_in_layout) { @@ -1165,12 +1175,18 @@ static void recenter_layout(nvLayoutPtr layout) if (metamode_idx == real_metamode_idx) continue; - set_screen_metamode(layout, screen, metamode_idx); + if (set_screen_metamode(layout, screen, metamode_idx)) { + modified = TRUE; + } } - set_screen_metamode(layout, screen, real_metamode_idx); + if (set_screen_metamode(layout, screen, real_metamode_idx)) { + modified = TRUE; + } } + return modified; + } /* recenter_layout() */ @@ -2015,8 +2031,12 @@ static int move_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap) modified = 1; } - recenter_layout(layout); - sync_scaling(ctk_object); + if (recenter_layout(layout)) { + modified = 1; + } + if (sync_scaling(ctk_object)) { + modified = 1; + } /* If what we moved required the layout to be shifted, offset @@ -2174,9 +2194,12 @@ static int pan_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap) modified = 1; } - recenter_layout(layout); - sync_scaling(ctk_object); - + if (recenter_layout(layout)) { + modified = 1; + } + if (sync_scaling(ctk_object)) { + modified = 1; + } /* Check if the item being moved has a new position */ /* Report if anything changed */ @@ -2613,6 +2636,7 @@ static int click_layout(CtkDisplayLayout *ctk_object, int x, int y) nvDisplayPtr display; nvScreenPtr screen; int *sdim; + GdkModifierType state; /* Assume user didn't actually click inside a display for now */ @@ -2620,6 +2644,9 @@ static int click_layout(CtkDisplayLayout *ctk_object, int x, int y) ctk_object->selected_display = NULL; ctk_object->selected_screen = NULL; + gdk_window_get_pointer + (GTK_WIDGET(ctk_get_parent_window(ctk_object->drawing_area))->window, + NULL, NULL, &state); /* Look through the Z-order for the next element */ for (i = 0; i < ctk_object->Zcount; i++) { @@ -2643,6 +2670,10 @@ static int click_layout(CtkDisplayLayout *ctk_object, int x, int y) } } + /* Select display's X screen when CTRL is held down on click */ + if (ctk_object->selected_screen && (state & GDK_CONTROL_MASK)) { + ctk_object->selected_display = NULL; + } /* Don't allow clicking outside - reselect what was last selected */ if (ctk_object->clicked_outside) { @@ -4264,7 +4295,7 @@ motion_event_callback(GtkWidget *widget, GdkEventMotion *event, gpointer data) } /* Swap between panning and moving */ - if (ctk_object->advanced_mode && (state & ShiftMask)) { + if (ctk_object->advanced_mode && (state & GDK_SHIFT_MASK)) { modify_panning = 1; } else { modify_panning = 0; diff --git a/src/gtk+-2.x/ctkevent.c b/src/gtk+-2.x/ctkevent.c index e6aaa0c..115b119 100644 --- a/src/gtk+-2.x/ctkevent.c +++ b/src/gtk+-2.x/ctkevent.c @@ -329,6 +329,7 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_SIGNAL(NV_CTRL_DISPLAY_ENABLED); MAKE_SIGNAL(NV_CTRL_FRAMELOCK_INCOMING_HOUSE_SYNC_RATE); MAKE_SIGNAL(NV_CTRL_FXAA); + MAKE_SIGNAL(NV_CTRL_DISPLAY_RANDR_OUTPUT_ID); #undef MAKE_SIGNAL /* @@ -338,7 +339,7 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) * knows about. */ -#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_FXAA +#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_DISPLAY_RANDR_OUTPUT_ID #warning "There are attributes that do not emit signals!" #endif diff --git a/src/gtk+-2.x/ctkwindow.c b/src/gtk+-2.x/ctkwindow.c index 0919bf1..dee4e6a 100644 --- a/src/gtk+-2.x/ctkwindow.c +++ b/src/gtk+-2.x/ctkwindow.c @@ -44,6 +44,7 @@ #include "ctkslimm.h" #include "ctkgpu.h" #include "ctkcolorcorrection.h" +#include "ctkcolorcorrectionpage.h" #include "ctkxvideo.h" #include "ctkcursorshadow.h" #include "ctkopengl.h" @@ -382,6 +383,16 @@ static gboolean tree_view_key_event(GtkWidget *tree_view, GdkEvent *event, } /* tree_view_key_event() */ +static gboolean has_randr_gamma(NvCtrlAttributeHandle *handle) +{ + ReturnStatus ret; + int val; + + ret = NvCtrlGetAttribute(handle, NV_CTRL_ATTR_RANDR_GAMMA_AVAILABLE, &val); + + return ((ret == NvCtrlSuccess) && (val == 1)); +} + /* * ctk_window_new() - create a new CtkWindow widget */ @@ -666,15 +677,22 @@ GtkWidget *ctk_window_new(ParsedAttribute *p, ConfigProperties *conf, } } - /* color correction */ + /* + * color correction, if RandR per-CRTC color correction is not + * available + */ + + if (!has_randr_gamma(screen_handle)) { - child = ctk_color_correction_new(screen_handle, ctk_config, - ctk_window->attribute_list, - ctk_event); - if (child) { - help = ctk_color_correction_create_help(tag_table); - add_page(child, help, ctk_window, &iter, NULL, - "X Server Color Correction", NULL, NULL, NULL); + child = ctk_color_correction_page_new(screen_handle, ctk_config, + ctk_window->attribute_list, + ctk_event); + if (child) { + const char *title = "X Server Color Correction"; + help = ctk_color_correction_page_create_help(tag_table, title); + add_page(child, help, ctk_window, &iter, NULL, + title, NULL, NULL, NULL); + } } /* xvideo settings */ @@ -1396,7 +1414,8 @@ static void add_display_devices(CtkWindow *ctk_window, GtkTreeIter *iter, NvCtrlAttributeInit(NvCtrlGetDisplayPtr(gpu_handle), NV_CTRL_TARGET_TYPE_DISPLAY, display_id, - NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM); + NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM | + NV_CTRL_ATTRIBUTES_XRANDR_SUBSYSTEM); if (!display_handle) { continue; } diff --git a/src/libXNVCtrl/NVCtrl.h b/src/libXNVCtrl/NVCtrl.h index 2b05050..98b8fda 100644 --- a/src/libXNVCtrl/NVCtrl.h +++ b/src/libXNVCtrl/NVCtrl.h @@ -3203,9 +3203,15 @@ #define NV_CTRL_FXAA_DISABLE 0 #define NV_CTRL_FXAA_ENABLE 1 +/* + * NV_CTRL_DISPLAY_RANDR_OUTPUT_ID - the RandR Output ID (type RROutput) + * that corresponds to the specified Display Device target. If a new + * enough version of RandR is not available in the X server, + * DISPLAY_RANDR_OUTPUT_ID will be 0. + */ +#define NV_CTRL_DISPLAY_RANDR_OUTPUT_ID 391 /* R-D- */ - -#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_FXAA +#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_DISPLAY_RANDR_OUTPUT_ID /**************************************************************************/ diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributes.c b/src/libXNVCtrlAttributes/NvCtrlAttributes.c index 1c2a78b..150126d 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributes.c +++ b/src/libXNVCtrlAttributes/NvCtrlAttributes.c @@ -2,7 +2,7 @@ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix * and Linux systems. * - * Copyright (C) 2004 NVIDIA Corporation. + * Copyright (C) 2004,2012 NVIDIA Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -29,6 +29,7 @@ #include <stdlib.h> #include <string.h> #include <stdio.h> +#include <math.h> /* pow(3) */ #include <sys/utsname.h> @@ -96,18 +97,16 @@ NvCtrlAttributeHandle *NvCtrlAttributeInit(Display *dpy, int target_type, if (subsystems & NV_CTRL_ATTRIBUTES_GLX_SUBSYSTEM) { h->glx = NvCtrlInitGlxAttributes(h); } - - /* - * initialize the XRandR extension and attributes; it is OK if - * this fails - */ - - if (subsystems & NV_CTRL_ATTRIBUTES_XRANDR_SUBSYSTEM) { - h->xrandr = NvCtrlInitXrandrAttributes(h); - } - } /* X Screen target type attribute subsystems */ - + + /* + * initialize the XRandR extension and attributes; this does not + * require an X screen and it is OK if this fails + */ + if (subsystems & NV_CTRL_ATTRIBUTES_XRANDR_SUBSYSTEM) { + h->xrandr = NvCtrlInitXrandrAttributes(h); + } + return (NvCtrlAttributeHandle *) h; failed: @@ -551,7 +550,12 @@ NvCtrlGetDisplayAttribute64(NvCtrlAttributeHandle *handle, } return NvCtrlSuccess; } - + + if (attr >= NV_CTRL_ATTR_RANDR_BASE && + attr <= NV_CTRL_ATTR_RANDR_LAST_ATTRIBUTE) { + return NvCtrlXrandrGetAttribute(h, display_mask, attr, val); + } + if (((attr >= 0) && (attr <= NV_CTRL_LAST_ATTRIBUTE)) || ((attr >= NV_CTRL_ATTR_NV_BASE) && (attr <= NV_CTRL_ATTR_NV_LAST_ATTRIBUTE))) { @@ -930,3 +934,206 @@ const char *NvCtrlGetMultisampleModeName(int multisample_mode) return mode_names[multisample_mode]; } /* NvCtrlGetMultisampleModeName */ + + +ReturnStatus NvCtrlGetColorAttributes(NvCtrlAttributeHandle *handle, + float contrast[3], + float brightness[3], + float gamma[3]) +{ + NvCtrlAttributePrivateHandle *h = (NvCtrlAttributePrivateHandle *) handle; + + if (h->target_type == NV_CTRL_TARGET_TYPE_X_SCREEN) { + return NvCtrlVidModeGetColorAttributes(h, contrast, brightness, gamma); + } else if (h->target_type == NV_CTRL_TARGET_TYPE_DISPLAY) { + return NvCtrlXrandrGetColorAttributes(h, contrast, brightness, gamma); + } + + return NvCtrlBadHandle; +} + +ReturnStatus NvCtrlSetColorAttributes(NvCtrlAttributeHandle *handle, + float c[3], + float b[3], + float g[3], + unsigned int bitmask) +{ + NvCtrlAttributePrivateHandle *h = (NvCtrlAttributePrivateHandle *) handle; + + if (h->target_type == NV_CTRL_TARGET_TYPE_X_SCREEN) { + return NvCtrlVidModeSetColorAttributes(h, c, b, g, bitmask); + } else if (h->target_type == NV_CTRL_TARGET_TYPE_DISPLAY) { + return NvCtrlXrandrSetColorAttributes(h, c, b, g, bitmask); + } + + return NvCtrlBadHandle; +} + + +ReturnStatus NvCtrlGetColorRamp(NvCtrlAttributeHandle *handle, + unsigned int channel, + uint16_t **lut, + int *n) +{ + NvCtrlAttributePrivateHandle *h = (NvCtrlAttributePrivateHandle *) handle; + + if (h->target_type == NV_CTRL_TARGET_TYPE_X_SCREEN) { + return NvCtrlVidModeGetColorRamp(h, channel, lut, n); + } else if (h->target_type == NV_CTRL_TARGET_TYPE_DISPLAY) { + return NvCtrlXrandrGetColorRamp(h, channel, lut, n); + } + + return NvCtrlBadHandle; +} + + +/* helper functions private to the libXNVCtrlAttributes backend */ + +void NvCtrlInitGammaInputStruct(NvCtrlGammaInput *pGammaInput) +{ + int ch; + + for (ch = FIRST_COLOR_CHANNEL; ch <= LAST_COLOR_CHANNEL; ch++) { + pGammaInput->brightness[ch] = BRIGHTNESS_DEFAULT; + pGammaInput->contrast[ch] = CONTRAST_DEFAULT; + pGammaInput->gamma[ch] = GAMMA_DEFAULT; + } +} + +/* + * Compute the gammaRamp entry given its index, and the contrast, + * brightness, and gamma. + */ +static unsigned short ComputeGammaRampVal(int gammaRampSize, + int i, + float contrast, + float brightness, + float gamma) +{ + double j, half, scale; + int shift, val, num; + + num = gammaRampSize - 1; + shift = 16 - (ffs(gammaRampSize) - 1); + + scale = (double) num / 3.0; /* how much brightness and contrast + affect the value */ + j = (double) i; + + /* contrast */ + + contrast *= scale; + + if (contrast > 0.0) { + half = ((double) num / 2.0) - 1.0; + j -= half; + j *= half / (half - contrast); + j += half; + } else { + half = (double) num / 2.0; + j -= half; + j *= (half + contrast) / half; + j += half; + } + + if (j < 0.0) j = 0.0; + + /* gamma */ + + gamma = 1.0 / (double) gamma; + + if (gamma == 1.0) { + val = (int) j; + } else { + val = (int) (pow (j / (double)num, gamma) * (double)num + 0.5); + } + + /* brightness */ + + brightness *= scale; + + val += (int)brightness; + if (val > num) val = num; + if (val < 0) val = 0; + + val <<= shift; + return (unsigned short) val; +} + +void NvCtrlUpdateGammaRamp(const NvCtrlGammaInput *pGammaInput, + int gammaRampSize, + unsigned short *gammaRamp[3], + unsigned int bitmask) +{ + int i, ch; + + /* update the requested channels within the gammaRamp */ + + for (ch = FIRST_COLOR_CHANNEL; ch <= LAST_COLOR_CHANNEL; ch++) { + + /* only update requested channels */ + + if ((bitmask & (1 << ch)) == 0) { + continue; + } + + for (i = 0; i < gammaRampSize; i++) { + gammaRamp[ch][i] = + ComputeGammaRampVal(gammaRampSize, + i, + pGammaInput->contrast[ch], + pGammaInput->brightness[ch], + pGammaInput->gamma[ch]); + } + } +} + +void NvCtrlAssignGammaInput(NvCtrlGammaInput *pGammaInput, + const float inContrast[3], + const float inBrightness[3], + const float inGamma[3], + const unsigned int bitmask) +{ + int ch; + + /* clamp input, but only the input specified in the bitmask */ + + for (ch = FIRST_COLOR_CHANNEL; ch <= LAST_COLOR_CHANNEL; ch++) { + + /* only update requested channels */ + + if ((bitmask & (1 << ch)) == 0) { + continue; + } + + if (bitmask & CONTRAST_VALUE) { + if (inContrast[ch] > CONTRAST_MAX) { + pGammaInput->contrast[ch] = CONTRAST_MAX; + } else if (inContrast[ch] < CONTRAST_MIN) { + pGammaInput->contrast[ch] = CONTRAST_MIN; + } else { + pGammaInput->contrast[ch] = inContrast[ch]; + } + } + + if (bitmask & BRIGHTNESS_VALUE) { + if (inBrightness[ch] > BRIGHTNESS_MAX) { + pGammaInput->brightness[ch] = BRIGHTNESS_MAX; + } else if (inBrightness[ch] < BRIGHTNESS_MIN) { + pGammaInput->brightness[ch] = BRIGHTNESS_MIN; + } else { + pGammaInput->brightness[ch] = inBrightness[ch]; + } + } + + if (bitmask & GAMMA_VALUE) { + if (inGamma[ch] > GAMMA_MAX) { + pGammaInput->gamma[ch] = GAMMA_MAX; + } else if (inGamma[ch] < GAMMA_MIN) { + pGammaInput->gamma[ch] = GAMMA_MIN; + } else { + pGammaInput->gamma[ch] = inGamma[ch]; + } + } + } +} diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributes.h b/src/libXNVCtrlAttributes/NvCtrlAttributes.h index 8da3aa5..bfb51d2 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributes.h +++ b/src/libXNVCtrlAttributes/NvCtrlAttributes.h @@ -43,6 +43,9 @@ typedef void NvCtrlAttributeHandle; #define GREEN_CHANNEL_INDEX 1 #define BLUE_CHANNEL_INDEX 2 +#define FIRST_COLOR_CHANNEL RED_CHANNEL_INDEX +#define LAST_COLOR_CHANNEL BLUE_CHANNEL_INDEX + #define CONTRAST_INDEX 3 #define BRIGHTNESS_INDEX 4 #define GAMMA_INDEX 5 @@ -106,7 +109,17 @@ typedef void NvCtrlAttributeHandle; #define NV_CTRL_ATTR_GLX_LAST_ATTRIBUTE \ (NV_CTRL_ATTR_GLX_FBCONFIG_ATTRIBS) -#define NV_CTRL_ATTR_LAST_ATTRIBUTE (NV_CTRL_ATTR_GLX_LAST_ATTRIBUTE) +/* RandR */ + +#define NV_CTRL_ATTR_RANDR_BASE \ + (NV_CTRL_ATTR_GLX_LAST_ATTRIBUTE + 1) + +#define NV_CTRL_ATTR_RANDR_GAMMA_AVAILABLE (NV_CTRL_ATTR_RANDR_BASE + 0) + +#define NV_CTRL_ATTR_RANDR_LAST_ATTRIBUTE \ + (NV_CTRL_ATTR_RANDR_GAMMA_AVAILABLE) + +#define NV_CTRL_ATTR_LAST_ATTRIBUTE (NV_CTRL_ATTR_RANDR_LAST_ATTRIBUTE) typedef enum { diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h b/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h index 5daa455..36cbcb9 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h +++ b/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h @@ -2,7 +2,7 @@ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix * and Linux systems. * - * Copyright (C) 2004 NVIDIA Corporation. + * Copyright (C) 2004,2012 NVIDIA Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -23,6 +23,7 @@ #include "NvCtrlAttributes.h" #include "NVCtrl.h" #include <GL/glx.h> /* GLX #defines */ +#include <X11/extensions/Xrandr.h> /* Xrandr */ #define EXTENSION_NV_CONTROL 0x1 @@ -80,6 +81,12 @@ typedef struct __NvCtrlXvBlitterAttributes NvCtrlXvBlitterAttributes; typedef struct __NvCtrlXvAttribute NvCtrlXvAttribute; typedef struct __NvCtrlXrandrAttributes NvCtrlXrandrAttributes; +typedef struct { + float brightness[3]; + float contrast[3]; + float gamma[3]; +} NvCtrlGammaInput; + struct __NvCtrlNvControlAttributes { int event_base; int error_base; @@ -88,14 +95,11 @@ struct __NvCtrlNvControlAttributes { }; struct __NvCtrlVidModeAttributes { - int n; - int sigbits; int major_version; int minor_version; unsigned short *lut[3]; - float brightness[3]; - float contrast[3]; - float gamma[3]; + int gammaRampSize; + NvCtrlGammaInput gammaInput; }; struct __NvCtrlXvAttributes { @@ -111,6 +115,10 @@ struct __NvCtrlXrandrAttributes { int error_base; int major_version; int minor_version; + Bool gammaAvailable; + RRCrtc gammaCrtc; + NvCtrlGammaInput gammaInput; + XRRCrtcGamma *pGammaRamp; }; struct __NvCtrlAttributePrivateHandle { @@ -177,12 +185,47 @@ NvCtrlXrandrGetStringAttribute (NvCtrlAttributePrivateHandle *, unsigned int, int, char **); +ReturnStatus NvCtrlXrandrGetColorAttributes(NvCtrlAttributePrivateHandle *h, + float contrast[3], + float brightness[3], + float gamma[3]); + +ReturnStatus NvCtrlXrandrSetColorAttributes(NvCtrlAttributePrivateHandle *h, + float c[3], + float b[3], + float g[3], + unsigned int bitmask); + +ReturnStatus NvCtrlXrandrGetColorRamp(NvCtrlAttributePrivateHandle *h, + unsigned int channel, + uint16_t **lut, + int *n); + /* XF86 Video Mode extension attribute functions */ +ReturnStatus NvCtrlVidModeGetColorAttributes(NvCtrlAttributePrivateHandle *h, + float contrast[3], + float brightness[3], + float gamma[3]); + +ReturnStatus NvCtrlVidModeSetColorAttributes(NvCtrlAttributePrivateHandle *h, + float c[3], + float b[3], + float g[3], + unsigned int bitmask); + +ReturnStatus NvCtrlVidModeGetColorRamp(NvCtrlAttributePrivateHandle *h, + unsigned int channel, + uint16_t **lut, + int *n); + ReturnStatus NvCtrlVidModeGetStringAttribute (NvCtrlAttributePrivateHandle *, unsigned int, int, char **); +ReturnStatus +NvCtrlXrandrGetAttribute(NvCtrlAttributePrivateHandle *h, + unsigned int display_mask, int attr, int64_t *val); /* Generic attribute functions */ @@ -230,4 +273,19 @@ NvCtrlNvControlStringOperation (NvCtrlAttributePrivateHandle *h, unsigned int display_mask, int attr, char *ptrIn, char **ptrOut); +/* helper functions for XV86VidMode and RandR backends */ + +void NvCtrlInitGammaInputStruct(NvCtrlGammaInput *pGammaInput); + +void NvCtrlUpdateGammaRamp(const NvCtrlGammaInput *pGammaInput, + int gammaRampSize, + unsigned short *gammaRamp[3], + unsigned int bitmask); + +void NvCtrlAssignGammaInput(NvCtrlGammaInput *pGammaInput, + const float inContrast[3], + const float inBrightness[3], + const float inGamma[3], + const unsigned int bitmask); + #endif /* __NVCTRL_ATTRIBUTES_PRIVATE__ */ diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesVidMode.c b/src/libXNVCtrlAttributes/NvCtrlAttributesVidMode.c index 013b9ab..f16db84 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributesVidMode.c +++ b/src/libXNVCtrlAttributes/NvCtrlAttributesVidMode.c @@ -2,7 +2,7 @@ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix * and Linux systems. * - * Copyright (C) 2004 NVIDIA Corporation. + * Copyright (C) 2004,2012 NVIDIA Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -26,176 +26,84 @@ #include <stdlib.h> #include <string.h> -#include <math.h> - -static unsigned short computeVal(NvCtrlAttributePrivateHandle *, - int, float, float, float); - -#define RED RED_CHANNEL_INDEX -#define GREEN GREEN_CHANNEL_INDEX -#define BLUE BLUE_CHANNEL_INDEX - - -/* - * XXX The XF86VidMode extension can block remote clients. - * Unfortunately, there doesn't seem to be a good way to determine if - * we're blocked or not. So, we temporarily plug in an error handler, - * and watch for the XF86VidModeClientNotLocal error code, set a flag - * indicating that we should not use the XF86VidMode extension, and - * then restore the previous error handler. Yuck. - * - * XXX Different versions of XFree86 trigger errors on different - * protocol; older versions trigger an error on - * XF86VidModeGetGammaRampSize(), but newer versions appear to only - * error on XF86VidModeSetGammaRamp(). - */ - -static Bool vidModeBlocked = False; -static int vidModeErrorBase = 0; -static int (*prev_error_handler)(Display *, XErrorEvent *) = NULL; - -static int vidModeErrorHandler(Display *dpy, XErrorEvent *err) -{ - if (err->error_code == (XF86VidModeClientNotLocal + vidModeErrorBase)) { - vidModeBlocked = True; - } else { - if (prev_error_handler) prev_error_handler(dpy, err); - } - - return 1; -} - NvCtrlVidModeAttributes * NvCtrlInitVidModeAttributes(NvCtrlAttributePrivateHandle *h) { NvCtrlVidModeAttributes *vm = NULL; - int ret, event, i; - + int event, error, size, permissions = 0; + Bool ret; /* Check parameters */ if (!h || !h->dpy || h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN) { goto failed; } - ret = XF86VidModeQueryExtension(h->dpy, &event, &vidModeErrorBase); - if (ret != True) goto failed; + ret = XF86VidModeQueryExtension(h->dpy, &event, &error); + if (!ret) goto failed; - vm = malloc(sizeof(NvCtrlVidModeAttributes)); + vm = calloc(1, sizeof(NvCtrlVidModeAttributes)); ret = XF86VidModeQueryVersion(h->dpy, &(vm->major_version), &(vm->minor_version)); - if (ret != True) goto failed; + if (!ret) goto failed; - if (vm->major_version < VM_MINMAJOR || (vm->major_version == VM_MINMAJOR && vm->minor_version < VM_MINMINOR)) { + if (vm->major_version < VM_MINMAJOR || + (vm->major_version == VM_MINMAJOR && vm->minor_version < VM_MINMINOR)) { nv_warning_msg("The version of the XF86VidMode extension present " "on this display (%d.%d) does not support updating " "gamma ramps. If you'd like to be able to adjust " "gamma ramps, please update your X server such that " "the version of the XF86VidMode extension is %d.%d " - "or higher.", vm->major_version, vm->minor_version, VM_MINMAJOR, VM_MINMINOR); + "or higher.", vm->major_version, vm->minor_version, + VM_MINMAJOR, VM_MINMINOR); goto failed; } - /* - * XXX setup an error handler to catch any errors caused by the - * VidMode extension blocking remote clients; we'll restore the - * original error handler below - */ - - prev_error_handler = XSetErrorHandler(vidModeErrorHandler); - - ret = XF86VidModeGetGammaRampSize(h->dpy, h->target_id, &vm->n); - - /* check if XF86VidModeGetGammaRampSize was blocked */ - - if (vidModeBlocked) { - goto blocked; + ret = XF86VidModeGetPermissions(h->dpy, h->target_id, &permissions); + + if (!ret) { + goto failed; } - - if (ret != True) goto failed; - - vm->lut[RED] = malloc(sizeof(unsigned short) * vm->n); - vm->lut[GREEN] = malloc(sizeof(unsigned short) * vm->n); - vm->lut[BLUE] = malloc(sizeof(unsigned short) * vm->n); - - ret = XF86VidModeGetGammaRamp(h->dpy, h->target_id, vm->n, vm->lut[RED], - vm->lut[GREEN], vm->lut[BLUE]); - - /* check if XF86VidModeGetGammaRamp was blocked */ - if (vidModeBlocked) { - goto blocked; + if (((permissions & XF86VM_READ_PERMISSION) == 0) || + ((permissions & XF86VM_WRITE_PERMISSION) == 0)) { + goto failed; } - if (ret != True) goto failed; - - /* - * XXX Currently, XF86VidModeSetGammaRamp() is the only other - * XF86VidMode protocol we send, and depending on the XFree86 - * version, it may induce an X error for remote clients. So, try - * sending it here to see if we get an error (yes, this is the - * data we just retrieved above from XF86VidModeGetGammaRamp). - * It's terrible that we have to do this. - */ - - ret = XF86VidModeSetGammaRamp(h->dpy, h->target_id, vm->n, - vm->lut[RED], - vm->lut[GREEN], - vm->lut[BLUE]); - /* - * sync the protocol stream to make sure we process any X error - * before continuing - */ - - XSync(h->dpy, False); - /* check if XF86VidModeSetGammaRamp was blocked */ - - if (vidModeBlocked) { - goto blocked; - } - - /* finally, restore the original error handler */ - - XSetErrorHandler(prev_error_handler); - - /* - * XXX can we initialize this to anything based on the current - * ramps? - */ - - for (i = RED; i <= BLUE; i++) { - vm->brightness[i] = BRIGHTNESS_DEFAULT; - vm->contrast[i] = CONTRAST_DEFAULT; - vm->gamma[i] = GAMMA_DEFAULT; + ret = XF86VidModeGetGammaRampSize(h->dpy, h->target_id, &size); + + if (!ret) goto failed; + + vm->lut[RED_CHANNEL_INDEX] = malloc(sizeof(unsigned short) * size); + vm->lut[GREEN_CHANNEL_INDEX] = malloc(sizeof(unsigned short) * size); + vm->lut[BLUE_CHANNEL_INDEX] = malloc(sizeof(unsigned short) * size); + + if ((vm->lut[RED_CHANNEL_INDEX] == NULL) || + (vm->lut[GREEN_CHANNEL_INDEX] == NULL) || + (vm->lut[BLUE_CHANNEL_INDEX] == NULL)) { + goto failed; } - - /* take log2 of vm->n to find the sigbits */ - - for (i = 0; ((vm->n >> i) > 0); i++); - vm->sigbits = i - 1; - - return (vm); - blocked: - - nv_warning_msg("The VidMode extension is blocked for remote " - "clients. To allow remote VidMode clients, the " - "XF86Config option \"AllowNonLocalXvidtune\" must be " - "set in the ServerFlags section of the XF86Config " - "file."); - - /* fall through */ + vm->gammaRampSize = size; - failed: - if (vm) free(vm); + ret = XF86VidModeGetGammaRamp(h->dpy, h->target_id, size, + vm->lut[RED_CHANNEL_INDEX], + vm->lut[GREEN_CHANNEL_INDEX], + vm->lut[BLUE_CHANNEL_INDEX]); + if (!ret) goto failed; + + NvCtrlInitGammaInputStruct(&vm->gammaInput); - /* restore the original error handler, if we overrode it */ + return vm; - if (prev_error_handler) { - XSetErrorHandler(prev_error_handler); - prev_error_handler = NULL; + failed: + if (vm) { + free(vm->lut[RED_CHANNEL_INDEX]); + free(vm->lut[GREEN_CHANNEL_INDEX]); + free(vm->lut[BLUE_CHANNEL_INDEX]); + free(vm); } return NULL; @@ -203,22 +111,19 @@ NvCtrlInitVidModeAttributes(NvCtrlAttributePrivateHandle *h) } /* NvCtrlInitVidModeAttributes() */ -ReturnStatus NvCtrlGetColorAttributes(NvCtrlAttributeHandle *handle, - float contrast[3], - float brightness[3], - float gamma[3]) +ReturnStatus NvCtrlVidModeGetColorAttributes(NvCtrlAttributePrivateHandle *h, + float contrast[3], + float brightness[3], + float gamma[3]) { int i; - NvCtrlAttributePrivateHandle *h; - - h = (NvCtrlAttributePrivateHandle *) handle; if (!h->vm) return NvCtrlMissingExtension; - for (i = RED; i <= BLUE; i++) { - contrast[i] = h->vm->contrast[i]; - brightness[i] = h->vm->brightness[i]; - gamma[i] = h->vm->gamma[i]; + for (i = FIRST_COLOR_CHANNEL; i <= LAST_COLOR_CHANNEL; i++) { + contrast[i] = h->vm->gammaInput.contrast[i]; + brightness[i] = h->vm->gammaInput.brightness[i]; + gamma[i] = h->vm->gammaInput.gamma[i]; } return NvCtrlSuccess; @@ -245,172 +150,62 @@ ReturnStatus NvCtrlGetColorAttributes(NvCtrlAttributeHandle *handle, * it to the X server. */ -ReturnStatus NvCtrlSetColorAttributes(NvCtrlAttributeHandle *handle, - float c[3], - float b[3], - float g[3], - unsigned int bitmask) +ReturnStatus NvCtrlVidModeSetColorAttributes(NvCtrlAttributePrivateHandle *h, + float c[3], + float b[3], + float g[3], + unsigned int bitmask) { - int i, ch; Bool ret; - - NvCtrlAttributePrivateHandle *h; - h = (NvCtrlAttributePrivateHandle *) handle; - - /* Check parameters */ if (!h || !h->dpy || h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN) { return NvCtrlBadHandle; } - if (!h->vm) return NvCtrlMissingExtension; - /* clamp input, but only the input specified in the bitmask */ - - for (ch = RED; ch <= BLUE; ch++) { - if (bitmask & (1 << ch)) { - if (bitmask & CONTRAST_VALUE) { - if (c[ch] > CONTRAST_MAX) c[ch] = CONTRAST_MAX; - if (c[ch] < CONTRAST_MIN) c[ch] = CONTRAST_MIN; - } - if (bitmask & BRIGHTNESS_VALUE) { - if (b[ch] > BRIGHTNESS_MAX) b[ch] = BRIGHTNESS_MAX; - if (b[ch] < BRIGHTNESS_MIN) b[ch] = BRIGHTNESS_MIN; - } - if (bitmask & GAMMA_VALUE) { - if (g[ch] > GAMMA_MAX) g[ch] = GAMMA_MAX; - if (g[ch] < GAMMA_MIN) g[ch] = GAMMA_MIN; - } - } + if (!h->vm) { + return NvCtrlMissingExtension; } - - /* assign specified values */ - if (bitmask & CONTRAST_VALUE) { - if (bitmask & RED_CHANNEL) h->vm->contrast[RED] = c[RED]; - if (bitmask & GREEN_CHANNEL) h->vm->contrast[GREEN] = c[GREEN]; - if (bitmask & BLUE_CHANNEL) h->vm->contrast[BLUE] = c[BLUE]; - } + NvCtrlAssignGammaInput(&h->vm->gammaInput, c, b, g, bitmask); - if (bitmask & BRIGHTNESS_VALUE) { - if (bitmask & RED_CHANNEL) h->vm->brightness[RED] = b[RED]; - if (bitmask & GREEN_CHANNEL) h->vm->brightness[GREEN] = b[GREEN]; - if (bitmask & BLUE_CHANNEL) h->vm->brightness[BLUE] = b[BLUE]; - } - - if (bitmask & GAMMA_VALUE) { - if (bitmask & RED_CHANNEL) h->vm->gamma[RED] = g[RED]; - if (bitmask & GREEN_CHANNEL) h->vm->gamma[GREEN] = g[GREEN]; - if (bitmask & BLUE_CHANNEL) h->vm->gamma[BLUE] = g[BLUE]; - } + NvCtrlUpdateGammaRamp(&h->vm->gammaInput, + h->vm->gammaRampSize, + h->vm->lut, + bitmask); - for (ch = RED; ch <= BLUE; ch++) { - if ( !(bitmask & (1 << ch))) continue; /* don't update this channel */ - for (i = 0; i < h->vm->n; i++) { - h->vm->lut[ch][i] = computeVal(h, i, h->vm->contrast[ch], - h->vm->brightness[ch], - h->vm->gamma[ch]); - } - } - - ret = XF86VidModeSetGammaRamp(h->dpy, h->target_id, h->vm->n, - h->vm->lut[RED], - h->vm->lut[GREEN], - h->vm->lut[BLUE]); - - if (ret != True) return NvCtrlError; + ret = XF86VidModeSetGammaRamp(h->dpy, h->target_id, h->vm->gammaRampSize, + h->vm->lut[RED_CHANNEL_INDEX], + h->vm->lut[GREEN_CHANNEL_INDEX], + h->vm->lut[BLUE_CHANNEL_INDEX]); - return NvCtrlSuccess; - -} /* NvCtrlSetColorAttribute() */ + return ret ? NvCtrlSuccess : NvCtrlError; +} -ReturnStatus NvCtrlGetColorRamp(NvCtrlAttributeHandle *handle, - unsigned int channel, - unsigned short **lut, - int *n) +ReturnStatus NvCtrlVidModeGetColorRamp(NvCtrlAttributePrivateHandle *h, + unsigned int channel, + unsigned short **lut, + int *n) { - NvCtrlAttributePrivateHandle *h; - - h = (NvCtrlAttributePrivateHandle *) handle; - - /* Check parameters */ if (!h || !h->dpy || h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN) { return NvCtrlBadHandle; } - if (!h->vm) return NvCtrlMissingExtension; + if (!h->vm) { + return NvCtrlMissingExtension; + } + + *n = h->vm->gammaRampSize; - *n = h->vm->n; - switch (channel) { - case RED_CHANNEL: *lut = h->vm->lut[RED]; break; - case GREEN_CHANNEL: *lut = h->vm->lut[GREEN]; break; - case BLUE_CHANNEL: *lut = h->vm->lut[BLUE]; break; + case RED_CHANNEL: *lut = h->vm->lut[RED_CHANNEL_INDEX]; break; + case GREEN_CHANNEL: *lut = h->vm->lut[GREEN_CHANNEL_INDEX]; break; + case BLUE_CHANNEL: *lut = h->vm->lut[BLUE_CHANNEL_INDEX]; break; default: return NvCtrlBadArgument; } return NvCtrlSuccess; } - -/* - * computeVal() - compute the LUT entry given its index, and the - * contrast, brightness, and gamma. - */ -static unsigned short computeVal(NvCtrlAttributePrivateHandle *h, - int i, float c, float b, float g) -{ - double j, half, scale; - int shift, val, num; - - num = h->vm->n - 1; - shift = 16 - h->vm->sigbits; - - scale = (double) num / 3.0; /* how much brightness and contrast - affect the value */ - j = (double) i; - - /* contrast */ - - c *= scale; - - if (c > 0.0) { - half = ((double) num / 2.0) - 1.0; - j -= half; - j *= half / (half - c); - j += half; - } else { - half = (double) num / 2.0; - j -= half; - j *= (half + c) / half; - j += half; - } - - if (j < 0.0) j = 0.0; - - /* gamma */ - - g = 1.0 / (double) g; - - if (g == 1.0) { - val = (int) j; - } else { - val = (int) (pow (j / (double)num, g) * (double)num + 0.5); - } - - /* brightness */ - - b *= scale; - - val += (int)b; - if (val > num) val = num; - if (val < 0) val = 0; - - val <<= shift; - return (unsigned short) val; - -} /* computeVal() */ - - /* * Get XF86 Video Mode String Attribute Values */ diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c b/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c index 99aa756..c9c5eb9 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c +++ b/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c @@ -62,6 +62,21 @@ typedef struct __libXrandrInfoRec { void (* XRRSelectInput) (Display *dpy, Window window, int mask); + /* gamma-related entry points */ + + XRRCrtcGamma *(* XRRGetCrtcGamma)(Display *dpy, RRCrtc crtc); + + void (* XRRSetCrtcGamma)(Display *dpy, RRCrtc crtc, XRRCrtcGamma *gamma); + + void (* XRRFreeGamma)(XRRCrtcGamma *gamma); + + /* output and crtc querying functions */ + + XRROutputInfo *(* XRRGetOutputInfo) + (Display *dpy, XRRScreenResources *resources, RROutput output); + + void (* XRRFreeOutputInfo)(XRROutputInfo *outputInfo); + } __libXrandrInfo; static __libXrandrInfo *__libXrandr = NULL; @@ -116,6 +131,24 @@ static Bool open_libxrandr(void) NV_DLSYM(__libXrandr->handle, "XRRSelectInput"); if ((error_str = dlerror()) != NULL) goto fail; + /* the gamma entry points are optional: we don't check dlerror(3) */ + + __libXrandr->XRRGetCrtcGamma = + NV_DLSYM(__libXrandr->handle, "XRRGetCrtcGamma"); + + __libXrandr->XRRSetCrtcGamma = + NV_DLSYM(__libXrandr->handle, "XRRSetCrtcGamma"); + + __libXrandr->XRRFreeGamma = + NV_DLSYM(__libXrandr->handle, "XRRFreeGamma"); + + /* the output/crtc functions are optional: we don't check dlerror(3) */ + + __libXrandr->XRRGetOutputInfo = + NV_DLSYM(__libXrandr->handle, "XRRGetOutputInfo"); + + __libXrandr->XRRFreeOutputInfo = + NV_DLSYM(__libXrandr->handle, "XRRFreeOutputInfo"); /* Up the ref count */ __libXrandr->ref_count++; @@ -165,7 +198,78 @@ static void close_libxrandr(void) } /* close_libxrandr() */ +static RROutput GetRandRCrtcForGamma(NvCtrlAttributePrivateHandle *h, + NvCtrlXrandrAttributes *xrandr) +{ + int output; + RRCrtc crtc; + ReturnStatus status; + XRROutputInfo *pOutputInfo; + XRRScreenResources screenResources; + + /* finding the RandR output only makes sense for display targets */ + + if (h->target_type != NV_CTRL_TARGET_TYPE_DISPLAY) { + return None; + } + + /* if the server does not support gamma manipulation, return */ + + if (!xrandr->gammaAvailable) { + return None; + } + + /* + * if the libXrandr library does not provide the needed entry + * points, return + */ + + if ((__libXrandr->XRRGetOutputInfo == NULL) || + (__libXrandr->XRRFreeOutputInfo == NULL)) { + return None; + } + + status = NvCtrlGetAttribute(h, NV_CTRL_DISPLAY_RANDR_OUTPUT_ID, &output); + if (status != NvCtrlSuccess) { + return None; + } + + if (output == 0) { + return None; + } + + if ((__libXrandr->XRRGetOutputInfo == NULL) || + (__libXrandr->XRRFreeOutputInfo == NULL)) { + return None; + } + + /* + * XXX Normally, an X client should query XRRGetScreenResources(3) + * to get an appropriately initialized XRRScreenResources data + * structure. However, XRRGetOutputInfo(3) only uses + * XRRScreenResources to get the configTimestamp for the protocol + * request, and XRRGetScreenResources(3) can be an expensive + * request (triggers reprobing all display hardware, etc). So, + * just zero-initialize XRRScreenResources and pass it into + * XRRGetOutputInfo(). + */ + memset(&screenResources, 0, sizeof(screenResources)); + screenResources.configTimestamp = CurrentTime; + + pOutputInfo = + __libXrandr->XRRGetOutputInfo(h->dpy, &screenResources, output); + + if (pOutputInfo == NULL) { + return None; + } + + crtc = pOutputInfo->crtc; + + __libXrandr->XRRFreeOutputInfo(pOutputInfo); + + return crtc; +} /****************************************************************************** * @@ -180,10 +284,15 @@ NvCtrlInitXrandrAttributes (NvCtrlAttributePrivateHandle *h) NvCtrlXrandrAttributes * xrandr = NULL; /* Check parameters */ - if ( !h || !h->dpy || h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN ) { + if (!h || !h->dpy) { goto fail; } + /* allow RandR on X_SCREEN and DISPLAY target types */ + if ((h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN) && + (h->target_type != NV_CTRL_TARGET_TYPE_DISPLAY)) { + goto fail; + } /* Open libXrandr.so.2 */ if ( !open_libxrandr() ) { @@ -208,16 +317,41 @@ NvCtrlInitXrandrAttributes (NvCtrlAttributePrivateHandle *h) } /* Verify server version of the XRandR extension */ - if ( !__libXrandr->XRRQueryVersion(h->dpy, &(xrandr->major_version), &(xrandr->minor_version)) || + if ( !__libXrandr->XRRQueryVersion(h->dpy, &(xrandr->major_version), + &(xrandr->minor_version)) || ((xrandr->major_version < MIN_RANDR_MAJOR) || ((xrandr->major_version == MIN_RANDR_MAJOR) && (xrandr->minor_version < MIN_RANDR_MINOR)))) { goto fail; } - /* Register to receive XRandR events */ - __libXrandr->XRRSelectInput(h->dpy, RootWindow(h->dpy, h->target_id), - RRScreenChangeNotifyMask); + /* Register to receive XRandR events if this is an X screen */ + if (h->target_type == NV_CTRL_TARGET_TYPE_X_SCREEN) { + __libXrandr->XRRSelectInput(h->dpy, RootWindow(h->dpy, h->target_id), + RRScreenChangeNotifyMask); + } + + /* check if this configuration supports gamma manipulation */ + + xrandr->gammaAvailable = + ((xrandr->major_version > 1) || + ((xrandr->major_version == 1) && (xrandr->minor_version >= 2))) && + (__libXrandr->XRRSetCrtcGamma != NULL); + + + /* + * get the RandR CRTC and gamma; the mapping of NV-CONTROL display + * device target to RandR CRTC could change at each modeset, so + * the frontend needs to reallocate this handle after each modeset + */ + + xrandr->gammaCrtc = GetRandRCrtcForGamma(h, xrandr); + + if ((xrandr->gammaCrtc != None) && (__libXrandr->XRRGetCrtcGamma != NULL)) { + xrandr->pGammaRamp = + __libXrandr->XRRGetCrtcGamma(h->dpy, xrandr->gammaCrtc); + NvCtrlInitGammaInputStruct(&xrandr->gammaInput); + } return xrandr; @@ -246,6 +380,11 @@ NvCtrlXrandrAttributesClose (NvCtrlAttributePrivateHandle *h) return; } + if ((h->xrandr->pGammaRamp != NULL) && + (__libXrandr->XRRFreeGamma != NULL)) { + __libXrandr->XRRFreeGamma(h->xrandr->pGammaRamp); + } + close_libxrandr(); free(h->xrandr); @@ -284,3 +423,123 @@ NvCtrlXrandrGetStringAttribute (NvCtrlAttributePrivateHandle *h, return NvCtrlNoAttribute; } /* NvCtrlXrandrGetStringAttribute() */ + + +ReturnStatus +NvCtrlXrandrGetAttribute(NvCtrlAttributePrivateHandle *h, + unsigned int display_mask, int attr, int64_t *val) +{ + if (!h || !h->xrandr) { + return NvCtrlBadHandle; + } + + if (attr != NV_CTRL_ATTR_RANDR_GAMMA_AVAILABLE) { + return NvCtrlNoAttribute; + } + + if (h->target_type == NV_CTRL_TARGET_TYPE_X_SCREEN) { + *val = h->xrandr->gammaAvailable; + } else { + *val = (h->xrandr->pGammaRamp != NULL); + } + + return NvCtrlSuccess; +} + +ReturnStatus NvCtrlXrandrGetColorAttributes(NvCtrlAttributePrivateHandle *h, + float contrast[3], + float brightness[3], + float gamma[3]) +{ + int i; + + if (!h->xrandr) return NvCtrlMissingExtension; + + for (i = FIRST_COLOR_CHANNEL; i <= LAST_COLOR_CHANNEL; i++) { + contrast[i] = h->xrandr->gammaInput.contrast[i]; + brightness[i] = h->xrandr->gammaInput.brightness[i]; + gamma[i] = h->xrandr->gammaInput.gamma[i]; + } + + return NvCtrlSuccess; + +} + +ReturnStatus NvCtrlXrandrSetColorAttributes(NvCtrlAttributePrivateHandle *h, + float c[3], + float b[3], + float g[3], + unsigned int bitmask) +{ + unsigned short *tmpGammaArray[3]; + + if (!h || !h->dpy) { + return NvCtrlBadHandle; + } + + if (!h->xrandr) { + return NvCtrlMissingExtension; + } + + if (h->xrandr->pGammaRamp == NULL) { + return NvCtrlMissingExtension; + } + + if (h->xrandr->gammaCrtc == None) { + return NvCtrlMissingExtension; + } + + NvCtrlAssignGammaInput(&h->xrandr->gammaInput, c, b, g, bitmask); + + tmpGammaArray[RED_CHANNEL_INDEX] = h->xrandr->pGammaRamp->red; + tmpGammaArray[GREEN_CHANNEL_INDEX] = h->xrandr->pGammaRamp->green; + tmpGammaArray[BLUE_CHANNEL_INDEX] = h->xrandr->pGammaRamp->blue; + + NvCtrlUpdateGammaRamp(&h->xrandr->gammaInput, + h->xrandr->pGammaRamp->size, + tmpGammaArray, + bitmask); + + __libXrandr->XRRSetCrtcGamma(h->dpy, h->xrandr->gammaCrtc, + h->xrandr->pGammaRamp); + + XFlush(h->dpy); + + return NvCtrlSuccess; +} + +ReturnStatus NvCtrlXrandrGetColorRamp(NvCtrlAttributePrivateHandle *h, + unsigned int channel, + uint16_t **lut, + int *n) +{ + if (!h || !h->dpy) { + return NvCtrlBadHandle; + } + + if (!h->xrandr) { + return NvCtrlMissingExtension; + } + + if (h->xrandr->pGammaRamp == NULL) { + return NvCtrlMissingExtension; + } + + *n = h->xrandr->pGammaRamp->size; + + switch (channel) { + case RED_CHANNEL: + *lut = h->xrandr->pGammaRamp->red; + break; + case GREEN_CHANNEL: + *lut = h->xrandr->pGammaRamp->green; + break; + case BLUE_CHANNEL: + *lut = h->xrandr->pGammaRamp->blue; + break; + default: + return NvCtrlBadArgument; + } + + return NvCtrlSuccess; +} diff --git a/src/parse.c b/src/parse.c index e4112dc..efb0ba4 100644 --- a/src/parse.c +++ b/src/parse.c @@ -305,6 +305,7 @@ AttributeTableEntry attributeTable[] = { { "CurrentMetaModeID", NV_CTRL_CURRENT_METAMODE_ID, N, "The ID of the current MetaMode." }, { "CurrentMetaMode", NV_CTRL_STRING_CURRENT_METAMODE_VERSION_2, S|N, "Controls the current MetaMode." }, { "XineramaInfoOrder", NV_CTRL_STRING_NVIDIA_XINERAMA_INFO_ORDER, S|N, "Controls the nvidiaXineramaInfoOrder." }, + { "RandROutputID", NV_CTRL_DISPLAY_RANDR_OUTPUT_ID, N, "The RandR Output ID that corresponds to the display device." }, /* TV */ { "TVOverScan", NV_CTRL_TV_OVERSCAN, 0, "Adjusts the amount of overscan on the specified display device." }, @@ -367,7 +368,7 @@ AttributeTableEntry attributeTable[] = { * about. */ -#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_FXAA +#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_DISPLAY_RANDR_OUTPUT_ID #warning "Have you forgotten to add a new integer attribute to attributeTable?" #endif @@ -179,6 +179,7 @@ GTK_SRC += gtk+-2.x/ctkframelock.c GTK_SRC += gtk+-2.x/ctkgauge.c GTK_SRC += gtk+-2.x/ctkcurve.c GTK_SRC += gtk+-2.x/ctkcolorcorrection.c +GTK_SRC += gtk+-2.x/ctkcolorcorrectionpage.c GTK_SRC += gtk+-2.x/ctkscale.c GTK_SRC += gtk+-2.x/ctkmultisample.c GTK_SRC += gtk+-2.x/ctkconfig.c @@ -226,6 +227,7 @@ GTK_EXTRA_DIST += gtk+-2.x/ctkframelock.h GTK_EXTRA_DIST += gtk+-2.x/ctkgauge.h GTK_EXTRA_DIST += gtk+-2.x/ctkcurve.h GTK_EXTRA_DIST += gtk+-2.x/ctkcolorcorrection.h +GTK_EXTRA_DIST += gtk+-2.x/ctkcolorcorrectionpage.h GTK_EXTRA_DIST += gtk+-2.x/ctkscale.h GTK_EXTRA_DIST += gtk+-2.x/ctkmultisample.h GTK_EXTRA_DIST += gtk+-2.x/ctkconfig.h diff --git a/src/version.mk b/src/version.mk index c7ccc7a..7753329 100644 --- a/src/version.mk +++ b/src/version.mk @@ -1 +1 @@ -NVIDIA_VERSION = 304.37 +NVIDIA_VERSION = 304.43 @@ -1 +1 @@ -NVIDIA_VERSION = 304.37 +NVIDIA_VERSION = 304.43 |