diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2014-02-09 11:42:09 -0800 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2014-02-09 11:42:09 -0800 |
commit | abe140773cfba324528a5f4f9d55645037dd1d97 (patch) | |
tree | bb1a8bbce48a9ff393edde001ac758a71aa7f363 | |
parent | cb1c07a3374bfa2638e26ef7f3453e8b128e7d54 (diff) |
334.16334.16
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | XF86Config-parser/Flags.c | 49 | ||||
-rw-r--r-- | XF86Config-parser/Generate.c | 19 | ||||
-rw-r--r-- | XF86Config-parser/xf86Parser.h | 19 | ||||
-rw-r--r-- | common-utils/common-utils.c | 307 | ||||
-rw-r--r-- | common-utils/common-utils.h | 89 | ||||
-rw-r--r-- | common-utils/gen-manpage-opts-helper.c | 33 | ||||
-rw-r--r-- | common-utils/msg.c | 416 | ||||
-rw-r--r-- | common-utils/msg.h | 137 | ||||
-rw-r--r-- | common-utils/src.mk | 2 | ||||
-rw-r--r-- | extract_edids.c | 27 | ||||
-rw-r--r-- | lscf.c | 9 | ||||
-rw-r--r-- | make_usable.c | 12 | ||||
-rw-r--r-- | multiple_screens.c | 407 | ||||
-rw-r--r-- | nvidia-xconfig.c | 143 | ||||
-rw-r--r-- | nvidia-xconfig.h | 6 | ||||
-rw-r--r-- | option_table.h | 28 | ||||
-rw-r--r-- | options.c | 34 | ||||
-rw-r--r-- | query_gpu_info.c | 35 | ||||
-rw-r--r-- | util.c | 43 | ||||
-rw-r--r-- | utils.mk | 1 | ||||
-rw-r--r-- | version.mk | 2 |
22 files changed, 1085 insertions, 737 deletions
@@ -55,7 +55,7 @@ ifeq ($(MANPAGE_GZIP),1) else MANPAGE = $(MANPAGE_not_gzipped) endif -GEN_MANPAGE_OPTS = $(OUTPUTDIR)/gen-manpage-opts +GEN_MANPAGE_OPTS = $(OUTPUTDIR_ABSOLUTE)/gen-manpage-opts OPTIONS_1_INC = $(OUTPUTDIR)/options.1.inc @@ -156,7 +156,7 @@ $(GEN_MANPAGE_OPTS): $(GEN_MANPAGE_OPTS_OBJS) $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_BIN_LDFLAGS) $^ -o $@ $(OPTIONS_1_INC): $(GEN_MANPAGE_OPTS) - @./$< > $@ + @$< > $@ $(MANPAGE_not_gzipped): nvidia-xconfig.1.m4 $(OPTIONS_1_INC) $(VERSION_MK) $(call quiet_cmd,M4) -D__HEADER__=$(AUTO_TEXT) -I $(OUTPUTDIR) \ diff --git a/XF86Config-parser/Flags.c b/XF86Config-parser/Flags.c index 55720e0..3413edc 100644 --- a/XF86Config-parser/Flags.c +++ b/XF86Config-parser/Flags.c @@ -512,30 +512,29 @@ xconfigPrintOptionList(FILE *fp, XConfigOptionPtr list, int tabs) * - If the extension can be enabled, this function returns NULL. * * - If the extension should be disabled, this function returns a - * string that lists the conflicting options that are enabled. + * string that lists the conflicting options that are enabled. The string + * returned has to be freed by the caller. */ -const char *xconfigValidateComposite(XConfigPtr config, - GenerateOptions *gop, - int composite_specified, - int xinerama_enabled, - int depth, - int overlay_enabled, - int cioverlay_enabled, - int ubb_enabled, - int stereo_enabled) +char *xconfigValidateComposite(XConfigPtr config, + GenerateOptions *gop, + int composite_specified, + int xinerama_enabled, + int depth, + int overlay_enabled, + int cioverlay_enabled, + int ubb_enabled, + int stereo_enabled) { - int i, n, disable_composite; - static char err_str[256]; - int size = 256; - char *s; + int i, n; + char *err_str; const struct { const char *name; int value; } composite_incompatible_options[] = { - { "Xinerama", xinerama_enabled }, + { "Xinerama", xinerama_enabled && !gop->xinerama_plus_composite_works }, { "Overlay", overlay_enabled }, { "CIOverlay", cioverlay_enabled }, { "UBB", ubb_enabled }, @@ -558,34 +557,26 @@ const char *xconfigValidateComposite(XConfigPtr config, return NULL; } - disable_composite = FALSE; - s = err_str; n = 0; - err_str[0] = '\0'; + err_str = NULL; for (i = 0; i < ARRAY_LEN(composite_incompatible_options); i++) { int value = composite_incompatible_options[i].value; const char *name = composite_incompatible_options[i].name; - int wrote; if (value) { - disable_composite = TRUE; + err_str = nv_prepend_to_string_list(err_str, name, + (n > 1) ? ", " : " or "); n++; - - wrote = snprintf(s, size, "%s%s", (n > 1) ? " or " : "", name); - if (wrote <= 0) { - break; - } - size -= wrote; - s += wrote; } } /* Special case checking for depth 8 */ if (depth <= 8) { - snprintf(s, size, "%sdepth=8", (n > 1) ? " or " : ""); + err_str = nv_prepend_to_string_list(err_str, "depth=8", + (n > 1) ? ", " : " or "); } - return disable_composite ? err_str : NULL; + return err_str; } diff --git a/XF86Config-parser/Generate.c b/XF86Config-parser/Generate.c index 0705b39..cdd7054 100644 --- a/XF86Config-parser/Generate.c +++ b/XF86Config-parser/Generate.c @@ -1321,7 +1321,8 @@ static int get_xserver_information(const char *versionString, int *isXorg, int *isModular, int *autoloadsGLX, - int *supportsExtensionSection) + int *supportsExtensionSection, + int *xineramaPlusCompositeWorks) { #define XSERVER_VERSION_FORMAT_1 "X Window System Version" #define XSERVER_VERSION_FORMAT_2 "X.Org X Server" @@ -1336,6 +1337,7 @@ static int get_xserver_information(const char *versionString, *isModular = FALSE; *autoloadsGLX = FALSE; *supportsExtensionSection = FALSE; + *xineramaPlusCompositeWorks = FALSE; return TRUE; } @@ -1400,6 +1402,17 @@ static int get_xserver_information(const char *versionString, *autoloadsGLX = TRUE; } + /* + * support for Xinerama and Composite at the same time works on X.Org + * xserver 1.15. + */ + + if ((major == 6) || (major == 7) || ((major == 1) && (minor < 15))) { + *xineramaPlusCompositeWorks = FALSE; + } else { + *xineramaPlusCompositeWorks = TRUE; + } + return TRUE; } /* get_xserver_information() */ @@ -1435,6 +1448,7 @@ void xconfigGetXServerInUse(GenerateOptions *gop) gop->supports_extension_section = FALSE; gop->autoloads_glx = FALSE; + gop->xinerama_plus_composite_works = FALSE; /* run `X -version` with a PATH that hopefully includes the X binary */ @@ -1464,7 +1478,8 @@ void xconfigGetXServerInUse(GenerateOptions *gop) &isXorg, &dummy, /* isModular */ &gop->autoloads_glx, - &gop->supports_extension_section); + &gop->supports_extension_section, + &gop->xinerama_plus_composite_works); if (found) { if (isXorg) { diff --git a/XF86Config-parser/xf86Parser.h b/XF86Config-parser/xf86Parser.h index 1135ffd..89c1569 100644 --- a/XF86Config-parser/xf86Parser.h +++ b/XF86Config-parser/xf86Parser.h @@ -624,6 +624,7 @@ typedef struct { int supports_extension_section; int autoloads_glx; + int xinerama_plus_composite_works; } GenerateOptions; @@ -762,15 +763,15 @@ void xconfigGenerateLoadDefaultOptions(GenerateOptions *gop); void xconfigGetXServerInUse(GenerateOptions *gop); -const char *xconfigValidateComposite(XConfigPtr config, - GenerateOptions *gop, - int composite_enabled, - int xinerama_enabled, - int depth, - int overlay_enabled, - int cioverlay_enabled, - int ubb_enabled, - int stereo); +char *xconfigValidateComposite(XConfigPtr config, + GenerateOptions *gop, + int composite_enabled, + int xinerama_enabled, + int depth, + int overlay_enabled, + int cioverlay_enabled, + int ubb_enabled, + int stereo); /* * check (and update, if necessary) the inputs in the specified layout diff --git a/common-utils/common-utils.c b/common-utils/common-utils.c index 9bd349e..f581f0d 100644 --- a/common-utils/common-utils.c +++ b/common-utils/common-utils.c @@ -29,8 +29,6 @@ #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> -#include <sys/ioctl.h> -#include <sys/termios.h> #include "common-utils.h" @@ -354,311 +352,6 @@ char *nv_prepend_to_string_list(char *list, const char *item, const char *delim) } -/****************************************************************************/ -/* TextRows helper functions */ -/****************************************************************************/ - -/* - * nv_format_text_rows() - this function breaks the given string str - * into some number of rows, where each row is not longer than the - * specified width. - * - * If prefix is non-NULL, the first line is prepended with the prefix, - * and subsequent lines are indented to line up with the prefix. - * - * If word_boundary is TRUE, then attempt to only break lines on - * boundaries between words. - */ - -TextRows *nv_format_text_rows(const char *prefix, - const char *str, - int width, int word_boundary) -{ - int len, prefix_len, z, w, i; - char *line, *buf, *local_prefix, *a, *b, *c; - TextRows *t; - - /* initialize the TextRows structure */ - - t = (TextRows *) malloc(sizeof(TextRows)); - - if (!t) return NULL; - - t->t = NULL; - t->n = 0; - t->m = 0; - - if (!str) return t; - - buf = strdup(str); - - if (!buf) return t; - - z = strlen(buf); /* length of entire string */ - a = buf; /* pointer to the start of the string */ - - /* initialize the prefix fields */ - - if (prefix) { - prefix_len = strlen(prefix); - local_prefix = strdup(prefix); - } else { - prefix_len = 0; - local_prefix = NULL; - } - - /* adjust the max width for any prefix */ - - w = width - prefix_len; - - do { - /* - * if the string will fit on one line, point b to the end of the - * string - */ - - if (z < w) b = a + z; - - /* - * if the string won't fit on one line, move b to where the - * end of the line should be, and then move b back until we - * find a space; if we don't find a space before we back b all - * the way up to a, just assign b to where the line should end. - */ - - else { - b = a + w; - - if (word_boundary) { - while ((b >= a) && (!isspace(*b))) b--; - if (b <= a) b = a + w; - } - } - - /* look for any newline between a and b, and move b to it */ - - for (c = a; c < b; c++) if (*c == '\n') { b = c; break; } - - /* - * copy the string that starts at a and ends at b, prepending - * with a prefix, if present - */ - - len = b-a; - len += prefix_len; - line = (char *) malloc(len+1); - if (local_prefix) strncpy(line, local_prefix, prefix_len); - strncpy(line + prefix_len, a, len - prefix_len); - line[len] = '\0'; - - /* append the new line to the array of text rows */ - - t->t = (char **) realloc(t->t, sizeof(char *) * (t->n + 1)); - t->t[t->n] = line; - t->n++; - - if (t->m < len) t->m = len; - - /* - * adjust the length of the string and move the pointer to the - * beginning of the new line - */ - - z -= (b - a + 1); - a = b + 1; - - /* move to the first non whitespace character (excluding newlines) */ - - if (word_boundary && isspace(*b)) { - while ((z) && (isspace(*a)) && (*a != '\n')) a++, z--; - } else { - if (!isspace(*b)) z++, a--; - } - - if (local_prefix) { - for (i = 0; i < prefix_len; i++) local_prefix[i] = ' '; - } - - } while (z > 0); - - if (local_prefix) free(local_prefix); - free(buf); - - return t; -} - - -/* - * nv_text_rows_append() - append the given msg to the existing TextRows - */ - -void nv_text_rows_append(TextRows *t, const char *msg) -{ - int len; - - t->t = realloc(t->t, sizeof(char *) * (t->n + 1)); - - if (msg) { - t->t[t->n] = strdup(msg); - len = strlen(msg); - if (t->m < len) t->m = len; - } else { - t->t[t->n] = NULL; - } - - t->n++; -} - -/* - * nv_concat_text_rows() - concatenate two text rows, storing the - * result in t0 - */ - -void nv_concat_text_rows(TextRows *t0, TextRows *t1) -{ - int n, i; - - n = t0->n + t1->n; - - t0->t = realloc(t0->t, sizeof(char *) * n); - - for (i = 0; i < t1->n; i++) { - t0->t[i + t0->n] = strdup(t1->t[i]); - } - - t0->m = NV_MAX(t0->m, t1->m); - t0->n = n; - -} /* nv_concat_text_rows() */ - - -/* - * nv_free_text_rows() - free the TextRows data structure allocated by - * nv_format_text_rows() - */ - -void nv_free_text_rows(TextRows *t) -{ - int i; - - if (!t) return; - for (i = 0; i < t->n; i++) free(t->t[i]); - if (t->t) free(t->t); - free(t); - -} /* nv_free_text_rows() */ - - -/****************************************************************************/ -/* printing helper functions */ -/****************************************************************************/ - -#define DEFAULT_WIDTH 75 - -static unsigned short __terminal_width = 0; - -/* - * reset_current_terminal_width() - if new_val is zero, then use the - * TIOCGWINSZ ioctl to get the current width of the terminal, and - * assign it the value to __terminal_width. If the ioctl fails, use a - * hardcoded constant. If new_val is non-zero, then use new_val. - */ - -void reset_current_terminal_width(unsigned short new_val) -{ - struct winsize ws; - - if (new_val) { - __terminal_width = new_val; - return; - } - - if (ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) { - __terminal_width = DEFAULT_WIDTH; - } else { - __terminal_width = ws.ws_col - 1; - } -} - -/* - * Call silence_fmt(1) to turn fmtout(), fmtoutp() and format() into noops. - */ -static int __silent = 0; - -void silence_fmt(int val) -{ - __silent = val; -} - - -static void vformat(FILE *stream, const int wb, - const char *prefix, const char *buf) -{ - int i; - TextRows *t; - - if (!__terminal_width) reset_current_terminal_width(0); - - t = nv_format_text_rows(prefix, buf, __terminal_width, wb); - - for (i = 0; i < t->n; i++) fprintf(stream, "%s\n", t->t[i]); - - nv_free_text_rows(t); -} - - -#define NV_VFORMAT(stream, wb, prefix, fmt) \ -do { \ - char *buf; \ - NV_VSNPRINTF(buf, fmt); \ - vformat(stream, wb, prefix, buf); \ - free (buf); \ -} while(0) - - -void fmtout(const char *fmt, ...) -{ - if (__silent > 0) { - return; - } - NV_VFORMAT(stdout, TRUE, NULL, fmt); -} - - -void fmtoutp(const char *prefix, const char *fmt, ...) -{ - if (__silent > 0) { - return; - } - NV_VFORMAT(stdout, TRUE, prefix, fmt); -} - - -void fmterr(const char *fmt, ...) -{ - vformat(stderr, 0, NULL, ""); - NV_VFORMAT(stderr, TRUE, "ERROR: ", fmt); - vformat(stderr, 0, NULL, ""); -} - - -void fmtwarn(const char *fmt, ...) -{ - vformat(stderr, 0, NULL, ""); - NV_VFORMAT(stderr, TRUE, "WARNING: ", fmt); - vformat(stderr, 0, NULL, ""); -} - - -void fmt(FILE *stream, const char *prefix, const char *fmt, ...) -{ - if (__silent > 0) { - return; - } - NV_VFORMAT(stream, TRUE, prefix, fmt); -} - - /* * Read from the given FILE stream until a newline, EOF, or nul * terminator is encountered, writing data into a growable buffer. diff --git a/common-utils/common-utils.h b/common-utils/common-utils.h index e9d505e..3db71b6 100644 --- a/common-utils/common-utils.h +++ b/common-utils/common-utils.h @@ -22,6 +22,8 @@ #include <sys/types.h> #include <stdint.h> +#include "msg.h" + #if !defined(TRUE) #define TRUE 1 #endif @@ -38,32 +40,6 @@ #define TAB " " #define BIGTAB " " -#define VERBOSITY_NONE 0 /* nothing */ -#define VERBOSITY_ERROR 1 /* errors only */ -#define VERBOSITY_DEPRECATED 2 /* errors, deprecation messages and warnings */ -#define VERBOSITY_WARNING 3 /* errors and warnings */ -#define VERBOSITY_ALL 4 /* errors, warnings and other info */ - -#define VERBOSITY_DEFAULT VERBOSITY_ERROR - -/* - * Define a printf format attribute macro. This definition is based on the one - * from Xfuncproto.h, available in the 'xproto' package at - * http://xorg.freedesktop.org/releases/individual/proto/ - */ - -#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203) -# define NV_ATTRIBUTE_PRINTF(x,y) __attribute__((__format__(__printf__,x,y))) -#else /* not gcc >= 2.3 */ -# define NV_ATTRIBUTE_PRINTF(x,y) -#endif - -typedef struct { - char **t; /* the text rows */ - int n; /* number of rows */ - int m; /* maximum row length */ -} TextRows; - void *nvalloc(size_t size); char *nvstrcat(const char *str, ...); void *nvrealloc(void *ptr, size_t size); @@ -79,22 +55,6 @@ void nvfree(void *s); char *tilde_expansion(const char *str); char *nv_prepend_to_string_list(char *list, const char *item, const char *delim); -TextRows *nv_format_text_rows(const char *prefix, - const char *str, - int width, int word_boundary); -void nv_text_rows_append(TextRows *t, const char *msg); -void nv_concat_text_rows(TextRows *t0, TextRows *t1); -void nv_free_text_rows(TextRows *t); - -void reset_current_terminal_width(unsigned short new_val); - -void silence_fmt(int val); -void fmtout(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2); -void fmtoutp(const char *prefix, const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3); -void fmterr(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2); -void fmtwarn(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2); -void fmt(FILE *stream, const char *prefix, const char *fmt, ...) NV_ATTRIBUTE_PRINTF(3, 4); - char *fget_next_line(FILE *fp, int *eof); int nv_open(const char *pathname, int flags, mode_t mode); @@ -107,51 +67,6 @@ char *nv_trim_space(char *string); char *nv_trim_char(char *string, char trim); char *nv_trim_char_strict(char *string, char trim); -/* - * NV_VSNPRINTF(): macro that assigns buf using vsnprintf(). This is - * correct for differing semantics of the vsnprintf() return value: - * - * -1 when the buffer is not long enough (glibc < 2.1) - * - * or - * - * the length the string would have been if the buffer had been large - * enough (glibc >= 2.1) - * - * This macro allocates memory for buf; the caller should free it when - * done. - */ - -#define NV_FMT_BUF_LEN 256 - -#define NV_VSNPRINTF(buf, fmt) \ -do { \ - if (!fmt) { \ - (buf) = NULL; \ - } else { \ - va_list ap; \ - int len, current_len = NV_FMT_BUF_LEN; \ - \ - while (1) { \ - (buf) = nvalloc(current_len); \ - \ - va_start(ap, fmt); \ - len = vsnprintf((buf), current_len, (fmt), ap); \ - va_end(ap); \ - \ - if ((len > -1) && (len < current_len)) { \ - break; \ - } else if (len > -1) { \ - current_len = len + 1; \ - } else { \ - current_len += NV_FMT_BUF_LEN; \ - } \ - \ - nvfree(buf); \ - } \ - } \ -} while (0) - #if defined(__GNUC__) # define NV_INLINE __inline__ #else diff --git a/common-utils/gen-manpage-opts-helper.c b/common-utils/gen-manpage-opts-helper.c index 532015d..c05ef38 100644 --- a/common-utils/gen-manpage-opts-helper.c +++ b/common-utils/gen-manpage-opts-helper.c @@ -17,16 +17,18 @@ #include <stdio.h> #include <ctype.h> #include <string.h> +#include <stdlib.h> #include "nvgetopt.h" #include "gen-manpage-opts-helper.h" +#include "common-utils.h" static void print_option(const NVGetoptOption *o) { char scratch[64], *s; int j, len; - int italics, bold, omitWhiteSpace; + int italics, bold, omitWhiteSpace, firstchar; /* if we are going to need the argument, process it now */ if (o->flags & NVGETOPT_HAS_ARGUMENT) { @@ -88,13 +90,15 @@ static void print_option(const NVGetoptOption *o) * '&' : toggles italics on and off * '^' : toggles bold on and off * '-' : is backslashified: "\-" + * '.' : must not be the first character of a line * - * Whitespace is omitted when italics or bold is on + * Trailing whitespace is omitted when italics or bold is on */ - italics = 0; - bold = 0; - omitWhiteSpace = 0; + italics = FALSE; + bold = FALSE; + omitWhiteSpace = FALSE; + firstchar = TRUE; for (s = o->description; s && *s; s++) { @@ -107,6 +111,7 @@ static void print_option(const NVGetoptOption *o) } omitWhiteSpace = italics; italics = !italics; + firstchar = TRUE; break; case '^': if (bold) { @@ -116,19 +121,33 @@ static void print_option(const NVGetoptOption *o) } omitWhiteSpace = bold; bold = !bold; + firstchar = TRUE; break; case '-': printf("\\-"); - omitWhiteSpace = 0; + omitWhiteSpace = FALSE; + firstchar = FALSE; break; case ' ': if (!omitWhiteSpace) { printf(" "); + firstchar = FALSE; } break; + case '.': + if (firstchar) { + fprintf(stderr, "Error: *roff can't start a line with '.' " + "If you used '&' or '^' to format text in the " + "description of the '%s' option, please add some " + "text before the end of the sentence, so that a " + "valid manpage can be generated.\n", o->name); + exit(1); + } + /* fall through */ default: printf("%c", *s); - omitWhiteSpace = 0; + omitWhiteSpace = FALSE; + firstchar = FALSE; break; } } diff --git a/common-utils/msg.c b/common-utils/msg.c new file mode 100644 index 0000000..cdd3c4f --- /dev/null +++ b/common-utils/msg.c @@ -0,0 +1,416 @@ +/* + * Copyright (C) 2004 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, 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 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, see <http://www.gnu.org/licenses>. + */ + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#if defined(__sun) +#include <sys/termios.h> +#endif + +#include "msg.h" +#include "common-utils.h" + + +/* + * verbosity, controls output of errors, warnings and other + * information. + */ + +static NvVerbosity __verbosity = NV_VERBOSITY_DEFAULT; + +NvVerbosity nv_get_verbosity() +{ + return __verbosity; +} + +void nv_set_verbosity(NvVerbosity level) +{ + __verbosity = level; +} + + +/****************************************************************************/ +/* Formatted I/O functions */ +/****************************************************************************/ + +#define DEFAULT_WIDTH 75 + +static unsigned short __terminal_width = 0; + +/* + * reset_current_terminal_width() - if new_val is zero, then use the + * TIOCGWINSZ ioctl to get the current width of the terminal, and + * assign it the value to __terminal_width. If the ioctl fails, use a + * hardcoded constant. If new_val is non-zero, then use new_val. + */ + +void reset_current_terminal_width(unsigned short new_val) +{ + struct winsize ws; + + if (new_val) { + __terminal_width = new_val; + return; + } + + if (ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) { + __terminal_width = DEFAULT_WIDTH; + } else { + __terminal_width = ws.ws_col - 1; + } +} + + +static void format(FILE *stream, const char *prefix, const char *buf, + const int whitespace) +{ + int i; + TextRows *t; + + if (!__terminal_width) reset_current_terminal_width(0); + + t = nv_format_text_rows(prefix, buf, __terminal_width, whitespace); + + for (i = 0; i < t->n; i++) fprintf(stream, "%s\n", t->t[i]); + + nv_free_text_rows(t); +} + + +#define NV_FORMAT(stream, prefix, fmt, whitespace) \ +do { \ + char *buf; \ + NV_VSNPRINTF(buf, fmt); \ + format(stream, prefix, buf, whitespace); \ + free (buf); \ +} while(0) + + +/* + * nv_error_msg() - print an error message, nicely formatted using the + * format() function. + * + * This function should be used for all errors. + */ + +void nv_error_msg(const char *fmt, ...) +{ + if (__verbosity < NV_VERBOSITY_ERROR) return; + + format(stderr, NULL, "", TRUE); + NV_FORMAT(stderr, "ERROR: ", fmt, TRUE); + format(stderr, NULL, "", TRUE); +} /* nv_error_msg() */ + + +/* + * nv_deprecated_msg() - print a deprecation message, nicely formatted using + * the format() function. + * + * This function should be used for all deprecation messages. + */ + +void nv_deprecated_msg(const char *fmt, ...) +{ + if (__verbosity < NV_VERBOSITY_DEPRECATED) return; + + format(stderr, NULL, "", TRUE); + NV_FORMAT(stderr, "DEPRECATED: ", fmt, TRUE); + format(stderr, NULL, "", TRUE); +} + + +/* + * nv_warning_msg() - print a warning message, nicely formatted using + * the format() function. + * + * This function should be used for all warnings. + */ + +void nv_warning_msg(const char *fmt, ...) +{ + if (__verbosity < NV_VERBOSITY_WARNING) return; + + format(stderr, NULL, "", TRUE); + NV_FORMAT(stderr, "WARNING: ", fmt, TRUE); + format(stderr, NULL, "", TRUE); +} /* nv_warning_msg() */ + + +/* + * nv_info_msg() - print an info message, nicely formatted using + * the format() function. + * + * This function should be used to display verbose information. + */ + +void nv_info_msg(const char *prefix, const char *fmt, ...) +{ + if (__verbosity < NV_VERBOSITY_ALL) return; + + NV_FORMAT(stdout, prefix, fmt, TRUE); +} /* nv_info_msg() */ + + +/* + * nv_info_msg_to_file() - Prints the message, just like nv_info_msg() + * using format() the difference is, it prints to any stream defined by + * the corresponding argument. + */ + +void nv_info_msg_to_file(FILE *stream, const char *prefix, const char *fmt, ...) +{ + if (__verbosity < NV_VERBOSITY_ALL) return; + + NV_FORMAT(stream, prefix, fmt, TRUE); +} /* nv_info_msg_to_file() */ + + +/* + * nv_msg() - print a message, nicely formatted using the format() + * function. + * + * This function should be used to display messages independent + * of the verbosity level. + */ + +void nv_msg(const char *prefix, const char *fmt, ...) +{ + NV_FORMAT(stdout, prefix, fmt, TRUE); +} /* 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, FALSE); +} /* nv_msg_preserve_whitespace() */ + + +/* + * XXX gcc's '-ansi' option causes vsnprintf to not be defined, so + * declare the prototype here. + */ + +#if defined(__STRICT_ANSI__) +int vsnprintf(char *str, size_t size, const char *format, + va_list ap); +#endif + + +/****************************************************************************/ +/* TextRows helper functions */ +/****************************************************************************/ + +/* + * nv_format_text_rows() - this function breaks the given string str + * into some number of rows, where each row is not longer than the + * specified width. + * + * If prefix is non-NULL, the first line is prepended with the prefix, + * and subsequent lines are indented to line up with the prefix. + * + * If word_boundary is TRUE, then attempt to only break lines on + * boundaries between words. + */ + +TextRows *nv_format_text_rows(const char *prefix, const char *str, int width, + int word_boundary) +{ + int len, prefix_len, z, w, i; + char *line, *buf, *local_prefix, *a, *b, *c; + TextRows *t; + + /* initialize the TextRows structure */ + + t = (TextRows *) malloc(sizeof(TextRows)); + + if (!t) return NULL; + + t->t = NULL; + t->n = 0; + t->m = 0; + + if (!str) return t; + + buf = strdup(str); + + if (!buf) return t; + + z = strlen(buf); /* length of entire string */ + a = buf; /* pointer to the start of the string */ + + /* initialize the prefix fields */ + + if (prefix) { + prefix_len = strlen(prefix); + local_prefix = strdup(prefix); + } else { + prefix_len = 0; + local_prefix = NULL; + } + + /* adjust the max width for any prefix */ + + w = width - prefix_len; + + do { + /* + * if the string will fit on one line, point b to the end of the + * string + */ + + if (z < w) b = a + z; + + /* + * if the string won't fit on one line, move b to where the + * end of the line should be, and then move b back until we + * find a space; if we don't find a space before we back b all + * the way up to a, just assign b to where the line should end. + */ + + else { + b = a + w; + + if (word_boundary) { + while ((b >= a) && (!isspace(*b))) b--; + if (b <= a) b = a + w; + } + } + + /* look for any newline between a and b, and move b to it */ + + for (c = a; c < b; c++) if (*c == '\n') { b = c; break; } + + /* + * copy the string that starts at a and ends at b, prepending + * with a prefix, if present + */ + + len = b-a; + len += prefix_len; + line = (char *) malloc(len+1); + if (local_prefix) strncpy(line, local_prefix, prefix_len); + strncpy(line + prefix_len, a, len - prefix_len); + line[len] = '\0'; + + /* append the new line to the array of text rows */ + + t->t = (char **) realloc(t->t, sizeof(char *) * (t->n + 1)); + t->t[t->n] = line; + t->n++; + + if (t->m < len) t->m = len; + + /* + * adjust the length of the string and move the pointer to the + * beginning of the new line + */ + + z -= (b - a + 1); + a = b + 1; + + /* move to the first non whitespace character (excluding newlines) */ + + if (word_boundary && isspace(*b)) { + while ((z) && (isspace(*a)) && (*a != '\n')) a++, z--; + } else { + if (!isspace(*b)) z++, a--; + } + + if (local_prefix) { + for (i = 0; i < prefix_len; i++) local_prefix[i] = ' '; + } + + } while (z > 0); + + if (local_prefix) free(local_prefix); + free(buf); + + return t; +} + + +/* + * nv_text_rows_append() - append the given msg to the existing TextRows + */ + +void nv_text_rows_append(TextRows *t, const char *msg) +{ + int len; + + t->t = realloc(t->t, sizeof(char *) * (t->n + 1)); + + if (msg) { + t->t[t->n] = strdup(msg); + len = strlen(msg); + if (t->m < len) t->m = len; + } else { + t->t[t->n] = NULL; + } + + t->n++; +} + +/* + * nv_concat_text_rows() - concatenate two text rows, storing the + * result in t0 + */ + +void nv_concat_text_rows(TextRows *t0, TextRows *t1) +{ + int n, i; + + n = t0->n + t1->n; + + t0->t = realloc(t0->t, sizeof(char *) * n); + + for (i = 0; i < t1->n; i++) { + t0->t[i + t0->n] = strdup(t1->t[i]); + } + + t0->m = NV_MAX(t0->m, t1->m); + t0->n = n; + +} /* nv_concat_text_rows() */ + + +/* + * nv_free_text_rows() - free the TextRows data structure allocated by + * nv_format_text_rows() + */ + +void nv_free_text_rows(TextRows *t) +{ + int i; + + if (!t) return; + for (i = 0; i < t->n; i++) free(t->t[i]); + if (t->t) free(t->t); + free(t); + +} /* nv_free_text_rows() */ + diff --git a/common-utils/msg.h b/common-utils/msg.h new file mode 100644 index 0000000..5e32c19 --- /dev/null +++ b/common-utils/msg.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2004 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, 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 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, see <http://www.gnu.org/licenses>. + */ + +#ifndef __MSG_H__ +#define __MSG_H__ + +#include <stdarg.h> +#include <stdio.h> + + +/* + * Define a printf format attribute macro. This definition is based on the one + * from Xfuncproto.h, available in the 'xproto' package at + * http://xorg.freedesktop.org/releases/individual/proto/ + */ + +#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203) +# define NV_ATTRIBUTE_PRINTF(x,y) __attribute__((__format__(__printf__,x,y))) +#else /* not gcc >= 2.3 */ +# define NV_ATTRIBUTE_PRINTF(x,y) +#endif + + +/* + * NV_VSNPRINTF(): macro that assigns buf using vsnprintf(). This is + * correct for differing semantics of the vsnprintf() return value: + * + * -1 when the buffer is not long enough (glibc < 2.1) + * + * or + * + * the length the string would have been if the buffer had been large + * enough (glibc >= 2.1) + * + * This macro allocates memory for buf; the caller should free it when + * done. + */ + +#define NV_FMT_BUF_LEN 256 + +#define NV_VSNPRINTF(buf, fmt) \ +do { \ + if (!fmt) { \ + (buf) = NULL; \ + } else { \ + va_list ap; \ + int len, current_len = NV_FMT_BUF_LEN; \ + \ + while (1) { \ + (buf) = nvalloc(current_len); \ + \ + va_start(ap, fmt); \ + len = vsnprintf((buf), current_len, (fmt), ap); \ + va_end(ap); \ + \ + if ((len > -1) && (len < current_len)) { \ + break; \ + } else if (len > -1) { \ + current_len = len + 1; \ + } else { \ + current_len += NV_FMT_BUF_LEN; \ + } \ + \ + nvfree(buf); \ + } \ + } \ +} while (0) + + +/* + * verbosity, controls output of errors, warnings and other + * information. + */ + +typedef enum { + NV_VERBOSITY_NONE = 0, /* no errors, warnings or info */ + NV_VERBOSITY_ERROR, /* errors only */ + NV_VERBOSITY_DEPRECATED, /* errors and deprecation messages */ + NV_VERBOSITY_WARNING, /* errors and all warnings */ + NV_VERBOSITY_ALL, /* errors, all warnings and other info */ + NV_VERBOSITY_DEFAULT = NV_VERBOSITY_ALL +} NvVerbosity; + +NvVerbosity nv_get_verbosity(void); +void nv_set_verbosity(NvVerbosity level); + + +/* + * Formatted I/O functions + */ + +void reset_current_terminal_width(unsigned short new_val); + +void nv_error_msg(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2); +void nv_deprecated_msg(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2); +void nv_warning_msg(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2); +void nv_info_msg(const char *prefix, + const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3); +void nv_info_msg_to_file(FILE *stream, + const char *prefix, + const char *fmt, ...) NV_ATTRIBUTE_PRINTF(3, 4); +void nv_msg(const char *prefix, const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3); +void nv_msg_preserve_whitespace(const char *prefix, + const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3); + + +/* + * TextRows structure and helper functions + */ + +typedef struct { + char **t; /* the text rows */ + int n; /* number of rows */ + int m; /* maximum row length */ +} TextRows; + +TextRows *nv_format_text_rows(const char *prefix, const char *str, int width, + int word_boundary); +void nv_text_rows_append(TextRows *t, const char *msg); +void nv_concat_text_rows(TextRows *t0, TextRows *t1); +void nv_free_text_rows(TextRows *t); + + +#endif /* __MSG_H__ */ diff --git a/common-utils/src.mk b/common-utils/src.mk index 12ba143..6dbed7a 100644 --- a/common-utils/src.mk +++ b/common-utils/src.mk @@ -2,9 +2,11 @@ COMMON_UTILS_SRC += nvgetopt.c COMMON_UTILS_SRC += common-utils.c +COMMON_UTILS_SRC += msg.c COMMON_UTILS_EXTRA_DIST += nvgetopt.h COMMON_UTILS_EXTRA_DIST += common-utils.h +COMMON_UTILS_EXTRA_DIST += msg.h COMMON_UTILS_EXTRA_DIST += src.mk # gen-manpage-opts-helper.c is listed in EXTRA_DIST, rather than SRC, diff --git a/extract_edids.c b/extract_edids.c index cd0569d..bcc8389 100644 --- a/extract_edids.c +++ b/extract_edids.c @@ -95,6 +95,7 @@ #include <strings.h> /* bzero() */ #include "nvidia-xconfig.h" +#include "msg.h" #define NIBBLE_TO_HEX(n) (((n) <= 9) ? ('0' + (n)) : ('a' - 0xa + (n))) @@ -198,22 +199,22 @@ int extract_edids(Options *op) fd = open(op->extract_edids_from_file, O_RDONLY); if (fd == -1) { - fmterr("Unable to open file \"%s\".", op->extract_edids_from_file); + nv_error_msg("Unable to open file \"%s\".", op->extract_edids_from_file); goto done; } ret = fstat(fd, &stat_buf); if (ret == -1) { - fmterr("Unable to get length of file \"%s\".", - op->extract_edids_from_file); + nv_error_msg("Unable to get length of file \"%s\".", + op->extract_edids_from_file); goto done; } file.length = stat_buf.st_size; if (file.length == 0) { - fmterr("File \"%s\" is empty.", op->extract_edids_from_file); + nv_error_msg("File \"%s\" is empty.", op->extract_edids_from_file); goto done; } @@ -223,7 +224,7 @@ int extract_edids(Options *op) MAP_SHARED, fd, 0); if (file.start == (void *) -1) { - fmterr("Unable to map file \"%s\".", op->extract_edids_from_file); + nv_error_msg("Unable to map file \"%s\".", op->extract_edids_from_file); goto done; } @@ -298,9 +299,9 @@ int extract_edids(Options *op) * writeEdidFile; it will unique-ify from there */ - fmtout(""); - fmtout("Found %d EDID%s in \"%s\".", - nEdids, (nEdids == 1) ? "": "s", op->extract_edids_from_file); + nv_info_msg(NULL, ""); + nv_info_msg(NULL, "Found %d EDID%s in \"%s\".", + nEdids, (nEdids == 1) ? "": "s", op->extract_edids_from_file); filename = findFileName(op->extract_edids_output_file); @@ -317,7 +318,7 @@ int extract_edids(Options *op) nvfree(filename); - fmtout(""); + nv_info_msg(NULL, ""); return funcRet; @@ -1075,11 +1076,11 @@ static int writeEdidFile(EdidPtr pEdid, char *filename) /* report what happened */ if (ret) { - fmtout(" Wrote EDID for \"%s\" to \"%s\" (%d bytes).", - pEdid->name, working_filename, pEdid->size); + nv_info_msg(NULL, " Wrote EDID for \"%s\" to \"%s\" (%d bytes).", + pEdid->name, working_filename, pEdid->size); } else { - fmterr("Failed to write EDID for \"%s\" to \"%s\" (%s)", - pEdid->name, working_filename, msg); + nv_error_msg("Failed to write EDID for \"%s\" to \"%s\" (%s)", + pEdid->name, working_filename, msg); } nvfree(working_filename); @@ -20,6 +20,7 @@ #include <libscf.h> +#include "msg.h" static int lscf_init_handle(scf_handle_t **scf_handle, scf_scope_t **scf_scope); @@ -75,8 +76,8 @@ done: scf_handle_destroy(scf_handle); } if (!status) { - fmterr("Unable to set X server default depth through " - "Solaris Service Management Facility"); + nv_error_msg("Unable to set X server default depth through " + "Solaris Service Management Facility"); } return status; } @@ -118,8 +119,8 @@ done: scf_handle_destroy(scf_handle); } if (!status) { - fmterr("Unable to get X server default depth from " - "Solaris Service Management Facility"); + nv_error_msg("Unable to get X server default depth from " + "Solaris Service Management Facility"); } return status; } diff --git a/make_usable.c b/make_usable.c index dd73347..3858b4a 100644 --- a/make_usable.c +++ b/make_usable.c @@ -28,6 +28,7 @@ #include "nvidia-xconfig.h" #include "xf86Parser.h" #include "configProcs.h" +#include "msg.h" static void ensure_module_loaded(XConfigPtr config, char *name); @@ -139,7 +140,7 @@ XConfigLayoutPtr get_layout(Options *op, XConfigPtr config) layout = xconfigFindLayout(op->layout, config->layouts); if (!layout) { - fmterr("Unable to find layout \"%s\".\n", op->layout); + nv_error_msg("Unable to find layout \"%s\".\n", op->layout); return NULL; } } else { @@ -147,7 +148,7 @@ XConfigLayoutPtr get_layout(Options *op, XConfigPtr config) /* otherwise, use the first layout in the config file */ if (!config->layouts) { - fmterr("unable to select ScreenLayout to use.\n"); + nv_error_msg("unable to select ScreenLayout to use.\n"); return NULL; } @@ -331,9 +332,10 @@ static void update_depth(Options *op, XConfigScreenPtr screen) int scf_depth; if (read_scf_depth(&scf_depth) && scf_depth != screen->defaultdepth) { - fmtwarn("The default depth of %d read from " - "the Solaris Management Facility is set as the default " - "depth for screen \"%s\"", scf_depth, screen->identifier); + nv_warning_msg("The default depth of %d read from " + "the Solaris Management Facility is set as the " + "default depth for screen \"%s\"", scf_depth, + screen->identifier); screen->defaultdepth = scf_depth; } } diff --git a/multiple_screens.c b/multiple_screens.c index 295318a..25813ee 100644 --- a/multiple_screens.c +++ b/multiple_screens.c @@ -22,6 +22,7 @@ #include "nvidia-xconfig.h" #include "xf86Parser.h" +#include "msg.h" #include <stdlib.h> #include <string.h> @@ -36,8 +37,8 @@ static int disable_separate_x_screens(Options *op, XConfigPtr config, static int set_xinerama(int xinerama_enabled, XConfigLayoutPtr layout); static XConfigDisplayPtr clone_display_list(XConfigDisplayPtr display0); -static XConfigDevicePtr clone_device(XConfigDevicePtr device0); -static XConfigScreenPtr clone_screen(XConfigScreenPtr screen0); +static XConfigDevicePtr clone_device(XConfigDevicePtr device0, int idx); +static XConfigScreenPtr clone_screen(XConfigScreenPtr screen0, int idx); static void create_adjacencies(Options *op, XConfigPtr config, XConfigLayoutPtr layout); @@ -52,6 +53,199 @@ static int only_one_screen(Options *op, XConfigPtr config, XConfigLayoutPtr layout); /* + * get_screens_to_clone() - try to detect automatically how many heads has each + * device in order to use that number to create more than two separate X + * screens. If the user specifies the option --num-x-screens <quantity>, that + * value is used. If neither the user specifies the quantity or the number of + * heads can be detected automatically, it uses 2 heads (the standard + * behavior). This function returns an array of size nscreens with the number + * of screens to clone per screen candidate. The caller is responsible of + * freeing the memory of that array. + */ +static int* get_screens_to_clone(Options *op, + const XConfigScreenPtr *screen_candidates, + int nscreens) +{ + DevicesPtr pDevices; + int *screens_to_clone, *supported_screens; + int i, j, devs_found; + + screens_to_clone = nvalloc(nscreens * sizeof(int)); + supported_screens = nvalloc(nscreens * sizeof(int)); + + /* Detect the number of supported screens per screen candidate */ + devs_found = FALSE; + pDevices = find_devices(op); + if (pDevices) { + for (i = 0; i < nscreens; i++) { + int bus, slot, scratch; + + if (!screen_candidates[i]) { + continue; + } + + /* parse the bus id for this candidate screen */ + if (!xconfigParsePciBusString(screen_candidates[i]->device->busid, + &bus, &slot, &scratch)) { + continue; + } + + for (j = 0; j < pDevices->nDevices; j++) { + if ((pDevices->devices[j].dev.bus == bus) && + (pDevices->devices[j].dev.slot == slot)) { + + if (pDevices->devices[j].crtcs > 0) { + supported_screens[i] = pDevices->devices[j].crtcs; + } + break; + } + } + } + free_devices(pDevices); + devs_found = TRUE; + } + + /* If user has defined a number of screens per GPU, use that value */ + if (op->num_x_screens > 0) { + for (i = 0; i < nscreens; i++) { + if (!screen_candidates[i]) { + continue; + } + + /* Print error when user specifies more X screens than supported */ + if (devs_found && op->num_x_screens > supported_screens[i]) { + nv_warning_msg("Number of X screens specified is higher than the " + "supported quantity (%d)", supported_screens[i]); + } + + screens_to_clone[i] = op->num_x_screens; + } + + goto done; + } + + for (i = 0; i < nscreens; i++) { + if (screen_candidates[i]) { + if (devs_found) { + /* If devices found, use the supported screens number */ + screens_to_clone[i] = supported_screens[i]; + } + else { + /* Default behavior (2 heads per GPU) */ + screens_to_clone[i] = 2; + } + } + } + +done: + nvfree(supported_screens); + return screens_to_clone; +} + +/* + * clean_screen_list() - Used by enable_separate_x_screens and + * disable_separate_x_screens. Given the array screen_list and the config + * pointer, this function will leave only one screen per different busid in both + * screen_list array and config->screens list (i.e all the resulting screens in + * screen_list and config->screens will have an unique busid). + */ +static void clean_screen_list(XConfigScreenPtr *screen_list, + XConfigPtr config, + int nscreens) +{ + int i, j; + int *bus, *slot, scratch; + + /* trim out duplicates and get the bus ids*/ + + bus = nvalloc(sizeof(int) * nscreens); + slot = nvalloc(sizeof(int) * nscreens); + + for (i = 0; i < nscreens; i++) { + bus[i] = -1; + } + + for (i = 0; i < nscreens; i++) { + if (!screen_list[i] || (bus[i] == -1 && + !xconfigParsePciBusString(screen_list[i]->device->busid, + &bus[i], &slot[i], &scratch))) { + continue; + } + + for (j = i+1; j < nscreens; j++) { + if (!screen_list[j] || (bus[j] == -1 && + !xconfigParsePciBusString(screen_list[j]->device->busid, + &bus[j], &slot[j], &scratch))) { + continue; + } + + if ((bus[i] == bus[j]) && (slot[i] == slot[j])) { + screen_list[j] = NULL; + } + } + } + + /* + * for every screen in the screen list, scan through all + * screens; if any screen, other than *this* screen has the same + * busid, remove it + */ + + for (i = 0; i < nscreens; i++) { + XConfigScreenPtr screen, prev; + int bus0, slot0; + + if (!screen_list[i]) { + continue; + } + + screen = config->screens; + prev = NULL; + + while (screen) { + if (screen_list[i] == screen) { + goto next_screen; + } + if (!screen->device) { + goto next_screen; + } + if (!screen->device->busid) { + goto next_screen; + } + if (!xconfigParsePciBusString(screen->device->busid, + &bus0, &slot0, &scratch)) { + goto next_screen; + } + + if ((bus[i] == bus0) && (slot[i] == slot0)) { + XConfigScreenPtr next; + + if (prev) { + prev->next = screen->next; + } + else { + config->screens = screen->next; + } + + next = screen->next; + screen->next = NULL; + xconfigFreeScreenList(&screen); + screen = next; + } + else { + + next_screen: + + prev = screen; + screen = screen->next; + } + } + + screen_list[i]->device->screen = -1; + } +} + +/* * apply_multi_screen_options() - there are 4 options that can affect * multiple X screens: * @@ -148,17 +342,17 @@ DevicesPtr find_devices(Options *op) nvfree(lib_path); if (!lib_handle) { - fmtwarn("error opening %s: %s.", __LIB_NAME, dlerror()); + nv_warning_msg("error opening %s: %s.", __LIB_NAME, dlerror()); return NULL; } -#define __GET_FUNC(proc, name) \ - (proc) = dlsym(lib_handle, (name)); \ - if (!(proc)) { \ - fmtwarn("error retrieving symbol %s from %s: %s", \ - (name), __LIB_NAME, dlerror()); \ - dlclose(lib_handle); \ - return NULL; \ +#define __GET_FUNC(proc, name) \ + (proc) = dlsym(lib_handle, (name)); \ + if (!(proc)) { \ + nv_warning_msg("error retrieving symbol %s from %s: %s", \ + (name), __LIB_NAME, dlerror()); \ + dlclose(lib_handle); \ + return NULL; \ } /* required functions */ @@ -275,8 +469,8 @@ DevicesPtr find_devices(Options *op) fail: - fmtwarn("Unable to use the nvidia-cfg library to query NVIDIA " - "hardware."); + nv_warning_msg("Unable to use the nvidia-cfg library to query NVIDIA " + "hardware."); for (i = 0; i < pDevices->nDevices; i++) { /* close the opened device */ @@ -354,16 +548,13 @@ static int set_xinerama(int xinerama_enabled, XConfigLayoutPtr layout) * step 2: assign a busID to every screen that is in the list (if * BusIDs are not already assigned) * - * step 3: for every candidate screen, check if it is already one of - * multiple screens on a gpu; if so, then it is not eligible for - * cloning. Note that this has to check all screens in the adjacency - * list, not just the ones in the candidate list. + * step 3: clean the candidate list + * + * step 4: get the number of clones per screen candidate * * step 4: clone each eligible screen * * step 5: update adjacency list (just wipe the list and restart) - * - * XXX we need to check that there are actually 2 CRTCs on this GPU */ static int enable_separate_x_screens(Options *op, XConfigPtr config, @@ -371,16 +562,17 @@ static int enable_separate_x_screens(Options *op, XConfigPtr config, { XConfigScreenPtr screen, *screenlist = NULL; XConfigAdjacencyPtr adj; + int* screens_to_clone = NULL; int i, nscreens = 0; int have_busids; - /* build the list of screens that are candidate to be cloned */ + /* step 1: build the list of screens that are candidate to be cloned */ if (op->screen) { screen = xconfigFindScreen(op->screen, config->screens); if (!screen) { - fmterr("Unable to find screen '%s'.", op->screen); + nv_error_msg("Unable to find screen '%s'.", op->screen); return FALSE; } @@ -400,7 +592,7 @@ static int enable_separate_x_screens(Options *op, XConfigPtr config, if (!nscreens) return FALSE; - /* do all screens in the list have a bus ID? */ + /* step 2: do all screens in the list have a bus ID? */ have_busids = TRUE; @@ -426,9 +618,9 @@ static int enable_separate_x_screens(Options *op, XConfigPtr config, pDevices = find_devices(op); if (!pDevices) { - fmterr("Unable to determine number or location of " - "GPUs in system; cannot " - "honor '--separate-x-screens' option."); + nv_error_msg("Unable to determine number or location of " + "GPUs in system; cannot " + "honor '--separate-x-screens' option."); return FALSE; } @@ -453,65 +645,36 @@ static int enable_separate_x_screens(Options *op, XConfigPtr config, free_devices(pDevices); } - - /* - * step 3: for every candidate screen, check if it is already one - * of multiple screens on a gpu; if so, then it is not eligible - * for cloning. Note that this has to check all screens in the - * adjacency list, not just the ones in the candidate list - */ - - for (i = 0; i < nscreens; i++) { - int bus0, bus1, slot0, slot1, scratch; - if (!screenlist[i]) continue; - - /* parse the bus id for this candidate screen */ - if (!xconfigParsePciBusString(screenlist[i]->device->busid, - &bus0, &slot0, &scratch)) { - /* parsing failed; this screen is no longer a candidate */ - screenlist[i] = NULL; - continue; - } + /* step 3 */ + clean_screen_list(screenlist, config, nscreens); - /* - * scan through all the screens; if any screen, other than - * *this* screen, have the same busid, then this screen is no - * longer a candidate - */ - - for (screen = config->screens; screen; screen = screen->next) { - if (screen == screenlist[i]) continue; - if (!screen->device) continue; - if (!screen->device->busid) continue; - if (!xconfigParsePciBusString(screen->device->busid, - &bus1, &slot1, &scratch)) continue; - if ((bus0 == bus1) && (slot0 == slot1)) { - screenlist[i] = NULL; /* no longer a candidate */ - break; - } - } - } + /* step 4 */ + screens_to_clone = get_screens_to_clone(op, screenlist, nscreens); - /* clone each eligible screen */ + /* step 5: clone each eligible screen */ for (i = 0; i < nscreens; i++) { if (!screenlist[i]) continue; - clone_screen(screenlist[i]); + + while (--screens_to_clone[i] > 0) { + clone_screen(screenlist[i], screens_to_clone[i]); + } } + + nvfree(screens_to_clone); - /* - * wipe the existing adjacencies and recreate them - * - * XXX we should really only use the screens in the current - * adjacency list, plus the new cloned screens, when building the - * new adjacencies - */ + /* step 6: wipe the existing adjacencies and recreate them */ xconfigFreeAdjacencyList(&layout->adjacencies); create_adjacencies(op, config, layout); + /* free unused device and monitor sections */ + + free_unused_devices(op, config); + free_unused_monitors(op, config); + /* free stuff */ free(screenlist); @@ -533,27 +696,25 @@ static int enable_separate_x_screens(Options *op, XConfigPtr config, * step 2: narrow that list down to screens that have a busid * specified * - * step 3: find all other screens that have the same busid and remove - * them + * step 3: clean the candidate list * - * step 3: recompute the adjacency list + * step 4: recompute the adjacency list */ static int disable_separate_x_screens(Options *op, XConfigPtr config, XConfigLayoutPtr layout) { - XConfigScreenPtr screen, prev, next, *screenlist = NULL; + XConfigScreenPtr screen, *screenlist = NULL; XConfigAdjacencyPtr adj; - int i, j, nscreens = 0; - int *bus, *slot, scratch; + int i, nscreens = 0; - /* build the list of screens that are candidate to be de-cloned */ + /* step 1: build the list of screens that are candidate to be de-cloned */ if (op->screen) { screen = xconfigFindScreen(op->screen, config->screens); if (!screen) { - fmterr("Unable to find screen '%s'.", op->screen); + nv_error_msg("Unable to find screen '%s'.", op->screen); return FALSE; } @@ -572,83 +733,27 @@ static int disable_separate_x_screens(Options *op, XConfigPtr config, } /* - * limit the list to screens that have a BusID; parse the busIDs + * step 2: limit the list to screens that have a BusID; parse the busIDs * while we're at it */ - bus = nvalloc(sizeof(int) * nscreens); - slot = nvalloc(sizeof(int) * nscreens); - for (i = 0; i < nscreens; i++) { + int bus, slot, scratch; if (screenlist[i] && screenlist[i]->device && screenlist[i]->device->busid && xconfigParsePciBusString(screenlist[i]->device->busid, - &bus[i], &slot[i], &scratch)) { + &bus, &slot, &scratch)) { // this screen has a valid busid } else { screenlist[i] = NULL; } } - - /* trim out duplicates */ - - for (i = 0; i < nscreens; i++) { - - if (!screenlist[i]) continue; - - for (j = i+1; j < nscreens; j++) { - if (!screenlist[j]) continue; - if ((bus[i] == bus[j]) && (slot[i] == slot[j])) { - screenlist[j] = NULL; - } - } - } - - /* - * for every screen in the de-clone list, scan through all - * screens; if any screen, other than *this* screen has the same - * busid, remove it - */ - - for (i = 0; i < nscreens; i++) { - int bus0, slot0; - if (!screenlist[i]) continue; - - screen = config->screens; - prev = NULL; - - while (screen) { - if (screenlist[i] == screen) goto next_screen; - if (!screen->device) goto next_screen; - if (!screen->device->busid) goto next_screen; - if (!xconfigParsePciBusString(screen->device->busid, - &bus0, &slot0, &scratch)) - goto next_screen; - - if ((bus0 == bus[i]) && (slot0 == slot[i])) { - if (prev) { - prev->next = screen->next; - } else { - config->screens = screen->next; - } - next = screen->next; - screen->next = NULL; - xconfigFreeScreenList(&screen); - screen = next; - } else { - - next_screen: - - prev = screen; - screen = screen->next; - } - } - screenlist[i]->device->screen = -1; - } + /* step 3 */ + clean_screen_list(screenlist, config, nscreens); - /* wipe the existing adjacencies and recreate them */ + /* step 4: wipe the existing adjacencies and recreate them */ xconfigFreeAdjacencyList(&layout->adjacencies); @@ -662,8 +767,6 @@ static int disable_separate_x_screens(Options *op, XConfigPtr config, /* free stuff */ free(screenlist); - free(bus); - free(slot); return TRUE; @@ -703,13 +806,13 @@ static XConfigDisplayPtr clone_display_list(XConfigDisplayPtr display0) * the screen indices as approprate for multiple X screens on one GPU */ -static XConfigDevicePtr clone_device(XConfigDevicePtr device0) +static XConfigDevicePtr clone_device(XConfigDevicePtr device0, int idx) { XConfigDevicePtr device; device = nvalloc(sizeof(XConfigDeviceRec)); - device->identifier = nvstrcat(device0->identifier, " (2nd)", NULL); + device->identifier = nvasprintf("%s (%d)", device0->identifier, idx); if (device0->vendor) device->vendor = nvstrdup(device0->vendor); if (device0->board) device->board = nvstrdup(device0->board); @@ -722,9 +825,9 @@ static XConfigDevicePtr clone_device(XConfigDevicePtr device0) /* these are needed for multiple X screens on one GPU */ - device->screen = 1; + device->screen = idx; device0->screen = 0; - + device->chipid = -1; device->chiprev = -1; device->irq = -1; @@ -743,17 +846,17 @@ static XConfigDevicePtr clone_device(XConfigDevicePtr device0) /* - * clone_screen() - duplicate the given screen, for use as the second + * clone_screen() - duplicate the given screen, for use as the ith * X screen on one GPU */ -static XConfigScreenPtr clone_screen(XConfigScreenPtr screen0) +static XConfigScreenPtr clone_screen(XConfigScreenPtr screen0, int idx) { XConfigScreenPtr screen = nvalloc(sizeof(XConfigScreenRec)); - screen->identifier = nvstrcat(screen0->identifier, " (2nd)", NULL); + screen->identifier = nvasprintf("%s (%d)", screen0->identifier, idx); - screen->device = clone_device(screen0->device); + screen->device = clone_device(screen0->device, idx); screen->device_name = nvstrdup(screen->device->identifier); screen->monitor = screen0->monitor; @@ -833,8 +936,8 @@ static int enable_all_gpus(Options *op, XConfigPtr config, pDevices = find_devices(op); if (!pDevices) { - fmterr("Unable to determine number of GPUs in system; cannot " - "honor '--enable-all-gpus' option."); + nv_error_msg("Unable to determine number of GPUs in system; cannot " + "honor '--enable-all-gpus' option."); return FALSE; } diff --git a/nvidia-xconfig.c b/nvidia-xconfig.c index 5f2339e..17d0eab 100644 --- a/nvidia-xconfig.c +++ b/nvidia-xconfig.c @@ -33,6 +33,7 @@ #include "nvidia-xconfig.h" #include "nvgetopt.h" +#include "msg.h" #define TAB " " #define BIGTAB " " @@ -49,31 +50,31 @@ extern const char *pNV_ID; static void print_version(void) { - fmtout(""); - fmtout("%s", pNV_ID); - fmtoutp(TAB, "The NVIDIA X Configuration Tool."); - fmtout(""); - fmtoutp(TAB, "This program is used to manipulate X configuration files, " - "specifically to enable NVIDIA X driver functionality."); - fmtout(""); - fmtoutp(TAB, "Copyright (C) 2005 - 2010 NVIDIA Corporation."); - fmtout(""); - + nv_info_msg(NULL, ""); + nv_info_msg(NULL, "%s", pNV_ID); + nv_info_msg(TAB, "The NVIDIA X Configuration Tool."); + nv_info_msg(NULL, ""); + nv_info_msg(TAB, "This program is used to manipulate X configuration files, " + "specifically to enable NVIDIA X driver functionality."); + nv_info_msg(NULL, ""); + nv_info_msg(TAB, "Copyright (C) 2005 - 2010 NVIDIA Corporation."); + nv_info_msg(NULL, ""); } /* print_version() */ static void print_summary(void) { - fmtout(""); - fmtoutp(TAB, "In its normal operation, nvidia-xconfig finds the system " - "X configuration file (or generates a new X configuration if it " - "cannot find the system file), makes sure the configuration is " - "usable by the NVIDIA X driver, applies any updates requested " - "on the commandline, and writes the new configuration to file."); - fmtout(""); - fmtoutp(TAB, "Please see the NVIDIA README for a description of NVIDIA " - "X configuration file options."); - fmtout(""); + nv_info_msg(NULL, ""); + nv_info_msg(TAB, "In its normal operation, nvidia-xconfig finds the system " + "X configuration file (or generates a new X configuration " + "if it cannot find the system file), makes sure the " + "configuration is usable by the NVIDIA X driver, applies " + "any updates requested on the commandline, and writes the " + "new configuration to file."); + nv_info_msg(NULL, ""); + nv_info_msg(TAB, "Please see the NVIDIA README for a description of NVIDIA " + "X configuration file options."); + nv_info_msg(NULL, ""); } @@ -87,9 +88,9 @@ static void print_summary(void) static void print_help_helper(const char *name, const char *description) { - fmtoutp(TAB, "%s", name); - fmtoutp(BIGTAB, "%s", description); - fmtout(""); + nv_info_msg(TAB, "%s", name); + nv_info_msg(BIGTAB, "%s", description); + nv_info_msg(NULL, ""); } static void print_help(int advanced) @@ -99,9 +100,9 @@ static void print_help(int advanced) print_version(); print_summary(); - fmtout(""); - fmtout("nvidia-xconfig [options]"); - fmtout(""); + nv_info_msg(NULL, ""); + nv_info_msg(NULL, "nvidia-xconfig [options]"); + nv_info_msg(NULL, ""); if (!advanced) { /* only print options with the ALWAYS flag */ @@ -153,7 +154,7 @@ static void parse_commandline(Options *op, int argc, char *argv[]) case 'T': op->post_tree = TRUE; break; case 'h': print_help(FALSE); exit(0); break; case 'A': print_help(TRUE); exit(0); break; - case 's': silence_fmt(1); break; + case 's': nv_set_verbosity(NV_VERBOSITY_WARNING); break; case 'a': op->enable_all_gpus = TRUE; break; case '1': op->only_one_screen = TRUE; break; @@ -602,6 +603,23 @@ static void parse_commandline(Options *op, int argc, char *argv[]) op->restore_original_backup = TRUE; break; + case NUM_X_SCREENS_OPTION: + + if (intval < 1) { + fprintf(stderr, "\n"); + fprintf(stderr, "Invalid number of X screens: %d.\n", intval); + fprintf(stderr, "\n"); + goto fail; + } + + /* Enable separate X screens */ + set_boolean_option(op, + XCONFIG_BOOL_VAL(SEPARATE_X_SCREENS_BOOL_OPTION) - + XCONFIG_BOOL_OPTION_START, TRUE); + + op->num_x_screens = intval; + break; + default: goto fail; } @@ -639,11 +657,13 @@ static Options *load_default_options(void) op = (Options *) nvalloc(sizeof(Options)); if (!op) return NULL; + op->depth = 24; op->transparent_index = -1; op->stereo = -1; op->cool_bits = -1; op->nvidia_3dvision_display_type = -1; op->tv_over_scan = -1.0; + op->num_x_screens = -1; xconfigGenerateLoadDefaultOptions(&op->gop); @@ -687,8 +707,8 @@ static int backup_file(Options *op, const char *orig_filename, if (access(filename, F_OK) == 0) { if (unlink(filename) != 0) { - fmterr("Unable to create backup file '%s' (%s)", - filename, strerror(errno)); + nv_error_msg("Unable to create backup file '%s' (%s)", + filename, strerror(errno)); goto done; } } @@ -700,7 +720,7 @@ static int backup_file(Options *op, const char *orig_filename, goto done; } - fmtout("Backed up file '%s' as '%s'", orig_filename, filename); + nv_info_msg(NULL, "Backed up file '%s' as '%s'", orig_filename, filename); ret = TRUE; done: @@ -783,8 +803,8 @@ static int restore_backup(Options *op, XConfigPtr config, const char *suffix) int ret = FALSE; if (lstat(backup, &st) != 0) { - fmterr("Unable to restore from original backup file '%s' (%s)", - backup, strerror(errno)); + nv_error_msg("Unable to restore from original backup file '%s' (%s)", + backup, strerror(errno)); goto done; } @@ -797,8 +817,8 @@ static int restore_backup(Options *op, XConfigPtr config, const char *suffix) st.st_uid != 0 /* not owned by root*/ || (st.st_gid != 0 && (st.st_mode & S_IWGRP)) /* non-root group write */ || (st.st_mode & S_IWOTH) /* world writable */ ) { - fmterr("The permissions of the original backup file '%s' are too loose " - "to be trusted. The file will not be restored.", backup); + nv_error_msg("The permissions of the original backup file '%s' are too " + "loose to be trusted. The file will not be restored.", backup); goto done; } @@ -809,8 +829,8 @@ static int restore_backup(Options *op, XConfigPtr config, const char *suffix) if (st.st_size == 0) { if (unlink(filename) != 0) { - fmterr("Unable to remove file '%s' (%s)", - filename, strerror(errno)); + nv_error_msg("Unable to remove file '%s' (%s)", + filename, strerror(errno)); goto done; } } else { @@ -826,19 +846,20 @@ static int restore_backup(Options *op, XConfigPtr config, const char *suffix) if (access(backup, F_OK) == 0) { if (unlink(backup) != 0) { - fmterr("Unable to remove backup file '%s' (%s)", - backup, strerror(errno)); + nv_error_msg("Unable to remove backup file '%s' (%s)", + backup, strerror(errno)); goto done; } } if (st.st_size == 0) { - fmtout("The backup file '%s' was empty. This usually means that nvidia-" - "xconfig did not find an X configuration file the first time it " - "was run. The X configuration file '%s' was deleted.", - backup, filename); + nv_info_msg(NULL, "The backup file '%s' was empty. This usually means " + "that nvidia-xconfig did not find an X configuration " + "file the first time it was run. The X configuration " + "file '%s' was deleted.", + backup, filename); } else { - fmtout("Restored backup file '%s' to '%s'", backup, filename); + nv_info_msg(NULL, "Restored backup file '%s' to '%s'", backup, filename); } ret = TRUE; @@ -878,7 +899,7 @@ static int write_xconfig(Options *op, XConfigPtr config, int first_touch) tmp = nvstrdup(filename); d = dirname(tmp); if (access(d, W_OK) != 0) { - fmterr("Unable to write to directory '%s'.", d); + nv_error_msg("Unable to write to directory '%s'.", d); goto done; } @@ -900,7 +921,8 @@ static int write_xconfig(Options *op, XConfigPtr config, int first_touch) else if (first_touch) { char *fakeorig = nvstrcat(filename, ORIG_SUFFIX, NULL); if (!copy_file("/dev/null", fakeorig, 0644)) { - fmtwarn("Unable to write an empty backup file \"%s\".", fakeorig); + nv_warning_msg("Unable to write an empty backup file \"%s\".", + fakeorig); } free(fakeorig); } @@ -908,14 +930,14 @@ static int write_xconfig(Options *op, XConfigPtr config, int first_touch) /* write the config file */ if (!xconfigWriteConfigFile(filename, config)) { - fmterr("Unable to write file \"%s\"; please use the " - "\"--output-xconfig\" commandline " - "option to specify an alternative output file.", filename); + nv_error_msg("Unable to write file \"%s\"; please use the " + "\"--output-xconfig\" commandline option to specify " + "an alternative output file.", filename); goto done; } - fmtout("New X configuration file written to '%s'", filename); - fmtout(""); + nv_info_msg(NULL, "New X configuration file written to '%s'", filename); + nv_info_msg(NULL, ""); /* Set the default depth in the Solaris Management Facility @@ -1054,10 +1076,10 @@ static XConfigPtr find_system_xconfig(Options *op) filename = xconfigOpenConfigFile(op->xconfig, op->gop.x_project_root); if (filename) { - fmtout(""); - fmtout("Using X configuration file: \"%s\".", filename); + nv_info_msg(NULL, ""); + nv_info_msg(NULL, "Using X configuration file: \"%s\".", filename); } else { - fmtwarn("Unable to locate/open X configuration file."); + nv_warning_msg("Unable to locate/open X configuration file."); return NULL; } @@ -1136,12 +1158,12 @@ static int update_xconfig(Options *op, XConfigPtr config) } if (op->screen && !updated) { - fmterr("Unable to find screen '%s'", op->screen); + nv_error_msg("Unable to find screen '%s'", op->screen); return FALSE; } if (op->device && !updated) { - fmterr("Unable to find device '%s'", op->device); + nv_error_msg("Unable to find device '%s'", op->device); return FALSE; } @@ -1177,7 +1199,6 @@ int main(int argc, char *argv[]) XConfigPtr config = NULL; int first_touch = 0; - /* Load defaults */ op = load_default_options(); @@ -1196,15 +1217,15 @@ int main(int argc, char *argv[]) */ if (op->keyboard_list) { - fmtout("\nPossible keyboard types; the short name is what should be " - "passed to the \"--keyboard\" option.\n\n"); + nv_info_msg(NULL, "\nPossible keyboard types; the short name is what " + "should be passed to the \"--keyboard\" option.\n\n"); xconfigGeneratePrintPossibleKeyboards(); return 0; } if (op->mouse_list) { - fmtout("\nPossible mouse types; the short name is what should be " - "passed to the \"--mouse\" option.\n\n"); + nv_info_msg(NULL, "\nPossible mouse types; the short name is what should " + "be passed to the \"--mouse\" option.\n\n"); xconfigGeneratePrintPossibleMice(); return 0; } @@ -1265,7 +1286,7 @@ int main(int argc, char *argv[]) */ if (!config) { - fmterr("Unable to generate a usable X configuration file."); + nv_error_msg("Unable to generate a usable X configuration file."); return 1; } diff --git a/nvidia-xconfig.h b/nvidia-xconfig.h index 6d5b10e..85ae21e 100644 --- a/nvidia-xconfig.h +++ b/nvidia-xconfig.h @@ -66,8 +66,10 @@ #define PRESERVE_BUSID_BOOL_OPTION 40 #define BASE_MOSAIC_BOOL_OPTION 41 #define ALLOW_EMPTY_INITIAL_CONFIGURATION 42 +#define DELETE_UNUSED_DP12_DPYS 43 +#define INBAND_STEREO_SIGNALING 44 -#define XCONFIG_BOOL_OPTION_COUNT (ALLOW_EMPTY_INITIAL_CONFIGURATION + 1) +#define XCONFIG_BOOL_OPTION_COUNT (INBAND_STEREO_SIGNALING + 1) /* # of 32-bit variables needed to hold all the boolean options (bits) */ #define XCONFIG_BOOL_OPTION_SLOTS \ @@ -121,6 +123,8 @@ typedef struct __options { int cool_bits; int nvidia_3dvision_display_type; + int num_x_screens; + char *xconfig; char *output_xconfig; char *layout; diff --git a/option_table.h b/option_table.h index f21488f..994243f 100644 --- a/option_table.h +++ b/option_table.h @@ -58,6 +58,7 @@ enum { NVIDIA_3DVISIONPRO_CONFIG_FILE_OPTION, NVIDIA_3DVISION_DISPLAY_TYPE_OPTION, RESTORE_ORIGINAL_BACKUP_OPTION, + NUM_X_SCREENS_OPTION, }; /* @@ -481,10 +482,21 @@ static const NVGetoptOption __options[] = { "drive these display devices in a single X screen, or as separate X " "screens. When the '--separate-x-screens' option is specified, each GPU " "on which an X screen is currently configured will be updated to have " - "two X screens configured. The '--no-separate-x-screens' option will " - "remove the second configured X screen on each GPU. Please see the " - "NVIDIA README description of \"Separate X Screens on One GPU\" for " - "further details." }, + "two or more (depending on the capabilities of that GPU) X screens " + "configured. The '--no-separate-x-screens' option will remove any " + "extra configured X screens on each GPU. Please see the NVIDIA README " + "description of \"Separate X Screens on One GPU\" for further details." }, + + { "x-screens-per-gpu", NUM_X_SCREENS_OPTION, + NVGETOPT_INTEGER_ARGUMENT, NULL, + "A GPU that supports multiple simultaneous display devices can either " + "drive these display devices in a single X screen, or as separate X " + "screens. When the '--x-screens-per-gpu=<quantity>' option is " + "specified, each GPU on which an X screen is currently configured will " + "be updated to have <quantity> X screens. <quantity> has to be greater " + "than 0. Setting <quantity> to 1 is equivalent to specifying the " + "'--no-separate-x-screens' option. Please see the NVIDIA README " + "description of \"Separate X Screens on One GPU\" for further details." }, { "sli", SLI_OPTION, NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, NULL, @@ -640,5 +652,13 @@ static const NVGetoptOption __options[] = { NVGETOPT_IS_BOOLEAN, NULL, "Allow the X server to start even if no " "connected display devices could be detected." }, + { "delete-unused-dp12-displays", XCONFIG_BOOL_VAL(DELETE_UNUSED_DP12_DPYS), + NVGETOPT_IS_BOOLEAN, NULL, "Delete DisplayPort 1.2 RandR outputs that " + "are disconnected and not named in any MetaModes." }, + + { "inband-stereo-signaling", XCONFIG_BOOL_VAL(INBAND_STEREO_SIGNALING), + NVGETOPT_IS_BOOLEAN, NULL, "Enable or disable the " + "\"InbandStereoSignaling\" X configuration option." }, + { NULL, 0, 0, NULL, NULL }, }; @@ -26,6 +26,7 @@ #include "nvidia-xconfig.h" #include "xf86Parser.h" +#include "msg.h" typedef struct { @@ -68,6 +69,8 @@ static const NvidiaXConfigOption __options[] = { { MODE_DEBUG_BOOL_OPTION, FALSE, "ModeDebug" }, { BASE_MOSAIC_BOOL_OPTION, FALSE, "BaseMosaic" }, { ALLOW_EMPTY_INITIAL_CONFIGURATION, FALSE, "AllowEmptyInitialConfiguration" }, + { DELETE_UNUSED_DP12_DPYS, FALSE, "DeleteUnusedDP12Displays" }, + { INBAND_STEREO_SIGNALING, FALSE, "InbandStereoSignaling" }, { 0, FALSE, NULL }, }; @@ -126,7 +129,7 @@ void validate_composite(Options *op, XConfigPtr config) int cioverlay_enabled; int ubb_enabled; int stereo_enabled; - const char *err_str; + char *err_str; composite_specified = GET_BOOL_OPTION(op->boolean_options, @@ -178,11 +181,12 @@ void validate_composite(Options *op, XConfigPtr config) */ if (err_str) { - fmtwarn("The Composite X extension does not currently interact well " - "with the %s option(s); the Composite X extension will be " - "disabled.", err_str); + nv_warning_msg("The Composite X extension does not currently interact " + "well with the %s option(s); the Composite X extension " + "will be disabled.", err_str); set_boolean_option(op, COMPOSITE_BOOL_OPTION, FALSE); + nvfree(err_str); } } /* validate_composite() */ @@ -498,7 +502,7 @@ void update_options(Options *op, XConfigScreenPtr screen) o = get_option(i); if (!o) { - fmterr("Unrecognized X Config option %d", i); + nv_error_msg("Unrecognized X Config option %d", i); continue; } @@ -509,8 +513,8 @@ void update_options(Options *op, XConfigScreenPtr screen) } set_option_value(screen, o->name, val); - fmtout("Option \"%s\" \"%s\" added to " - "Screen \"%s\".", o->name, val, screen->identifier); + nv_info_msg(NULL, "Option \"%s\" \"%s\" added to Screen \"%s\".", + o->name, val, screen->identifier); } } @@ -594,14 +598,14 @@ void update_options(Options *op, XConfigScreenPtr screen) op->metamode_orientation); if (remove_metamode_offsets(screen, &old_metamodes, &new_metamodes)) { - fmtwarn("The MetaModes option contained explicit offsets, " - "which would have overridden the specified " - "MetaModeOrientation; in order to honor the " - "requested MetaModeOrientation, the explicit offsets " - "have been removed from the MetaModes option.\n\n" - "Old MetaModes option: \"%s\"\n" - "New MetaModes option: \"%s\".", - old_metamodes, new_metamodes); + nv_warning_msg("The MetaModes option contained explicit offsets, " + "which would have overridden the specified " + "MetaModeOrientation; in order to honor the " + "requested MetaModeOrientation, the explicit offsets " + "have been removed from the MetaModes option.\n\n" + "Old MetaModes option: \"%s\"\n" + "New MetaModes option: \"%s\".", + old_metamodes, new_metamodes); nvfree(old_metamodes); nvfree(new_metamodes); } diff --git a/query_gpu_info.c b/query_gpu_info.c index 17152ff..01e6152 100644 --- a/query_gpu_info.c +++ b/query_gpu_info.c @@ -21,6 +21,7 @@ */ #include "nvidia-xconfig.h" +#include "msg.h" #include <string.h> static char *display_device_mask_to_display_device_name(unsigned int mask); @@ -46,32 +47,32 @@ int query_gpu_info(Options *op) pDevices = find_devices(op); if (!pDevices) { - fmterr("Unable to query GPU information"); + nv_error_msg("Unable to query GPU information"); return FALSE; } /* print the GPU information */ - fmtout("Number of GPUs: %d", pDevices->nDevices); + nv_info_msg(NULL, "Number of GPUs: %d", pDevices->nDevices); for (i = 0; i < pDevices->nDevices; i++) { - fmtout(""); - fmtout("GPU #%d:", i); - fmtoutp(TAB, "Name : %s", pDevices->devices[i].name); - fmtoutp(TAB, "UUID : %s", pDevices->devices[i].uuid); + nv_info_msg(NULL, ""); + nv_info_msg(NULL, "GPU #%d:", i); + nv_info_msg(TAB, "Name : %s", pDevices->devices[i].name); + nv_info_msg(TAB, "UUID : %s", pDevices->devices[i].uuid); memset(busid, 0, BUS_ID_STRING_LENGTH); xconfigFormatPciBusString(busid, BUS_ID_STRING_LENGTH, pDevices->devices[i].dev.domain, pDevices->devices[i].dev.bus, pDevices->devices[i].dev.slot, 0); - fmtoutp(TAB, "PCI BusID : %s", busid); + nv_info_msg(TAB, "PCI BusID : %s", busid); - fmtout(""); - fmtoutp(TAB, "Number of Display Devices: %d", - pDevices->devices[i].nDisplayDevices); - fmtout(""); + nv_info_msg(NULL, ""); + nv_info_msg(TAB, "Number of Display Devices: %d", + pDevices->devices[i].nDisplayDevices); + nv_info_msg(NULL, ""); for (j = 0; j < pDevices->devices[i].nDisplayDevices; j++) { @@ -82,7 +83,7 @@ int query_gpu_info(Options *op) if (!name) name = nvstrdup("Unknown"); - fmtoutp(TAB, "Display Device %d (%s):", j, name); + nv_info_msg(TAB, "Display Device %d (%s):", j, name); nvfree(name); @@ -91,9 +92,9 @@ int query_gpu_info(Options *op) * non-zero */ - #define PRT(_fmt, _val) \ - if (_val) { \ - fmtoutp(BIGTAB, (_fmt), (_val)); \ + #define PRT(_fmt, _val) \ + if (_val) { \ + nv_info_msg(BIGTAB, (_fmt), (_val)); \ } if (pDisplayDevice->info_valid) { @@ -138,10 +139,10 @@ int query_gpu_info(Options *op) pDisplayDevice->info.physical_height); } else { - fmtoutp(BIGTAB, "No EDID information available."); + nv_info_msg(BIGTAB, "No EDID information available."); } - fmtout(""); + nv_info_msg(NULL, ""); } } @@ -39,6 +39,7 @@ #include <sys/termios.h> #include "nvidia-xconfig.h" +#include "msg.h" Options *__op = NULL; @@ -59,18 +60,18 @@ int copy_file(const char *srcfile, const char *dstfile, mode_t mode) int ret = FALSE; if ((src_fd = open(srcfile, O_RDONLY)) == -1) { - fmterr("Unable to open '%s' for copying (%s)", - srcfile, strerror (errno)); + nv_error_msg("Unable to open '%s' for copying (%s)", + srcfile, strerror (errno)); goto done; } if ((dst_fd = open(dstfile, O_RDWR | O_CREAT | O_TRUNC, mode)) == -1) { - fmterr("Unable to create '%s' for copying (%s)", - dstfile, strerror (errno)); + nv_error_msg("Unable to create '%s' for copying (%s)", + dstfile, strerror (errno)); goto done; } if (fstat(src_fd, &stat_buf) == -1) { - fmterr("Unable to determine size of '%s' (%s)", - srcfile, strerror (errno)); + nv_error_msg("Unable to determine size of '%s' (%s)", + srcfile, strerror (errno)); goto done; } if (stat_buf.st_size == 0) { @@ -79,38 +80,38 @@ int copy_file(const char *srcfile, const char *dstfile, mode_t mode) goto done; } if (lseek(dst_fd, stat_buf.st_size - 1, SEEK_SET) == -1) { - fmterr("Unable to set file size for '%s' (%s)", - dstfile, strerror (errno)); + nv_error_msg("Unable to set file size for '%s' (%s)", + dstfile, strerror (errno)); goto done; } if (write(dst_fd, "", 1) != 1) { - fmterr("Unable to write file size for '%s' (%s)", - dstfile, strerror (errno)); + nv_error_msg("Unable to write file size for '%s' (%s)", + dstfile, strerror (errno)); goto done; } if ((src = mmap(0, stat_buf.st_size, PROT_READ, MAP_SHARED, src_fd, 0)) == (void *) -1) { - fmterr("Unable to map source file '%s' for " - "copying (%s)", srcfile, strerror (errno)); + nv_error_msg("Unable to map source file '%s' for " + "copying (%s)", srcfile, strerror (errno)); goto done; } if ((dst = mmap(0, stat_buf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, dst_fd, 0)) == (void *) -1) { - fmterr("Unable to map destination file '%s' for " - "copying (%s)", dstfile, strerror (errno)); + nv_error_msg("Unable to map destination file '%s' for " + "copying (%s)", dstfile, strerror (errno)); goto done; } memcpy(dst, src, stat_buf.st_size); if (munmap (src, stat_buf.st_size) == -1) { - fmterr("Unable to unmap source file '%s' after " - "copying (%s)", srcfile, strerror (errno)); + nv_error_msg("Unable to unmap source file '%s' after " + "copying (%s)", srcfile, strerror (errno)); goto done; } if (munmap (dst, stat_buf.st_size) == -1) { - fmterr("Unable to unmap destination file '%s' after " - "copying (%s)", dstfile, strerror (errno)); + nv_error_msg("Unable to unmap destination file '%s' after " + "copying (%s)", dstfile, strerror (errno)); goto done; } @@ -182,8 +183,8 @@ void xconfigPrint(MsgType t, const char *msg) } } - if (newline) fmt(stream, NULL, ""); - fmt(stream, prefix, "%s", msg); - if (newline) fmt(stream, NULL, ""); + if (newline) nv_info_msg_to_file(stream, NULL, ""); + nv_info_msg_to_file(stream, prefix, "%s", msg); + if (newline) nv_info_msg_to_file(stream, NULL, ""); } /* xconfigPrint */ @@ -114,6 +114,7 @@ endif TARGET_ARCH_ABI ?= OUTPUTDIR ?= _out/$(TARGET_OS)_$(TARGET_ARCH) +OUTPUTDIR_ABSOLUTE ?= $(CURDIR)/$(OUTPUTDIR) NV_QUIET_COMMAND_REMOVED_TARGET_PREFIX ?= @@ -1 +1 @@ -NVIDIA_VERSION = 331.38 +NVIDIA_VERSION = 334.16 |