From aedec718b1d6e9487861528dfb310db0b3a53c89 Mon Sep 17 00:00:00 2001 From: Aaron Plattner Date: Wed, 13 Feb 2008 10:26:53 -0800 Subject: 1.0-9746 --- XF86Config-parser/Generate.c | 2 + XF86Config-parser/Monitor.c | 11 +- extract_edids.c | 410 +++++++++++++++++++++++++++++++++++++++---- make_usable.c | 43 +++-- nvidia-xconfig.c | 96 +++++++--- nvidia-xconfig.h | 8 +- option_table.h | 14 +- options.c | 140 +++++++++++++++ 8 files changed, 640 insertions(+), 84 deletions(-) diff --git a/XF86Config-parser/Generate.c b/XF86Config-parser/Generate.c index d61771a..3d2da41 100644 --- a/XF86Config-parser/Generate.c +++ b/XF86Config-parser/Generate.c @@ -405,6 +405,8 @@ static void add_modules(GenerateOptions *gop, XConfigPtr config) XCONFIG_LOAD_MODULE, NULL, FALSE); l = xconfigAddNewLoadDirective(l, xconfigStrdup("bitstream"), XCONFIG_LOAD_MODULE, NULL, FALSE); + l = xconfigAddNewLoadDirective(l, xconfigStrdup("xtsol"), + XCONFIG_LOAD_MODULE, NULL, FALSE); #else l = xconfigAddNewLoadDirective(l, xconfigStrdup("freetype"), XCONFIG_LOAD_MODULE, NULL, FALSE); diff --git a/XF86Config-parser/Monitor.c b/XF86Config-parser/Monitor.c index 8c273c4..cacc284 100644 --- a/XF86Config-parser/Monitor.c +++ b/XF86Config-parser/Monitor.c @@ -668,9 +668,14 @@ xconfigPrintMonitorSection (FILE * cf, XConfigMonitorPtr ptr) } for (i = 0; i < ptr->n_vrefresh; i++) { - fprintf (cf, " VertRefresh %2.1f - %2.1f\n", - ptr->vrefresh[i].lo, - ptr->vrefresh[i].hi); + if (ptr->vrefresh[i].lo == ptr->vrefresh[i].hi) { + fprintf (cf, " VertRefresh %2.1f\n", + ptr->vrefresh[i].lo); + } else { + fprintf (cf, " VertRefresh %2.1f - %2.1f\n", + ptr->vrefresh[i].lo, + ptr->vrefresh[i].hi); + } } if (ptr->gamma_red) { if (ptr->gamma_red == ptr->gamma_green diff --git a/extract_edids.c b/extract_edids.c index 9fc1603..25a4747 100644 --- a/extract_edids.c +++ b/extract_edids.c @@ -25,8 +25,8 @@ * extract-edids.c * * This source file gives us the means to extract EDIDs from verbose X - * log files. A verbose log will contain a raw EDID byte dump like - * this: + * log files or from .txt files. A verbose log will contain a raw EDID + * byte dump like this: * * (--) NVIDIA(0): Raw EDID bytes: * (--) NVIDIA(0): @@ -41,14 +41,27 @@ * (--) NVIDIA(0): * (--) NVIDIA(0): --- End of EDID for ViewSonic VPD150 (DFP-1) --- * - * We read a log file, identify and read any EDID(s) contained in the - * log file, and then write the EDID bytes to edid.bin files (just + * A .txt file will contain a raw EDID byte dump like this: + * + * 00 FF FF FF FF FF FF 00-06 10 F4 01 01 01 01 01 ................ + * 27 08 01 01 28 1F 17 96-E8 44 E4 A1 57 4A 97 23 '...(....D..WJ.# + * 19 4F 57 BF EE 00 01 01-01 01 01 01 01 01 01 01 .OW............. + * 01 01 01 01 01 01 64 19-00 40 41 00 26 30 18 88 ......d..@A.&0.. + * 36 00 33 E6 10 00 00 18-40 1F 00 30 41 00 24 30 6.3.....@..0A.$0 + * 20 60 33 00 33 E6 10 00-00 18 00 00 00 FD 00 38 `3.3..........8 + * 4C 1F 3D 08 00 0A 20 20-20 20 20 20 00 00 00 FC L.=... .... + * 00 41 70 70 6C 65 53 74-75 64 69 6F 0A 20 00 88 .AppleStudio. .. + * + * EDID Version : 1.1 + * + * We read a log file or a .txt file, identify and read any EDID(s) contained + * in the file, and then write the EDID bytes to edid.bin files (just * like what nvidia-settings can capture for display devices running * on the current X server). * * This is useful for NVIDIA engineers to simulate users' display - * environments, based on a verbose nvidia-bug-report.log or X log. - * This utility is included in nvidia-xconfig, since maybe users will + * environments, based on a verbose nvidia-bug-report.log or X log or a .txt + * file. This utility is included in nvidia-xconfig, since maybe users will * find use for this, too. */ @@ -84,6 +97,9 @@ #define EDID_OUTPUT_FILE_NAME "edid.bin" +#define LOG_FILE 10 +#define TEXT_FILE 20 +#define UNKNOWN_FILE 30 typedef struct { int size; @@ -98,12 +114,18 @@ typedef struct { } FileRec, *FilePtr; +static int findFileType(FilePtr pFile); + +static EdidPtr findEdidforLogFile(FilePtr pFile); +static EdidPtr findEdidforTextFile(FilePtr pFile); -static EdidPtr findEdid(FilePtr pFile); +static int findEdidHeaderforLogFile(FilePtr pFile); +static int readEdidDataforLogFile(FilePtr pFile, EdidPtr pEdid); +static int readEdidFooterforLogFile(FilePtr pFile, EdidPtr pEdid); -static int findEdidHeader(FilePtr pFile); -static int readEdidData(FilePtr pFile, EdidPtr pEdid); -static int readEdidFooter(FilePtr pFile, EdidPtr pEdid); +static int findEdidfooterforTextFile(FilePtr pFile); +static int readEdidDataforTextFile(FilePtr pFile, EdidPtr pEdid); +static int readMonitorNameforTextFile(FilePtr pFile, EdidPtr pEdid); static char *findFileName(char *option); static int writeEdidFile(EdidPtr pEdid, char *filename); @@ -118,27 +140,28 @@ static void freeEdid(EdidPtr pEdid); int extract_edids(Options *op) { - int fd = -1, ret, funcRet = FALSE; + int fd = -1, ret, fileType, funcRet = FALSE; char *filename; struct stat stat_buf; - + FileRec file; EdidPtr pEdid, *pEdids; int nEdids, i; nEdids = 0; + pEdid = NULL; pEdids = NULL; memset(&file, 0, sizeof(FileRec)); file.start = (void *) -1; /* open the file and get its length */ - - fd = open(op->extract_edids_from_log, O_RDONLY); - + + fd = open(op->extract_edids_from_file, O_RDONLY); + if (fd == -1) { - fmterr("Unable to open file \"%s\".", op->extract_edids_from_log); + fmterr("Unable to open file \"%s\".", op->extract_edids_from_file); goto done; } @@ -146,14 +169,14 @@ int extract_edids(Options *op) if (ret == -1) { fmterr("Unable to get length of file \"%s\".", - op->extract_edids_from_log); + 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_log); + fmterr("File \"%s\" is empty.", op->extract_edids_from_file); goto done; } @@ -163,26 +186,55 @@ int extract_edids(Options *op) MAP_SHARED, fd, 0); if (file.start == (void *) -1) { - fmterr("Unable to map file \"%s\".", op->extract_edids_from_log); + fmterr("Unable to map file \"%s\".", op->extract_edids_from_file); goto done; } /* start parsing at the start of file */ file.current = file.start; + + /* check for the file type(log or .txt) */ - /* scan through the whole file, and build a list of pEdids */ + fileType = findFileType(&file); + + /* if the file does not contain any edid information, goto done */ + + if (fileType == UNKNOWN_FILE) { + funcRet = TRUE; + goto done; + } + + if (fileType == LOG_FILE) { + file.current = file.start; + } + /* scan through the whole file, and build a list of pEdids */ + while(1) { + + if (fileType == LOG_FILE) { + + pEdid = findEdidforLogFile(&file); + + } - pEdid = findEdid(&file); - + if (fileType == TEXT_FILE) { + + pEdid = findEdidforTextFile(&file); + + } + if (!pEdid) break; pEdids = nvrealloc(pEdids, sizeof(pEdids) * (nEdids + 1)); pEdids[nEdids] = pEdid; nEdids++; + + /* Only one edid in a .txt file */ + + if (fileType == TEXT_FILE) break; } /* fall through to the 'done' label */ @@ -211,7 +263,7 @@ int extract_edids(Options *op) fmtout(""); fmtout("Found %d EDID%s in \"%s\".", - nEdids, (nEdids == 1) ? "": "s", op->extract_edids_from_log); + nEdids, (nEdids == 1) ? "": "s", op->extract_edids_from_file); filename = findFileName(op->extract_edids_output_file); @@ -234,7 +286,20 @@ int extract_edids(Options *op) } // extract_edids() +/* + * findFileType() - scan through the pFile to determine the file type + * file type can be LOG_FILE, TEXT_FILE, UNKNOWN_FILE(file with no EDID) + */ + +static int findFileType(FilePtr pFile) +{ + if (findEdidHeaderforLogFile(pFile)) return LOG_FILE; + + if (findEdidfooterforTextFile(pFile)) return TEXT_FILE; + return UNKNOWN_FILE; + +} // findFileType() /* * findEdid() - scan through pFile for an EDID header, if we find one, @@ -242,15 +307,15 @@ int extract_edids(Options *op) * allocated pEdid data structure. On failure, return NULL. */ -static EdidPtr findEdid(FilePtr pFile) +static EdidPtr findEdidforLogFile(FilePtr pFile) { EdidPtr pEdid = nvalloc(sizeof(EdidRec)); - if (!findEdidHeader(pFile)) goto fail; + if (!findEdidHeaderforLogFile(pFile)) goto fail; - if (!readEdidData(pFile, pEdid)) goto fail; + if (!readEdidDataforLogFile(pFile, pEdid)) goto fail; - if (!readEdidFooter(pFile, pEdid)) goto fail; + if (!readEdidFooterforLogFile(pFile, pEdid)) goto fail; return pEdid; @@ -260,10 +325,28 @@ static EdidPtr findEdid(FilePtr pFile) return NULL; -} // findEdid() +} // findEdidforLogFile() + +/* + * scan through the pFile for EDID data and Monitor name. + */ + +static EdidPtr findEdidforTextFile(FilePtr pFile) +{ + EdidPtr pEdid = nvalloc(sizeof(EdidRec)); + + if (!readEdidDataforTextFile(pFile,pEdid)) goto fail; + if (!readMonitorNameforTextFile(pFile, pEdid)) goto fail; + return pEdid; + fail: + freeEdid(pEdid); + + return NULL; + +} // findEdidforTextFile() /* @@ -274,7 +357,7 @@ static EdidPtr findEdid(FilePtr pFile) * file, return FALSE. */ -static int findEdidHeader(FilePtr pFile) +static int findEdidHeaderforLogFile(FilePtr pFile) { while (((pFile->current - pFile->start) + 15) <= pFile->length) { @@ -302,7 +385,7 @@ static int findEdidHeader(FilePtr pFile) return FALSE; -} // findEdidHeader() +} // findEdidHeaderforLogFile() @@ -314,14 +397,14 @@ static int findEdidHeader(FilePtr pFile) * and upper nibbles of each EDID byte, and to advance past the label, * that looks something like "(--) NVIDIA(0):". */ - + #define STATE_LOOKING_FOR_TOP_NIBBLE 0 #define STATE_LOOKING_FOR_BOTTOM_NIBBLE 1 #define STATE_LOOKING_FOR_END_OF_LABEL 2 #define MAX_EDID_SIZE 4096 -static int readEdidData(FilePtr pFile, EdidPtr pEdid) +static int readEdidDataforLogFile(FilePtr pFile, EdidPtr pEdid) { int state; @@ -333,7 +416,7 @@ static int readEdidData(FilePtr pFile, EdidPtr pEdid) /* clear the scratch EDID data */ bzero(pData, MAX_EDID_SIZE); - + /* * start the parsing state machine by looking for the upper nibble * of the first byte in the EDID @@ -468,9 +551,166 @@ static int readEdidData(FilePtr pFile, EdidPtr pEdid) return FALSE; -} // readEdidData() +} // readEdidDataforLogFile() + +/* + * read EDID data for the .txt file; pFile->current gives the starting + * position of the EDID bytes, which is same as file starting position. + * We use a state machine to look for the lower and upper nibbles of each + * EDID byte, and to advance past the label. + */ + +static int readEdidDataforTextFile(FilePtr pFile, EdidPtr pEdid) +{ + int state; + + unsigned char pData[MAX_EDID_SIZE]; + int k; + + char c; + + /* clear the scratch EDID data */ + + bzero(pData, MAX_EDID_SIZE); + + /* + * start the parsing state machine by looking for the upper nibble + * of the first byte in the EDID + */ + + state = STATE_LOOKING_FOR_TOP_NIBBLE; + k = 0; + + while(1) { + + c = pFile->current[0]; + + switch (state) { + + case STATE_LOOKING_FOR_TOP_NIBBLE: + + /* + * if we found a hex value, treat it as upper nibble, then + * look for lower nibble + */ + + if (IS_HEX(c)) { + pData[k] |= ((HEX_TO_NIBBLE(c)) << 4); + state = STATE_LOOKING_FOR_BOTTOM_NIBBLE; + goto nextChar; + } + + /* skip '-' and keep looking for top nibble */ + + if (c == '-') { + state = STATE_LOOKING_FOR_TOP_NIBBLE; + goto nextChar; + } + + /* + * if two consecutive white space, change lebel. + * if one white space, skip it. + */ + + if (isspace(c)) { + + if (isspace(pFile->current[1])) { + state = STATE_LOOKING_FOR_END_OF_LABEL; + goto nextChar; + } else { + state = STATE_LOOKING_FOR_TOP_NIBBLE; + goto nextChar; + } + } + + goto fail; /* anything else is an error */ + + break; + + case STATE_LOOKING_FOR_BOTTOM_NIBBLE: + + /* + * if we found a hex value, treat it as the lower nibble, + * then look for the upper nibble of the next byte + */ + + if (IS_HEX(c)) { + pData[k] |= (HEX_TO_NIBBLE(c)); + state = STATE_LOOKING_FOR_TOP_NIBBLE; + k++; + if (k >= MAX_EDID_SIZE) goto fail; + goto nextChar; + } + + goto fail; /* anything else is an error */ + + break; + + case STATE_LOOKING_FOR_END_OF_LABEL: + + /* if we found two consecutive '\r\n', then the reding of EDID + * information is complete. if only one '\r\n', then change the + * state. + */ + + if (c == '\r' && pFile->current[1] == '\n') { + + if (pFile->current[2] == '\r' && pFile->current[3] == '\n') { + goto done; + } else { + state = STATE_LOOKING_FOR_TOP_NIBBLE; + goto nextChar; + } + } + + /* skip the white space */ + + if (isspace(c)) { + + state = STATE_LOOKING_FOR_END_OF_LABEL; + goto nextChar; + + } + + break; + + default: + goto fail; + break; + } + + nextChar: + + /* + * if we are at the end of the mapping without hitting our + * exit condition, fail + */ + + if ((pFile->current - pFile->start) >= pFile->length) goto fail; + + pFile->current++; + } /* while(1) */ + + done: + + /* we are done parsing the EDID, save what we have into pEdid */ + + if (k <= 0) goto fail; + + pEdid->size = k; + pEdid->bytes = nvalloc(k); + + memcpy(pEdid->bytes, pData, k); + + return TRUE; + + fail: + + return FALSE; + +} // readEdidDataforTextFile() /* * readEdidFooter() - the EDID footer is in the form: @@ -482,7 +722,7 @@ static int readEdidData(FilePtr pFile, EdidPtr pEdid) * assigned and TRUE is returned. On failure, FALSE is returned. */ -static int readEdidFooter(FilePtr pFile, EdidPtr pEdid) +static int readEdidFooterforLogFile(FilePtr pFile, EdidPtr pEdid) { char *begin; int len; @@ -555,9 +795,107 @@ static int readEdidFooter(FilePtr pFile, EdidPtr pEdid) return FALSE; -} // readEdidFooter() +} // readEdidFooterforLogFile() + +/* + * read Edid Footer i.e. "EDID Version". + * this information is used to check whether the .txt file contains + * any edid information or not + */ + +static int findEdidfooterforTextFile(FilePtr pFile) +{ + pFile->current = pFile->start; + while (((pFile->current - pFile->start) + 12) <= pFile->length) { + + if ((pFile->current[0] == 'E') && + (pFile->current[1] == 'D') && + (pFile->current[2] == 'I') && + (pFile->current[3] == 'D') && + (pFile->current[4] == ' ') && + (pFile->current[5] == 'V') && + (pFile->current[6] == 'e') && + (pFile->current[7] == 'r') && + (pFile->current[8] == 's') && + (pFile->current[9] == 'i') && + (pFile->current[10] == 'o') && + (pFile->current[11] == 'n')) { + + pFile->current = pFile->start; + return TRUE; + } + pFile->current++; + } + +return FALSE; + +} // findEdidfooterforTextFile() + +/* read the monitor information */ + +static int readMonitorNameforTextFile(FilePtr pFile, EdidPtr pEdid) +{ + char *begin; + int len; + + while (((pFile->current - pFile->start) + 12) <= pFile->length) { + + if ((pFile->current[0] == 'M') && + (pFile->current[1] == 'o') && + (pFile->current[2] == 'n') && + (pFile->current[3] == 'i') && + (pFile->current[4] == 't') && + (pFile->current[5] == 'o') && + (pFile->current[6] == 'r') && + (pFile->current[7] == ' ') && + (pFile->current[8] == 'N') && + (pFile->current[9] == 'a') && + (pFile->current[10] == 'm') && + (pFile->current[11] == 'e')) { + + pFile->current += 12; + goto next; + } + + pFile->current++; + + } + return FALSE; + + next: + + /* search for start of the expected text */ + + while (pFile->current[0] != ':') pFile->current++; + pFile->current += 2; + + begin = pFile->current; + + /* search for the end of expected text */ + + while (((pFile->current - pFile->start) + 2) <= pFile->length) { + + if ((pFile->current[0] == '\r') && (pFile->current[1] == '\n')) { + + len = pFile->current - begin; + + if ((len > 512) || (len < 1)) { + return FALSE; + } + + pEdid->name = nvalloc(len + 1); + + strncpy(pEdid->name, begin, len); + pEdid->name[len] = '\0'; + + return TRUE; + } + pFile->current++; + } + return FALSE; +} // readMonitorNameforTextFile() /* * findFileName() - determine the filename to use for writing out the diff --git a/make_usable.c b/make_usable.c index 920a7dc..74c4ca2 100644 --- a/make_usable.c +++ b/make_usable.c @@ -35,10 +35,30 @@ #include "configProcs.h" +static void ensure_module_loaded(XConfigPtr config, char *name); static int update_device(XConfigPtr config, XConfigDevicePtr device); static void update_depth(Options *op, XConfigScreenPtr screen); static void update_display(Options *op, XConfigScreenPtr screen); +/* + * ensure_module_loaded() - make sure the given module is present + */ + +static void ensure_module_loaded(XConfigPtr config, char *name) { + XConfigLoadPtr load; + int found = FALSE; + + for (load = config->modules->loads; load && !found; load = load->next) { + if (xconfigNameCompare(name, load->name) == 0) found = TRUE; + } + + if (!found) { + config->modules->loads = + xconfigAddNewLoadDirective(config->modules->loads, + name, XCONFIG_LOAD_MODULE, + NULL, FALSE); + } +} /* ensure_module_loaded */ /* * update_modules() - make sure the glx module is present, and remove @@ -48,25 +68,16 @@ static void update_display(Options *op, XConfigScreenPtr screen); int update_modules(XConfigPtr config) { XConfigLoadPtr load, next; - int found; if (config->modules == NULL) { config->modules = xconfigAlloc(sizeof(XConfigModuleRec)); } - /* make sure glx is loaded */ - - found = FALSE; - for (load = config->modules->loads; load; load = load->next) { - if (xconfigNameCompare("glx", load->name) == 0) found = TRUE; - } - - if (!found) { - config->modules->loads = - xconfigAddNewLoadDirective(config->modules->loads, - "glx", XCONFIG_LOAD_MODULE, - NULL, FALSE); - } + /* make sure all our required modules are loaded */ + ensure_module_loaded(config, "glx"); +#if defined(NV_SUNOS) + ensure_module_loaded(config, "xtsol"); +#endif // defined(NV_SUNOS) /* make sure GLcore and dri are not loaded */ @@ -158,6 +169,10 @@ int update_extensions(Options *op, XConfigPtr config) { char *value; + /* validate the composite option against any other options specified */ + + validate_composite(op, config); + if (GET_BOOL_OPTION(op->boolean_options, COMPOSITE_BOOL_OPTION)) { /* if we don't already have the Extensions section, create it now */ diff --git a/nvidia-xconfig.c b/nvidia-xconfig.c index dfb43b5..3ae1af8 100644 --- a/nvidia-xconfig.c +++ b/nvidia-xconfig.c @@ -234,7 +234,6 @@ Options *parse_commandline(int argc, char *argv[]) { Options *op; int c, boolval; - u32 bit; char *strval; int intval, disable; @@ -257,17 +256,9 @@ Options *parse_commandline(int argc, char *argv[]) if ((c >= XCONFIG_BOOL_OPTION_START) && (c <= (XCONFIG_BOOL_OPTION_START + XCONFIG_BOOL_OPTION_COUNT))) { + + set_boolean_option(op, c - XCONFIG_BOOL_OPTION_START, boolval); - bit = GET_BOOL_OPTION_BIT(c - XCONFIG_BOOL_OPTION_START); - GET_BOOL_OPTION_SLOT(op->boolean_options, - c - XCONFIG_BOOL_OPTION_START) |= bit; - if (boolval) { - GET_BOOL_OPTION_SLOT(op->boolean_option_values, - c - XCONFIG_BOOL_OPTION_START) |= bit; - } else { - GET_BOOL_OPTION_SLOT(op->boolean_option_values, - c - XCONFIG_BOOL_OPTION_START) &= ~bit; - } continue; } @@ -512,7 +503,7 @@ Options *parse_commandline(int argc, char *argv[]) case QUERY_GPU_INFO_OPTION: op->query_gpu_info = TRUE; break; case 'E': - op->extract_edids_from_log = strval; + op->extract_edids_from_file = strval; break; case EXTRACT_EDIDS_OUTPUT_FILE_OPTION: @@ -583,6 +574,15 @@ Options *parse_commandline(int argc, char *argv[]) op->logo_path = disable ? NV_DISABLE_STRING_OPTION : strval; break; + case USE_DISPLAY_DEVICE_OPTION: + op->use_display_device = + disable ? NV_DISABLE_STRING_OPTION : strval; + break; + + case CUSTOM_EDID_OPTION: + op->custom_edid = disable ? NV_DISABLE_STRING_OPTION : strval; + break; + default: goto fail; } @@ -939,33 +939,71 @@ int update_xconfig(Options *op, XConfigPtr config) /* * get_xserver_in_use() - try to determine which X server is in use - * (XFree86, Xorg) + * (XFree86, Xorg); also determine if the X server supports the + * Extension section of the X config file; support for the "Extension" + * section was added between X.Org 6.7 and 6.8. * - * XXX need to update for modular layout + * Some of the parsing here mimics what is done in the + * check_for_modular_xorg() function in nvidia-installer */ -# define NV_LINE_LEN 1024 +#define NV_LINE_LEN 1024 +#define EXTRA_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/X11R6/bin:/usr/bin/X11" +#define VERSION_FORMAT "X Protocol Version %d, Revision %d, Release %d.%d" + static void get_xserver_in_use(Options *op) { #if defined(NV_SUNOS) - op->gop.xserver=X_IS_XORG; + + /* + * Solaris x86/x64 always uses X.Org 6.8 or higher, atleast as far + * as the NVIDIA X driver is concerned + */ + + op->gop.xserver = X_IS_XORG; + op->supports_extension_section = TRUE; + #else - char *cmd; + FILE *stream = NULL; int xserver = -1; - - cmd = xconfigStrcat(op->gop.x_project_root, "/bin/X -version 2>&1", NULL); + int dummy, len, release_major, release_minor; + char *cmd, *ptr, *ret; + + op->supports_extension_section = FALSE; + + /* run `X -version` with a PATH that hopefully includes the X binary */ + + cmd = xconfigStrcat("PATH=", op->gop.x_project_root, ":", + EXTRA_PATH, ":$PATH X -version 2>&1", NULL); + if ((stream = popen(cmd, "r"))) { - char buf[NV_LINE_LEN]; + char buf[NV_LINE_LEN]; + + /* read in as much of the input as we can fit into the buffer */ + + ptr = buf; - while (1) { - if (fgets(buf, NV_LINE_LEN-1, stream) == NULL) break; - - if (xserver == -1) { - if (strcmp(buf, "XFree86") >= 0) { - xserver = X_IS_XF86; - } else if (strcmp(buf, "X Window System") >= 0) { - xserver = X_IS_XORG; + do { + len = NV_LINE_LEN - (ptr - buf) - 1; + ret = fgets(ptr, len, stream); + ptr = strchr(ptr, '\0'); + } while ((ret != NULL) && (len > 1)); + + /* Check if this is an XFree86 release */ + + if (strstr(buf, "XFree86 Version") != NULL) { + xserver = X_IS_XF86; + op->supports_extension_section = FALSE; + } else if (strstr(buf, "X Window System") != NULL) { + xserver = X_IS_XORG; + if ((ptr = strstr(buf, "X Protocol Version")) != NULL && + sscanf(ptr, VERSION_FORMAT, &dummy, &dummy, + &release_major, &release_minor) == 4) { + + if ((release_major > 6) || + ((release_major == 6) && (release_minor >= 8))) { + op->supports_extension_section = TRUE; } } } @@ -1037,7 +1075,7 @@ int main(int argc, char *argv[]) return (ret ? 0 : 1); } - if (op->extract_edids_from_log) { + if (op->extract_edids_from_file) { ret = extract_edids(op); return (ret ? 0 : 1); } diff --git a/nvidia-xconfig.h b/nvidia-xconfig.h index 521e494..b252b6d 100644 --- a/nvidia-xconfig.h +++ b/nvidia-xconfig.h @@ -150,11 +150,13 @@ typedef struct __options { char *rotate; char *nvidia_cfg_path; - char *extract_edids_from_log; + char *extract_edids_from_file; char *extract_edids_output_file; char *twinview_xinerama_info_order; char *logo_path; char *twinview_orientation; + char *use_display_device; + char *custom_edid; struct { int x; @@ -164,6 +166,8 @@ typedef struct __options { TextRows add_modes; TextRows remove_modes; + int supports_extension_section; + GenerateOptions gop; } Options; @@ -243,6 +247,8 @@ int print_tree(Options *op, XConfigPtr config); /* options.c */ void remove_option_from_list(XConfigOptionPtr *list, const char *name); +void set_boolean_option(Options *op, const int c, const int boolval); +void validate_composite(Options *op, XConfigPtr config); void update_options(Options *op, XConfigScreenPtr screen); /* lscf.c */ diff --git a/option_table.h b/option_table.h index 6eaec1f..8b59c03 100644 --- a/option_table.h +++ b/option_table.h @@ -35,6 +35,8 @@ #define LOGO_PATH_OPTION 24 #define TWINVIEW_ORIENTATION_OPTION 25 #define VIRTUAL_OPTION 26 +#define USE_DISPLAY_DEVICE_OPTION 27 +#define CUSTOM_EDID_OPTION 28 /* * To add a boolean option to nvidia-xconfig: @@ -148,6 +150,12 @@ static const NVGetoptOption __options[] = { "millimeters of the X screen when XRandR changes the size in pixels " "of the X screen." }, + { "custom-edid", CUSTOM_EDID_OPTION, + NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "CUSTOM-EDID", + "Enable or disable the \"CustomEDID\" X configuration option; " + "setting this option forces the X driver to use the EDID specified " + "in a file rather than the display's EDID." }, + { "dac-8bit", XCONFIG_BOOL_VAL(DAC_8BIT_BOOL_OPTION), NVGETOPT_IS_BOOLEAN, NULL, "Most Quadro parts by default use a 10 bit color look up table (LUT) " @@ -194,7 +202,7 @@ static const NVGetoptOption __options[] = { "Forces the initialization of the X server with " "the exact timings specified in the ModeLine." }, - { "extract-edids-from-log", 'E', NVGETOPT_STRING_ARGUMENT, "LOG", + { "extract-edids-from-file", 'E', NVGETOPT_STRING_ARGUMENT, "FILE", "Extract any raw EDID byte blocks contained in the specified X " "log file [LOG]; raw EDID bytes are printed by the NVIDIA X driver to " "the X log as hexidecimal when verbose logging is enabled with the " @@ -476,6 +484,10 @@ static const NVGetoptOption __options[] = { "Enable use of the X Int10 module to soft-boot all secondary cards, " "rather than POSTing the cards through the NVIDIA kernel module." }, + { "use-display-device", USE_DISPLAY_DEVICE_OPTION, + NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "DISPLAY-DEVICE", + "Force the X driver to use the display device specified." }, + { "virtual", VIRTUAL_OPTION, NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "WIDTHxHEIGHT", "Specify the virtual screen resolution." }, diff --git a/options.c b/options.c index 5d7c081..2819f9d 100644 --- a/options.c +++ b/options.c @@ -112,6 +112,126 @@ void remove_option_from_list(XConfigOptionPtr *list, const char *name) +/* + * set_boolean_option() - set boolean option 'c' to the given 'boolval' + */ + +void set_boolean_option(Options *op, const int c, const int boolval) +{ + u32 bit; + + bit = GET_BOOL_OPTION_BIT(c); + + GET_BOOL_OPTION_SLOT(op->boolean_options, c) |= bit; + + if (boolval) { + GET_BOOL_OPTION_SLOT(op->boolean_option_values, c) |= bit; + } else { + GET_BOOL_OPTION_SLOT(op->boolean_option_values, c) &= ~bit; + } +} /* set_boolean_option() */ + + + +/* + * validate_composite() - check whether any options conflict with the + * Composite extension; update the composite option value, if + * appropriate. + */ + +void validate_composite(Options *op, XConfigPtr config) +{ + int i, n, opt, disable_composite; + char scratch[256], *s; + + + /* + * the composite_incompatible_options[] array lists all the + * options that are incompatible with the composite extension; we + * list boolean options and then special-case any non-boolean options + */ + + static int composite_incompatible_options[] = { + XINERAMA_BOOL_OPTION, + OVERLAY_BOOL_OPTION, + CIOVERLAY_BOOL_OPTION, + UBB_BOOL_OPTION, + -1, /* stereo */ + -2 /* end */ + }; + + disable_composite = FALSE; + s = scratch; + n = 0; + + /* + * loop through all the incompatible options, and check if the + * user specified any of them + */ + + for (i = 0; composite_incompatible_options[i] != -2; i++) { + + int present = 0; + const char *name; + + opt = composite_incompatible_options[i]; + + if (opt == -1) { /* special case stereo */ + + present = (op->stereo > 0); + name = "Stereo"; + + } else { + const NvidiaXConfigOption *o; + + present = (GET_BOOL_OPTION(op->boolean_options, opt) && + GET_BOOL_OPTION(op->boolean_option_values, opt)); + + o = get_option(opt); + name = o->name; + } + + /* + * if the option is present, then we have to disable + * composite; append to the scratch string that lists all the + * present conflicting options + */ + + if (present) { + disable_composite = TRUE; + n++; + s += sprintf(s, "%s%s", (n > 1) ? " or " : "", name); + } + } + + /* + * if we have to disable the composite extension, print a warning + * and set the option value. + * + * We need to be careful to only set the option value if the X + * server is going to recognize the Extension section and the + * composite option. We guess whether the server will recognize + * the option: if get_xserver_in_use() thinks the X server + * supports the "Composite" extension, or the current config + * already has an extension section, or the user specified the + * composite option. + */ + + if (disable_composite && + (op->supports_extension_section || + config->extensions || + GET_BOOL_OPTION(op->boolean_options, COMPOSITE_BOOL_OPTION))) { + + fmtwarn("The Composite X extension does not currently interact well " + "with the %s option%s; the Composite X extension will be " + "disabled.", scratch, (n > 1) ? "s": ""); + + set_boolean_option(op, COMPOSITE_BOOL_OPTION, FALSE); + } +} /* validate_composite() */ + + + /* * remove_option() - make sure the named option does not exist in any * of the possible option lists: @@ -375,4 +495,24 @@ void update_options(Options *op, XConfigScreenPtr screen) } } + /* add the UseDisplayDevice option */ + + if (op->use_display_device) { + remove_option(screen, "UseDisplayDevice"); + if (op->use_display_device != NV_DISABLE_STRING_OPTION) { + set_option_value(screen, "UseDisplayDevice", + op->use_display_device); + } + } + + /* add the CustomEDID option */ + + if (op->custom_edid) { + remove_option(screen, "CustomEDID"); + if (op->custom_edid != NV_DISABLE_STRING_OPTION) { + set_option_value(screen, "CustomEDID", op->custom_edid); + } + } + + } /* update_options() */ -- cgit v1.2.3