diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2010-09-28 13:09:37 -0700 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2010-09-28 13:09:37 -0700 |
commit | 98d47fcfbb9dc1ae90e194c101c1370cf715d742 (patch) | |
tree | 80c925a28ffea2642c0ca4bab1439bda9fe1e306 | |
parent | 229313f0e3192855999cae5034e20e4686217bad (diff) |
260.19.04260.19.04
51 files changed, 3422 insertions, 926 deletions
@@ -34,7 +34,6 @@ include utils.mk # assign default values if they are not exported by the caller ############################################################################## - ifndef X_LDFLAGS ifeq ($(TARGET_OS)-$(TARGET_ARCH),Linux-x86_64) X_LDFLAGS = -L/usr/X11R6/lib64 @@ -59,19 +58,20 @@ endif ############################################################################## -# The XF86Config-parser and libXNVCtrl directories may be in one of -# two places: either elsewhere in the driver source tree when building -# nvidia-settings as part of the NVIDIA driver build (in which case, -# XNVCTRL_DIR, XNVCTRL_ARCHIVE, and XCONFIG_PARSER_DIR should be -# defined by the calling makefile), or directly in the source -# directory when building from the nvidia-settings source tarball (in -# which case, the below conditional assignments should be used) +# The XF86Config-parser, libXNVCtrl, and common-utils directories may +# be in one of two places: either elsewhere in the driver source tree +# when building nvidia-settings as part of the NVIDIA driver build (in +# which case, XNVCTRL_DIR, XNVCTRL_ARCHIVE, XCONFIG_PARSER_DIR and +# COMMON_UTILS_DIR should be defined by the calling makefile), or +# directly in the source directory when building from the +# nvidia-settings source tarball (in which case, the below conditional +# assignments should be used) ############################################################################## XNVCTRL_DIR ?= src/libXNVCtrl XNVCTRL_ARCHIVE ?= $(XNVCTRL_DIR)/libXNVCtrl.a XCONFIG_PARSER_DIR ?= src/XF86Config-parser - +COMMON_UTILS_DIR ?= src/common-utils ############################################################################## # assign variables @@ -114,6 +114,8 @@ ifeq ($(MANPAGE_GZIP),1) else MANPAGE = $(MANPAGE_not_gzipped) endif +GEN_MANPAGE_OPTS = $(OUTPUTDIR)/gen-manpage-opts +OPTIONS_1_INC = $(OUTPUTDIR)/options.1.inc # Include all the source lists; dist-files.mk will define SRC include dist-files.mk @@ -121,6 +123,9 @@ include dist-files.mk include $(XCONFIG_PARSER_DIR)/src.mk SRC += $(addprefix $(XCONFIG_PARSER_DIR)/,$(XCONFIG_PARSER_SRC)) +include $(COMMON_UTILS_DIR)/src.mk +SRC += $(addprefix $(COMMON_UTILS_DIR)/,$(COMMON_UTILS_SRC)) + SRC += $(STAMP_C) OBJS = $(call BUILD_OBJECT_LIST,$(SRC)) @@ -132,6 +137,7 @@ CFLAGS += -I $(XCONFIG_PARSER_DIR)/.. CFLAGS += -I src/libXNVCtrlAttributes CFLAGS += -I src/xpm_data CFLAGS += -I src/gtk+-2.x +CFLAGS += -I $(COMMON_UTILS_DIR) CFLAGS += -I $(OUTPUTDIR) $(call BUILD_OBJECT_LIST,$(GTK_SRC)): CFLAGS += $(GTK_CFLAGS) @@ -168,7 +174,8 @@ $(eval $(call DEFINE_STAMP_C_RULE, $(OBJS),$(NVIDIA_SETTINGS_PROGRAM_NAME))) clean clobber: rm -rf $(NVIDIA_SETTINGS) $(MANPAGE) *~ $(STAMP_C) \ - $(OUTPUTDIR)/*.o $(OUTPUTDIR)/*.d + $(OUTPUTDIR)/*.o $(OUTPUTDIR)/*.d \ + $(GEN_MANPAGE_OPTS) $(OPTIONS_1_INC) ############################################################################## @@ -179,12 +186,33 @@ AUTO_TEXT = ".\\\" WARNING: THIS FILE IS AUTO-GENERATED! Edit $< instead." doc: $(MANPAGE) -$(MANPAGE_not_gzipped): doc/nvidia-settings.1.m4 +GEN_MANPAGE_OPTS_SRC = src/gen-manpage-opts.c + +BUILD_MANPAGE_OBJECT_LIST = \ + $(patsubst %.o,%.manpage.o,$(call BUILD_OBJECT_LIST,$(1))) + +GEN_MANPAGE_OPTS_OBJS = \ + $(call BUILD_MANPAGE_OBJECT_LIST,$(GEN_MANPAGE_OPTS_SRC)) + +$(GEN_MANPAGE_OPTS): $(GEN_MANPAGE_OPTS_OBJS) + $(call quiet_cmd,HOST_LINK) $(GEN_MANPAGE_OPTS_OBJS) -o $@ \ + $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_BIN_LDFLAGS) + +# define a rule to build each GEN_MANPAGE_OPTS object file +$(foreach src,$(GEN_MANPAGE_OPTS_SRC),\ + $(eval $(call DEFINE_OBJECT_RULE_WITH_OBJECT_NAME,HOST_CC,$(src),\ + $(call BUILD_MANPAGE_OBJECT_LIST,$(src))))) + +$(OPTIONS_1_INC): $(GEN_MANPAGE_OPTS) + @./$< > $@ + +$(MANPAGE_not_gzipped): doc/nvidia-settings.1.m4 $(OPTIONS_1_INC) $(call quiet_cmd,M4) \ -D__HEADER__=$(AUTO_TEXT) \ -D__BUILD_OS__=$(TARGET_OS) \ -D__VERSION__=$(NVIDIA_VERSION) \ -D__DATE__="`$(DATE) +%F`" \ + -I $(OUTPUTDIR) \ $< > $@ $(MANPAGE_gzipped): $(MANPAGE_not_gzipped) diff --git a/doc/nvidia-settings.1.m4 b/doc/nvidia-settings.1.m4 index c97e8af..1349ccd 100644 --- a/doc/nvidia-settings.1.m4 +++ b/doc/nvidia-settings.1.m4 @@ -1,4 +1,5 @@ changequote([[[, ]]])dnl +define(__OPTIONS__, [[[include([[[options.1.inc]]])dnl]]])dnl dnl Solaris man chokes on three-letter macros. ifelse(__BUILD_OS__,SunOS,[[[define(__URL__,UR)]]],[[[define(__URL__,URL)]]])dnl .\" Copyright (C) 2010 NVIDIA Corporation. @@ -51,166 +52,8 @@ Then, it displays a graphical user interface (GUI) for configuring the current s When .B nvidia\-settings exits, it queries the current settings from the X server and saves them to the configuration file. -.SH OPTIONS -.TP -.B \-v, \-\-version -Print the -.B nvidia\-settings -version and exit. -.TP -.B \-h, \-\-help -Print usage information and exit. -.TP -.BI "\-\-config=" config -Use the configuration file -.I config -rather than the default -.I ~/.nvidia\-settings\-rc -.TP -.BI "\-c, \-\-ctrl\-display=" ctrl-display -Control the specified X display. -If this option is not given, then -.B nvidia\-settings -will control the display specified by -.B \-\-display. -If that is not given, then the -.I $DISPLAY -environment variable is used. -.TP -.B \-n, \-\-no\-config -Do not load the configuration file. -This mode of operation is useful if -.B nvidia\-settings -has difficulties starting due to problems with applying settings in the configuration file. -.TP -.B \-l, \-\-load\-config\-only -Load the configuration file, send the values specified therein to the X server, and exit. -This mode of operation is useful to place in your .xinitrc file, for example. -.TP -.B \-r, \-\-rewrite\-config\-file -Write the current X server configuration to the configuration file, and exit without starting -a graphical user interface. -See the EXAMPLES section. -.TP -.BI "\-V, \-\-verbose=" verbosity -Controls how much information is printed. -By default, the verbosity is -.B errors -and only error messages are printed. -.br - -.I verbosity -can be one of the following values: -.ti +5 -.B errors -- Print errors. -.ti +5 -.B warnings -- Print errors and warnings. -.ti +5 -.B all -- Print errors, warnings, and other information. -.TP -.BI "\-a, \-\-assign=" assign -The -.I assign -argument to the -.B \-\-assign -command line option is of the form: -.nf - - {DISPLAY}/{attribute name}[{display devices}]={value} - -.fi -This assigns the attribute {attribute name} to the value {value} on the X Display {DISPLAY}. -{DISPLAY} follows the usual {host}:{display}.{screen} syntax of the DISPLAY environment variable and is optional; when it is not specified, then it is implied following the same rule as the -.B \-\-ctrl\-display -option. -If the X screen is not specified, then the assignment is made to all X screens. -Note that the '/' is only required when {DISPLAY} is present. -.sp -.br -{DISPLAY} can additionally include a target specification to direct an assignment to something other than an X screen. -A target specification is contained within brackets and consists of a target type name, a colon, and the target id. -The target type name can be one of -.B screen, -.B gpu, -.B framelock, -.B vcs, -.B gvi, -or -.B fan; -the target id is the index into the list of targets (for that target type). -The target specification can be used in {DISPLAY} wherever an X screen can be used, following the syntax {host}:{display}[{target_type}:{target_id}]. -See the output of -.nf - - nvidia-settings --query all - -.fi -for information on which target types can be used with which attributes. -See the output of -.nf - - nvidia-settings -q screens -q gpus -q framelocks -q vcs -q gvis -q fans - -.fi -for lists of targets for each target type. -.br -.sp -The [{display devices}] portion is also optional; if it is not specified, then the attribute is assigned to all display devices. -.br -.sp -Some examples: -.nf - - -a FSAA=5 - -a localhost:0.0/DigitalVibrance[CRT-0]=0 - --assign="SyncToVBlank=1" - -a [gpu:0]/DigitalVibrance[DFP-1]=63 - -.fi -.TP -.BI "\-q, \-\-query=" query -The -.I query -argument to the -.B \-\-query -command line option is of the form: -.nf - - {DISPLAY}/{attribute name}[{display devices}] - -.fi -This queries the current value of the attribute {attribute name} on the X Display {DISPLAY}. -The syntax is the same as that for the -.B \-\-assign -option, without -.B ={value}. -Specify -.B \-q screens, -.B \-q gpus, -.B \-q framelocks, -.B \-q vcs, -.B \-q gvis, -or -.B \-q fans -to query a list of X screens, GPUs, Frame Lock devices, Visual Computing Systems, SDI Input Devices, or fans, respectively, that are present on the X Display {DISPLAY}. -Specify -.B \-q all -to query all attributes. -.TP -.B \-t, \-\-terse -When querying attribute values with the '--query' command line option, only print the current value, rather than the more verbose description of the attribute, its valid values, and its current value. -.TP -.B \-d, \-\-display\-device\-string -When printing attribute values in response to the '--query' option, if the attribute value is a display device mask, print the value as a list of display devices (e.g., "CRT-0, DFP-0"), rather than a hexadecimal bit mask (e.g., 0x00010001). -.TP -.B \-g, \-\-glxinfo -Print GLX Information for the X display and exit. -.TP -.B \-e, \-\-describe -Prints information about a particular attribute. Specify 'all' to list the descriptions of all attributes. Specify 'list' to list the attribute names without a descriptions. +dnl Call gen-manpage-opts to generate this section. +__OPTIONS__ .SH "USER GUIDE" .SS Contents 1. Layout of the nvidia\-settings GUI diff --git a/samples/Makefile b/samples/Makefile index 1d5d350..3796158 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -2,7 +2,7 @@ # NV-CONTROL samples: Sample tools for configuring the NVIDIA X driver on Unix # and Linux systems. # -# Copyright (c) 2004-2008 NVIDIA, Corporation +# Copyright (c) 2010 NVIDIA, Corporation # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -24,62 +24,71 @@ # SOFTWARE. # -# Below are variables that users can override, either here or on the -# make commandline -# -# CC = gcc -# CFLAGS = -Wall -# LDFLAGS = -# X11R6_INC_DIR = /usr/X11R6/include -# X11R6_LIB_DIR = /usr/X11R6/lib/ +############################################################################## +# include common variables and functions +############################################################################## -BUILD_OS := $(shell uname) -BUILD_ARCH := $(shell uname -m) +UTILS_MK_DIR ?= .. -ifndef CC - CC = gcc -endif +include $(UTILS_MK_DIR)/utils.mk -ifndef CFLAGS - CFLAGS = -Wall -endif -ifndef LDFLAGS - LDFLAGS = -endif +############################################################################## +# The calling Makefile may export any of the following variables; we +# assign default values if they are not exported by the caller +############################################################################## -ifndef X11R6_INC_DIR - X11R6_INC_DIR = /usr/X11R6/include/ -endif - -ifndef X11R6_LIB_DIR - ifeq ($(BUILD_OS)-$(BUILD_ARCH),Linux-x86_64) - X11R6_LIB_DIR = /usr/X11R6/lib64 +ifndef X_LDFLAGS + ifeq ($(TARGET_OS)-$(TARGET_ARCH),Linux-x86_64) + X_LDFLAGS = -L/usr/X11R6/lib64 else - X11R6_LIB_DIR = /usr/X11R6/lib + X_LDFLAGS = -L/usr/X11R6/lib endif endif -LIBXNVCTRL_DIR = ../src/libXNVCtrl +X_CFLAGS ?= + +LIBXNVCTRL_DIR ?= ../src/libXNVCtrl + +CFLAGS += $(X_CFLAGS) +CFLAGS += -I $(LIBXNVCTRL_DIR) + +LDFLAGS += $(X_LDFLAGS) +LDFLAGS += -L $(LIBXNVCTRL_DIR) +LDFLAGS += -lXNVCtrl -lXext -lX11 + + +############################################################################## +# samples +############################################################################## + +SAMPLE_SOURCES += nv-control-info.c +SAMPLE_SOURCES += nv-control-dvc.c +SAMPLE_SOURCES += nv-control-events.c +SAMPLE_SOURCES += nv-control-dpy.c +SAMPLE_SOURCES += nv-control-targets.c +SAMPLE_SOURCES += nv-control-framelock.c +SAMPLE_SOURCES += nv-control-gvi.c + +############################################################################## +# build rules +############################################################################## -ALL_CFLAGS = $(CFLAGS) -I $(LIBXNVCTRL_DIR) -I $(X11R6_INC_DIR) -ALL_LDFLAGS = $(LDFLAGS) -L $(LIBXNVCTRL_DIR) -L $(X11R6_LIB_DIR) \ - -lXNVCtrl -lXext -lX11 +.PHONY: all clean clobber -SAMPLES = \ - nv-control-info \ - nv-control-dvc \ - nv-control-events \ - nv-control-dpy \ - nv-control-targets \ - nv-control-framelock \ - nv-control-gvi +# define the rule to build each object file +$(foreach src, $(SAMPLE_SOURCES), $(eval $(call DEFINE_OBJECT_RULE,CC,$(src)))) -all: $(SAMPLES) +# define the rule to link each sample app from its corresponding object file +define link_sample_from_object + $$(OUTPUTDIR)/$(1:.c=): $$(call BUILD_OBJECT_LIST,$(1)) + $$(call quiet_cmd,LINK) $$(CFLAGS) -o $$@ $$< $$(LDFLAGS) $$(BIN_LDFLAGS) + all:: $$(OUTPUTDIR)/$(1:.c=) + SAMPLES += $$(OUTPUTDIR)/$(1:.c=) +endef -% : %.c - $(CC) $(ALL_CFLAGS) $< -o $@ $(ALL_LDFLAGS) +$(foreach sample,$(SAMPLE_SOURCES),$(eval $(call link_sample_from_object,$(sample)))) -clean: - rm -rf *.o *~ $(SAMPLES) +clean clobber: + rm -rf *~ $(OUTPUTDIR)/*.o $(OUTPUTDIR)/*.d $(SAMPLES) diff --git a/samples/README b/samples/README index 750f115..4709166 100644 --- a/samples/README +++ b/samples/README @@ -2,7 +2,7 @@ NV-CONTROL X Extension Samples The `nvidia-settings` application is fairly involved, and is not the easiest source code to read through for someone interested in -learning how to use the NV-CONTROL. +learning how to use the NV-CONTROL X extension. The applications in this directory are trivial examples demonstrating how to use the NV-CONTROL X extension. For more thorough @@ -12,24 +12,29 @@ source package). Sample applications: - nv-control-info: demonstrates how to query for extension - presense, basic information. + nv-control-info: Demonstrates how to query for extension + presence and basic information. - nv-control-dvc: demonstrates how to query and assign an - integer attribute (NV_CTRL_DIGITAL_VIBRANCE); also - shows how to handle multiple display devices. + nv-control-dvc: Demonstrates how to query and assign an + integer attribute (NV_CTRL_DIGITAL_VIBRANCE); also + shows how to handle multiple display devices. - nv-control-events: demonstrates how to register to receive and - interpret NV-CONTROL events. + nv-control-events: Demonstrates how to register to receive and + interpret NV-CONTROL events. - nv-control-dpy: demonstrates how to configure display devices - using the NV-CONTROL X extension. + nv-control-dpy: Demonstrates how to configure display devices + using the NV-CONTROL X extension. - nv-control-targets: demonstrates how to query various attributes - from varying target types (GPUs, X Screens, - Frame Lock Boards) using the XNVCTRL target - functions. + nv-control-targets: Demonstrates how to query various attributes + from varying target types (GPUs, X Screens, + Frame Lock Boards) using the XNVCTRL target + functions. - nv-control-framelock: demonstrates how to query frame lock related + nv-control-framelock: Demonstrates how to query frame lock related attributes. Also demonstrates how to enable/ disable frame lock. + + nv-control-gvi: Demonstrates how to interact with the Graphics-to- + Video-In (GVI) capabilities of a GVI target via + NV-CONTROL. + diff --git a/samples/nv-control-gvi.c b/samples/nv-control-gvi.c index 8bc988b..6e0a4de 100644 --- a/samples/nv-control-gvi.c +++ b/samples/nv-control-gvi.c @@ -38,18 +38,22 @@ #include "NVCtrlLib.h" +/* Used to stringify NV_CTRL_XXX #defines */ + +#define ADD_NVCTRL_CASE(FMT) \ +case (FMT): \ + return #FMT; + + /* * Decode SDI input value returned. */ char *SyncTypeName(int value) { switch (value) { - case NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_HD: - return "NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_HD"; - case NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_SD: - return "NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_SD"; - case NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_NONE: - return "NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_NONE"; + ADD_NVCTRL_CASE(NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_HD); + ADD_NVCTRL_CASE(NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_SD); + ADD_NVCTRL_CASE(NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_NONE); default: return "Invalid Value"; } @@ -59,11 +63,6 @@ char *SyncTypeName(int value) * Decode provided signal format. */ -#define ADD_NVCTRL_CASE(FMT) \ -case (FMT): \ - return #FMT; - - char *VideoFormatName(int value) { switch(value) { @@ -663,6 +662,7 @@ void do_listconfig(Display *dpy, int gvi) unsigned int fmt_list = fmts[i]; unsigned int fmt_bit; unsigned int fmt; + unsigned int fmt_flags; unsigned int bpcs; unsigned int bpc_bit; @@ -678,7 +678,29 @@ void do_listconfig(Display *dpy, int gvi) fmt_list &= (~fmt_bit); fmt = ffs(fmt_bit) - 1 + (32*i); - printf("\n%s:\n", VideoFormatName(fmt)); + printf("\n%s", VideoFormatName(fmt)); + ret = XNVCTRLQueryTargetAttribute(dpy, + NV_CTRL_TARGET_TYPE_GVI, + gvi, + fmt, // display_mask + NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS, + (int *)&fmt_flags); + if (!ret) { + printf(" - Failed to query flag bits for video format for " + "GVI %d.\n", gvi); + } else if (fmt_flags == NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_NONE) { + printf(" (No flags set): \n"); + } else { + printf(" (Flags:"); + printf("%c", (fmt_flags & NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_INTERLACED) ? 'I' : '_'); + printf("%c", (fmt_flags & NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_PROGRESSIVE) ? 'P' : '_'); + printf("%c", (fmt_flags & NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_PSF) ? 'F' : '_'); + printf("%c", (fmt_flags & NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_A) ? 'A' : '_'); + printf("%c", (fmt_flags & NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_B) ? 'B' : '_'); + printf("%c", (fmt_flags & NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_1080P_NO_12BPC) ? 'N' : '_'); + printf("):\n"); + } + // Set the video format XNVCTRLSetTargetAttribute(dpy, diff --git a/samples/src.mk b/samples/src.mk index 930b684..e76f2ba 100644 --- a/samples/src.mk +++ b/samples/src.mk @@ -4,7 +4,6 @@ SAMPLES_SRC += -SAMPLES_EXTRA_DIST += Makefile SAMPLES_EXTRA_DIST += README SAMPLES_EXTRA_DIST += nv-control-dvc.c SAMPLES_EXTRA_DIST += nv-control-dpy.c diff --git a/src/command-line.c b/src/command-line.c index 7aa1452..8fe3843 100644 --- a/src/command-line.c +++ b/src/command-line.c @@ -30,7 +30,7 @@ #include <stdio.h> #include <ctype.h> -#include "command-line.h" +#include "option-table.h" #include "query-assign.h" #include "msg.h" #include "nvgetopt.h" @@ -39,13 +39,8 @@ #include "NvCtrlAttributes.h" -#define TAB " " -#define BIGTAB " " - /* local prototypes */ -static void print_assign_help(void); -static void print_query_help(void); static void print_attribute_help(char *attr); static void print_help(void); static char *nvstrcat(const char *str, ...); @@ -71,188 +66,15 @@ static void print_version(void) nv_msg(TAB, "The NVIDIA X Server Settings tool."); nv_msg(NULL, ""); nv_msg(TAB, "This program is used to configure the " - "NVIDIA Linux graphics driver."); + "NVIDIA Linux graphics driver."); + nv_msg(TAB, "For more detail, please see the nvidia-settings(1) " + "man page."); nv_msg(NULL, ""); nv_msg(TAB, "Copyright (C) 2004 - 2010 NVIDIA Corporation."); nv_msg(NULL, ""); } /* print_version() */ - -/* - * Options table; the fields are: - * - * name - this is the long option name - * - * shortname - this is the one character short option name - * - * flags - bitmask; possible values are NVGETOPT_HAS_ARGUMENT and - * NVGETOPT_IS_BOOLEAN - * - * description function - function to call to display description - * through nv_msg() - * - * description - text for use by print_help() to describe the option - */ - -#define CONFIG_FILE_OPTION 1 - -static const NVGetoptOption __options[] = { - { "version", 'v', 0, NULL, - "Print the nvidia-settings version and exit." }, - - { "help", 'h', 0, NULL, - "Print usage information and exit." }, - - { "config", CONFIG_FILE_OPTION, NVGETOPT_HAS_ARGUMENT, NULL, - "Use the configuration file [CONFIG] rather than the " - "default " DEFAULT_RC_FILE }, - - { "ctrl-display", 'c', NVGETOPT_HAS_ARGUMENT, NULL, - "Control the specified X display. If this option is not given, then " - "nvidia-settings will control the display specifed by '--display'. If " - "that is not given, then the $DISPLAY environment variable is used." }, - - { "load-config-only", 'l', 0, NULL, - "Load the configuration file, send the values specified therein to " - "the X server, and exit. This mode of operation is useful to place " - "in your .xinitrc file, for example." }, - - { "no-config", 'n', 0, NULL, - "Do not load the configuration file. This mode of operation is useful " - "if nvidia-settings has difficulties starting due to problems with " - "applying settings in the configuration file." }, - - { "rewrite-config-file", 'r', 0, NULL, - "Write the X server configuration to the configuration file, and exit, " - "without starting the graphical user interface." }, - - { "verbose", 'V', NVGETOPT_HAS_ARGUMENT|NVGETOPT_ARGUMENT_IS_OPTIONAL, NULL, - "Controls how much information is printed. Valid values are 'errors' " - "(print error messages), 'warnings' (print error and warning messages), " - "and 'all' (print error, warning and other informational messages). By " - "default, only errors are printed." }, - - { "assign", 'a', NVGETOPT_HAS_ARGUMENT, print_assign_help, NULL }, - - { "query", 'q', NVGETOPT_HAS_ARGUMENT, print_query_help, NULL }, - - { "terse", 't', 0, NULL, - "When querying attribute values with the '--query' commandline option, " - "only print the current value, rather than the more verbose description " - "of the attribute, its valid values, and its current value." }, - - { "display-device-string", 'd', 0, NULL, - "When printing attribute values in response to the '--query' option, " - "if the attribute value is a display device mask, print the value " - "as a list of display devices (e.g., \"CRT-0, DFP-0\"), rather than " - "a hexidecimal bitmask (e.g., 0x00010001)." }, - - { "glxinfo", 'g', 0, NULL, - "Print GLX Information for the X display and exit." }, - - { "describe", 'e', NVGETOPT_HAS_ARGUMENT, NULL, - "Prints information about a particular attribute. Specify 'all' to " - "list the descriptions of all attributes. Specify 'list' to list the " - "attribute names without a descriptions." }, - - { NULL, 0, 0, 0 }, -}; - - - -/* - * print_assign_help() - print help information for the assign option. - */ - -static void print_assign_help(void) -{ - nv_msg(BIGTAB, "The ASSIGN argument to the '--assign' commandline option " - "is of the form:"); - - nv_msg(NULL, ""); - - nv_msg(BIGTAB TAB, "{DISPLAY}/{attribute name}[{display devices}]" - "={value}"); - - nv_msg(NULL, ""); - - nv_msg(BIGTAB, "This assigns the attribute {attribute name} to the value " - "{value} on the X Display {DISPLAY}. {DISPLAY} follows the usual " - "{host}:{display}.{screen} syntax of the DISPLAY environment " - "variable and is optional; when it is not specified, then it is " - "implied following the same rule as the --ctrl-display option. " - "If the X screen is not specified, then the assignment is made to " - "all X screens. Note that the '/' is only required when {DISPLAY} " - "is present."); - - nv_msg(NULL, ""); - - nv_msg(BIGTAB, "{DISPLAY} can additionally include a target " - "specification to direct an assignment to something other than " - "an X screen. A target specification is contained within brackets " - "and consists of a target type name, a colon, and the " - "target id. The target type name can be one of \"screen\", " - "\"gpu\", \"framelock\", \"vcs\", \"gvi\", or \"fan\"; the target " - "id is the index into the " - "list of targets (for that target type). The target specification " - "can be used in {DISPLAY} wherever an X screen can be used, " - "following the syntax {host}:{display}[{target_type}:" - "{target_id}]. See the output of `nvidia-settings -q all` for " - "information on which target types can be used with which " - "attributes. See the output of `nvidia-settings -q screens " - "-q gpus -q framelocks -q vcs -q gvis -q fans` for lists of targets " - "for each target type."); - - nv_msg(NULL, ""); - - nv_msg(BIGTAB, "The [{display devices}] portion is also optional; " - "if it is not specified, then the attribute is assigned to all " - "display devices."); - - nv_msg(NULL, ""); - - nv_msg(BIGTAB, "Some examples:"); - - nv_msg(NULL, ""); - - nv_msg(BIGTAB TAB, "-a FSAA=5"); - nv_msg(BIGTAB TAB, "-a localhost:0.0/DigitalVibrance[CRT-0]=0"); - nv_msg(BIGTAB TAB, "--assign=\"SyncToVBlank=1\""); - nv_msg(BIGTAB TAB, "-a [gpu:0]/DigitalVibrance[DFP-1]=63"); - -} /* print_assign_help() */ - - - -/* - * print_query_help() - print help information for the query option. - */ - -static void print_query_help(void) -{ - nv_msg(BIGTAB, "The QUERY argument to the '--query' commandline option " - "is of the form:"); - - nv_msg(NULL, ""); - - nv_msg(BIGTAB TAB, "{DISPLAY}/{attribute name}[{display devices}]"); - - nv_msg(NULL, ""); - - nv_msg(BIGTAB, "This queries the current value of the attribute " - "{attribute name} on the X Display {DISPLAY}. The format is " - "the same as that for the '--assign' option, without " - "'={value}'. Specify '-q screens', '-q gpus', '-q framelocks', " - "'-q vcs', '-q gvis', or '-q fans' to query a list of X screens, " - "GPUs, Frame Lock devices, Visual Computing Systems, SDI Input " - "Devices, or Fans, respectively, that are present on the X Display " - "{DISPLAY}. Specify '-q all' to query all attributes."); - -} /* print_query_help() */ - - - /* * print_attribute_help() - print information about the specified attribute. */ @@ -362,10 +184,37 @@ void print_help(void) msg = tmp; } nv_msg(TAB, msg); - if (o->description) nv_msg(BIGTAB, o->description); - if (o->print_description) (*(o->print_description))(); - nv_msg(NULL, ""); free(msg); + + if (o->description) { + char *buf = NULL, *pbuf = NULL, *s = NULL; + + buf = calloc(1, 1 + strlen(o->description)); + if (!buf) { + /* XXX There should be better message than this */ + nv_error_msg("Not enough memory\n"); + return; + } + pbuf = buf; + + for (s = o->description; s && *s; s++) { + switch (*s) { + case '<': + case '>': + case '^': + break; + default: + *pbuf = *s; + pbuf++; + break; + } + } + *pbuf = '\0'; + nv_msg_preserve_whitespace(BIGTAB, buf); + free(buf); + } + + nv_msg(NULL, ""); } } /* print_help() */ @@ -400,7 +249,11 @@ Options *parse_command_line(int argc, char *argv[], char *dpy) op->ctrl_display = dpy; while (1) { - c = nvgetopt(argc, argv, __options, &strval, NULL); + c = nvgetopt(argc, argv, __options, &strval, + NULL, /* boolval */ + NULL, /* intval */ + NULL, /* doubleval */ + NULL); /* disable_val */ if (c == -1) break; diff --git a/src/command-line.h b/src/command-line.h index c173524..9e062be 100644 --- a/src/command-line.h +++ b/src/command-line.h @@ -28,6 +28,8 @@ #include <NvCtrlAttributes.h> #define DEFAULT_RC_FILE "~/.nvidia-settings-rc" +#define CONFIG_FILE_OPTION 1 + #define VERBOSITY_ERROR 0 /* errors only */ #define VERBOSITY_WARNING 1 /* errors and warnings */ diff --git a/src/nvgetopt.c b/src/common-utils/nvgetopt.c index 14a1d4c..3bea6f8 100644 --- a/src/nvgetopt.c +++ b/src/common-utils/nvgetopt.c @@ -1,31 +1,26 @@ /* - * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix - * and Linux systems. - * - * Copyright (C) 2004 NVIDIA Corporation. + * Copyright (C) 2004-2010 NVIDIA Corporation * * This program is free software; you can redistribute it and/or - * modify it under the terms of Version 2 of the GNU General Public - * License as published by the Free Software Foundation. + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2 - * of the GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the: * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307, USA + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307, USA + * * - */ - -/* * nvgetopt.c - portable getopt_long() replacement; removes the need - * for the stupid optstring argument. Also adds support for the - * "-feature"/"+feature" syntax. + * for the stupid optstring argument. */ #include <stdio.h> @@ -35,51 +30,45 @@ #include "nvgetopt.h" - -/* - * nvgetopt() - see the glibc getopt_long(3) manpage for usage - * description. Options can be prepended with any of "--", "-", or - * "+". - * - * A global variable stores the current index into the argv array, so - * subsequent calls to nvgetopt() will advance through argv[]. - * - * On success, the matching NVGetoptOption.val is returned. - * - * On failure, an error is printed to stderr, and 0 is returned. - * - * When there are no more options to parse, -1 is returned. - */ - -int nvgetopt(int argc, char *argv[], const NVGetoptOption *options, - char **strval, int *boolval) +int nvgetopt(int argc, + char *argv[], + const NVGetoptOption *options, + char **strval, + int *boolval, + int *intval, + double *doubleval, + int *disable_val) { char *c, *a, *arg, *name = NULL, *argument=NULL; - int i, found = NVGETOPT_FALSE, ret = 0, val = NVGETOPT_FALSE; + int i, found = NVGETOPT_FALSE; + int ret = 0; + int negate = NVGETOPT_FALSE; + int disable = NVGETOPT_FALSE; const NVGetoptOption *o = NULL; static int argv_index = 0; - + + if (strval) *strval = NULL; + if (boolval) *boolval = NVGETOPT_FALSE; + if (intval) *intval = 0; + if (doubleval) *doubleval = 0.0; + if (disable_val) *disable_val = NVGETOPT_FALSE; + argv_index++; /* if no more options, return -1 */ if (argv_index >= argc) return -1; - + /* get the argument in question */ arg = strdup(argv[argv_index]); - - /* look for "--", "-", or "+" */ - + + /* look for "--" or "-" */ + if ((arg[0] == '-') && (arg[1] == '-')) { name = arg + 2; - val = NVGETOPT_INVALID; } else if (arg[0] == '-') { name = arg + 1; - val = NVGETOPT_FALSE; - } else if (arg[0] == '+') { - name = arg + 1; - val = NVGETOPT_TRUE; } else { fprintf(stderr, "%s: invalid option: \"%s\"\n", argv[0], arg); goto done; @@ -96,7 +85,7 @@ int nvgetopt(int argc, char *argv[], const NVGetoptOption *options, if (*c == '=') { argument = c + 1; *c = '\0'; break; } c++; } - + /* * if the string is terminated after one character, interpret it * as a short option. Otherwise, interpret it as a long option. @@ -111,8 +100,30 @@ int nvgetopt(int argc, char *argv[], const NVGetoptOption *options, } } else { /* long option */ for (i = 0; options[i].name; i++) { - if (strcmp(options[i].name, name) == 0) { + const char *tmpname; + int tmp_negate; + + /* + * if this option allows negation by prepending with + * "--no-" (true for IS_BOOLEAN and ALLOW_DISABLE), then + * skip any leading "no-" in the argument + */ + + if ((options[i].flags & (NVGETOPT_IS_BOOLEAN | + NVGETOPT_ALLOW_DISABLE)) && + (name[0] == 'n') && + (name[1] == 'o') && + (name[2] == '-')) { + tmpname = name + 3; + tmp_negate = NVGETOPT_TRUE; + } else { + tmpname = name; + tmp_negate = NVGETOPT_FALSE; + } + + if (strcmp(tmpname, options[i].name) == 0) { o = &options[i]; + negate = tmp_negate; break; } } @@ -134,7 +145,7 @@ int nvgetopt(int argc, char *argv[], const NVGetoptOption *options, } if (!found) break; } - + if (found) { /* @@ -144,40 +155,40 @@ int nvgetopt(int argc, char *argv[], const NVGetoptOption *options, for (i = 0; options[i].name; i++) { if (options[i].val == name[0]) { - + /* * don't allow options with arguments to be * processed in this way */ - + if (options[i].flags & NVGETOPT_HAS_ARGUMENT) break; - + /* * remove the first short option from * argv[argv_index] */ - + a = argv[argv_index]; if (a[0] == '-') a++; if (a[0] == '-') a++; if (a[0] == '+') a++; - + while(a[0]) { a[0] = a[1]; a++; } - + /* * decrement argv_index so that we process this * entry again */ - + argv_index--; - + o = &options[i]; break; } } } } - + /* if we didn't find an option, return */ if (!o) { @@ -185,41 +196,41 @@ int nvgetopt(int argc, char *argv[], const NVGetoptOption *options, goto done; } + + /* if the option is boolean, record !negate as the boolean value */ + if (o->flags & NVGETOPT_IS_BOOLEAN) { + if (boolval) *boolval = !negate; + } - /* - * if this option is boolean, then make sure it wasn't - * prepended with "--" - */ - if (val == NVGETOPT_INVALID) { - fprintf(stderr, "%s: incorrect usage: \"%s\". The option \"%s\" " - "should be prepended with either one \"-\" (to disable " - "%s) or one \"+\" (to enable %s)\n", - argv[0], arg, o->name, o->name, o->name); - goto done; - } + /* + * if this option is flagged as "disable-able", then let the + * "--no-" prefix get interpreted to mean that the option should + * be disabled + */ - /* assign boolval */ - - if (boolval) *boolval = val; + if ((o->flags & NVGETOPT_ALLOW_DISABLE) && (negate == NVGETOPT_TRUE)) { + disable = NVGETOPT_TRUE; } + /* - * if this option takes an argument, then we either need to use - * what was after the "=" in this argv[] entry, ot we need to pull - * the next entry off of argv[] + * if the option takes an argument (either string or integer), and + * we haven't already decided to disable the option, then we + * either need to use what was after the "=" in this argv[] entry, + * or we need to pull the next entry off of argv[] */ - if (o->flags & NVGETOPT_HAS_ARGUMENT) { + if ((o->flags & NVGETOPT_HAS_ARGUMENT) && !disable) { if (argument) { if (!argument[0]) { - fprintf(stderr, "%s: option \"%s\" requires an argument.\n", - argv[0], arg); + fprintf(stderr, "%s: option \"%s\" requires an " + "argument.\n", argv[0], arg); goto done; } - if (strval) *strval = strdup(argument); } else { + /* * if the argument is optional, and we're either at the * end of the argv list, or the next argv starts with '-', @@ -229,23 +240,76 @@ int nvgetopt(int argc, char *argv[], const NVGetoptOption *options, if ((o->flags & NVGETOPT_ARGUMENT_IS_OPTIONAL) && ((argv_index == (argc - 1)) || (argv[argv_index + 1][0] == '-'))) { - if (strval) *strval = NULL; + argument = NULL; + goto argument_processing_done; } else { argv_index++; if (argv_index >= argc) { - fprintf(stderr, "%s: option \"%s\" requires an argument.\n", - argv[0], arg); + fprintf(stderr, "%s: option \"%s\" requires an " + "argument.\n", argv[0], arg); goto done; } - if (strval) *strval = argv[argv_index]; + argument = argv[argv_index]; + } + } + + /* argument is now a valid string: parse it */ + + if ((o->flags & NVGETOPT_INTEGER_ARGUMENT) && (intval)) { + + /* parse the argument as an integer */ + + char *endptr; + *intval = (int) strtol(argument, &endptr, 0); + if (*endptr) { + fprintf(stderr, "%s: \"%s\" is not a valid argument for " + "option \"%s\".\n", argv[0], argument, arg); + goto done; + } + } else if ((o->flags & NVGETOPT_STRING_ARGUMENT) && (strval)) { + + /* treat the argument as a string */ + + *strval = strdup(argument); + } else if ((o->flags & NVGETOPT_DOUBLE_ARGUMENT) && (doubleval)) { + + /* parse the argument as a double */ + + char *endptr; + *doubleval = (double) strtod(argument, &endptr); + if (*endptr) { + fprintf(stderr, "%s: \"%s\" is not a valid argument for " + "option \"%s\".\n", argv[0], argument, arg); + goto done; } + } else { + fprintf(stderr, "%s: error while assigning argument for " + "option \"%s\".\n", argv[0], arg); + goto done; + } + + } else { + + /* if we have an argument when we shouldn't; complain */ + + if (argument) { + fprintf(stderr, "%s: option \"%s\" does not take an argument, but " + "was given an argument of \"%s\".\n", + argv[0], arg, argument); + goto done; } } - + + argument_processing_done: + ret = o->val; + /* fall through */ + done: + if (disable_val) *disable_val = disable; + free(arg); return ret; diff --git a/src/common-utils/nvgetopt.h b/src/common-utils/nvgetopt.h new file mode 100644 index 0000000..7083860 --- /dev/null +++ b/src/common-utils/nvgetopt.h @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2004-2010 NVIDIA Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307, USA + * + * + * nvgetopt.h + */ + +#ifndef __NVGETOPT_H__ +#define __NVGETOPT_H__ + +#define NVGETOPT_FALSE 0 +#define NVGETOPT_TRUE 1 + + +/* + * indicates that the option is a boolean value; the presence of the + * option will be interpretted as a TRUE value; if the option is + * prepended with '--no-', the option will be interpretted as a FALSE + * value. On success, nvgetopt will return the parsed boolean value + * through 'boolval'. + */ + +#define NVGETOPT_IS_BOOLEAN 0x01 + + +/* + * indicates that the option takes an argument to be interpreted as a + * string; on success, nvgetopt will return the parsed string argument + * through 'strval'. + */ + +#define NVGETOPT_STRING_ARGUMENT 0x02 + + +/* + * indicates that the option takes an argument to be interpreted as an + * integer; on success, nvgetopt will return the parsed integer + * argument through 'intval'. + */ + +#define NVGETOPT_INTEGER_ARGUMENT 0x04 + + +/* + * indicates that the option takes an argument to be interpreted as + * an double; on success, nvgetopt will return the parsed double + * argument through 'doubleval'. + */ + +#define NVGETOPT_DOUBLE_ARGUMENT 0x08 + + +/* helper macro */ + +#define NVGETOPT_HAS_ARGUMENT (NVGETOPT_STRING_ARGUMENT | \ + NVGETOPT_INTEGER_ARGUMENT | \ + NVGETOPT_DOUBLE_ARGUMENT) + +/* + * indicates that the option, which normally takes an argument, can be + * disabled if the option is prepended with '--no-', in which case, + * the option does not take an argument. If the option is disabled, + * nvgetopt will return TRUE through 'disable_val'. + * + * Note that NVGETOPT_ALLOW_DISABLE can only be used with options that + * take arguments. + */ + +#define NVGETOPT_ALLOW_DISABLE 0x10 + + +/* + * indicates that the argument for this option is optional; if no + * argument is present (either the option is already at the end of the + * argv array, or the next option in argv starts with '-'), then the + * option is returned without an argument. + */ + +#define NVGETOPT_ARGUMENT_IS_OPTIONAL 0x20 + + +/* + * The NVGETOPT_HELP_ALWAYS flag is not used by nvgetopt() itself, but + * is often used by other users of NVGetoptOption tables, who print + * out basic and advanced help. In such cases, OPTION_HELP_ALWAYS is + * used to indicate that the help for the option should always be + * printed. + */ + +#define NVGETOPT_HELP_ALWAYS 0x40 + + +typedef struct { + const char *name; + int val; + unsigned int flags; + char *arg_name; /* not used by nvgetopt() */ + char *description; /* not used by nvgetopt() */ +} NVGetoptOption; + + +/* + * nvgetopt() - see the glibc getopt_long(3) manpage for usage + * description. Options can be prepended with "--", "-", or "--no-". + * + * A global variable stores the current index into the argv array, so + * subsequent calls to nvgetopt() will advance through argv[]. + * + * On success, the matching NVGetoptOption.val is returned. + * + * If the NVGETOPT_IS_BOOLEAN flag is set, boolval will be set to TRUE + * (or FALSE, if the option string was prepended with "--no-"). + * + * disable_val will be assigned TRUE if the option string was + * prepended with "--no-", otherwise it will be assigned FALSE. + * + * If an argument is successfully parsed, one of strval, intval, or + * doubleval will be assigned, based on which of + * NVGETOPT_STRING_ARGUMENT, NVGETOPT_INTEGER_ARGUMENT, or + * NVGETOPT_DOUBLE_ARGUMENT is set in the option's flags. If strval + * is assigned to a non-NULL value by nvgetopt, then it is the + * caller's responsibility to free the string when done with it. + * + * On failure, an error is printed to stderr, and 0 is returned. + * + * When there are no more options to parse, -1 is returned. + */ + +int nvgetopt(int argc, + char *argv[], + const NVGetoptOption *options, + char **strval, + int *boolval, + int *intval, + double *doubleval, + int *disable_val); + + +#endif /* __NVGETOPT_H__ */ diff --git a/src/common-utils/src.mk b/src/common-utils/src.mk new file mode 100644 index 0000000..b93479e --- /dev/null +++ b/src/common-utils/src.mk @@ -0,0 +1,7 @@ +# makefile fragment included by nvidia-xconfig, nvidia-settings, and nvidia-installer + +COMMON_UTILS_SRC += nvgetopt.c + +COMMON_UTILS_EXTRA_DIST += nvgetopt.h +COMMON_UTILS_EXTRA_DIST += src.mk + diff --git a/src/gen-manpage-opts.c b/src/gen-manpage-opts.c new file mode 100644 index 0000000..2bcd766 --- /dev/null +++ b/src/gen-manpage-opts.c @@ -0,0 +1,147 @@ +/* + * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix + * and Linux systems. + * + * Copyright (C) 2010 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of Version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2 + * of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307, USA + * + */ + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <stdlib.h> + +#include "nvgetopt.h" +#include "option-table.h" + +#define NV_FMT_BUF_LEN 512 + +/* + * Prints the option help in a form that is suitable to include in the manpage. + */ + +static void print_option(const NVGetoptOption *o) +{ + int omitWhiteSpace; + + /* if we are going to need the argument, process it now */ + + printf(".TP\n.BI \""); + /* Print the name of the option */ + /* XXX We should backslashify the '-' characters in o->name. */ + + if (isalpha(o->val)) { + /* '\-c \-\-name' */ + printf("\\-%c, \\-\\-%s", o->val, o->name); + } else { + printf("\\-\\-%s", o->name); + } + + /* '=" "ARG' */ + if (o->flags & NVGETOPT_HAS_ARGUMENT) { + int len, j; + char tbuf[32]; + len = strlen(o->name); + for (j = 0; j < len; j++) + tbuf[j] = toupper(o->name[j]); + tbuf[len] = '\0'; + printf("=\" \"%s", tbuf); + } + + printf("\"\n"); + + /* Print the option description */ + /* XXX Each sentence should be on its own line! */ + + /* + * Print the option description: write each character one at a + * time (ugh) so that we can special-case a few characters: + * + * "^" --> "\n.I " + * "<" --> "\n.B " + * ">" --> "\n" + * + * '^' is used to mark the text as underlined till it is turned off with '>'. + * '<' is used to mark the text as bold till it is turned off with '>'. + * + * XXX Each sentence should be on its own line! + */ + + if (o->description) { + char *buf = NULL, *s = NULL, *pbuf = NULL; + + buf = calloc(1, NV_FMT_BUF_LEN + strlen(o->description)); + if (!buf) { + /* XXX There should be better message than this */ + printf("Not enough memory\n"); + return; + } + pbuf = buf; + + omitWhiteSpace = 0; + for (s = o->description; s && *s; s++) { + switch (*s) { + case '<': + sprintf(pbuf, "\n.B "); + pbuf = pbuf + 4; + omitWhiteSpace = 0; + break; + case '^': + sprintf(pbuf, "\n.I "); + pbuf = pbuf + 4; + omitWhiteSpace = 0; + break; + case '>': + *pbuf = '\n'; + pbuf++; + omitWhiteSpace = 1; + break; + case ' ': + if (!omitWhiteSpace) { + *pbuf = *s; + pbuf++; + } + break; + default: + *pbuf = *s; + pbuf++; + omitWhiteSpace = 0; + break; + } + } + printf("%s", buf); + free(buf); + } + + printf("\n"); +} + +int main(int argc, char* argv[]) +{ + int i; + const NVGetoptOption *o; + + printf(".SH OPTIONS\n"); + for (i = 0; __options[i].name; i++) { + o = &__options[i]; + print_option(o); + } + + return 0; +} diff --git a/src/gtk+-2.x/ctkclocks.c b/src/gtk+-2.x/ctkclocks.c index e09b413..1a5ed78 100644 --- a/src/gtk+-2.x/ctkclocks.c +++ b/src/gtk+-2.x/ctkclocks.c @@ -101,9 +101,9 @@ static const char * __clock_menu_help = "Selects which clock frequencies to modify. Standard (2D) only affects 2D " "applications. Performance (3D) only affects 3D applications."; -static const char * __gpu_clock_help = -"The GPU Clock Frequency is the core clock speed that the NVIDIA GPU will be " -"set to when the graphics card is operating in this mode (2D/3D)."; +static const char * __graphics_clock_help = +"The Graphics Clock Frequency is the core clock speed that the NVIDIA " +"GPU will be set to when the graphics card is operating in this mode (2D/3D)."; static const char * __mem_clock_help = "The Memory Clock Frequency is the clock speed of the memory interface on " @@ -324,7 +324,7 @@ GtkWidget* ctk_clocks_new(NvCtrlAttributeHandle *handle, gtk_widget_set_sensitive(ctk_object->clock_menu, overclocking_enabled && !probing_optimal); - /* Create the GPU clock frequency slider widget */ + /* Create the Graphics clock frequency slider widget */ if ( can_access_2d_clocks ) { adjustment = @@ -352,7 +352,7 @@ GtkWidget* ctk_clocks_new(NvCtrlAttributeHandle *handle, ctk_config_set_tooltip(ctk_config, CTK_SCALE(ctk_object->gpu_clk_scale)->gtk_scale, - __gpu_clock_help); + __graphics_clock_help); gtk_widget_set_sensitive(ctk_object->gpu_clk_scale, overclocking_enabled && !probing_optimal); @@ -619,8 +619,8 @@ GtkTextBuffer *ctk_clocks_create_help(GtkTextTagTable *table, "The 3D clock frequencies are the performance clock " "frequencies used when running 3D applications." ); - ctk_help_heading(b, &i, "GPU Clock Frequency"); - ctk_help_para(b, &i, __gpu_clock_help); + ctk_help_heading(b, &i, "Graphics Clock Frequency"); + ctk_help_para(b, &i, __graphics_clock_help); ctk_help_heading(b, &i, "Memory Clock Frequency"); ctk_help_para(b, &i, __mem_clock_help); ctk_help_heading(b, &i, "Applying Custom Clock Frequencies"); @@ -679,7 +679,7 @@ static void sync_gui_sensitivity(CtkClocks *ctk_object) gtk_widget_set_sensitive(ctk_object->clock_menu, enabled && !probing); - /* Update the GPU clock slider */ + /* Update the Graphics clock slider */ gtk_widget_set_sensitive(ctk_object->gpu_clk_scale, enabled && !probing); diff --git a/src/gtk+-2.x/ctkcolorcontrols.c b/src/gtk+-2.x/ctkcolorcontrols.c new file mode 100644 index 0000000..6a2c23a --- /dev/null +++ b/src/gtk+-2.x/ctkcolorcontrols.c @@ -0,0 +1,580 @@ +/* + * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix + * and Linux systems. + * + * Copyright (C) 2010 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of Version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2 + * of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307, USA + * + */ + +#include <gtk/gtk.h> +#include <NvCtrlAttributes.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <errno.h> + +#include "ctkconfig.h" +#include "ctkhelp.h" +#include "ctkcolorcontrols.h" + +/* function prototypes */ +static gboolean build_color_space_table(CtkColorControls *ctk_color_controls, + NVCTRLAttributeValidValuesRec valid); + +static gint map_nvctrl_value_to_table(CtkColorControls *ctk_color_controls, + gint val); + +static Bool update_color_space_menu_info(gpointer user_data); + +static void color_space_menu_changed(GtkOptionMenu *color_space_menu, + gpointer user_data); +static void color_range_menu_changed(GtkOptionMenu *color_range_menu, + gpointer user_data); + +static void color_control_update_received(GtkObject *object, gpointer arg1, + gpointer user_data); + +static +void post_color_range_update(CtkColorControls *ctk_color_controls, + gint color_range); + +static +void post_color_space_update(CtkColorControls *ctk_color_controls, + gint color_space); + +/* macros */ +#define FRAME_PADDING 5 + +/* help text */ +static const char * __color_controls_help = +"The Color Controls allow changing the color space and color range " +"of the display device. The possible values for Color Space vary " +"depending on the capabilities of the display device and the GPU, but " +"may contain \"RGB\", \"YCbCr422\", and \"YCbCr444\". The possible values " +"for Color Range are \"Limited\" and \"Full\"."; + +GType ctk_color_controls_get_type(void) +{ + static GType ctk_color_controls_type = 0; + + if (!ctk_color_controls_type) { + static const GTypeInfo ctk_color_controls_info = { + sizeof (CtkColorControlsClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init, */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (CtkColorControls), + 0, /* n_preallocs */ + NULL, /* instance_init */ + }; + + ctk_color_controls_type = + g_type_register_static (GTK_TYPE_VBOX, + "CtkColorControls", + &ctk_color_controls_info, 0); + } + + return ctk_color_controls_type; +} /* ctk_color_controls_get_type() */ + +GtkWidget* ctk_color_controls_new(NvCtrlAttributeHandle *handle, + CtkConfig *ctk_config, + CtkEvent *ctk_event, + GtkWidget *reset_button, + unsigned int display_device_mask, + char *name) +{ + GObject *object; + CtkColorControls *ctk_color_controls; + GtkWidget *frame, *hbox, *label, *eventbox; + GtkWidget *menu, *table, *menu_item = NULL, *separator; + ReturnStatus ret1, ret2; + NVCTRLAttributeValidValuesRec valid1, valid2; + gint i; + + /* check if color configuration is supported */ + ret1 = NvCtrlGetValidDisplayAttributeValues(handle, display_device_mask, + NV_CTRL_COLOR_SPACE, + &valid1); + ret2 = NvCtrlGetValidDisplayAttributeValues(handle, display_device_mask, + NV_CTRL_COLOR_RANGE, + &valid2); + + if ((ret1 != NvCtrlSuccess) || (ret2 != NvCtrlSuccess)) { + return NULL; + } + + /* create the object */ + object = g_object_new(CTK_TYPE_COLOR_CONTROLS, NULL); + if (!object) { + return NULL; + } + + ctk_color_controls = CTK_COLOR_CONTROLS(object); + ctk_color_controls->handle = handle; + ctk_color_controls->ctk_config = ctk_config; + ctk_color_controls->reset_button = reset_button; + ctk_color_controls->display_device_mask = display_device_mask; + ctk_color_controls->name = strdup(name); + + /* build a table holding available color space */ + if (!build_color_space_table(ctk_color_controls, valid1)) { + return NULL; + } + + /* create main color box & frame */ + + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, FRAME_PADDING); + ctk_color_controls->color_controls_main = hbox; + + frame = gtk_frame_new("Color Controls"); + eventbox = gtk_event_box_new(); + gtk_container_add(GTK_CONTAINER(eventbox), frame); + gtk_box_pack_start(GTK_BOX(hbox), eventbox, FALSE, FALSE, 0); + ctk_config_set_tooltip(ctk_config, eventbox, __color_controls_help); + + table = gtk_table_new(1, 6, FALSE); + gtk_container_add(GTK_CONTAINER(frame), table); + gtk_table_set_row_spacings(GTK_TABLE(table), 5); + gtk_table_set_col_spacings(GTK_TABLE(table), 15); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + + /* dropdown list for color space */ + menu = gtk_menu_new(); + + for (i = 0; i < ctk_color_controls->color_space_table_size; i++) { + switch (ctk_color_controls->color_space_table[i]) { + case NV_CTRL_COLOR_SPACE_YCbCr422: + menu_item = gtk_menu_item_new_with_label("YCbCr422"); + break; + case NV_CTRL_COLOR_SPACE_YCbCr444: + menu_item = gtk_menu_item_new_with_label("YCbCr444"); + break; + default: + case NV_CTRL_COLOR_SPACE_RGB: + menu_item = gtk_menu_item_new_with_label("RGB"); + break; + } + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); + gtk_widget_show(menu_item); + } + + ctk_color_controls->color_space_menu = gtk_option_menu_new(); + gtk_option_menu_set_menu + (GTK_OPTION_MENU(ctk_color_controls->color_space_menu), + menu); + + g_signal_connect(G_OBJECT(ctk_color_controls->color_space_menu), + "changed", G_CALLBACK(color_space_menu_changed), + (gpointer) ctk_color_controls); + + + /* pack the label & drop down */ + hbox = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Color Space: "); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + hbox = gtk_hbox_new(FALSE, 0); + ctk_color_controls->color_space_box = hbox; + gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + gtk_box_pack_start(GTK_BOX(hbox), + ctk_color_controls->color_space_menu, + FALSE, FALSE, 0); + + /* V-bar */ + hbox = gtk_hbox_new(FALSE, 0); + separator = gtk_vseparator_new(); + gtk_box_pack_start(GTK_BOX(hbox), separator, FALSE, FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 2, 3, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + + /* Build color widgets & pack them in table */ + /* dropdown list for color range */ + menu = gtk_menu_new(); + + menu_item = gtk_menu_item_new_with_label("Full"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); + gtk_widget_show(menu_item); + + menu_item = gtk_menu_item_new_with_label("Limited"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); + gtk_widget_show(menu_item); + + ctk_color_controls->color_range_menu = gtk_option_menu_new(); + gtk_option_menu_set_menu + (GTK_OPTION_MENU(ctk_color_controls->color_range_menu), + menu); + + g_signal_connect(G_OBJECT(ctk_color_controls->color_range_menu), + "changed", G_CALLBACK(color_range_menu_changed), + (gpointer) ctk_color_controls); + + /* Packing label & dropdown */ + hbox = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 3, 4, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + + label = gtk_label_new("Color Range: "); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + hbox = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 4, 5, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + gtk_box_pack_start(GTK_BOX(hbox), + ctk_color_controls->color_range_menu, + FALSE, FALSE, 0); + + gtk_widget_show_all(GTK_WIDGET(object)); + + ctk_color_controls_setup(ctk_color_controls); + + g_signal_connect(G_OBJECT(ctk_event), + CTK_EVENT_NAME(NV_CTRL_COLOR_RANGE), + G_CALLBACK(color_control_update_received), + (gpointer) ctk_color_controls); + g_signal_connect(G_OBJECT(ctk_event), + CTK_EVENT_NAME(NV_CTRL_COLOR_SPACE), + G_CALLBACK(color_control_update_received), + (gpointer) ctk_color_controls); + + return GTK_WIDGET(object); + +} /* ctk_color_controls_new() */ + + +/* + * ctk_color_controls_setup() - Setup routine for color attributes. Used + * in DFP setup stage as well as for updating the GUI when there is change in + * color range or color space. + */ +void ctk_color_controls_setup(CtkColorControls *ctk_color_controls) +{ + gint val; + + if (!ctk_color_controls) { + return; + } + + /* color range */ + if (NvCtrlSuccess != + NvCtrlGetDisplayAttribute(ctk_color_controls->handle, + ctk_color_controls->display_device_mask, + NV_CTRL_COLOR_RANGE, &val)) { + val = NV_CTRL_COLOR_RANGE_FULL; + } + + g_signal_handlers_block_by_func + (G_OBJECT(ctk_color_controls->color_range_menu), + G_CALLBACK(color_range_menu_changed), + (gpointer) ctk_color_controls); + + gtk_option_menu_set_history + (GTK_OPTION_MENU(ctk_color_controls->color_range_menu), + val); + + g_signal_handlers_unblock_by_func + (G_OBJECT(ctk_color_controls->color_range_menu), + G_CALLBACK(color_range_menu_changed), + (gpointer) ctk_color_controls); + + /* color space */ + if (!update_color_space_menu_info + ((gpointer)ctk_color_controls)) { + gtk_widget_set_sensitive(ctk_color_controls->color_controls_main, + FALSE); + gtk_widget_hide_all(ctk_color_controls->color_controls_main); + } + +} /* ctk_color_controls_setup() */ + + +static Bool update_color_space_menu_info(gpointer user_data) +{ + CtkColorControls *ctk_color_controls = + CTK_COLOR_CONTROLS(user_data); + gint color_space = NV_CTRL_COLOR_SPACE_RGB; + + /* color space */ + if (NvCtrlSuccess != + NvCtrlGetDisplayAttribute(ctk_color_controls->handle, + ctk_color_controls->display_device_mask, + NV_CTRL_COLOR_SPACE, + &color_space)) { + free(ctk_color_controls->color_space_table); + return FALSE; + } + + color_space = map_nvctrl_value_to_table(ctk_color_controls, + color_space); + + g_signal_handlers_block_by_func + (G_OBJECT(ctk_color_controls->color_space_menu), + G_CALLBACK(color_space_menu_changed), + (gpointer) ctk_color_controls); + + gtk_option_menu_set_history + (GTK_OPTION_MENU(ctk_color_controls->color_space_menu), + color_space); + + g_signal_handlers_unblock_by_func + (G_OBJECT(ctk_color_controls->color_space_menu), + G_CALLBACK(color_space_menu_changed), + (gpointer) ctk_color_controls); + + return True; +} /* update_color_space_menu_info() */ + +static +void post_color_range_update(CtkColorControls *ctk_color_controls, + gint color_range) +{ + static const char *color_range_table[] = { + "Full", /* NV_CTRL_COLOR_RANGE_FULL */ + "Limited" /* NV_CTRL_COLOR_RANGE_LIMITED */ + }; + + ctk_config_statusbar_message(ctk_color_controls->ctk_config, + "Color Range set to %s for %s.", + color_range_table[color_range], + ctk_color_controls->name); +} + +static +void post_color_space_update(CtkColorControls *ctk_color_controls, + gint color_space) +{ + static const char *color_space_table[] = { + "RGB", /* NV_CTRL_COLOR_SPACE_RGB */ + "YCbCr422", /* NV_CTRL_COLOR_SPACE_YCbCr422 */ + "YCbCr444" /* NV_CTRL_COLOR_SPACE_YCbCr444 */ + }; + + ctk_config_statusbar_message(ctk_color_controls->ctk_config, + "Color Space set to %s for %s.", + color_space_table[color_space], + ctk_color_controls->name); +} + +static void color_range_menu_changed(GtkOptionMenu *color_range_menu, + gpointer user_data) +{ + CtkColorControls *ctk_color_controls = + CTK_COLOR_CONTROLS(user_data); + gint history, color_range = NV_CTRL_COLOR_RANGE_FULL; + + history = gtk_option_menu_get_history(color_range_menu); + + switch (history) { + case 1: + color_range = NV_CTRL_COLOR_RANGE_LIMITED; + break; + default: + case 0: + color_range = NV_CTRL_COLOR_RANGE_FULL; + break; + } + + NvCtrlSetDisplayAttribute(ctk_color_controls->handle, + ctk_color_controls->display_device_mask, + NV_CTRL_COLOR_RANGE, + color_range); + + g_signal_handlers_block_by_func + (G_OBJECT(ctk_color_controls->color_range_menu), + G_CALLBACK(color_range_menu_changed), + (gpointer) ctk_color_controls); + + gtk_option_menu_set_history + (GTK_OPTION_MENU(ctk_color_controls->color_range_menu), + color_range); + + g_signal_handlers_unblock_by_func + (G_OBJECT(ctk_color_controls->color_range_menu), + G_CALLBACK(color_range_menu_changed), + (gpointer) ctk_color_controls); + + /* reflecting the change in color range to other widgets & reset button */ + ctk_color_controls_setup(ctk_color_controls); + post_color_range_update(ctk_color_controls, color_range); + gtk_widget_set_sensitive(ctk_color_controls->reset_button, TRUE); + +} /* color_range_menu_changed() */ + + +static void color_space_menu_changed(GtkOptionMenu *color_space_menu, + gpointer user_data) +{ + CtkColorControls *ctk_color_controls = + CTK_COLOR_CONTROLS(user_data); + gint history, color_space = NV_CTRL_COLOR_SPACE_RGB; + + history = gtk_option_menu_get_history(color_space_menu); + + color_space = ctk_color_controls->color_space_table[history]; + + NvCtrlSetDisplayAttribute(ctk_color_controls->handle, + ctk_color_controls->display_device_mask, + NV_CTRL_COLOR_SPACE, + color_space); + + color_space = map_nvctrl_value_to_table(ctk_color_controls, + color_space); + g_signal_handlers_block_by_func + (G_OBJECT(ctk_color_controls->color_space_menu), + G_CALLBACK(color_space_menu_changed), + (gpointer) ctk_color_controls); + + gtk_option_menu_set_history + (GTK_OPTION_MENU(ctk_color_controls->color_space_menu), + color_space); + + g_signal_handlers_unblock_by_func + (G_OBJECT(ctk_color_controls->color_space_menu), + G_CALLBACK(color_space_menu_changed), + (gpointer) ctk_color_controls); + + /* reflecting the change in color space to other widgets & reset button */ + ctk_color_controls_setup(ctk_color_controls); + post_color_space_update(ctk_color_controls, color_space); + gtk_widget_set_sensitive(ctk_color_controls->reset_button, TRUE); + +} /* color_space_menu_changed() */ + + +/* + * ctk_color_controls_reset() - Resets the color range and + * & color space when Reset HW Defaults is clicked + */ +void ctk_color_controls_reset(CtkColorControls *ctk_color_controls) +{ + if (!ctk_color_controls) { + return; + } + + NvCtrlSetDisplayAttribute(ctk_color_controls->handle, + ctk_color_controls->display_device_mask, + NV_CTRL_COLOR_SPACE, + NV_CTRL_COLOR_SPACE_RGB); + + NvCtrlSetDisplayAttribute(ctk_color_controls->handle, + ctk_color_controls->display_device_mask, + NV_CTRL_COLOR_RANGE, + NV_CTRL_COLOR_RANGE_FULL); + + ctk_color_controls_setup(ctk_color_controls); +} /* ctk_color_controls_reset() */ + + +/* + * add_color_controls_help() - + */ +void add_color_controls_help(CtkColorControls *ctk_color_controls, + GtkTextBuffer *b, + GtkTextIter *i) +{ + ctk_help_heading(b, i, "Color Controls"); + ctk_help_para(b, i, __color_controls_help); +} /* add_color_controls_help() */ + + +/* + * When other client updated color controls + * we should update the GUI to reflect the current color range + * and color space. + */ +static void color_control_update_received(GtkObject *object, gpointer arg1, + gpointer user_data) +{ + CtkColorControls *ctk_object = CTK_COLOR_CONTROLS(user_data); + CtkEventStruct *event_struct = (CtkEventStruct *) arg1; + + /* if the event is not for this display device, return */ + + if (!(event_struct->display_mask & ctk_object->display_device_mask)) { + return; + } + + ctk_color_controls_setup(ctk_object); +} /* color_control_update_received() */ + + +/* + * build_color_space_table() - build a table of color space, showing + * modes supported by the DFP. + */ +static gboolean build_color_space_table(CtkColorControls *ctk_color_controls, + NVCTRLAttributeValidValuesRec valid) +{ + gint i, n = 0, color_space_count = 0; + gint mask = valid.u.bits.ints; + + if (valid.type != ATTRIBUTE_TYPE_INT_BITS) { + return False; + } + + /* count no. of supported color space */ + while(mask) { + mask = mask & (mask - 1); + color_space_count++; + } + + ctk_color_controls->color_space_table_size = color_space_count; + ctk_color_controls->color_space_table = + calloc(color_space_count, sizeof(ctk_color_controls->color_space_table[0])); + if (!ctk_color_controls->color_space_table) { + return False; + } + + for (i = 0, n = 0; n < ctk_color_controls->color_space_table_size; i++) { + if (valid.u.bits.ints & (1 << i)) { + ctk_color_controls->color_space_table[n] = i; + n++; + } + } + + return True; + +} /* build_color_space_table() */ + + +static gint map_nvctrl_value_to_table(CtkColorControls *ctk_color_controls, + gint val) +{ + int i; + for (i = 0; i < ctk_color_controls->color_space_table_size; i++) { + if (val == ctk_color_controls->color_space_table[i]) { + return i; + } + } + + return 0; +} /*map_nvctrl_value_to_table() */ diff --git a/src/gtk+-2.x/ctkcolorcontrols.h b/src/gtk+-2.x/ctkcolorcontrols.h new file mode 100644 index 0000000..5faa6ab --- /dev/null +++ b/src/gtk+-2.x/ctkcolorcontrols.h @@ -0,0 +1,97 @@ +/* + * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix + * and Linux systems. + * + * Copyright (C) 2010 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of Version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2 + * of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307, USA + * + */ + +#ifndef __CTK_COLOR_CONTROLS_H__ +#define __CTK_COLOR_CONTROLS_H__ + +#include "ctkevent.h" +#include "ctkconfig.h" + +G_BEGIN_DECLS + +#define CTK_TYPE_COLOR_CONTROLS (ctk_color_controls_get_type()) + +#define CTK_COLOR_CONTROLS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_COLOR_CONTROLS, \ + CtkColorControls)) + +#define CTK_COLOR_CONTROLS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_COLOR_CONTROLS, \ + CtkColorControlsClass)) + +#define CTK_IS_COLOR_CONTROLS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_COLOR_CONTROLS)) + +#define CTK_IS_COLOR_CONTROLS_CLASS(class) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_COLOR_CONTROLS)) + +#define CTK_COLOR_CONTROLS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_COLOR_CONTROLS, \ + CtkCOLORControlsClass)) + +typedef struct _CtkColorControls CtkColorControls; +typedef struct _CtkColorControlsClass CtkColorControlsClass; + +struct _CtkColorControls +{ + GtkVBox parent; + + NvCtrlAttributeHandle *handle; + CtkConfig *ctk_config; + GtkWidget *reset_button; + GtkWidget *color_controls_main; + GtkWidget *color_space_box; + + GtkWidget *color_range_menu; + GtkWidget *color_space_menu; + GtkWidget *color_current_config; + + gint display_device_mask; + gint *color_space_table; + gint color_space_table_size; + gint default_color_config; + gint default_color_space; + char *name; +}; + +struct _CtkColorControlsClass +{ + GtkVBoxClass parent_class; +}; + +GType ctk_color_controls_get_type (void) G_GNUC_CONST; +GtkWidget* ctk_color_controls_new (NvCtrlAttributeHandle *, + CtkConfig *, CtkEvent *, + GtkWidget *, + unsigned int display_device_mask, + char *); + +void ctk_color_controls_reset (CtkColorControls*); +void ctk_color_controls_setup (CtkColorControls*); +void add_color_controls_help (CtkColorControls*, GtkTextBuffer *b, + GtkTextIter *i); + +G_END_DECLS + +#endif /* __CTK_COLOR_CONTROLS_H__ */ diff --git a/src/gtk+-2.x/ctkcolorcorrection.c b/src/gtk+-2.x/ctkcolorcorrection.c index 169190e..464905d 100644 --- a/src/gtk+-2.x/ctkcolorcorrection.c +++ b/src/gtk+-2.x/ctkcolorcorrection.c @@ -84,7 +84,7 @@ static gfloat get_attribute_channel_value (CtkColorCorrection *, gint, gint); static void -flush_attribute_channel_values (CtkColorCorrection *, gint, gint, gfloat); +flush_attribute_channel_values (CtkColorCorrection *, gint, gint); static void ctk_color_correction_class_init(CtkColorCorrectionClass *); @@ -109,6 +109,8 @@ static guint signals[LAST_SIGNAL] = { 0 }; #define GREEN GREEN_CHANNEL_INDEX #define BLUE BLUE_CHANNEL_INDEX +#define ALL_CHANNELS_INDEX 3 + #define CONTRAST (CONTRAST_INDEX - CONTRAST_INDEX) #define BRIGHTNESS (BRIGHTNESS_INDEX - CONTRAST_INDEX) #define GAMMA (GAMMA_INDEX - CONTRAST_INDEX) @@ -536,6 +538,15 @@ static void option_menu_changed( break; } + /* + * store the currently selected color channel, so that + * adjustment_value_changed() can update the correct channel(s) in + * response to slider changes + */ + + g_object_set_data(G_OBJECT(option_menu), "color_channel", + GINT_TO_POINTER(channel)); + for (i = 0; i < 3; i++) { if (i == 0) { @@ -549,9 +560,6 @@ static void option_menu_changed( attribute = GAMMA_VALUE; } - g_object_set_data(G_OBJECT(option_menu), "color_channel", - GINT_TO_POINTER(channel)); - value = get_attribute_channel_value(ctk_color_correction, attribute, channel); @@ -566,9 +574,6 @@ static void option_menu_changed( (G_OBJECT(adjustment), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, G_CALLBACK(adjustment_value_changed), NULL); - - if (channel == ALL_CHANNELS) - gtk_adjustment_value_changed(GTK_ADJUSTMENT(adjustment)); } } @@ -583,27 +588,43 @@ static void set_button_sensitive( /** set_color_state() ******************* * - * Stores color state to cur_val[attribute][channel] - * and prev_val[attribute][channel]. + * Stores color state to cur_slider_val[attribute][channel] + * and prev_slider_val[attribute][channel]. * **/ static void set_color_state(CtkColorCorrection *ctk_color_correction, - gint attribute_idx, gint channel_idx, + gint attribute_idx, gint channel_mask, gfloat value, gboolean all ) { - if ( channel_idx != ALL_CHANNELS ) { - ctk_color_correction->cur_val - [attribute_idx][channel_idx] = value; - if ( all ) { - ctk_color_correction->prev_val - [attribute_idx][channel_idx] = value; + if (channel_mask & RED_CHANNEL) { + ctk_color_correction->cur_slider_val[attribute_idx][RED] = value; + if (all) { + ctk_color_correction->prev_slider_val[attribute_idx][RED] = value; } - } else { - gint ch; - for ( ch = RED; ch <= BLUE; ch++ ) { - set_color_state(ctk_color_correction, attribute_idx, ch, value, all); + } + + if (channel_mask & GREEN_CHANNEL) { + ctk_color_correction->cur_slider_val[attribute_idx][GREEN] = value; + if (all) { + ctk_color_correction->prev_slider_val[attribute_idx][GREEN] = value; + } + } + + if (channel_mask & BLUE_CHANNEL) { + ctk_color_correction->cur_slider_val[attribute_idx][BLUE] = value; + if (all) { + ctk_color_correction->prev_slider_val[attribute_idx][BLUE] = value; + } + } + + if (channel_mask == ALL_CHANNELS) { + ctk_color_correction->cur_slider_val + [attribute_idx][ALL_CHANNELS_INDEX] = value; + if (all) { + ctk_color_correction->prev_slider_val + [attribute_idx][ALL_CHANNELS_INDEX] = value; } } } /* set_color_state() */ @@ -624,9 +645,11 @@ static void confirm_button_clicked( { CtkColorCorrection *ctk_color_correction = CTK_COLOR_CORRECTION(user_data); - /* Store cur_val[attribute][channel] to prev_val[attribute][channel]. */ - memcpy (ctk_color_correction->prev_val, ctk_color_correction->cur_val, - sizeof(ctk_color_correction->cur_val)); + /* Store cur_slider_val[attribute][channel] to + prev_slider_val[attribute][channel]. */ + memcpy (ctk_color_correction->prev_slider_val, + ctk_color_correction->cur_slider_val, + sizeof(ctk_color_correction->cur_slider_val)); /* kill the timer */ g_source_remove(ctk_color_correction->confirm_timer); @@ -657,12 +680,9 @@ static void reset_button_clicked( set_color_state(ctk_color_correction, GAMMA, ALL_CHANNELS, GAMMA_DEFAULT, TRUE); - NvCtrlSetColorAttributes(ctk_color_correction->handle, - ctk_color_correction->cur_val[CONTRAST], - ctk_color_correction->cur_val[BRIGHTNESS], - ctk_color_correction->cur_val[GAMMA], - ALL_VALUES | ALL_CHANNELS); - + flush_attribute_channel_values(ctk_color_correction, + ALL_VALUES, ALL_CHANNELS); + option_menu = GTK_OPTION_MENU(ctk_color_correction->option_menu); if (gtk_option_menu_get_history(option_menu) == 0) { @@ -699,7 +719,7 @@ static void adjustment_value_changed( { CtkColorCorrection *ctk_color_correction; gint attribute, channel; - gint attribute_idx, channel_idx; + gint attribute_idx; gfloat value; gchar *channel_str, *attribute_str; @@ -745,30 +765,25 @@ static void adjustment_value_changed( switch (channel) { case RED_CHANNEL: - channel_idx = RED; channel_str = "red "; break; case GREEN_CHANNEL: - channel_idx = GREEN; channel_str = "green "; break; case BLUE_CHANNEL: - channel_idx = BLUE; channel_str = "blue "; break; case ALL_CHANNELS: - channel_idx = ALL_CHANNELS; channel_str = ""; break; default: return; } - set_color_state(ctk_color_correction, attribute_idx, channel_idx, + set_color_state(ctk_color_correction, attribute_idx, channel, value, FALSE); - flush_attribute_channel_values(ctk_color_correction, - attribute, channel, value); + flush_attribute_channel_values(ctk_color_correction, attribute, channel); ctk_config_statusbar_message(ctk_color_correction->ctk_config, "Set %s%s to %f.", @@ -781,51 +796,54 @@ static gfloat get_attribute_channel_value(CtkColorCorrection *ctk_color_correction, gint attribute, gint channel) { - gfloat values[3] = { 0.0, 0.0, 0.0 }; - gfloat ignore[3] = { 0.0, 0.0, 0.0 }; - - NvCtrlAttributeHandle *handle = ctk_color_correction->handle; + int attribute_idx, channel_idx; switch (attribute) { case CONTRAST_VALUE: - NvCtrlGetColorAttributes(handle, values, ignore, ignore); + attribute_idx = CONTRAST; break; case BRIGHTNESS_VALUE: - NvCtrlGetColorAttributes(handle, ignore, values, ignore); + attribute_idx = BRIGHTNESS; break; case GAMMA_VALUE: - NvCtrlGetColorAttributes(handle, ignore, ignore, values); + attribute_idx = GAMMA; break; default: return 0.0; } switch (channel) { - case ALL_CHANNELS: /* XXX what to do for all channels? */ + case ALL_CHANNELS: + channel_idx = ALL_CHANNELS_INDEX; + break; case RED_CHANNEL: - return values[0]; + channel_idx = RED_CHANNEL_INDEX; + break; case GREEN_CHANNEL: - return values[1]; + channel_idx = GREEN_CHANNEL_INDEX; + break; case BLUE_CHANNEL: - return values[2]; + channel_idx = BLUE_CHANNEL_INDEX; + break; default: - return 0; + return 0.0; } + + return ctk_color_correction->cur_slider_val[attribute_idx][channel_idx]; } static void flush_attribute_channel_values( CtkColorCorrection *ctk_color_correction, gint attribute, - gint channel, - gfloat value + gint channel ) { NvCtrlAttributeHandle *handle = ctk_color_correction->handle; NvCtrlSetColorAttributes(handle, - ctk_color_correction->cur_val[CONTRAST], - ctk_color_correction->cur_val[BRIGHTNESS], - ctk_color_correction->cur_val[GAMMA], + ctk_color_correction->cur_slider_val[CONTRAST], + ctk_color_correction->cur_slider_val[BRIGHTNESS], + ctk_color_correction->cur_slider_val[GAMMA], attribute | channel); g_signal_emit(ctk_color_correction, signals[CHANGED], 0); @@ -867,39 +885,39 @@ static void apply_parsed_attribute_list( switch (p->attr & (ALL_VALUES | ALL_CHANNELS)) { case (CONTRAST_VALUE | RED_CHANNEL): set_color_state(ctk_color_correction, CONTRAST, - RED, p->fval, TRUE); break; + RED_CHANNEL, p->fval, TRUE); break; case (CONTRAST_VALUE | GREEN_CHANNEL): set_color_state(ctk_color_correction, CONTRAST, - GREEN, p->fval, TRUE); break; + GREEN_CHANNEL, p->fval, TRUE); break; case (CONTRAST_VALUE | BLUE_CHANNEL): set_color_state(ctk_color_correction, CONTRAST, - BLUE, p->fval, TRUE); break; + BLUE_CHANNEL, p->fval, TRUE); break; case (CONTRAST_VALUE | ALL_CHANNELS): set_color_state(ctk_color_correction, CONTRAST, ALL_CHANNELS, p->fval, TRUE); break; case (BRIGHTNESS_VALUE | RED_CHANNEL): set_color_state(ctk_color_correction, BRIGHTNESS, - RED, p->fval, TRUE); break; + RED_CHANNEL, p->fval, TRUE); break; case (BRIGHTNESS_VALUE | GREEN_CHANNEL): set_color_state(ctk_color_correction, BRIGHTNESS, - GREEN, p->fval, TRUE); break; + GREEN_CHANNEL, p->fval, TRUE); break; case (BRIGHTNESS_VALUE | BLUE_CHANNEL): set_color_state(ctk_color_correction, BRIGHTNESS, - BLUE, p->fval, TRUE); break; + BLUE_CHANNEL, p->fval, TRUE); break; case (BRIGHTNESS_VALUE | ALL_CHANNELS): set_color_state(ctk_color_correction, BRIGHTNESS, ALL_CHANNELS, p->fval, TRUE); break; case (GAMMA_VALUE | RED_CHANNEL): set_color_state(ctk_color_correction, GAMMA, - RED, p->fval, TRUE); break; + RED_CHANNEL, p->fval, TRUE); break; case (GAMMA_VALUE | GREEN_CHANNEL): set_color_state(ctk_color_correction, GAMMA, - GREEN, p->fval, TRUE); break; + GREEN_CHANNEL, p->fval, TRUE); break; case (GAMMA_VALUE | BLUE_CHANNEL): set_color_state(ctk_color_correction, GAMMA, - BLUE, p->fval, TRUE); break; + BLUE_CHANNEL, p->fval, TRUE); break; case (GAMMA_VALUE | ALL_CHANNELS): set_color_state(ctk_color_correction, GAMMA, ALL_CHANNELS, p->fval, TRUE); break; @@ -917,9 +935,9 @@ static void apply_parsed_attribute_list( if (attr) { NvCtrlSetColorAttributes(ctk_color_correction->handle, - ctk_color_correction->cur_val[CONTRAST], - ctk_color_correction->cur_val[BRIGHTNESS], - ctk_color_correction->cur_val[GAMMA], + ctk_color_correction->cur_slider_val[CONTRAST], + ctk_color_correction->cur_slider_val[BRIGHTNESS], + ctk_color_correction->cur_slider_val[GAMMA], attr); } @@ -952,7 +970,8 @@ static gboolean do_confirm_countdown(gpointer data) { gint attr, ch; CtkColorCorrection *ctk_color_correction = (CtkColorCorrection *)(data); - unsigned int active_attributes_channels = 0; + unsigned int channels = 0; + unsigned int attributes = 0; GtkOptionMenu *option_menu = GTK_OPTION_MENU(ctk_color_correction->option_menu); @@ -964,23 +983,21 @@ static gboolean do_confirm_countdown(gpointer data) /* Countdown timed out, reset color settings to previous state */ for (attr = CONTRAST_INDEX; attr <= GAMMA_INDEX; attr++) { - for (ch = RED; ch <= BLUE; ch++) { + for (ch = RED; ch <= ALL_CHANNELS_INDEX; ch++) { /* Check for attribute channel value change. */ - if (ctk_color_correction->cur_val[attr - CONTRAST_INDEX][ch] != - ctk_color_correction->prev_val[attr - CONTRAST_INDEX][ch]) { - ctk_color_correction->cur_val[attr - CONTRAST_INDEX][ch] = - ctk_color_correction->prev_val[attr - CONTRAST_INDEX][ch]; - active_attributes_channels |= (1 << attr) | (1 << ch); + int index = attr - CONTRAST_INDEX; + if (ctk_color_correction->cur_slider_val[index][ch] != + ctk_color_correction->prev_slider_val[index][ch]) { + ctk_color_correction->cur_slider_val[index][ch] = + ctk_color_correction->prev_slider_val[index][ch]; + attributes |= (1 << attr); + channels |= (1 << ch); } } } - if (active_attributes_channels) { - NvCtrlSetColorAttributes(ctk_color_correction->handle, - ctk_color_correction->cur_val[CONTRAST], - ctk_color_correction->cur_val[BRIGHTNESS], - ctk_color_correction->cur_val[GAMMA], - active_attributes_channels); - g_signal_emit(ctk_color_correction, signals[CHANGED], 0); + if (attributes | channels) { + flush_attribute_channel_values(ctk_color_correction, + attributes, channels); } /* Refresh color correction page for current selected channel. */ diff --git a/src/gtk+-2.x/ctkcolorcorrection.h b/src/gtk+-2.x/ctkcolorcorrection.h index 746a787..28ea926 100644 --- a/src/gtk+-2.x/ctkcolorcorrection.h +++ b/src/gtk+-2.x/ctkcolorcorrection.h @@ -67,8 +67,8 @@ struct _CtkColorCorrection GtkWidget *confirm_button; gint confirm_countdown; guint confirm_timer; - gfloat cur_val[3][3]; // as [attribute][channel] - gfloat prev_val[3][3]; // as [attribute][channel] + gfloat cur_slider_val[3][4]; // as [attribute][channel] + gfloat prev_slider_val[3][4]; // as [attribute][channel] guint enabled_display_devices; }; diff --git a/src/gtk+-2.x/ctkdisplayconfig.c b/src/gtk+-2.x/ctkdisplayconfig.c index f8c5250..f9bd9f0 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.c +++ b/src/gtk+-2.x/ctkdisplayconfig.c @@ -495,6 +495,43 @@ static void consolidate_xinerama(CtkDisplayConfig *ctk_object, +/** update_btn_apply() ************************************************** + * + * Updates the apply button's sensitvity (if possible) + * + **/ + +void update_btn_apply(CtkDisplayConfig *ctk_object, Bool sensitive) +{ + Bool xrandr_available = FALSE; + nvGpuPtr gpu; + nvScreenPtr screen; + + + if (sensitive) { + /* If XRandR is disabled (for all screens), we can't apply */ + for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { + + for (screen = gpu->screens; screen; screen = screen->next) { + if (NvCtrlGetXrandrEventBase(screen->handle) >= 0) { + xrandr_available = TRUE; + break; + } + } + if (xrandr_available) break; + } + + if (!xrandr_available) { + sensitive = FALSE; + } + } + + gtk_widget_set_sensitive(ctk_object->btn_apply, sensitive); + +} /* update_btn_apply() */ + + + /** xconfigPrint() ****************************************************** * * xconfigPrint() - this is the one entry point that a user of the @@ -1013,7 +1050,7 @@ GtkWidget * create_validation_apply_dialog(CtkDisplayConfig *ctk_object) static void user_changed_attributes(CtkDisplayConfig *ctk_object) { if (ctk_object->forced_reset_allowed) { - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + update_btn_apply(ctk_object, TRUE); ctk_object->forced_reset_allowed = FALSE; } @@ -1185,11 +1222,7 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, ctk_object->obj_layout = ctk_display_layout_new(handle, ctk_config, ctk_object->layout, 300, /* min width */ - 225, /* min height */ - layout_selected_callback, - (void *)ctk_object, - layout_modified_callback, - (void *)ctk_object); + 225); /* min height */ /* Make sure all X screens have the same depth if Xinerama is enabled */ consolidate_xinerama(ctk_object, NULL); @@ -1518,7 +1551,7 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, /* Apply button */ ctk_object->btn_apply = gtk_button_new_with_label("Apply"); - gtk_widget_set_sensitive(ctk_object->btn_apply, False); + update_btn_apply(ctk_object, FALSE); ctk_config_set_tooltip(ctk_config, ctk_object->btn_apply, __apply_button_help); g_signal_connect(G_OBJECT(ctk_object->btn_apply), "clicked", @@ -1873,6 +1906,12 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, setup_display_page(ctk_object); setup_screen_page(ctk_object); + /* Register to receive updates when layout changed */ + ctk_display_layout_register_callbacks(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), + layout_selected_callback, + (void *)ctk_object, + layout_modified_callback, + (void *)ctk_object); return GTK_WIDGET(ctk_object); @@ -1978,12 +2017,14 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table, ctk_help_para(b, &i, ""); ctk_help_heading(b, &i, "Buttons"); ctk_help_heading(b, &i, "Apply"); - ctk_help_para(b, &i, "%s Note that not all settings can be applied to an " - "active X server; these require restarting the X server " - "after saving the desired settings to the X configuration " - "file. Examples of such settings include changing the " - "position of any X screen, adding/removing an X screen, and " - "changing the X screen color depth.", __apply_button_help); + ctk_help_para(b, &i, "%s Note that XRandR must be available to apply " + "settings. Also note that even when XRandR is available, " + "not all settings can be applied to an active X server; " + "these require restarting the X server after saving the " + "desired settings to the X configuration file. Examples " + "of such settings include changing the position of any X " + "screen, adding/removing an X screen, and changing the X " + "screen color depth.", __apply_button_help); ctk_help_heading(b, &i, "Detect Displays"); ctk_help_para(b, &i, __detect_displays_button_help); ctk_help_heading(b, &i, "Advanced/Basic..."); @@ -5980,7 +6021,7 @@ static Bool switch_to_current_metamode(CtkDisplayConfig *ctk_object, /* XRandR must be available to do mode switching */ - if (!NvCtrlGetXrandrEventBase(screen->handle)) { + if (NvCtrlGetXrandrEventBase(screen->handle) < 0) { dlg = gtk_message_dialog_new (GTK_WINDOW(parent), GTK_DIALOG_DESTROY_WITH_PARENT, @@ -7609,7 +7650,7 @@ static void reset_layout(CtkDisplayConfig *ctk_object) /* Clear the apply button */ ctk_object->apply_possible = TRUE; - gtk_widget_set_sensitive(ctk_object->btn_apply, FALSE); + update_btn_apply(ctk_object, FALSE); ctk_object->forced_reset_allowed = TRUE; /* OK to reset w/o user input */ ctk_object->notify_user_of_reset = TRUE; /* Notify user of new changes */ @@ -7733,7 +7774,7 @@ static gboolean force_layout_reset(gpointer user_data) * until they have reloaded the layout manually. */ ctk_object->notify_user_of_reset = FALSE; - gtk_widget_set_sensitive(ctk_object->btn_apply, False); + update_btn_apply(ctk_object, FALSE); break; } gtk_widget_destroy(dlg); diff --git a/src/gtk+-2.x/ctkdisplaydevice-dfp.c b/src/gtk+-2.x/ctkdisplaydevice-dfp.c index 887fbd1..b9c7747 100644 --- a/src/gtk+-2.x/ctkdisplaydevice-dfp.c +++ b/src/gtk+-2.x/ctkdisplaydevice-dfp.c @@ -29,6 +29,8 @@ #include "ctkdisplaydevice-dfp.h" +#include "ctkditheringcontrols.h" +#include "ctkcolorcontrols.h" #include "ctkimagesliders.h" #include "ctkedid.h" #include "ctkconfig.h" @@ -459,6 +461,32 @@ GtkWidget* ctk_display_device_dfp_new(NvCtrlAttributeHandle *handle, 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 = @@ -705,7 +733,19 @@ static void reset_button_clicked(GtkButton *button, gpointer user_data) dfp_scaling_setup(ctk_display_device_dfp); } - + + /* Reset the color configuration */ + if (ctk_display_device_dfp->color_controls) { + ctk_color_controls_reset + (CTK_COLOR_CONTROLS(ctk_display_device_dfp->color_controls)); + } + + /* Reset the dithering configuration */ + if (ctk_display_device_dfp->dithering_controls) { + ctk_dithering_controls_reset + (CTK_DITHERING_CONTROLS(ctk_display_device_dfp->dithering_controls)); + } + /* Update the reset button */ gtk_widget_set_sensitive(ctk_display_device_dfp->reset_button, FALSE); @@ -907,6 +947,16 @@ GtkTextBuffer *ctk_display_device_dfp_create_help(GtkTextTagTable *table, "aspect ratio) to expand and fit as much of the entire " "flat panel as possible."); + if (ctk_display_device_dfp->color_controls) { + add_color_controls_help + (CTK_COLOR_CONTROLS(ctk_display_device_dfp->color_controls), b, &i); + } + + if (ctk_display_device_dfp->dithering_controls) { + add_dithering_controls_help + (CTK_DITHERING_CONTROLS(ctk_display_device_dfp->dithering_controls), b, &i); + } + add_image_sliders_help (CTK_IMAGE_SLIDERS(ctk_display_device_dfp->image_sliders), b, &i); @@ -1242,6 +1292,15 @@ static void ctk_display_device_dfp_setup(CtkDisplayDeviceDfp ctk_display_device_dfp->edid, TRUE, TRUE, 0); } + /* Update the color control setup */ + + ctk_color_controls_setup + (CTK_COLOR_CONTROLS(ctk_display_device_dfp->color_controls)); + + /* Update the dithering setup */ + + ctk_dithering_controls_setup + (CTK_DITHERING_CONTROLS(ctk_display_device_dfp->dithering_controls)); /* update the reset button */ diff --git a/src/gtk+-2.x/ctkdisplaydevice-dfp.h b/src/gtk+-2.x/ctkdisplaydevice-dfp.h index bd9b1ee..f247412 100644 --- a/src/gtk+-2.x/ctkdisplaydevice-dfp.h +++ b/src/gtk+-2.x/ctkdisplaydevice-dfp.h @@ -65,6 +65,8 @@ struct _CtkDisplayDeviceDfp GtkWidget *reset_button; GtkWidget *edid_box; GtkWidget *edid; + GtkWidget *dithering_controls; + GtkWidget *color_controls; GtkWidget *txt_chip_location; GtkWidget *txt_link; diff --git a/src/gtk+-2.x/ctkdisplaylayout.c b/src/gtk+-2.x/ctkdisplaylayout.c index 3a119f3..d43737a 100644 --- a/src/gtk+-2.x/ctkdisplaylayout.c +++ b/src/gtk+-2.x/ctkdisplaylayout.c @@ -682,7 +682,8 @@ static int resolve_display(nvDisplayPtr display, int mode_idx, * **/ -static void resolve_displays_in_screen(nvScreenPtr screen, int all_modes) +static void resolve_displays_in_screen(nvScreenPtr screen, + int resolve_all_modes) { nvDisplayPtr display; int pos[4]; @@ -690,7 +691,7 @@ static void resolve_displays_in_screen(nvScreenPtr screen, int all_modes) int last_idx; int mode_idx; - if (all_modes) { + if (resolve_all_modes) { first_idx = 0; last_idx = screen->num_metamodes -1; } else { @@ -1191,17 +1192,17 @@ static void recenter_layout(nvLayoutPtr layout) * **/ -void reposition_screen(nvScreenPtr screen, int advanced) +static void reposition_screen(nvScreenPtr screen, int resolve_all_modes) { int orig_screen_x = screen->dim[X]; int orig_screen_y = screen->dim[Y]; - + /* Resolve new relative positions. In basic mode, * relative position changes apply to all modes of a * display so we should resolve all modes (since they * were all changed.) */ - resolve_displays_in_screen(screen, !advanced); + resolve_displays_in_screen(screen, resolve_all_modes); /* Reestablish the screen's original position */ screen->dim[X] = orig_screen_x; @@ -1856,7 +1857,7 @@ static int move_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap) } /* Make sure the screen position does not change */ - reposition_screen(info->screen, ctk_object->advanced_mode); + reposition_screen(info->screen, !ctk_object->advanced_mode); /* Always update the modify dim for relative positioning */ info->modify_dirty = 1; } @@ -2819,11 +2820,7 @@ GtkWidget* ctk_display_layout_new(NvCtrlAttributeHandle *handle, CtkConfig *ctk_config, nvLayoutPtr layout, int width, - int height, - ctk_display_layout_selected_callback selected_callback, - void *selected_callback_data, - ctk_display_layout_modified_callback modified_callback, - void *modified_callback_data) + int height) { GObject *object; CtkDisplayLayout *ctk_object; @@ -2839,13 +2836,13 @@ GtkWidget* ctk_display_layout_new(NvCtrlAttributeHandle *handle, /* Create the ctk object */ object = g_object_new(CTK_TYPE_DISPLAY_LAYOUT, NULL); ctk_object = CTK_DISPLAY_LAYOUT(object); + ctk_object->selected_callback = NULL; + ctk_object->selected_callback_data = NULL; + ctk_object->modified_callback = NULL; + ctk_object->modified_callback_data = NULL; /* Setup widget properties */ ctk_object->ctk_config = ctk_config; - ctk_object->selected_callback = selected_callback; - ctk_object->selected_callback_data = selected_callback_data; - ctk_object->modified_callback = modified_callback; - ctk_object->modified_callback_data = modified_callback_data; ctk_object->handle = handle; ctk_object->layout = layout; @@ -3900,10 +3897,12 @@ void ctk_display_layout_set_mode_modeline(CtkDisplayLayout *ctk_object, mode->pan[H] = mode->display->modelines->data.vdisplay; } - /* The metamode that this mode belongs to should now be - * considered a user metamode. + /* In advanced mode, changing the resolution a display uses for a + * particular metamode should make this metamode non-implicit. */ - if (mode->metamode) { + if (ctk_object->advanced_mode && + (old_modeline != modeline) && + mode->metamode) { mode->metamode->source = METAMODE_SOURCE_NVCONTROL; } @@ -3931,6 +3930,7 @@ void ctk_display_layout_set_display_position(CtkDisplayLayout *ctk_object, GdkGC *fg_gc = get_widget_fg_gc(drawing_area); GdkGCValues old_gc_values; int modified = 0; + int resolve_all_modes = !ctk_object->advanced_mode; if (!display) return; @@ -3953,25 +3953,36 @@ void ctk_display_layout_set_display_position(CtkDisplayLayout *ctk_object, */ if (position_type != CONF_ADJ_ABSOLUTE) { - + nvDisplayPtr other; + nvModePtr mode; for (other = display->gpu->displays; other; other = other->next) { if (other->screen != display->screen) continue; - if (!other->cur_mode) continue; + if (!resolve_all_modes) { + mode = other->cur_mode; + if (mode && mode->relative_to == display) { + mode->position_type = CONF_ADJ_ABSOLUTE; + mode->relative_to = NULL; + } - if (other->cur_mode->relative_to == display) { - other->cur_mode->position_type = CONF_ADJ_ABSOLUTE; - other->cur_mode->relative_to = NULL; + } else { + + for (mode = other->modes; mode; mode = mode->next) { + if (mode->relative_to == display) { + mode->position_type = CONF_ADJ_ABSOLUTE; + mode->relative_to = NULL; + } + } } } } /* Set the new positioning type */ - if (ctk_object->advanced_mode) { + if (!resolve_all_modes) { display->cur_mode->position_type = position_type; display->cur_mode->relative_to = relative_to; @@ -4006,7 +4017,7 @@ void ctk_display_layout_set_display_position(CtkDisplayLayout *ctk_object, default: /* Make sure the screen position does not change */ - reposition_screen(display->screen, ctk_object->advanced_mode); + reposition_screen(display->screen, resolve_all_modes); /* Recalculate the layout */ ctk_display_layout_update(ctk_object); @@ -4361,6 +4372,28 @@ void ctk_display_layout_set_advanced_mode(CtkDisplayLayout *ctk_object, +/** ctk_display_layout_register_callbacks() ************************** + * + * Sets up callbacks so users of the display layout can recieve + * notifications. + * + **/ + +void ctk_display_layout_register_callbacks(CtkDisplayLayout *ctk_object, + ctk_display_layout_selected_callback selected_callback, + void *selected_callback_data, + ctk_display_layout_modified_callback modified_callback, + void *modified_callback_data) +{ + ctk_object->selected_callback = selected_callback; + ctk_object->selected_callback_data = selected_callback_data; + ctk_object->modified_callback = modified_callback; + ctk_object->modified_callback_data = modified_callback_data; + +} /* ctk_display_layout_register_callbacks() */ + + + /** expose_event_callback() ****************************************** * * Handles expose events. diff --git a/src/gtk+-2.x/ctkdisplaylayout.h b/src/gtk+-2.x/ctkdisplaylayout.h index 63b44c9..784094a 100644 --- a/src/gtk+-2.x/ctkdisplaylayout.h +++ b/src/gtk+-2.x/ctkdisplaylayout.h @@ -463,11 +463,7 @@ GtkWidget* ctk_display_layout_new (NvCtrlAttributeHandle *, CtkConfig *, nvLayoutPtr, /* Layout to display */ int, /* Width of image */ - int, /* Height of image */ - ctk_display_layout_selected_callback, - void *selected_callback_data, - ctk_display_layout_modified_callback, - void *modified_callback_data + int /* Height of image */ ); void ctk_display_layout_update (CtkDisplayLayout *); @@ -526,6 +522,11 @@ void ctk_display_layout_disable_display (CtkDisplayLayout *ctk_object, void ctk_display_layout_set_advanced_mode (CtkDisplayLayout *ctk_object, int advanced_mode); +void ctk_display_layout_register_callbacks(CtkDisplayLayout *ctk_object, + ctk_display_layout_selected_callback, + void *selected_callback_data, + ctk_display_layout_modified_callback, + void *modified_callback_data); G_END_DECLS diff --git a/src/gtk+-2.x/ctkditheringcontrols.c b/src/gtk+-2.x/ctkditheringcontrols.c new file mode 100644 index 0000000..6b1de92 --- /dev/null +++ b/src/gtk+-2.x/ctkditheringcontrols.c @@ -0,0 +1,683 @@ +/* + * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix + * and Linux systems. + * + * Copyright (C) 2010 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of Version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2 + * of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307, USA + * + */ + +#include <gtk/gtk.h> +#include <NvCtrlAttributes.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <errno.h> + +#include "ctkconfig.h" +#include "ctkhelp.h" +#include "ctkditheringcontrols.h" + +/* function prototypes */ +static gboolean build_dithering_mode_table(CtkDitheringControls *ctk_dithering_controls, + NVCTRLAttributeValidValuesRec valid); + +static gint map_nvctrl_value_to_table(CtkDitheringControls *ctk_dithering_controls, + gint val); + +static Bool update_dithering_mode_menu_info(gpointer user_data); + +static void dithering_mode_menu_changed(GtkOptionMenu *dithering_mode_menu, + gpointer user_data); +static void dithering_config_menu_changed(GtkOptionMenu *dithering_config_menu, + gpointer user_data); + +static void dithering_update_received(GtkObject *object, gpointer arg1, + gpointer user_data); + +static +void post_dithering_config_update(CtkDitheringControls *ctk_dithering_controls, + gint dithering_config); + +static +void post_dithering_mode_update(CtkDitheringControls *ctk_dithering_controls, + gint dithering_mode); + +/* macros */ +#define FRAME_PADDING 5 + +/* help text */ +static const char * __dithering_help = +"The Dithering Controls show the current state of dithering and allow " +"changing the dithering configuration and/or mode. Dithering will be " +"performed when dithering is enabled here, and the panel's bitdepth is " +"less than that of the GPU's internal pixel pipeline."; + +GType ctk_dithering_controls_get_type(void) +{ + static GType ctk_dithering_controls_type = 0; + + if (!ctk_dithering_controls_type) { + static const GTypeInfo ctk_dithering_controls_info = { + sizeof (CtkDitheringControlsClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init, */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (CtkDitheringControls), + 0, /* n_preallocs */ + NULL, /* instance_init */ + }; + + ctk_dithering_controls_type = + g_type_register_static (GTK_TYPE_VBOX, + "CtkDitheringControls", + &ctk_dithering_controls_info, 0); + } + + return ctk_dithering_controls_type; +} /* ctk_dithering_controls_get_type() */ + +GtkWidget* ctk_dithering_controls_new(NvCtrlAttributeHandle *handle, + CtkConfig *ctk_config, + CtkEvent *ctk_event, + GtkWidget *reset_button, + unsigned int display_device_mask, + char *name) +{ + GObject *object; + CtkDitheringControls *ctk_dithering_controls; + GtkWidget *frame, *vbox, *hbox, *label, *eventbox; + GtkWidget *menu, *table, *menu_item = NULL, *separator; + ReturnStatus ret1, ret2; + NVCTRLAttributeValidValuesRec valid1, valid2; + gint i; + + /* check if dithering configuration is supported */ + ret1 = NvCtrlGetValidDisplayAttributeValues(handle, display_device_mask, + NV_CTRL_DITHERING, + &valid1); + ret2 = NvCtrlGetValidDisplayAttributeValues(handle, display_device_mask, + NV_CTRL_DITHERING_MODE, + &valid2); + + if ((ret1 != NvCtrlSuccess) || (ret2 != NvCtrlSuccess) || + (valid1.type != ATTRIBUTE_TYPE_INTEGER) || + (valid2.type != ATTRIBUTE_TYPE_INT_BITS)) { + return NULL; + } + + /* create the object */ + object = g_object_new(CTK_TYPE_DITHERING_CONTROLS, NULL); + if (!object) { + return NULL; + } + + ctk_dithering_controls = CTK_DITHERING_CONTROLS(object); + ctk_dithering_controls->handle = handle; + ctk_dithering_controls->ctk_config = ctk_config; + ctk_dithering_controls->reset_button = reset_button; + ctk_dithering_controls->display_device_mask = display_device_mask; + ctk_dithering_controls->name = strdup(name); + + /* build a table holding available dithering modes */ + if (!build_dithering_mode_table(ctk_dithering_controls, valid2)) { + return NULL; + } + + /* create main dithering box & frame */ + + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, FRAME_PADDING); + ctk_dithering_controls->dithering_controls_main = hbox; + + frame = gtk_frame_new("Dithering Controls"); + eventbox = gtk_event_box_new(); + gtk_container_add(GTK_CONTAINER(eventbox), frame); + gtk_box_pack_start(GTK_BOX(hbox), eventbox, FALSE, FALSE, 0); + ctk_config_set_tooltip(ctk_config, eventbox, __dithering_help); + + table = gtk_table_new(3, 4, FALSE); + gtk_container_add(GTK_CONTAINER(frame), table); + gtk_table_set_row_spacings(GTK_TABLE(table), 5); + gtk_table_set_col_spacings(GTK_TABLE(table), 15); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + + /* Build Dithering widgets & pack them in table */ + /* dropdown list for dithering configuration */ + menu = gtk_menu_new(); + + menu_item = gtk_menu_item_new_with_label("Auto"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); + gtk_widget_show(menu_item); + + menu_item = gtk_menu_item_new_with_label("Enabled"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); + gtk_widget_show(menu_item); + + menu_item = gtk_menu_item_new_with_label("Disabled"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); + gtk_widget_show(menu_item); + + ctk_dithering_controls->dithering_config_menu = gtk_option_menu_new(); + gtk_option_menu_set_menu + (GTK_OPTION_MENU(ctk_dithering_controls->dithering_config_menu), + menu); + + g_signal_connect(G_OBJECT(ctk_dithering_controls->dithering_config_menu), + "changed", G_CALLBACK(dithering_config_menu_changed), + (gpointer) ctk_dithering_controls); + + /* Packing label & dropdown */ + hbox = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + + label = gtk_label_new("Dithering: "); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + hbox = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + gtk_box_pack_start(GTK_BOX(hbox), + ctk_dithering_controls->dithering_config_menu, + FALSE, FALSE, 0); + + /* Build CurrentDithering widget */ + hbox = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 2, 3, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Current Dithering: "); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + hbox = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 3, 4, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new(NULL); + ctk_dithering_controls->dithering_current_config = label; + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + /* H-bar */ + vbox = gtk_vbox_new(FALSE, 0); + separator = gtk_hseparator_new(); + gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, FALSE, 0); + gtk_table_attach(GTK_TABLE(table), vbox, 0, 4, 1, 2, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + + /* dropdown list for dithering modes */ + menu = gtk_menu_new(); + + for (i = 0; i < ctk_dithering_controls->dithering_mode_table_size; i++) { + switch (ctk_dithering_controls->dithering_mode_table[i]) { + case NV_CTRL_DITHERING_MODE_DYNAMIC_2X2: + menu_item = gtk_menu_item_new_with_label("Dynamic 2X2"); + break; + case NV_CTRL_DITHERING_MODE_STATIC_2X2: + menu_item = gtk_menu_item_new_with_label("Static 2X2"); + break; + default: + case NV_CTRL_DITHERING_MODE_AUTO: + menu_item = gtk_menu_item_new_with_label("Auto"); + break; + } + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); + gtk_widget_show(menu_item); + } + + ctk_dithering_controls->dithering_mode_menu = gtk_option_menu_new(); + gtk_option_menu_set_menu + (GTK_OPTION_MENU(ctk_dithering_controls->dithering_mode_menu), + menu); + + g_signal_connect(G_OBJECT(ctk_dithering_controls->dithering_mode_menu), + "changed", G_CALLBACK(dithering_mode_menu_changed), + (gpointer) ctk_dithering_controls); + + + /* pack the label & drop down */ + hbox = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 2, 3, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Mode: "); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + hbox = gtk_hbox_new(FALSE, 0); + ctk_dithering_controls->dithering_mode_box = hbox; + gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 2, 3, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + gtk_box_pack_start(GTK_BOX(hbox), + ctk_dithering_controls->dithering_mode_menu, + FALSE, FALSE, 0); + + /* Build CurrentMode widget */ + hbox = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 2, 3, 2, 3, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new("Current Mode: "); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + hbox = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox, 3, 4, 2, 3, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + label = gtk_label_new(NULL); + ctk_dithering_controls->dithering_current_mode = label; + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + gtk_widget_show_all(GTK_WIDGET(object)); + + ctk_dithering_controls_setup(ctk_dithering_controls); + + g_signal_connect(G_OBJECT(ctk_event), + CTK_EVENT_NAME(NV_CTRL_DITHERING), + G_CALLBACK(dithering_update_received), + (gpointer) ctk_dithering_controls); + g_signal_connect(G_OBJECT(ctk_event), + CTK_EVENT_NAME(NV_CTRL_DITHERING_MODE), + G_CALLBACK(dithering_update_received), + (gpointer) ctk_dithering_controls); + g_signal_connect(G_OBJECT(ctk_event), + CTK_EVENT_NAME(NV_CTRL_CURRENT_DITHERING), + G_CALLBACK(dithering_update_received), + (gpointer) ctk_dithering_controls); + g_signal_connect(G_OBJECT(ctk_event), + CTK_EVENT_NAME(NV_CTRL_CURRENT_DITHERING_MODE), + G_CALLBACK(dithering_update_received), + (gpointer) ctk_dithering_controls); + + return GTK_WIDGET(object); + +} /* ctk_dithering_controls_new() */ + + +/* + * ctk_dithering_controls_setup() - Setup routine for dithering attributes. Used + * in DFP setup stage as well as for updating the GUI when there is change in + * dithering mode or config (enabled/disabled). + */ +void ctk_dithering_controls_setup(CtkDitheringControls *ctk_dithering_controls) +{ + gint val; + + if (!ctk_dithering_controls) { + return; + } + + /* dithering */ + if (NvCtrlSuccess != + NvCtrlGetDisplayAttribute(ctk_dithering_controls->handle, + ctk_dithering_controls->display_device_mask, + NV_CTRL_DITHERING, &val)) { + val = NV_CTRL_DITHERING_AUTO; + } + + g_signal_handlers_block_by_func + (G_OBJECT(ctk_dithering_controls->dithering_config_menu), + G_CALLBACK(dithering_config_menu_changed), + (gpointer) ctk_dithering_controls); + + gtk_option_menu_set_history + (GTK_OPTION_MENU(ctk_dithering_controls->dithering_config_menu), + val); + + g_signal_handlers_unblock_by_func + (G_OBJECT(ctk_dithering_controls->dithering_config_menu), + G_CALLBACK(dithering_config_menu_changed), + (gpointer) ctk_dithering_controls); + + if (!update_dithering_mode_menu_info + ((gpointer)ctk_dithering_controls)) { + gtk_widget_set_sensitive(ctk_dithering_controls->dithering_controls_main, + FALSE); + gtk_widget_hide_all(ctk_dithering_controls->dithering_controls_main); + } + +} /* ctk_dithering_controls_setup() */ + + +static Bool update_dithering_mode_menu_info(gpointer user_data) +{ + CtkDitheringControls *ctk_dithering_controls = + CTK_DITHERING_CONTROLS(user_data); + gint val, dithering_mode = NV_CTRL_DITHERING_MODE_AUTO; + + /* dithering mode */ + if (NvCtrlSuccess != + NvCtrlGetDisplayAttribute(ctk_dithering_controls->handle, + ctk_dithering_controls->display_device_mask, + NV_CTRL_DITHERING_MODE, + &dithering_mode)) { + free(ctk_dithering_controls->dithering_mode_table); + return FALSE; + } + + dithering_mode = map_nvctrl_value_to_table(ctk_dithering_controls, + dithering_mode); + + g_signal_handlers_block_by_func + (G_OBJECT(ctk_dithering_controls->dithering_mode_menu), + G_CALLBACK(dithering_mode_menu_changed), + (gpointer) ctk_dithering_controls); + + gtk_option_menu_set_history + (GTK_OPTION_MENU(ctk_dithering_controls->dithering_mode_menu), + dithering_mode); + + g_signal_handlers_unblock_by_func + (G_OBJECT(ctk_dithering_controls->dithering_mode_menu), + G_CALLBACK(dithering_mode_menu_changed), + (gpointer) ctk_dithering_controls); + + /* current dithering */ + if (NvCtrlSuccess != + NvCtrlGetDisplayAttribute(ctk_dithering_controls->handle, + ctk_dithering_controls->display_device_mask, + NV_CTRL_CURRENT_DITHERING, &val)) { + val = NV_CTRL_CURRENT_DITHERING_DISABLED; + } + + if (val == NV_CTRL_CURRENT_DITHERING_ENABLED) { + gtk_label_set_text(GTK_LABEL(ctk_dithering_controls->dithering_current_config), + "Enabled"); + gtk_widget_set_sensitive(ctk_dithering_controls->dithering_mode_box, TRUE); + gtk_widget_show(ctk_dithering_controls->dithering_mode_box); + } else if (val == NV_CTRL_CURRENT_DITHERING_DISABLED) { + gtk_label_set_text(GTK_LABEL(ctk_dithering_controls->dithering_current_config), + "Disabled"); + gtk_widget_set_sensitive(ctk_dithering_controls->dithering_mode_box, FALSE); + } + + /* current dithering mode */ + dithering_mode = NV_CTRL_CURRENT_DITHERING_MODE_NONE; + if (NvCtrlSuccess != + NvCtrlGetDisplayAttribute(ctk_dithering_controls->handle, + ctk_dithering_controls->display_device_mask, + NV_CTRL_CURRENT_DITHERING_MODE, + &dithering_mode)) { + free(ctk_dithering_controls->dithering_mode_table); + return FALSE; + } + + switch (dithering_mode) { + case NV_CTRL_CURRENT_DITHERING_MODE_DYNAMIC_2X2: + gtk_label_set_text(GTK_LABEL(ctk_dithering_controls->dithering_current_mode), + "Dynamic 2x2"); + break; + case NV_CTRL_CURRENT_DITHERING_MODE_STATIC_2X2: + gtk_label_set_text(GTK_LABEL(ctk_dithering_controls->dithering_current_mode), + "Static 2x2"); + break; + default: + case NV_CTRL_CURRENT_DITHERING_MODE_NONE: + gtk_label_set_text(GTK_LABEL(ctk_dithering_controls->dithering_current_mode), + "None"); + break; + } + + return True; +} /* update_dithering_mode_menu_info() */ + +static +void post_dithering_config_update(CtkDitheringControls *ctk_dithering_controls, + gint dithering_config) +{ + static const char *dither_config_table[] = { + "Auto", /* NV_CTRL_DITHERING_AUTO */ + "Enabled", /* NV_CTRL_DITHERING_ENABLED */ + "Disabled" /* NV_CTRL_DITHERING_DISABLED */ + }; + + if (dithering_config < NV_CTRL_DITHERING_AUTO || + dithering_config > NV_CTRL_DITHERING_DISABLED) { + return; + } + + ctk_config_statusbar_message(ctk_dithering_controls->ctk_config, + "Dithering set to %s for %s.", + dither_config_table[dithering_config], + ctk_dithering_controls->name); +} + +static +void post_dithering_mode_update(CtkDitheringControls *ctk_dithering_controls, + gint dithering_mode) +{ + static const char *dither_mode_table[] = { + "Auto", /* NV_CTRL_DITHERING_MODE_AUTO */ + "Dynamic 2x2", /* NV_CTRL_DITHERING_MODE_DYNAMIC_2X2 */ + "Static 2x2" /* NV_CTRL_DITHERING_MODE_STATIC_2X2 */ + }; + + if (dithering_mode < NV_CTRL_DITHERING_MODE_AUTO || + dithering_mode > NV_CTRL_DITHERING_MODE_STATIC_2X2) { + return; + } + + ctk_config_statusbar_message(ctk_dithering_controls->ctk_config, + "Dithering mode set to %s for %s.", + dither_mode_table[dithering_mode], + ctk_dithering_controls->name); +} + +static void dithering_config_menu_changed(GtkOptionMenu *dithering_config_menu, + gpointer user_data) +{ + CtkDitheringControls *ctk_dithering_controls = + CTK_DITHERING_CONTROLS(user_data); + gint history, dithering_config = NV_CTRL_DITHERING_AUTO; + + history = gtk_option_menu_get_history(dithering_config_menu); + + switch (history) { + case 2: + dithering_config = NV_CTRL_DITHERING_DISABLED; + break; + case 1: + dithering_config = NV_CTRL_DITHERING_ENABLED; + break; + default: + case 0: + dithering_config = NV_CTRL_DITHERING_AUTO; + break; + } + + NvCtrlSetDisplayAttribute(ctk_dithering_controls->handle, + ctk_dithering_controls->display_device_mask, + NV_CTRL_DITHERING, + dithering_config); + + g_signal_handlers_block_by_func + (G_OBJECT(ctk_dithering_controls->dithering_config_menu), + G_CALLBACK(dithering_config_menu_changed), + (gpointer) ctk_dithering_controls); + + gtk_option_menu_set_history + (GTK_OPTION_MENU(ctk_dithering_controls->dithering_config_menu), + dithering_config); + + g_signal_handlers_unblock_by_func + (G_OBJECT(ctk_dithering_controls->dithering_config_menu), + G_CALLBACK(dithering_config_menu_changed), + (gpointer) ctk_dithering_controls); + + /* reflecting the change in configuration to other widgets & reset button */ + ctk_dithering_controls_setup(ctk_dithering_controls); + post_dithering_config_update(ctk_dithering_controls, dithering_config); + gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE); + +} /* dithering_config_menu_changed() */ + + +static void dithering_mode_menu_changed(GtkOptionMenu *dithering_mode_menu, + gpointer user_data) +{ + CtkDitheringControls *ctk_dithering_controls = + CTK_DITHERING_CONTROLS(user_data); + gint history, dithering_mode = NV_CTRL_DITHERING_MODE_AUTO; + + history = gtk_option_menu_get_history(dithering_mode_menu); + + dithering_mode = ctk_dithering_controls->dithering_mode_table[history]; + + NvCtrlSetDisplayAttribute(ctk_dithering_controls->handle, + ctk_dithering_controls->display_device_mask, + NV_CTRL_DITHERING_MODE, + dithering_mode); + + dithering_mode = map_nvctrl_value_to_table(ctk_dithering_controls, + dithering_mode); + g_signal_handlers_block_by_func + (G_OBJECT(ctk_dithering_controls->dithering_mode_menu), + G_CALLBACK(dithering_mode_menu_changed), + (gpointer) ctk_dithering_controls); + + gtk_option_menu_set_history + (GTK_OPTION_MENU(ctk_dithering_controls->dithering_mode_menu), + dithering_mode); + + g_signal_handlers_unblock_by_func + (G_OBJECT(ctk_dithering_controls->dithering_mode_menu), + G_CALLBACK(dithering_mode_menu_changed), + (gpointer) ctk_dithering_controls); + + /* reflecting the change in mode to other widgets & reset button */ + ctk_dithering_controls_setup(ctk_dithering_controls); + post_dithering_mode_update(ctk_dithering_controls, dithering_mode); + gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE); + +} /* dithering_mode_menu_changed() */ + + +/* + * ctk_dithering_controls_reset() - Resets the dithering config (enabled/disabled) + * & dithering mode when Reset HW Defaults is clicked + */ +void ctk_dithering_controls_reset(CtkDitheringControls *ctk_dithering_controls) +{ + if (!ctk_dithering_controls) { + return; + } + + NvCtrlSetDisplayAttribute(ctk_dithering_controls->handle, + ctk_dithering_controls->display_device_mask, + NV_CTRL_DITHERING, + NV_CTRL_DITHERING_AUTO); + + NvCtrlSetDisplayAttribute(ctk_dithering_controls->handle, + ctk_dithering_controls->display_device_mask, + NV_CTRL_DITHERING_MODE, + NV_CTRL_DITHERING_MODE_AUTO); + + ctk_dithering_controls_setup(ctk_dithering_controls); +} /* ctk_dithering_controls_reset() */ + + +/* + * add_dithering_controls_help() - + */ +void add_dithering_controls_help(CtkDitheringControls *ctk_dithering_controls, + GtkTextBuffer *b, + GtkTextIter *i) +{ + ctk_help_heading(b, i, "Dithering Controls"); + ctk_help_para(b, i, __dithering_help); +} /* add_dithering_controls_help() */ + + +/* + * When dithering configuration is enabled/disabled, + * we should update the GUI to reflect the current state & mode. + */ +static void dithering_update_received(GtkObject *object, gpointer arg1, + gpointer user_data) +{ + CtkDitheringControls *ctk_object = CTK_DITHERING_CONTROLS(user_data); + CtkEventStruct *event_struct = (CtkEventStruct *) arg1; + + /* if the event is not for this display device, return */ + + if (!(event_struct->display_mask & ctk_object->display_device_mask)) { + return; + } + + ctk_dithering_controls_setup(ctk_object); +} /* dithering_update_received() */ + + +/* + * 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, + NVCTRLAttributeValidValuesRec valid) +{ + gint i, n = 0, num_of_modes = 0; + gint mask = valid.u.bits.ints; + + if (valid.type != ATTRIBUTE_TYPE_INT_BITS) { + return False; + } + + /* count no. of supported modes */ + 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) { + 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() */ + + +static gint map_nvctrl_value_to_table(CtkDitheringControls *ctk_dithering_controls, + gint val) +{ + int i; + for (i = 0; i < ctk_dithering_controls->dithering_mode_table_size; i++) { + if (val == ctk_dithering_controls->dithering_mode_table[i]) { + return i; + } + } + + return 0; +} /*map_nvctrl_value_to_table() */ diff --git a/src/gtk+-2.x/ctkditheringcontrols.h b/src/gtk+-2.x/ctkditheringcontrols.h new file mode 100644 index 0000000..72178a1 --- /dev/null +++ b/src/gtk+-2.x/ctkditheringcontrols.h @@ -0,0 +1,98 @@ +/* + * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix + * and Linux systems. + * + * Copyright (C) 2010 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of Version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2 + * of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307, USA + * + */ + +#ifndef __CTK_DITHERING_CONTROLS_H__ +#define __CTK_DITHERING_CONTROLS_H__ + +#include "ctkevent.h" +#include "ctkconfig.h" + +G_BEGIN_DECLS + +#define CTK_TYPE_DITHERING_CONTROLS (ctk_dithering_controls_get_type()) + +#define CTK_DITHERING_CONTROLS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_DITHERING_CONTROLS, \ + CtkDitheringControls)) + +#define CTK_DITHERING_CONTROLS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_DITHERING_CONTROLS, \ + CtkDitheringControlsClass)) + +#define CTK_IS_DITHERING_CONTROLS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_DITHERING_CONTROLS)) + +#define CTK_IS_DITHERING_CONTROLS_CLASS(class) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_DITHERING_CONTROLS)) + +#define CTK_DITHERING_CONTROLS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_DITHERING_CONTROLS, \ + CtkDitheringControlsClass)) + +typedef struct _CtkDitheringControls CtkDitheringControls; +typedef struct _CtkDitheringControlsClass CtkDitheringControlsClass; + +struct _CtkDitheringControls +{ + GtkVBox parent; + + NvCtrlAttributeHandle *handle; + CtkConfig *ctk_config; + GtkWidget *reset_button; + GtkWidget *dithering_controls_main; + GtkWidget *dithering_mode_box; + + GtkWidget *dithering_config_menu; + GtkWidget *dithering_mode_menu; + GtkWidget *dithering_current_config; + GtkWidget *dithering_current_mode; + + gint display_device_mask; + gint *dithering_mode_table; + gint dithering_mode_table_size; + gint default_dithering_config; + gint default_dithering_mode; + char *name; +}; + +struct _CtkDitheringControlsClass +{ + GtkVBoxClass parent_class; +}; + +GType ctk_dithering_controls_get_type (void) G_GNUC_CONST; +GtkWidget* ctk_dithering_controls_new (NvCtrlAttributeHandle *, + CtkConfig *, CtkEvent *, + GtkWidget *, + unsigned int display_device_mask, + char *); + +void ctk_dithering_controls_reset (CtkDitheringControls*); +void ctk_dithering_controls_setup (CtkDitheringControls*); +void add_dithering_controls_help (CtkDitheringControls*, GtkTextBuffer *b, + GtkTextIter *i); + +G_END_DECLS + +#endif /* __CTK_DITHERING_CONTROLS_H__ */ diff --git a/src/gtk+-2.x/ctkedid.c b/src/gtk+-2.x/ctkedid.c index 6c625ea..aacd26c 100644 --- a/src/gtk+-2.x/ctkedid.c +++ b/src/gtk+-2.x/ctkedid.c @@ -35,23 +35,32 @@ #include <sys/types.h> #include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/mman.h> +#include <stdio.h> +#include <stdlib.h> #include <errno.h> #define FRAME_PADDING 5 -#define DEFAULT_EDID_FILENAME "edid.bin" +/* file formats */ +#define FILE_FORMAT_BINARY 1 +#define FILE_FORMAT_ASCII 2 + +/* default file names */ +#define DEFAULT_EDID_FILENAME_BINARY "edid.bin" +#define DEFAULT_EDID_FILENAME_ASCII "edid.txt" static const char *__acquire_edid_help = "The Acquire EDID button allows you to save the display device's EDID " -"(Extended Display Identification Data) information to a file."; +"(Extended Display Identification Data) information to a file. By " +"default it saves information in binary format but one can also choose " +"to save in ASCII format."; +static void file_format_changed(GtkWidget *widget, gpointer user_data); +static void normalize_filename(CtkEdid *ctk_edid); static void button_clicked(GtkButton *button, gpointer user_data); static gboolean write_edid_to_file(CtkConfig *ctk_config, const gchar *filename, - unsigned char *data, int len); + int format, unsigned char *data, int len); GType ctk_edid_get_type(void) { @@ -110,13 +119,15 @@ GtkWidget* ctk_edid_new(NvCtrlAttributeHandle *handle, ctk_edid->reset_button = reset_button; ctk_edid->display_device_mask = display_device_mask; ctk_edid->name = name; - ctk_edid->filename = DEFAULT_EDID_FILENAME; + ctk_edid->filename = DEFAULT_EDID_FILENAME_BINARY; + ctk_edid->file_format = FILE_FORMAT_BINARY; ctk_edid->file_selector = gtk_file_selection_new("Please select file where " "EDID data will be " "saved."); - gtk_file_selection_set_select_multiple(GTK_FILE_SELECTION(ctk_edid->file_selector), - FALSE); + gtk_file_selection_set_select_multiple + (GTK_FILE_SELECTION(ctk_edid->file_selector), + FALSE); /* create the frame and vbox */ @@ -148,6 +159,47 @@ GtkWidget* ctk_edid_new(NvCtrlAttributeHandle *handle, G_CALLBACK(button_clicked), (gpointer) ctk_edid); + /* adding file format selection option to file selector dialog */ + + frame = gtk_frame_new(NULL); + gtk_box_pack_start + (GTK_BOX(GTK_FILE_SELECTION(ctk_edid->file_selector)->main_vbox), + frame, FALSE, FALSE, 15); + gtk_box_reorder_child + (GTK_BOX(GTK_FILE_SELECTION(ctk_edid->file_selector)->main_vbox), + frame, 0); + + hbox = gtk_hbox_new(FALSE, 10); + gtk_container_set_border_width(GTK_CONTAINER(hbox), FRAME_PADDING); + gtk_container_add(GTK_CONTAINER(frame), hbox); + + label = gtk_label_new("EDID File Format: "); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + ctk_edid->file_format_binary_radio_button = + gtk_radio_button_new_with_label(NULL, "Binary"); + gtk_box_pack_start(GTK_BOX(hbox), ctk_edid->file_format_binary_radio_button, + FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(ctk_edid->file_format_binary_radio_button), + "toggled", G_CALLBACK(file_format_changed), + (gpointer) ctk_edid); + + ctk_edid->file_format_ascii_radio_button = + gtk_radio_button_new_with_label_from_widget + (GTK_RADIO_BUTTON(ctk_edid->file_format_binary_radio_button), + "ASCII"); + gtk_box_pack_start(GTK_BOX(hbox), ctk_edid->file_format_ascii_radio_button, + FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(ctk_edid->file_format_ascii_radio_button), + "toggled", G_CALLBACK(file_format_changed), + (gpointer) ctk_edid); + + gtk_window_set_resizable(GTK_WINDOW(ctk_edid->file_selector), + FALSE); + gtk_toggle_button_set_active + (GTK_TOGGLE_BUTTON(ctk_edid->file_format_binary_radio_button), TRUE); + gtk_widget_show_all(GTK_FILE_SELECTION(ctk_edid->file_selector)->main_vbox); + gtk_widget_show_all(GTK_WIDGET(object)); return GTK_WIDGET(object); @@ -155,6 +207,83 @@ GtkWidget* ctk_edid_new(NvCtrlAttributeHandle *handle, } /* ctk_edid_new() */ +static void normalize_filename(CtkEdid *ctk_edid) +{ + char *buffer = NULL, *filename = NULL; + char *end = NULL, *slash = NULL; + int len = 0, n; + + ctk_edid->filename = + gtk_file_selection_get_filename(GTK_FILE_SELECTION(ctk_edid->file_selector)); + + len = strlen(ctk_edid->filename); + filename = malloc(len + 1); + if (!filename) { + goto done; + } + strncpy(filename, ctk_edid->filename, len); + + /* + * It is possible that filename is entered without any extension, + * in that case we need to make room for the extension string e.g. + * '.bin' or '.txt', so total buffer length will be filename plus 5. + */ + buffer = malloc(len + 5); + if (!buffer) { + goto done; + } + + /* find the last forward slash (or the start of the filename) */ + + slash = strrchr(filename, '/'); + if (!slash) { + slash = filename; + } + + /* + * find where to truncate the filename: either the last period + * after 'slash', or the end of the filename + */ + + for (end = filename + len; end > slash; end--) { + if (*end == '.') break; + } + + if (end == slash) { + end = filename + len; + } + + /* + * print the characters between filename and end; then append the + * suffix + */ + n = end - filename; + strncpy(buffer, filename, n); + + if (gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON(ctk_edid->file_format_binary_radio_button))) { + ctk_edid->file_format = FILE_FORMAT_BINARY; + snprintf(buffer + n, 5, ".bin"); + } else if (gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON(ctk_edid->file_format_ascii_radio_button))) { + ctk_edid->file_format = FILE_FORMAT_ASCII; + snprintf(buffer + n, 5, ".txt"); + } + + /* modify the file name as per the format selected */ + gtk_file_selection_set_filename(GTK_FILE_SELECTION(ctk_edid->file_selector), + buffer); + done: + free(filename); + free(buffer); +} + +static void file_format_changed(GtkWidget *widget, gpointer user_data) +{ + CtkEdid *ctk_edid = CTK_EDID(user_data); + normalize_filename(ctk_edid); +} + static void button_clicked(GtkButton *button, gpointer user_data) { ReturnStatus ret; @@ -188,11 +317,12 @@ static void button_clicked(GtkButton *button, gpointer user_data) case GTK_RESPONSE_ACCEPT: case GTK_RESPONSE_OK: + normalize_filename(ctk_edid); ctk_edid->filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(ctk_edid->file_selector)); write_edid_to_file(ctk_edid->ctk_config, ctk_edid->filename, - data, len); + ctk_edid->file_format, data, len); break; default: @@ -209,51 +339,77 @@ static void button_clicked(GtkButton *button, gpointer user_data) static gboolean write_edid_to_file(CtkConfig *ctk_config, const gchar *filename, - unsigned char *data, int len) + int format, unsigned char *data, int len) { - int fd = -1; - char *dst = (void *) -1; + int i; + FILE *fp = NULL; char *msg = ""; + char *tmpbuf = NULL, *pbuf = NULL; - fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR | S_IRGRP); - if (fd == -1) { - msg = "Unable to open file for writing"; - goto fail; - } - - if (lseek(fd, len - 1, SEEK_SET) == -1) { - msg = "Unable to set file size"; - goto fail; - } - - if (write(fd, "", 1) != 1) { - msg = "Unable to write output file size"; - goto fail; - } - - if ((dst = mmap(0, len, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0)) == (void *) -1) { - msg = "Unable to map file for copying"; - goto fail; - } - - memcpy(dst, data, len); - - if (munmap(dst, len) == -1) { - msg = "Unable to unmap output file"; - goto fail; + + if (format == FILE_FORMAT_ASCII) { + fp = fopen(filename, "wt"); + if (!fp) { + msg = "ASCII Mode: Unable to open file for writing"; + goto fail; + } + /* + * for printing every member we reserve 2 locations i.e. %02x and + * one extra space to comply with NVIDIA Windows Control Panel + * ASCII file output, so in all 3 bytes are required for every entry. + */ + tmpbuf = calloc(1, 1 + (len * 3)); + if (!tmpbuf) { + msg = "ASCII Mode: Could not allocate enough memory"; + goto fail; + } + pbuf = tmpbuf; + + for (i = 0; i < len; i++) { + if (sprintf(pbuf, "%02x ", data[i]) < 0) { + msg = "ASCII Mode: Unable to write to buffer"; + goto fail; + } + pbuf = pbuf + 3; + } + /* being extra cautious */ + sprintf(pbuf, "%c", '\0'); + + if (fprintf(fp, "%s", tmpbuf) < 0) { + msg = "ASCII Mode: Unable to write to file"; + goto fail; + } + + free(tmpbuf); + tmpbuf = pbuf = NULL; + + } else { + fp = fopen(filename, "wb"); + if (!fp) { + msg = "Binary Mode: Unable to open file for writing"; + goto fail; + } + + if (fwrite(data, 1, len, fp) != len) { + msg = "Binary Mode: Unable to write to file"; + goto fail; + } } - - close(fd); - + + fclose(fp); + ctk_config_statusbar_message(ctk_config, "EDID written to %s.", filename); return TRUE; fail: - if (fd != -1) close(fd); + free(tmpbuf); + tmpbuf = pbuf = NULL; + + if (fp) { + fclose(fp); + } ctk_config_statusbar_message(ctk_config, "Unable to write EDID to file '%s': %s (%s).", diff --git a/src/gtk+-2.x/ctkedid.h b/src/gtk+-2.x/ctkedid.h index 80a4258..1f48c0f 100644 --- a/src/gtk+-2.x/ctkedid.h +++ b/src/gtk+-2.x/ctkedid.h @@ -62,11 +62,14 @@ struct _CtkEdid GtkWidget *reset_button; GtkWidget *button; GtkWidget *file_selector; + GtkWidget *file_format_binary_radio_button; + GtkWidget *file_format_ascii_radio_button; const gchar *filename; char *name; unsigned int display_device_mask; + gint file_format; }; struct _CtkEdidClass diff --git a/src/gtk+-2.x/ctkevent.c b/src/gtk+-2.x/ctkevent.c index c3e369e..7acaea6 100644 --- a/src/gtk+-2.x/ctkevent.c +++ b/src/gtk+-2.x/ctkevent.c @@ -302,9 +302,17 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_SIGNAL(NV_CTRL_GPU_CORES); MAKE_SIGNAL(NV_CTRL_GPU_MEMORY_BUS_WIDTH); MAKE_SIGNAL(NV_CTRL_GVI_TEST_MODE); + MAKE_SIGNAL(NV_CTRL_COLOR_SPACE); + MAKE_SIGNAL(NV_CTRL_COLOR_RANGE); + MAKE_SIGNAL(NV_CTRL_DITHERING); + MAKE_SIGNAL(NV_CTRL_DITHERING_MODE); + MAKE_SIGNAL(NV_CTRL_CURRENT_DITHERING); + MAKE_SIGNAL(NV_CTRL_CURRENT_DITHERING_MODE); MAKE_SIGNAL(NV_CTRL_THERMAL_SENSOR_READING); MAKE_SIGNAL(NV_CTRL_THERMAL_SENSOR_PROVIDER); MAKE_SIGNAL(NV_CTRL_THERMAL_SENSOR_TARGET); + MAKE_SIGNAL(NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS); + MAKE_SIGNAL(NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS); MAKE_SIGNAL(NV_CTRL_GPU_PCIE_MAX_LINK_SPEED); #undef MAKE_SIGNAL @@ -358,9 +366,10 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_STRING_SIGNAL(NV_CTRL_STRING_SLI_MODE); MAKE_STRING_SIGNAL(NV_CTRL_STRING_PERFORMANCE_MODES); MAKE_STRING_SIGNAL(NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME); + MAKE_STRING_SIGNAL(NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS); #undef MAKE_STRING_SIGNAL -#if NV_CTRL_STRING_LAST_ATTRIBUTE != NV_CTRL_STRING_GVO_VIDEO_FORMAT_NAME +#if NV_CTRL_STRING_LAST_ATTRIBUTE != NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS #warning "There are attributes that do not emit signals!" #endif diff --git a/src/gtk+-2.x/ctkframelock.c b/src/gtk+-2.x/ctkframelock.c index c9e1ad9..d0c3e01 100644 --- a/src/gtk+-2.x/ctkframelock.c +++ b/src/gtk+-2.x/ctkframelock.c @@ -287,8 +287,8 @@ static const char * __use_house_sync_button_help = "(if a house sync signal is detected) instead of using internal timing from " "the server GPU/display device."; -static const char * __sync_interval_entry_help = -"The Sync Interval entry allows you to set the number of incoming house sync " +static const char * __sync_interval_scale_help = +"The Sync Interval allows you to set the number of incoming house sync " "pulses the master frame lock board recieves before generating an outgoing " "frame lock sync pulse. A value of 0 means a frame lock sync pulse is sent " "for every house sync pulse."; @@ -350,7 +350,7 @@ static void toggle_server(GtkWidget *, gpointer); static void toggle_client(GtkWidget *, gpointer); static void toggle_sync_enable(GtkWidget *, gpointer); static void toggle_test_link(GtkWidget *, gpointer); -static void activate_sync_interval(GtkEntry *, gpointer); +static void sync_interval_changed(GtkRange *, gpointer); static void changed_video_mode(GtkEditable *, gpointer); static void toggle_detect_video_mode(GtkToggleButton *, gpointer); @@ -3151,24 +3151,23 @@ static void toggle_test_link(GtkWidget *button, gpointer data) -/** activate_sync_interval() ***************************************** +/** sync_interval_changed() ***************************************** * * Callback function for when the user changes the house sync * interval. * */ -static void activate_sync_interval(GtkEntry *widget, gpointer user_data) +static void sync_interval_changed(GtkRange *range, gpointer user_data) { CtkFramelock *ctk_framelock = (CtkFramelock *)user_data; nvListTreePtr tree = (nvListTreePtr)(ctk_framelock->tree); nvListEntryPtr entry = get_framelock_server_entry(tree); - nvFrameLockDataPtr data; - const gchar *str = gtk_entry_get_text(widget); - gint interval; - - if (!entry || !str) return; + nvFrameLockDataPtr data = NULL; + gint interval = gtk_range_get_value(range); - interval = strtol(str, NULL, 10); + if (!entry) { + return; + } data = (nvFrameLockDataPtr)(entry->data); @@ -3177,6 +3176,20 @@ static void activate_sync_interval(GtkEntry *widget, gpointer user_data) } +/* + * format_sync_interval() - callback for the "format-value" signal from + * the sync interval scale; return a string describing the current value of the + * scale. + */ +static gchar *format_sync_interval(GtkScale *scale, gdouble arg1, + gpointer user_data) +{ + gint val = (gint)arg1; + + return g_strdup_printf("%d", val); + +} + /** changed_sync_edge() ********************************************** * @@ -3786,16 +3799,15 @@ static void update_house_sync_controls(CtkFramelock *ctk_framelock) gtk_widget_set_sensitive(ctk_framelock->house_sync_frame, !enabled); if (enabled || !use_house) { - gtk_widget_set_sensitive(ctk_framelock->house_sync_hbox, FALSE); + gtk_widget_set_sensitive(ctk_framelock->house_sync_vbox, FALSE); } else { gint sync_interval; gint sync_edge; gint house_format; - gchar str[32]; nvFrameLockDataPtr data; - gtk_widget_set_sensitive(ctk_framelock->house_sync_hbox, TRUE); + gtk_widget_set_sensitive(ctk_framelock->house_sync_vbox, TRUE); data = (nvFrameLockDataPtr)(entry->data); @@ -3812,9 +3824,18 @@ static void update_house_sync_controls(CtkFramelock *ctk_framelock) /* Update GUI to reflect server settings */ - snprintf(str, 32, "%d", sync_interval); - gtk_entry_set_text(GTK_ENTRY(ctk_framelock->sync_interval_entry), - str); + g_signal_handlers_block_by_func + (G_OBJECT(ctk_framelock->sync_interval_scale), + G_CALLBACK(sync_interval_changed), + (gpointer) ctk_framelock); + + gtk_range_set_value(GTK_RANGE(ctk_framelock->sync_interval_scale), + sync_interval); + + g_signal_handlers_unblock_by_func + (G_OBJECT(ctk_framelock->sync_interval_scale), + G_CALLBACK(sync_interval_changed), + (gpointer) ctk_framelock); if (sync_edge < NV_CTRL_FRAMELOCK_POLARITY_RISING_EDGE) sync_edge = NV_CTRL_FRAMELOCK_POLARITY_RISING_EDGE; @@ -4130,7 +4151,6 @@ static void framelock_state_received(GtkObject *object, nvListEntryPtr server_entry = get_framelock_server_entry(entry->tree); - char str[32]; gint sync_edge; gint house_format; @@ -4160,17 +4180,16 @@ static void framelock_state_received(GtkObject *object, case NV_CTRL_FRAMELOCK_SYNC_INTERVAL: g_signal_handlers_block_by_func - (G_OBJECT(ctk_framelock->sync_interval_entry), - G_CALLBACK(activate_sync_interval), + (G_OBJECT(ctk_framelock->sync_interval_scale), + G_CALLBACK(sync_interval_changed), (gpointer) ctk_framelock); - snprintf(str, 32, "%d", event->value); - gtk_entry_set_text(GTK_ENTRY(ctk_framelock->sync_interval_entry), - str); + gtk_range_set_value(GTK_RANGE(ctk_framelock->sync_interval_scale), + event->value); g_signal_handlers_unblock_by_func - (G_OBJECT(ctk_framelock->sync_interval_entry), - G_CALLBACK(activate_sync_interval), + (G_OBJECT(ctk_framelock->sync_interval_scale), + G_CALLBACK(sync_interval_changed), (gpointer) ctk_framelock); break; @@ -4310,20 +4329,23 @@ GtkWidget* ctk_framelock_new(NvCtrlAttributeHandle *handle, ReturnStatus ret; unsigned int num_framelocks; gchar *string; + gint val; GtkWidget *frame; GtkWidget *padding; GtkWidget *sw; /* Scrollable window */ GtkWidget *vp; /* Viewport */ + GtkWidget *scale; + GtkObject *adjustment; GtkWidget *hbox; GtkWidget *vbox; GtkWidget *label; - GtkWidget *entry; GtkWidget *combo; GList *glist; GtkWidget *button; GtkWidget *image; + NVCTRLAttributeValidValuesRec valid; @@ -4605,33 +4627,60 @@ GtkWidget* ctk_framelock_new(NvCtrlAttributeHandle *handle, gtk_box_pack_start(GTK_BOX(hbox), ctk_framelock->use_house_sync, FALSE, FALSE, 0); - padding = gtk_hbox_new(FALSE, 5); - ctk_framelock->house_sync_hbox = padding; + padding = gtk_vbox_new(FALSE, 5); + ctk_framelock->house_sync_vbox = padding; gtk_box_pack_start(GTK_BOX(vbox), padding, FALSE, FALSE, 0); /* add the house sync interval */ { GtkWidget *frame2 = gtk_frame_new(NULL); + + ret = NvCtrlGetValidAttributeValues(ctk_framelock->attribute_handle, + NV_CTRL_FRAMELOCK_SYNC_INTERVAL, + &valid); + /* + * pick a conservative default range if we could not query the + * range from NV-CONTROL + */ + + if ((ret != NvCtrlSuccess) || (valid.type != ATTRIBUTE_TYPE_RANGE)) { + valid.type = ATTRIBUTE_TYPE_RANGE; + valid.u.range.min = 0; + valid.u.range.max = 4; + } + + if (NvCtrlSuccess != + NvCtrlGetAttribute(ctk_framelock->attribute_handle, + NV_CTRL_FRAMELOCK_SYNC_INTERVAL, + &val)) { + return NULL; + } + hbox = gtk_hbox_new(FALSE, 5); label = gtk_label_new("Sync Interval:"); - entry = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(entry), "0"); - gtk_entry_set_width_chars(GTK_ENTRY(entry), 4); - g_signal_connect(G_OBJECT(entry), - "activate", G_CALLBACK(activate_sync_interval), + + adjustment = gtk_adjustment_new(val, valid.u.range.min, + valid.u.range.max, 1, 1, 0); + scale = gtk_hscale_new(GTK_ADJUSTMENT(adjustment)); + gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustment), val); + + gtk_scale_set_draw_value(GTK_SCALE(scale), TRUE); + gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_TOP); + + g_signal_connect(G_OBJECT(scale), "format-value", + G_CALLBACK(format_sync_interval), + (gpointer) ctk_framelock); + g_signal_connect(G_OBJECT(scale), "value-changed", + G_CALLBACK(sync_interval_changed), (gpointer) ctk_framelock); - ctk_config_set_tooltip(ctk_config, entry, __sync_interval_entry_help); + ctk_config_set_tooltip(ctk_config, scale, __sync_interval_scale_help); + ctk_framelock->sync_interval_frame = frame2; - ctk_framelock->sync_interval_entry = entry; + ctk_framelock->sync_interval_scale = scale; gtk_box_pack_start(GTK_BOX(padding), frame2, FALSE, FALSE, 0); - - gtk_entry_set_text(GTK_ENTRY(entry), "0"); - gtk_entry_set_width_chars(GTK_ENTRY(entry), 4); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5); - gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, TRUE, 5); - + gtk_box_pack_start(GTK_BOX(hbox), scale, TRUE, TRUE, 5); gtk_container_add(GTK_CONTAINER(frame2), hbox); } @@ -5779,7 +5828,7 @@ GtkTextBuffer *ctk_framelock_create_help(GtkTextTagTable *table) "fall back to using internal timings from the primary GPU."); ctk_help_heading(b, &i, "Sync Interval"); - ctk_help_para(b, &i, __sync_interval_entry_help); + ctk_help_para(b, &i, __sync_interval_scale_help); ctk_help_heading(b, &i, "Sync Edge"); ctk_help_para(b, &i, __sync_edge_combo_help); diff --git a/src/gtk+-2.x/ctkframelock.h b/src/gtk+-2.x/ctkframelock.h index 24f3ad3..96398ee 100644 --- a/src/gtk+-2.x/ctkframelock.h +++ b/src/gtk+-2.x/ctkframelock.h @@ -76,10 +76,10 @@ struct _CtkFramelock /* House sync */ GtkWidget *house_sync_frame; - GtkWidget *house_sync_hbox; + GtkWidget *house_sync_vbox; GtkWidget *use_house_sync; GtkWidget *sync_interval_frame; - GtkWidget *sync_interval_entry; + GtkWidget *sync_interval_scale; GtkWidget *sync_edge_frame; GtkWidget *sync_edge_combo; GtkWidget *video_mode_frame; diff --git a/src/gtk+-2.x/ctkgvi.c b/src/gtk+-2.x/ctkgvi.c index 1087009..d2a89d5 100755 --- a/src/gtk+-2.x/ctkgvi.c +++ b/src/gtk+-2.x/ctkgvi.c @@ -751,25 +751,21 @@ GtkTextBuffer *ctk_gvi_create_help(GtkTextTagTable *table, ctk_help_para(b, &i, "This is the interrupt request line assigned to " "this GVI device."); - ctk_help_heading(b, &i, "Fill A"); - ctk_help_para(b, &i, "This reports the detected incoming video format on " - "first jack on the GVI device."); - - ctk_help_heading(b, &i, "Key A"); - ctk_help_para(b, &i, "This reports the detected incoming video format on " - "second jack on the GVI device."); - - ctk_help_heading(b, &i, "Fill B"); - ctk_help_para(b, &i, "This reports the detected incoming video format on " - "third jack on the GVI device."); - - ctk_help_heading(b, &i, "Key B"); - ctk_help_para(b, &i, "This reports the detected incoming video format on " - "fourth jack on the GVI device."); - - ctk_help_heading(b, &i, "Sync Output"); - ctk_help_para(b, &i, "This reports the output sync signal from " - "the GVI device."); + ctk_help_heading(b, &i, "Input Information"); + ctk_help_para(b, &i, "This section shows the detected video format(s) on " + "each jack of the GVI device. When condensed mode is " + "selected, the detected video format is shown for each " + "jack (and channel). when detailed mode is selected, " + "information pertaining to the single channel on a jack " + "selected is given as such:"); + + ctk_help_para(b, &i, "Video Format: The detected SMPTE video format."); + ctk_help_para(b, &i, "Component Sampling: The detected composition of the " + "channel."); + ctk_help_para(b, &i, "Color Space: The detected color space."); + ctk_help_para(b, &i, "Bites Per Component: The detected number of bits " + "per component."); + ctk_help_para(b, &i, "Link ID: The detected link ID of the channel."); ctk_help_finish(b); diff --git a/src/gtk+-2.x/ctkgvo-csc.c b/src/gtk+-2.x/ctkgvo-csc.c index 51433b0..e511968 100644 --- a/src/gtk+-2.x/ctkgvo-csc.c +++ b/src/gtk+-2.x/ctkgvo-csc.c @@ -930,64 +930,41 @@ static void initialize_csc_dropdown_changed(CtkDropDownMenu *menu, gpointer user_data) { CtkGvoCsc *ctk_gvo_csc = (CtkGvoCsc *) user_data; - const gfloat (*std)[5]; + const float *std = NULL; gint column, row, value; - - // red green blue offset scale - static const float itu601[3][5] = { - { 0.2991, 0.5870, 0.1150, 0.0625, 0.85547 }, // Y - { 0.5000, -0.4185, -0.0810, 0.5000, 0.87500 }, // Cr - { -0.1685, -0.3310, 0.5000, 0.5000, 0.87500 }, // Cb - }; - - static const float itu709[3][5] = { - { 0.2130, 0.7156, 0.0725, 0.0625, 0.85547 }, // Y - { 0.5000, -0.4542, -0.0455, 0.5000, 0.87500 }, // Cr - { -0.1146, -0.3850, 0.5000, 0.5000, 0.87500 }, // Cb - }; - - static const float itu177[3][5] = { - { 0.412391, 0.357584, 0.180481, 0.0, 0.85547 }, // Y - { 0.019331, 0.119195, 0.950532, 0.0, 0.87500 }, // Cr - { 0.212639, 0.715169, 0.072192, 0.0, 0.87500 }, // Cb - }; - - static const float identity[3][5] = { - { 0.0000, 1.0000, 0.0000, 0.0000, 1.0 }, // Y (Green) - { 1.0000, 0.0000, 0.0000, 0.0000, 1.0 }, // Cr (Red) - { 0.0000, 0.0000, 1.0000, 0.0000, 1.0 }, // Cb (Blue) - }; - value = ctk_drop_down_menu_get_current_value(menu); - + switch (value) { - case CSC_STANDARD_ITU_601: std = itu601; break; - case CSC_STANDARD_ITU_709: std = itu709; break; - case CSC_STANDARD_ITU_177: std = itu177; break; - case CSC_STANDARD_IDENTITY: std = identity; break; - default: return; + case CSC_STANDARD_ITU_601: std = nv_get_sdi_csc_matrix("itu_601"); break; + case CSC_STANDARD_ITU_709: std = nv_get_sdi_csc_matrix("itu_709"); break; + case CSC_STANDARD_ITU_177: std = nv_get_sdi_csc_matrix("itu_177"); break; + case CSC_STANDARD_IDENTITY: std = nv_get_sdi_csc_matrix("identity"); break; + default: return; } - + if (!std) { + return; + } + for (row = 0; row < 3; row++) { for (column = 0; column < 3; column++) { - ctk_gvo_csc->matrix[row][column] = std[row][column]; + ctk_gvo_csc->matrix[row][column] = std[row*5 + column]; gtk_spin_button_set_value (GTK_SPIN_BUTTON(ctk_gvo_csc->matrixWidget[row][column]), ctk_gvo_csc->matrix[row][column]); } - - ctk_gvo_csc->offset[row] = std[row][3]; + + ctk_gvo_csc->offset[row] = std[row*5 + 3]; gtk_spin_button_set_value (GTK_SPIN_BUTTON(ctk_gvo_csc->offsetWidget[row]), ctk_gvo_csc->offset[row]); - ctk_gvo_csc->scale[row] = std[row][4]; + ctk_gvo_csc->scale[row] = std[row*5 + 4]; gtk_spin_button_set_value (GTK_SPIN_BUTTON(ctk_gvo_csc->scaleWidget[row]), ctk_gvo_csc->scale[row]); } - + /* * the data has changed, make sure the apply button is sensitive */ diff --git a/src/gtk+-2.x/ctkgvo.c b/src/gtk+-2.x/ctkgvo.c index 614a88c..417f51f 100644 --- a/src/gtk+-2.x/ctkgvo.c +++ b/src/gtk+-2.x/ctkgvo.c @@ -1428,6 +1428,10 @@ static void output_video_format_ui_changed(CtkDropDownMenu *menu, update_gvo_sensitivity(ctk_gvo); + /* Made GVO banner to update current output video format */ + CTK_GVO_BANNER(ctk_gvo->banner)->output_video_format = + ctk_gvo->output_video_format; + post_output_video_format_changed(ctk_gvo); } /* output_video_format_ui_changed() */ diff --git a/src/gtk+-2.x/ctkimagesliders.c b/src/gtk+-2.x/ctkimagesliders.c index 761acf3..5450436 100644 --- a/src/gtk+-2.x/ctkimagesliders.c +++ b/src/gtk+-2.x/ctkimagesliders.c @@ -340,6 +340,27 @@ void ctk_image_sliders_reset(CtkImageSliders *ctk_image_sliders) 0); } + /* + * The above may have triggered events (e.g., changing + * NV_CTRL_OVERSCAN_COMPENSATION may trigger an + * NV_CTRL_IMAGE_SHARPENING value change). Such an event will + * cause scale_value_changed() and post_scale_value_changed() to + * be called when control returns to the gtk_main loop. + * post_scale_value_changed() will write a status message to the + * statusbar. + * + * However, the caller of ctk_image_sliders_reset() (e.g., + * ctkdisplaydevice-dfp.c:reset_button_clicked()) may also want to + * write a status message to the statusbar. To ensure that the + * caller's statusbar message takes precedence (i.e., is the last + * thing written to the statusbar), process any generated events + * now, before returning to the caller. + */ + + while (gtk_events_pending()) { + gtk_main_iteration_do(FALSE); + } + ctk_image_sliders_setup(ctk_image_sliders); } /* ctk_image_sliders_reset() */ diff --git a/src/gtk+-2.x/ctkpowermizer.c b/src/gtk+-2.x/ctkpowermizer.c index 714b3bd..716b5ab 100644 --- a/src/gtk+-2.x/ctkpowermizer.c +++ b/src/gtk+-2.x/ctkpowermizer.c @@ -69,28 +69,32 @@ static const char *__performance_mode_help = "CUDA application is running)."; static const char *__gpu_clock_freq_help = -"This indicates the current GPU Clock frequency."; +"This indicates the current Graphics Clock frequency."; static const char *__memory_clock_freq_help = "This indicates the current Memory Clock frequency."; +static const char *__processor_clock_freq_help = +"This indicates the current Processor Clock frequency."; + static const char *__clock_freq_help = -"This indicates the current GPU Clock and Memory Clock frequencies."; +"This indicates the GPU's current Graphics Clock, Memory Clock and Processor " +"Clock frequencies."; static const char *__performance_levels_table_help = "This indicates the Performance Levels available for the GPU. Each " "performance level is indicated by a Performance Level number, along with " -"the GPU and Memory clocks for that level. The currently active performance " -"level is shown in regular text. All other performance levels are shown in " -"gray."; +"the Graphics, Memory and Processor clocks for that level. The currently active " +"performance level is shown in regular text. All other performance " +"levels are shown in gray."; static const char *__powermizer_menu_help = "The Preferred Mode menu allows you to choose the preferred Performance " "State for the GPU, provided the GPU has multiple Performance Levels. " "'Adaptive' mode allows the GPU clocks to be adjusted based on GPU " "utilization. 'Prefer Maximum Performance' hints to the driver to prefer " -"higher GPU clocks, when possible. If a single X server is running, the mode " -"selected in nvidia-settings is what the system will be using; if two or " +"higher GPU clocks, when possible. If a single X server is running, the " +"mode selected in nvidia-settings is what the system will be using; if two or " "more X servers are running, the behavior is undefined. If any CUDA " "application is running, the system will always be in the 'Prefer Maximum " "Performance' mode."; @@ -127,6 +131,7 @@ typedef struct { gint perf_level; gint nvclock; gint memclock; + gint processorclock; } perfModeEntry, * perfModeEntryPtr; @@ -140,6 +145,8 @@ static void apply_perf_mode_token(char *token, char *value, void *data) pEntry->nvclock = atoi(value); } else if (!strcasecmp("memclock", token)) { pEntry->memclock = atoi(value); + } else if (!strcasecmp("processorclock", token)) { + pEntry->processorclock = atoi(value); } else { nv_warning_msg("Unknown Perf Mode token value pair: %s=%s", token, value); @@ -170,7 +177,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, /* Generate a new table */ - table = gtk_table_new(1, 3, FALSE); + table = gtk_table_new(1, 4, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 3); gtk_table_set_col_spacings(GTK_TABLE(table), 15); gtk_container_set_border_width(GTK_CONTAINER(table), 5); @@ -183,7 +190,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("NV Clock"); + label = gtk_label_new("Graphics Clock"); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), label, 1, 2, 0, 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); @@ -193,6 +200,12 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + if (ctk_powermizer->processor_clock) { + label = gtk_label_new("Processor Clock"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 3, 4, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } /* Get the current list of perf levels */ ret = NvCtrlGetStringAttribute(ctk_powermizer->attribute_handle, @@ -216,6 +229,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, entry.perf_level = -1; entry.nvclock = -1; entry.memclock = -1; + entry.processorclock = -1; parse_token_value_pairs(tokens, apply_perf_mode_token, &entry); @@ -229,7 +243,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, /* XXX Assume the perf levels are sorted by the server */ - gtk_table_resize(GTK_TABLE(table), row_idx+1, 3); + gtk_table_resize(GTK_TABLE(table), row_idx+1, 4); g_snprintf(tmp_str, 24, "%d", entry.perf_level); label = gtk_label_new(tmp_str); @@ -252,11 +266,20 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, gtk_table_attach(GTK_TABLE(table), label, 2, 3, row_idx, row_idx+1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + if (ctk_powermizer->processor_clock) { + g_snprintf(tmp_str, 24, "%d MHz", entry.processorclock); + label = gtk_label_new(tmp_str); + gtk_widget_set_sensitive(label, active); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 3, 4, row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + } row_idx++; } else { nv_warning_msg("Incomplete Perf Mode (perf=%d, nvclock=%d," " memclock=%d)", - entry.perf_level, entry.nvclock, entry.memclock); + entry.perf_level, entry.nvclock, + entry.memclock); } } @@ -270,7 +293,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, static gboolean update_powermizer_info(gpointer user_data) { gint power_source, perf_mode, adaptive_clock, perf_level; - gint clockret, gpu_clock, memory_clock; + gint clockret, gpu_clock, memory_clock, processor_clock; CtkPowermizer *ctk_powermizer; NvCtrlAttributeHandle *handle; @@ -316,6 +339,17 @@ static gboolean update_powermizer_info(gpointer user_data) gtk_label_set_text(GTK_LABEL(ctk_powermizer->memory_clock), s); g_free(s); + if (ctk_powermizer->processor_clock) { + ret = NvCtrlGetAttribute(handle, + NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS, + &processor_clock); + if (ret == NvCtrlSuccess) { + s = g_strdup_printf("%d Mhz", processor_clock); + gtk_label_set_text(GTK_LABEL(ctk_powermizer->processor_clock), s); + g_free(s); + } + } + ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_POWER_SOURCE, &power_source); if (ret != NvCtrlSuccess) { return FALSE; @@ -382,6 +416,7 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, ReturnStatus ret; gchar *s; gint val; + gboolean processor_clock_available = FALSE; /* make sure we have a handle */ @@ -419,6 +454,12 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, return NULL; } + ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS, + &val); + if (ret == NvCtrlSuccess) { + processor_clock_available = TRUE; + } + /* create the CtkPowermizer object */ object = g_object_new(CTK_TYPE_POWERMIZER, NULL); @@ -480,7 +521,7 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, gtk_table_attach(GTK_TABLE(table), hbox2, 0, 1, 4, 5, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("GPU Clock:"); + label = gtk_label_new("Graphics Clock:"); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); @@ -512,6 +553,26 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle, ctk_config_set_tooltip(ctk_config, eventbox, __memory_clock_freq_help); ctk_powermizer->memory_clock = label; + /* Processor clock */ + if (processor_clock_available) { + hbox2 = gtk_hbox_new(FALSE, 0); + gtk_table_attach(GTK_TABLE(table), hbox2, 0, 1, 6, 7, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + + label = gtk_label_new("Processor Clock:"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); + + eventbox = gtk_event_box_new(); + gtk_table_attach(GTK_TABLE(table), eventbox, 1, 2, 6, 7, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + + label = gtk_label_new(NULL); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + gtk_container_add(GTK_CONTAINER(eventbox), label); + ctk_config_set_tooltip(ctk_config, eventbox, __processor_clock_freq_help); + ctk_powermizer->processor_clock = label; + } /* Power Source */ hbox2 = gtk_hbox_new(FALSE, 0); diff --git a/src/gtk+-2.x/ctkpowermizer.h b/src/gtk+-2.x/ctkpowermizer.h index 316d94a..90f3127 100644 --- a/src/gtk+-2.x/ctkpowermizer.h +++ b/src/gtk+-2.x/ctkpowermizer.h @@ -62,6 +62,7 @@ struct _CtkPowermizer GtkWidget *adaptive_clock_status; GtkWidget *gpu_clock; GtkWidget *memory_clock; + GtkWidget *processor_clock; GtkWidget *power_source; GtkWidget *performance_level; GtkWidget *performance_mode; diff --git a/src/gtk+-2.x/ctkscreen.c b/src/gtk+-2.x/ctkscreen.c index 8cb5490..2d3f764 100644 --- a/src/gtk+-2.x/ctkscreen.c +++ b/src/gtk+-2.x/ctkscreen.c @@ -44,7 +44,7 @@ static const _CtkStereoMode stereoMode[] = { { NV_CTRL_STEREO_DDC, "DDC Stereo" }, { NV_CTRL_STEREO_BLUELINE, "Blueline Stereo" }, { NV_CTRL_STEREO_DIN, "Onboard DIN Stereo" }, - { NV_CTRL_STEREO_TWINVIEW, "TwinView clone Stereo" }, + { NV_CTRL_STEREO_PASSIVE_EYE_PER_DPY, "Passive One-Eye-per-Display Stereo" }, { NV_CTRL_STEREO_VERTICAL_INTERLACED, "Vertical Interlaced Stereo" }, { NV_CTRL_STEREO_COLOR_INTERLACED, "Color Interleaved Stereo" }, { NV_CTRL_STEREO_HORIZONTAL_INTERLACED, "Horizontal Interlaced Stereo" }, @@ -104,39 +104,73 @@ GType ctk_screen_get_type( -static gchar *make_display_device_list(NvCtrlAttributeHandle *handle, - unsigned int display_devices) +/* Generates a list of display device names for those display devices that + * are enabled on the given GPU and, if Xinerama is disabled, are also + * associated to the given X screen (handle). + */ +static gchar *make_gpu_display_device_list(NvCtrlAttributeHandle *handle, + int gpu_id, + int xinerama_enabled) { gchar *displays = NULL; gchar *type; gchar *name; gchar *tmp_str; + unsigned int display_devices; unsigned int mask; - ReturnStatus ret; - + Bool valid; + + + /* Get the list of enabled display devices on the GPU */ + + valid = + XNVCTRLQueryTargetAttribute(NvCtrlGetDisplayPtr(handle), + NV_CTRL_TARGET_TYPE_GPU, + gpu_id, + 0, + NV_CTRL_ENABLED_DISPLAYS, + (int *)&display_devices); + if (!valid) return NULL; - /* List of Display Device connected on GPU */ + /* If Xinerama is disabled, only show displays that are associated + * to this X screen. + */ + if (!xinerama_enabled) { + ReturnStatus ret; + unsigned int associated_devices; + + ret = NvCtrlGetAttribute(handle, + NV_CTRL_ASSOCIATED_DISPLAY_DEVICES, + (int *)&associated_devices); + if (ret == NvCtrlSuccess) { + display_devices &= associated_devices; + } + } + + /* Make the list of display device names */ for (mask = 1; mask; mask <<= 1) { - + if (!(mask & display_devices)) continue; - + type = display_device_mask_to_display_device_name(mask); name = NULL; - - ret = - NvCtrlGetStringDisplayAttribute(handle, - mask, - NV_CTRL_STRING_DISPLAY_DEVICE_NAME, - &name); - if (ret != NvCtrlSuccess) { + + valid = + XNVCTRLQueryTargetStringAttribute(NvCtrlGetDisplayPtr(handle), + NV_CTRL_TARGET_TYPE_GPU, + gpu_id, + mask, + NV_CTRL_STRING_DISPLAY_DEVICE_NAME, + &name); + if (!valid) { tmp_str = g_strdup_printf("Unknown (%s)", type); } else { tmp_str = g_strdup_printf("%s (%s)", name, type); XFree(name); } free(type); - + if (displays) { name = g_strdup_printf("%s,\n%s", tmp_str, displays); g_free(displays); @@ -147,6 +181,60 @@ static gchar *make_display_device_list(NvCtrlAttributeHandle *handle, displays = name; } + return displays; +} + + + +/* Generates a list of display devices for the logical X screen + * given as "handle". + */ +static gchar *make_display_device_list(NvCtrlAttributeHandle *handle) +{ + ReturnStatus ret; + int len; + int i; + int *pData; + gchar *displays = NULL; + int xinerama_enabled; + + + /* See if Xinerama is enabled */ + ret = NvCtrlGetAttribute(handle, NV_CTRL_XINERAMA, &xinerama_enabled); + if (ret != NvCtrlSuccess) { + goto done; + } + + /* Get all GPUs driving this X screen */ + ret = NvCtrlGetBinaryAttribute(handle, + 0, + NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN, + (unsigned char **)(&pData), + &len); + if (ret != NvCtrlSuccess) { + goto done; + } + + /* Generate the list of display device names that display this X screen */ + for (i = 1; i <= pData[0]; i++) { + gchar *new_str; + gchar *tmp_str; + + new_str = make_gpu_display_device_list(handle, pData[i], + xinerama_enabled); + if (new_str) { + if (displays) { + tmp_str = g_strdup_printf("%s,\n%s", displays, new_str); + g_free(displays); + g_free(new_str); + displays = tmp_str; + } else { + displays = new_str; + } + } + } + + done: if (!displays) { displays = g_strdup("None"); } @@ -224,8 +312,6 @@ GtkWidget* ctk_screen_new(NvCtrlAttributeHandle *handle, double xres, yres; - unsigned int display_devices; - int *pData; int len; int i; @@ -308,12 +394,7 @@ GtkWidget* ctk_screen_new(NvCtrlAttributeHandle *handle, /* get the list of Display Devices displaying this X screen */ - displays = NULL; - ret = NvCtrlGetAttribute(handle, NV_CTRL_ASSOCIATED_DISPLAY_DEVICES, - (int *)&display_devices); - if (ret == NvCtrlSuccess) { - displays = make_display_device_list(handle, display_devices); - } + displays = make_display_device_list(handle); /* get the number of gpu errors occurred */ @@ -522,12 +603,10 @@ void ctk_screen_event_handler(GtkWidget *widget, static void associated_displays_received(GtkObject *object, gpointer arg1, gpointer user_data) { - CtkEventStruct *event_struct = (CtkEventStruct *) arg1; CtkScreen *ctk_object = CTK_SCREEN(user_data); - unsigned int associated_displays = event_struct->value; gchar *str; - str = make_display_device_list(ctk_object->handle, associated_displays); + str = make_display_device_list(ctk_object->handle); gtk_label_set_text(GTK_LABEL(ctk_object->displays), str); diff --git a/src/gtk+-2.x/ctkslimm.c b/src/gtk+-2.x/ctkslimm.c index 7566614..fc8f896 100644 --- a/src/gtk+-2.x/ctkslimm.c +++ b/src/gtk+-2.x/ctkslimm.c @@ -1248,6 +1248,8 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle, gchar *tmp; gchar *sli_mode = NULL; ReturnStatus ret; + ReturnStatus ret1; + int major = 0, minor = 0; gint val; nvLayoutPtr layout; @@ -1258,6 +1260,8 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle, int count; Bool valid_layout = FALSE; + Bool trust_slimm_available = FALSE; + int vcs_target_count; int hoverlap = 0; int voverlap = 0; @@ -1273,7 +1277,29 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle, ctk_slimm->handle = handle; ctk_slimm->ctk_config = ctk_config; ctk_object = ctk_slimm; + + /* + * Check for NV-CONTROL protocol version. + * This used for not trust old X drivers which always reported + * it available (on NV50+). + */ + ret = NvCtrlGetAttribute(handle, + NV_CTRL_ATTR_NV_MAJOR_VERSION, &major); + ret1 = NvCtrlGetAttribute(handle, + NV_CTRL_ATTR_NV_MINOR_VERSION, &minor); + + if ((ret == NvCtrlSuccess) && (ret1 == NvCtrlSuccess) && + ((major > 1) || ((major == 1) && (minor > 23)))) { + trust_slimm_available = TRUE; + } + vcs_target_count = ctk_config->pCtrlHandles->targets[VCS_TARGET].n; + + /* return on old X drivers if target is other than VCS. */ + if (!vcs_target_count && !trust_slimm_available) { + return NULL; + } + /* Check if this screen supports SLI Mosaic Mode */ ret = NvCtrlGetAttribute(ctk_object->handle, NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE, &val); diff --git a/src/gtk+-2.x/ctkwindow.c b/src/gtk+-2.x/ctkwindow.c index d14b6bf..11daaa2 100644 --- a/src/gtk+-2.x/ctkwindow.c +++ b/src/gtk+-2.x/ctkwindow.c @@ -638,7 +638,7 @@ GtkWidget *ctk_window_new(ParsedAttribute *p, ConfigProperties *conf, CTK_WINDOW_CONFIG_FILE_ATTRIBUTES_FUNC_COLUMN, NULL, -1); - if (h->targets[VCS_TARGET].n && !slimm_page_added) { + if (!slimm_page_added) { /* SLI Mosaic Mode information */ child = ctk_slimm_new(screen_handle, ctk_event, ctk_config); diff --git a/src/gtk+-2.x/src.mk b/src/gtk+-2.x/src.mk index c867aa6..4b7ad45 100644 --- a/src/gtk+-2.x/src.mk +++ b/src/gtk+-2.x/src.mk @@ -21,6 +21,7 @@ GTK_SRC += ctkimagesliders.c GTK_SRC += ctkdisplaydevice-crt.c GTK_SRC += ctkdisplaydevice-tv.c GTK_SRC += ctkdisplaydevice-dfp.c +GTK_SRC += ctkditheringcontrols.c GTK_SRC += ctkthermal.c GTK_SRC += ctkpowermizer.c GTK_SRC += ctkgvo.c @@ -45,6 +46,7 @@ GTK_SRC += ctkpowersavings.c GTK_SRC += ctkgvi.c GTK_SRC += ctklicense.c GTK_SRC += ctkecc.c +GTK_SRC += ctkcolorcontrols.c GTK_EXTRA_DIST += ctkxvideo.h GTK_EXTRA_DIST += ctkcursorshadow.h @@ -65,6 +67,7 @@ GTK_EXTRA_DIST += ctkimagesliders.h GTK_EXTRA_DIST += ctkdisplaydevice-crt.h GTK_EXTRA_DIST += ctkdisplaydevice-tv.h GTK_EXTRA_DIST += ctkdisplaydevice-dfp.h +GTK_EXTRA_DIST += ctkditheringcontrols.h GTK_EXTRA_DIST += ctkconstants.h GTK_EXTRA_DIST += ctkthermal.h GTK_EXTRA_DIST += ctkpowermizer.h @@ -90,4 +93,5 @@ GTK_EXTRA_DIST += ctkgvo-sync.h GTK_EXTRA_DIST += ctkgvi.h GTK_EXTRA_DIST += ctklicense.h GTK_EXTRA_DIST += ctkecc.h +GTK_EXTRA_DIST += ctkcolorcontrols.h GTK_EXTRA_DIST += src.mk diff --git a/src/libXNVCtrl/NVCtrl.h b/src/libXNVCtrl/NVCtrl.h index 180b4c7..45d976d 100644 --- a/src/libXNVCtrl/NVCtrl.h +++ b/src/libXNVCtrl/NVCtrl.h @@ -152,14 +152,8 @@ /* - * NV_CTRL_FLATPANEL_DITHERING - the current flat panel dithering - * state; possible values are: - * - * 0: default (the driver will decide when to dither) - * 1: enabled (the driver will always dither when possible) - * 2: disabled (the driver will never dither) - * - * USAGE NOTE: This attribute had been deprecated. + * NV_CTRL_FLATPANEL_DITHERING is deprecated; NV_CTRL_DITHERING should + * be used instead. */ #define NV_CTRL_FLATPANEL_DITHERING 3 /* RWDG */ @@ -167,6 +161,20 @@ #define NV_CTRL_FLATPANEL_DITHERING_ENABLED 1 #define NV_CTRL_FLATPANEL_DITHERING_DISABLED 2 +/* + * NV_CTRL_DITHERING - the requested dithering configuration; + * possible values are: + * + * 0: auto (the driver will decide when to dither) + * 1: enabled (the driver will always dither when possible) + * 2: disabled (the driver will never dither) + */ + +#define NV_CTRL_DITHERING 3 /* RWDG */ +#define NV_CTRL_DITHERING_AUTO 0 +#define NV_CTRL_DITHERING_ENABLED 1 +#define NV_CTRL_DITHERING_DISABLED 2 + /* * NV_CTRL_DIGITAL_VIBRANCE - sets the digital vibrance level for the @@ -323,7 +331,7 @@ #define NV_CTRL_STEREO_DDC 1 #define NV_CTRL_STEREO_BLUELINE 2 #define NV_CTRL_STEREO_DIN 3 -#define NV_CTRL_STEREO_TWINVIEW 4 +#define NV_CTRL_STEREO_PASSIVE_EYE_PER_DPY 4 #define NV_CTRL_STEREO_VERTICAL_INTERLACED 5 #define NV_CTRL_STEREO_COLOR_INTERLACED 6 #define NV_CTRL_STEREO_HORIZONTAL_INTERLACED 7 @@ -2844,7 +2852,7 @@ #define NV_CTRL_GPU_CORES 345 /* R--G */ -/* +/* * NV_CTRL_GPU_MEMORY_BUS_WIDTH - Returns memory bus bandwidth on the associated * subdevice. */ @@ -2863,6 +2871,22 @@ #define NV_CTRL_GVI_TEST_MODE_DISABLE 0 #define NV_CTRL_GVI_TEST_MODE_ENABLE 1 +/* + * NV_CTRL_COLOR_SPACE - This option sets color space of the video + * signal. + */ +#define NV_CTRL_COLOR_SPACE 348 /* RWDG */ +#define NV_CTRL_COLOR_SPACE_RGB 0 +#define NV_CTRL_COLOR_SPACE_YCbCr422 1 +#define NV_CTRL_COLOR_SPACE_YCbCr444 2 + +/* + * NV_CTRL_COLOR_RANGE - This option sets color range of the video + * signal. + */ +#define NV_CTRL_COLOR_RANGE 349 /* RWDG */ +#define NV_CTRL_COLOR_RANGE_FULL 0 +#define NV_CTRL_COLOR_RANGE_LIMITED 1 /* * NV_CTRL_GPU_SCALING_DEFAULT_TARGET - Returns the default scaling target @@ -2877,6 +2901,40 @@ #define NV_CTRL_GPU_SCALING_DEFAULT_TARGET 350 /* R-DG */ #define NV_CTRL_GPU_SCALING_DEFAULT_METHOD 351 /* R-DG */ +/* + * NV_CTRL_DITHERING_MODE - Controls the dithering mode, when + * NV_CTRL_CURRENT_DITHERING is Enabled. + * + * AUTO: allow the driver to choose the dithering mode automatically. + * + * DYNAMIC_2X2: use a 2x2 matrix to dither from the GPU's pixel + * pipeline to the bit depth of the flat panel. The matrix values + * are changed from frame to frame. + * + * STATIC_2X2: use a 2x2 matrix to dither from the GPU's pixel + * pipeline to the bit depth of the flat panel. The matrix values + * do not change from frame to frame. + */ +#define NV_CTRL_DITHERING_MODE 352 /* RWDG */ +#define NV_CTRL_DITHERING_MODE_AUTO 0 +#define NV_CTRL_DITHERING_MODE_DYNAMIC_2X2 1 +#define NV_CTRL_DITHERING_MODE_STATIC_2X2 2 + +/* + * NV_CTRL_CURRENT_DITHERING - Returns the current dithering state. + */ +#define NV_CTRL_CURRENT_DITHERING 353 /* R-DG */ +#define NV_CTRL_CURRENT_DITHERING_DISABLED 0 +#define NV_CTRL_CURRENT_DITHERING_ENABLED 1 + +/* + * NV_CTRL_CURRENT_DITHERING_MODE - Returns the current dithering + * mode. + */ +#define NV_CTRL_CURRENT_DITHERING_MODE 354 /* R-DG */ +#define NV_CTRL_CURRENT_DITHERING_MODE_NONE 0 +#define NV_CTRL_CURRENT_DITHERING_MODE_DYNAMIC_2X2 1 +#define NV_CTRL_CURRENT_DITHERING_MODE_STATIC_2X2 2 /* * NV_CTRL_THERMAL_SENSOR_READING - Returns the thermal sensor's current @@ -2961,7 +3019,6 @@ (NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_B)) #define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_1080P_NO_12BPC 0x00000020 - /* * NV_CTRL_GPU_PCIE_MAX_LINK_SPEED - returns maximum PCI-E link speed. */ @@ -3358,8 +3415,8 @@ * * Token Value * "perf" integer - the Performance level - * "nvClock" integer - the GPU clocks (in MHz) for the perf level - * "memClock" integer - the memory clocks (in MHz) for the perf level + * "nvclock" integer - the GPU clocks (in MHz) for the perf level + * "memclock" integer - the memory clocks (in MHz) for the perf level * * * Example: @@ -3471,8 +3528,40 @@ */ #define NV_CTRL_STRING_GVO_VIDEO_FORMAT_NAME 33 /* R--- */ + +/* + * NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS - returns a string with the + * associated NV Clock, Memory Clock and Processor Clock values. + * + * Current valid tokens are "nvclock", "memclock", and "processorclock". + * Not all tokens will be reported on all GPUs, and additional tokens + * may be added in the future. + * + * Clock values are returned as a comma-separated list of + * "token=value" pairs. + * Valid tokens: + * + * Token Value + * "nvclock" integer - the GPU clocks (in MHz) for the current + * perf level + * "memclock" integer - the memory clocks (in MHz) for the current + * perf level + * "processorclock" integer - the processor clocks (in MHz) for the perf level + * + * + * Example: + * + * nvclock=459, memclock=400, processorclock=918 + * + * This attribute may be queried through XNVCTRLQueryTargetStringAttribute() + * using an NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. + */ + +#define NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS 34 /* RW-G */ + + #define NV_CTRL_STRING_LAST_ATTRIBUTE \ - NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME + NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS /**************************************************************************/ diff --git a/src/libXNVCtrl/nv_control.h b/src/libXNVCtrl/nv_control.h index 97229f9..a6b8546 100644 --- a/src/libXNVCtrl/nv_control.h +++ b/src/libXNVCtrl/nv_control.h @@ -46,8 +46,10 @@ * 1.20 Added COOLER TargetType * 1.21 Added initial 64-bit integer attribute support (read-only) * 1.22 Added X_nvCtrlQueryValidStringAttributeValues to check - * string attribute permissions. + * string attribute permissions. * 1.23 Added SENSOR TargetType + * 1.24 Fixed a bug where SLI_MOSAIC_MODE_AVAILABLE attribute would + * report false positives via the GPU and X screen target types */ #ifndef __NVCONTROL_H @@ -58,7 +60,7 @@ #define NV_CONTROL_NAME "NV-CONTROL" #define NV_CONTROL_MAJOR 1 -#define NV_CONTROL_MINOR 23 +#define NV_CONTROL_MINOR 24 #define X_nvCtrlQueryExtension 0 #define X_nvCtrlIsNv 1 @@ -38,15 +38,15 @@ extern int __verbosity; -static void format(FILE*, const char*, char *); +static void format(FILE*, const char*, char *, int); static int get_terminal_width(void); -#define NV_FORMAT(stream, prefix, fmt) \ -do { \ - char *buf; \ - NV_VSNPRINTF(buf, fmt); \ - format(stream, prefix, buf); \ - free (buf); \ +#define NV_FORMAT(stream, prefix, fmt, whitespace) \ +do { \ + char *buf; \ + NV_VSNPRINTF(buf, fmt); \ + format(stream, prefix, buf, whitespace); \ + free (buf); \ } while(0) /* @@ -62,7 +62,7 @@ void nv_error_msg(const char *fmt, ...) fprintf(stderr, "\n"); - NV_FORMAT(stderr, "ERROR: ", fmt); + NV_FORMAT(stderr, "ERROR: ", fmt, False); fprintf(stderr, "\n"); @@ -83,7 +83,7 @@ void nv_warning_msg(const char *fmt, ...) fprintf(stdout, "\n"); - NV_FORMAT(stdout, "WARNING: ", fmt); + NV_FORMAT(stdout, "WARNING: ", fmt, False); fprintf(stdout, "\n"); @@ -102,7 +102,7 @@ void nv_info_msg(const char *prefix, const char *fmt, ...) { if (__verbosity < VERBOSITY_ALL) return; - NV_FORMAT(stdout, prefix, fmt); + NV_FORMAT(stdout, prefix, fmt, False); } /* nv_info_msg() */ @@ -118,11 +118,23 @@ void nv_info_msg(const char *prefix, const char *fmt, ...) void nv_msg(const char *prefix, const char *fmt, ...) { - NV_FORMAT(stdout, prefix, fmt); + NV_FORMAT(stdout, prefix, fmt, False); } /* nv_msg() */ +/* + * nv_msg_preserve_whitespace() - Prints the message, just like nv_msg() + * using format(), the difference is, whitespace characters are not + * skipped during the text processing. + */ + +void nv_msg_preserve_whitespace(const char *prefix, const char *fmt, ...) +{ + NV_FORMAT(stdout, prefix, fmt, True); + +} /* nv_msg_preserve_whitespace() */ + /* * XXX gcc's '-ansi' option causes vsnprintf to not be defined, so @@ -142,7 +154,7 @@ int vsnprintf(char *str, size_t size, const char *format, */ static void format(FILE *stream, const char *prefix, - char *buf) + char *buf, int preserveWhitespace) { int len, prefix_len, z, w, i, max_width; char *line, *local_prefix, *a, *b, *c; @@ -224,9 +236,10 @@ static void format(FILE *stream, const char *prefix, z -= (b - a + 1); a = b + 1; - /* move to the first non whitespace character */ - - while ((z > 0) && (isspace(*a))) a++, z--; + if (!preserveWhitespace) { + /* move to the first non whitespace character */ + while ((z > 0) && (isspace(*a))) a++, z--; + } if (local_prefix) { for (i = 0; i < prefix_len; i++) local_prefix[i] = ' '; @@ -32,6 +32,7 @@ void nv_error_msg(const char*, ...); void nv_warning_msg(const char*, ...); void nv_info_msg(const char*, const char*, ...); void nv_msg(const char*, const char*, ...); +void nv_msg_preserve_whitespace(const char*, const char*, ...); /* * NV_VSNPRINTF(): macro that assigns buf using vsnprintf(). This is diff --git a/src/nvgetopt.h b/src/nvgetopt.h deleted file mode 100644 index d1cbcc8..0000000 --- a/src/nvgetopt.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix - * and Linux systems. - * - * Copyright (C) 2004 NVIDIA Corporation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of Version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2 - * of the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307, USA - * - */ - -#ifndef __NVGETOPT_H__ -#define __NVGETOPT_H__ - -#define NVGETOPT_FALSE 0 -#define NVGETOPT_TRUE 1 -#define NVGETOPT_INVALID 2 - -#define NVGETOPT_HAS_ARGUMENT 0x1 -#define NVGETOPT_IS_BOOLEAN 0x2 -#define NVGETOPT_ARGUMENT_IS_OPTIONAL 0x4 - -typedef struct { - const char *name; - int val; - unsigned int flags; - void (*print_description)(void); /* not used by nvgetopt() */ - char *description; /* not used by nvgetopt() */ -} NVGetoptOption; - -int nvgetopt(int argc, char *argv[], const NVGetoptOption *options, - char **strval, int *boolval); - -#endif /* __NVGETOPT_H__ */ diff --git a/src/option-table.h b/src/option-table.h new file mode 100644 index 0000000..c28f44c --- /dev/null +++ b/src/option-table.h @@ -0,0 +1,156 @@ +/* + * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix + * and Linux systems. + * + * Copyright (C) 2010 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of Version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2 + * of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307, USA + * + */ + +#ifndef __OPTION_TABLE_H__ +#define __OPTION_TABLE_H__ + +#include "nvgetopt.h" +#include "command-line.h" + +#define TAB " " +#define BIGTAB " " + +/* + * Options table; see nvgetopt.h for a description of the fields. + */ + +static const NVGetoptOption __options[] = { + { "version", 'v', 0, NULL, + "Print the <nvidia-settings> version and exit." }, + + { "help", 'h', 0, NULL, + "Print usage information and exit." }, + + { "config", CONFIG_FILE_OPTION, NVGETOPT_STRING_ARGUMENT, NULL, + "Use the configuration file ^CONFIG> rather than the " + "default ^" DEFAULT_RC_FILE ">" }, + + { "ctrl-display", 'c', NVGETOPT_STRING_ARGUMENT, NULL, + "Control the specified X display. If this option is not given, then " + "<nvidia-settings> will control the display specified by <'--display'>; " + "if that is not given, then the ^$DISPLAY> environment variable is used." }, + + { "load-config-only", 'l', 0, NULL, + "Load the configuration file, send the values specified therein to " + "the X server, and exit. This mode of operation is useful to place " + "in your xinitrc file, for example." }, + + { "no-config", 'n', 0, NULL, + "Do not load the configuration file. This mode of operation is useful " + "if <nvidia-settings> has difficulties starting due to problems with " + "applying settings in the configuration file." }, + + { "rewrite-config-file", 'r', 0, NULL, + "Write the X server configuration to the configuration file, and exit, " + "without starting the graphical user interface. See EXAMPLES section." }, + + { "verbose", 'V', + NVGETOPT_STRING_ARGUMENT | NVGETOPT_ARGUMENT_IS_OPTIONAL, NULL, + "Controls how much information is printed. By default, the verbosity " + "is <errors> and only error messages are printed. Valid values are " + "<'errors'> (print error messages), <'warnings'> (print error and " + "warning messages), and <'all'> (print error, warning and other " + "informational messages)." }, + + { "assign", 'a', NVGETOPT_STRING_ARGUMENT, NULL, + "The ^ASSIGN> argument to the <'--assign'> command line option is of the " + "form:\n" + "\n" + TAB "{DISPLAY}/{attribute name}[{display devices}]={value}\n" + "\n" + "This assigns the attribute {attribute name} to the value {value} on the " + "X Display {DISPLAY}. {DISPLAY} follows the usual {host}:{display}." + "{screen} syntax of the DISPLAY environment variable and is optional; " + "when it is not specified, then it is implied following the same rule as " + "the <--ctrl-display> option. If the X screen is not specified, then the " + "assignment is made to all X screens. Note that the '/' is only required " + "when {DISPLAY} is present.\n" + "\n" + "{DISPLAY} can additionally include a target specification to direct " + "an assignment to something other than an X screen. A target " + "specification is contained within brackets and consists of a target " + "type name, a colon, and the target id. The target type name can be " + "one of <\"screen\", \"gpu\", \"framelock\", \"vcs\", \"gvi\",> or " + "<\"fan\";> the target id is the index into the list of targets " + "(for that target type). The target specification can be used in " + "{DISPLAY} wherever an X screen can be used, following the syntax " + "{host}:{display}[{target_type}:{target_id}]. See the output of\n" + "\n" + TAB "nvidia-settings -q all \n" + "\n" + "for information on which target types can be used with which " + "attributes. See the output of\n" + "\n" + TAB " nvidia-settings -q screens -q gpus -q framelocks -q vcs -q gvis " + "-q fans \n" + "\n" + "for lists of targets for each target type.\n" + "\n" + "The [{display devices}] portion is also optional; if it is not " + "specified, then the attribute is assigned to all display devices.\n" + "\n" + "Some examples:\n" + "\n" + TAB "-a FSAA=5\n" + TAB "-a localhost:0.0/DigitalVibrance[CRT-0]=0\n" + TAB "--assign=\"SyncToVBlank=1\"\n" + TAB "-a [gpu:0]/DigitalVibrance[DFP-1]=63\n" }, + + { "query", 'q', NVGETOPT_STRING_ARGUMENT, NULL, + "The ^QUERY> argument to the <'--query'> command line option is of the " + "form:\n" + "\n" + TAB "{DISPLAY}/{attribute name}[{display devices}]\n" + "\n" + "This queries the current value of the attribute {attribute name} on the " + "X Display {DISPLAY}. The syntax is the same as that for the " + "<'--assign'> option, without '=<{value}'>; specify <'-q screens', " + "'-q gpus', '-q framelocks', '-q vcs', '-q gvis', or '-q fans'> to " + "query a list of X screens, GPUs, Frame Lock devices, Visual Computing " + "Systems, SDI Input Devices, or Fans, respectively, that are present " + "on the X Display {DISPLAY}. Specify <'-q all'> to query all attributes." }, + + { "terse", 't', 0, NULL, + "When querying attribute values with the '--query' command line option, " + "only print the current value, rather than the more verbose description " + "of the attribute, its valid values, and its current value." }, + + { "display-device-string", 'd', 0, NULL, + "When printing attribute values in response to the '--query' option, " + "if the attribute value is a display device mask, print the value " + "as a list of display devices (e.g., \"CRT-0, DFP-0\"), rather than " + "a hexadecimal bit mask (e.g., 0x00010001)." }, + + { "glxinfo", 'g', 0, NULL, + "Print GLX Information for the X display and exit." }, + + { "describe", 'e', NVGETOPT_STRING_ARGUMENT, NULL, + "Prints information about a particular attribute. Specify 'all' to " + "list the descriptions of all attributes. Specify 'list' to list the " + "attribute names without a descriptions." }, + + { NULL, 0, 0, NULL, NULL}, +}; + +#endif //_OPTION_TABLE_H diff --git a/src/parse.c b/src/parse.c index 3e66013..1232947 100644 --- a/src/parse.c +++ b/src/parse.c @@ -64,6 +64,7 @@ static char *nv_strndup(char *s, int n); #define S NV_PARSER_TYPE_STRING_ATTRIBUTE #define I NV_PARSER_TYPE_SDI #define W NV_PARSER_TYPE_VALUE_IS_SWITCH_DISPLAY +#define M NV_PARSER_TYPE_SDI_CSC AttributeTableEntry attributeTable[] = { @@ -148,6 +149,8 @@ AttributeTableEntry attributeTable[] = { { "GPUDefault2DClockFreqs", NV_CTRL_GPU_DEFAULT_2D_CLOCK_FREQS, N|P, "Returns the default memory and GPU core clocks when operating in 2D mode." }, { "GPUDefault3DClockFreqs", NV_CTRL_GPU_DEFAULT_3D_CLOCK_FREQS, N|P, "Returns the default memory and GPU core clocks when operating in 3D mode." }, { "GPUCurrentClockFreqs", NV_CTRL_GPU_CURRENT_CLOCK_FREQS, N|P, "Returns the current GPU and memory clocks of the graphics device driving the X screen." }, + { "GPUCurrentProcessorClockFreqs", NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS, N, "Returns the current processor clock of the graphics device driving the X screen." }, + { "GPUCurrentClockFreqsString", NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS, S|N, "Returns the current GPU, memory and Processor clocks of the graphics device driving the X screen." }, { "BusRate", NV_CTRL_BUS_RATE, 0, "If the device is on an AGP bus, then BusRate returns the configured AGP rate. If the device is on a PCI Express bus, then this attribute returns the width of the physical link." }, { "PCIDomain", NV_CTRL_PCI_DOMAIN, N, "Returns the PCI domain number for the specified device." }, { "PCIBus", NV_CTRL_PCI_BUS, N, "Returns the PCI bus number for the specified device." }, @@ -256,6 +259,7 @@ AttributeTableEntry attributeTable[] = { { "GviNumCaptureSurfaces", NV_CTRL_GVI_NUM_CAPTURE_SURFACES, I|N, "Controls the number of capture buffers for storing incoming video from the GVI device." }, { "GviBoundGpu", NV_CTRL_GVI_BOUND_GPU, I|N, "Returns the target index of the GPU currently attached to the GVI device." }, { "GviTestMode", NV_CTRL_GVI_TEST_MODE, I|N, "Enable or disable GVI test mode." }, + { "GvoCSCMatrix", 0, I|M|N, "Sets the GVO Color Space Conversion (CSC) matrix. Accepted values are \"ITU_601\", \"ITU_709\", \"ITU_177\", and \"Identity\"." }, /* Display */ { "Brightness", BRIGHTNESS_VALUE|ALL_CHANNELS, N|C|G, "Controls the overall brightness of the display." }, @@ -270,7 +274,10 @@ AttributeTableEntry attributeTable[] = { { "RedGamma", GAMMA_VALUE|RED_CHANNEL, C|G, "Controls the gamma of the color red in the display." }, { "GreenGamma", GAMMA_VALUE|GREEN_CHANNEL, C|G, "Controls the gamma of the color green in the display." }, { "BlueGamma", GAMMA_VALUE|BLUE_CHANNEL, C|G, "Controls the gamma of the color blue in the display." }, - { "FlatpanelDithering", NV_CTRL_FLATPANEL_DITHERING, 0, "This is the current state of flat panel dithering. This attribute has been deprecated." }, + { "Dithering", NV_CTRL_DITHERING, 0, "Controls the dithering: auto (0), enabled (1), disabled (2)." }, + { "CurrentDithering", NV_CTRL_CURRENT_DITHERING, 0, "Returns the current dithering state: enabled (1), disabled (0)." }, + { "DitheringMode", NV_CTRL_DITHERING_MODE, 0, "Controls the dithering mode when CurrentDithering=1; auto (0), temporally dynamic dithering pattern (1), temporally static dithering pattern (2)." }, + { "CurrentDitheringMode", NV_CTRL_CURRENT_DITHERING_MODE, 0, "Returns the current dithering mode: none (0), temporally dynamic dithering pattern (1), temporally static dithering pattern (2)." }, { "DigitalVibrance", NV_CTRL_DIGITAL_VIBRANCE, 0, "Sets the digital vibrance level of the display device." }, { "ImageSharpening", NV_CTRL_IMAGE_SHARPENING, 0, "Adjusts the sharpness of the display's image quality by amplifying high frequency content." }, { "ImageSharpeningDefault", NV_CTRL_IMAGE_SHARPENING_DEFAULT, 0, "Returns default value of image sharpening." }, @@ -286,6 +293,8 @@ AttributeTableEntry attributeTable[] = { { "RefreshRate", NV_CTRL_REFRESH_RATE, N|H, "Returns the refresh rate of the specified display device in cHz (Centihertz) (to get the refresh rate in Hz, divide the returned value by 100)." }, { "RefreshRate3", NV_CTRL_REFRESH_RATE_3, N|K, "Returns the refresh rate of the specified display device in mHz (Millihertz) (to get the refresh rate in Hz, divide the returned value by 1000)." }, { "OverscanCompensation", NV_CTRL_OVERSCAN_COMPENSATION, 0, "Adjust the amount of overscan compensation scaling, in pixels, to apply to the specified display device." }, + { "ColorSpace", NV_CTRL_COLOR_SPACE, 0, "Sets the color space of the signal sent to the display device." }, + { "ColorRange", NV_CTRL_COLOR_RANGE, 0, "Sets the color range of the signal sent to the display device." }, /* TV */ { "TVOverScan", NV_CTRL_TV_OVERSCAN, 0, "Adjusts the amount of overscan on the specified display device." }, @@ -308,7 +317,7 @@ AttributeTableEntry attributeTable[] = { { "XVideoTextureSyncToVBlank", NV_CTRL_ATTR_XV_TEXTURE_SYNC_TO_VBLANK, V, "Enables sync to vertical blanking for X video texture adaptor." }, { "XVideoBlitterSyncToVBlank", NV_CTRL_ATTR_XV_BLITTER_SYNC_TO_VBLANK, V, "Enables sync to vertical blanking for X video blitter adaptor." }, { "XVideoSyncToDisplay", NV_CTRL_XV_SYNC_TO_DISPLAY, D|Z, "Controls which display device is synced to by the texture and blitter adaptors when they are set to synchronize to the vertical blanking." }, - + { NULL, 0, 0, NULL } }; @@ -409,6 +418,48 @@ TargetTypeEntry targetTypeTable[] = { /* + * nv_get_sdi_csc_matrix() - see comments in parse.h + */ + +static const float sdi_csc_itu601[15] = { + 0.2991, 0.5870, 0.1150, 0.0625, 0.85547, // Y + 0.5000, -0.4185, -0.0810, 0.5000, 0.87500, // Cr + -0.1685, -0.3310, 0.5000, 0.5000, 0.87500, // Cb +}; +static const float sdi_csc_itu709[15] = { + 0.2130, 0.7156, 0.0725, 0.0625, 0.85547, // Y + 0.5000, -0.4542, -0.0455, 0.5000, 0.87500, // Cr + -0.1146, -0.3850, 0.5000, 0.5000, 0.87500, // Cb +}; +static const float sdi_csc_itu177[15] = { + 0.412391, 0.357584, 0.180481, 0.0, 0.85547, // Y + 0.019331, 0.119195, 0.950532, 0.0, 0.87500, // Cr + 0.212639, 0.715169, 0.072192, 0.0, 0.87500, // Cb +}; +static const float sdi_csc_identity[15] = { + 0.0000, 1.0000, 0.0000, 0.0000, 1.0, // Y (Green) + 1.0000, 0.0000, 0.0000, 0.0000, 1.0, // Cr (Red) + 0.0000, 0.0000, 1.0000, 0.0000, 1.0, // Cb (Blue) +}; + +const float * nv_get_sdi_csc_matrix(char *s) +{ + if (nv_strcasecmp(s, "itu_601")) { + return sdi_csc_itu601; + } else if (nv_strcasecmp(s, "itu_709")) { + return sdi_csc_itu709; + } else if (nv_strcasecmp(s, "itu_177")) { + return sdi_csc_itu177; + } else if (nv_strcasecmp(s, "identity")) { + return sdi_csc_identity; + } + + return NULL; +} + + + +/* * nv_parse_attribute_string() - see comments in parse.h */ @@ -542,6 +593,10 @@ int nv_parse_attribute_string(const char *str, int query, ParsedAttribute *a) a->val = strtol(s, &tmp, 0); } } + } else if (a->flags & NV_PARSER_TYPE_SDI_CSC) { + /* String that names a standard CSC matrix */ + a->pfval = nv_get_sdi_csc_matrix(s); + tmp = s + strlen(s); } else { /* all other attributes are integer */ a->val = strtol(s, &tmp, 0); diff --git a/src/parse.h b/src/parse.h index 403782d..852e32b 100644 --- a/src/parse.h +++ b/src/parse.h @@ -58,6 +58,7 @@ #define NV_PARSER_TYPE_VALUE_IS_SWITCH_DISPLAY (1<<28) #define NV_PARSER_TYPE_1000Hz (1<<29) #define NV_PARSER_TYPE_SDI (1<<30) +#define NV_PARSER_TYPE_SDI_CSC (1<<31) #define NV_PARSER_ASSIGNMENT 0 #define NV_PARSER_QUERY 1 @@ -123,6 +124,7 @@ typedef struct _ParsedAttribute { int attr; int val; float fval; /* XXX put in a union with val? */ + const float *pfval; /* XXX put in a union with val? */ uint32 display_device_mask; uint32 flags; struct _ParsedAttribute *next; @@ -189,6 +191,18 @@ typedef struct { extern TargetTypeEntry targetTypeTable[]; +/* nv_get_sdi_csc_matrxi() - Returns an array of floats that specifies + * all the color, offset and scale values for specifing one of the + * Standard CSC. 's' is a string that names the matrix values to return. + * The values are placed in the float buffer like so: + * + * { YR, YG, YB, YOffset, YScale, + * CrR, CrG, CrB, CrOffset, CrScale, + * CbR, CbG, CbB, CbOffset, CbScale } + * + */ +const float * nv_get_sdi_csc_matrix(char *s); + /* * nv_parse_attribute_string() - this function parses an attribute * string, the syntax for which is: diff --git a/src/query-assign.c b/src/query-assign.c index 64f6d64..61d1df6 100644 --- a/src/query-assign.c +++ b/src/query-assign.c @@ -2018,6 +2018,85 @@ int nv_process_parsed_attribute(ParsedAttribute *a, CtrlHandles *h, } } + /* Special case the GVO CSC attribute */ + + if (a->flags & NV_PARSER_TYPE_SDI_CSC) { + float colorMatrix[3][3]; + float colorOffset[3]; + float colorScale[3]; + int r, c; + + if (assign) { + + /* Make sure the standard is known */ + if (!a->pfval) { + nv_error_msg("The attribute '%s' specified %s cannot be " + "assigned; valid values are \"ITU_601\", " + "\"ITU_709\", \"ITU_177\", and \"Identity\".", + a->name, whence); + continue; + } + + for (r = 0; r < 3; r++) { + for (c = 0; c < 3; c++) { + colorMatrix[r][c] = a->pfval[r*5 + c]; + } + colorOffset[r] = a->pfval[r*5 + 3]; + colorScale[r] = a->pfval[r*5 + 4]; + } + + status = NvCtrlSetGvoColorConversion(t->h, + colorMatrix, + colorOffset, + colorScale); + } else { + status = NvCtrlGetGvoColorConversion(t->h, + colorMatrix, + colorOffset, + colorScale); + } + + if (status != NvCtrlSuccess) { + nv_error_msg("The attribute '%s' specified %s cannot be " + "%s; error on %s (%s).", + a->name, whence, + assign ? "assigned" : "queried", + t->name, NvCtrlAttributesStrError(status)); + continue; + } + + + /* Print results */ + if (!assign) { +#define INDENT " " + + nv_msg(INDENT, " Red Green Blue Offset Scale"); + nv_msg(INDENT, "----------------------------------------------------"); + nv_msg(INDENT, " Y % -0.6f % -0.6f % -0.6f % -0.6f % -0.6f", + colorMatrix[0][0], + colorMatrix[0][1], + colorMatrix[0][2], + colorOffset[0], + colorScale[0]); + nv_msg(INDENT, "Cr % -0.6f % -0.6f % -0.6f % -0.6f % -0.6f", + colorMatrix[1][0], + colorMatrix[1][1], + colorMatrix[1][2], + colorOffset[1], + colorScale[1]); + nv_msg(INDENT, "Cb % -0.6f % -0.6f % -0.6f % -0.6f % -0.6f", + colorMatrix[2][0], + colorMatrix[2][1], + colorMatrix[2][2], + colorOffset[2], + colorScale[2]); +#undef INDENT + } + + continue; + } + + /* loop over the display devices */ for (bit = 0; bit < 24; bit++) { @@ -9,15 +9,15 @@ SRC_SRC += msg.c SRC_SRC += nvidia-settings.c SRC_SRC += parse.c SRC_SRC += query-assign.c -SRC_SRC += nvgetopt.c SRC_SRC += glxinfo.c SRC_EXTRA_DIST += src.mk SRC_EXTRA_DIST += command-line.h +SRC_EXTRA_DIST += option-table.h SRC_EXTRA_DIST += config-file.h SRC_EXTRA_DIST += lscf.h SRC_EXTRA_DIST += msg.h SRC_EXTRA_DIST += parse.h SRC_EXTRA_DIST += query-assign.h -SRC_EXTRA_DIST += nvgetopt.h SRC_EXTRA_DIST += glxinfo.h +SRC_EXTRA_DIST += gen-manpage-opts.c @@ -33,7 +33,8 @@ CC ?= gcc LD ?= ld -CFLAGS ?= -Wall -fno-strict-aliasing +CFLAGS ?= +CFLAGS += -Wall -fno-strict-aliasing -Wno-unused-parameter CFLAGS += -O2 -fno-omit-frame-pointer CC_ONLY_CFLAGS ?= LDFLAGS ?= @@ -147,14 +148,15 @@ include $(wildcard $(OUTPUTDIR)/version.mk version.mk) # # Arguments: # $(1): CC command (CC or HOST_CC) -# $(2): object filename +# $(2): source filename +# $(3): object filename ############################################################################## ifeq ($(NV_AUTO_DEPEND),1) AUTO_DEP_CMD = && $($(1)) -MM $$(CFLAGS) $$< | $$(SED) \ -e "s,: ,: $$$$\(wildcard ," \ -e "s,\([^\\]\)$$$$,\1)," \ - -e "s;^$$(notdir $(2)): ;$(2): ;" \ + -e "s;^$$(addsuffix .o,$$(notdir $$(basename $(2)))): ;$(3): ;" \ > $$(@:.o=.d) else AUTO_DEP_CMD = @@ -244,7 +246,7 @@ define DEFINE_OBJECT_RULE_WITH_OBJECT_NAME $(3): $(2) @$(MKDIR) $(OUTPUTDIR) $$(call quiet_cmd,$(1)) -c $$< -o $$@ $$(CFLAGS) \ - $(call AUTO_DEP_CMD,$(1),$(3)) + $(call AUTO_DEP_CMD,$(1),$(2),$(3)) -include $$(call BUILD_DEPENDENCY_LIST,$(3)) @@ -1 +1 @@ -NVIDIA_VERSION = 256.53 +NVIDIA_VERSION = 260.19.04 |