QByteArray UINVControl::GetNVEDID(Display *XDisplay, int Screen) { if (!NVControlAvailable(XDisplay)) return QByteArray(); QMutexLocker locker(gNVCtrlLock); QByteArray result; if (!XNVCTRLIsNvScreen(XDisplay, Screen)) { LOG(VB_GENERAL, LOG_ERR, QString("NV-CONTROL is not available on screen %1 of display '%2'") .arg(Screen).arg(XDisplayName(NULL))); return result; } int displays = 0; Bool ok = XNVCTRLQueryAttribute(XDisplay, Screen, 0, NV_CTRL_CONNECTED_DISPLAYS, &displays); if (ok != True) { LOG(VB_GENERAL, LOG_ERR, "Failed to retrieve display list"); return result; } int displaycount = ListDisplays(displays); if (displaycount != 1) { LOG(VB_GENERAL, LOG_WARNING, "There is more than one physical display attached to this screen. Ignoring EDID"); return result; } int edid = NV_CTRL_EDID_AVAILABLE_FALSE; ok = XNVCTRLQueryAttribute(XDisplay, Screen, displays, NV_CTRL_EDID_AVAILABLE, &edid); if (ok != True) { LOG(VB_GENERAL, LOG_INFO, "Failed to check EDID_AVAILABLE attribute"); return result; } if (edid != NV_CTRL_EDID_AVAILABLE_TRUE) { LOG(VB_GENERAL, LOG_INFO, "EDID not available"); return result; } unsigned char* data = NULL; int datalength = 0; ok = XNVCTRLQueryBinaryData(XDisplay, Screen, displays, NV_CTRL_BINARY_DATA_EDID, &data, &datalength); if (ok != True) { LOG(VB_GENERAL, LOG_INFO, QString("EDID not available on screen %1 of display '%2'") .arg(Screen).arg(XDisplayName(NULL))); return result; } result = QByteArray((const char*)data, datalength); delete data; return result; }
/* * nv-control-screen.h - trivial helper for NV-CONTROL sample clients: use * the default screen if it is an NVIDIA X screen. If it isn't, then look * for the first NVIDIA X screen. Abort if no NVIDIA X screens are found. */ static inline int GetNvXScreen(Display *dpy) { int defaultScreen, screen; defaultScreen = DefaultScreen(dpy); if (XNVCTRLIsNvScreen(dpy, defaultScreen)) { return defaultScreen; } for (screen = 0; screen < ScreenCount(dpy); screen++) { if (XNVCTRLIsNvScreen(dpy, screen)) { printf("Default X screen %d is not an NVIDIA X screen. " "Using X screen %d instead.\n", defaultScreen, screen); return screen; } } fprintf(stderr, "Unable to find any NVIDIA X screens; aborting.\n"); return -1; }
int CheckNVOpenGLSyncToVBlank(void) { MythXDisplay *d = OpenMythXDisplay(); if (!d) return -1; Display *dpy = d->GetDisplay(); int screen = d->GetScreen(); if (!XNVCTRLIsNvScreen(dpy, screen)) { delete d; return -1; } int major, minor; if (!XNVCTRLQueryVersion(dpy, &major, &minor)) return -1; int sync = NV_CTRL_SYNC_TO_VBLANK_OFF; if (!XNVCTRLQueryAttribute(dpy, screen, 0, NV_CTRL_SYNC_TO_VBLANK, &sync)) { delete d; return -1; } if (!sync) { LOG(VB_GENERAL, LOG_WARNING, LOC + "OpenGL Sync to VBlank is disabled."); LOG(VB_GENERAL, LOG_WARNING, LOC + "For best results enable this in NVidia settings or try running:"); LOG(VB_GENERAL, LOG_WARNING, LOC + "nvidia-settings -a \"SyncToVBlank=1\""); } if (!sync && getenv("__GL_SYNC_TO_VBLANK")) { LOG(VB_GENERAL, LOG_INFO, LOC + "OpenGL Sync to VBlank enabled via __GL_SYNC_TO_VBLANK."); sync = 1; } else if (!sync) { LOG(VB_GENERAL, LOG_WARNING, LOC + "Alternatively try setting the '__GL_SYNC_TO_VBLANK' environment variable."); } return sync; }
egl::Error DisplayGLX::getNVIDIADriverVersion(std::string *version) const { *version = ""; int eventBase = 0; int errorBase = 0; if (XNVCTRLQueryExtension(mXDisplay, &eventBase, &errorBase)) { int screenCount = ScreenCount(mXDisplay); for (int screen = 0; screen < screenCount; ++screen) { char *buffer = nullptr; if (XNVCTRLIsNvScreen(mXDisplay, screen) && XNVCTRLQueryStringAttribute(mXDisplay, screen, 0, NV_CTRL_STRING_NVIDIA_DRIVER_VERSION, &buffer)) { *version = buffer; XFree(buffer); } } } return egl::Error(EGL_SUCCESS); }
// this function does some checks int nvidia_gpu_init(Display * dpy, int screen) { int event_base, error_base; int ret = XNVCTRLQueryExtension(dpy, &event_base, &error_base); if (ret != True) { fprintf(stderr, "The NV-CONTROL X extension does not exist on '%s'.\n", XDisplayName(NULL)); return 0; } if(!XNVCTRLIsNvScreen(dpy, screen)) { fprintf(stderr, "Screen %d does not support the NV-Control extension\n", screen); return 0; } int max; ret = XNVCTRLQueryAttribute(dpy, screen, 0, NV_CTRL_GPU_CORE_THRESHOLD, &max); if(ret) { nvidia_gpu_max_temperature = max; } return 1; }
static void hwloc_gl_query_devices(struct hwloc_gl_backend_data_s *data) { int err; unsigned i,j; /* mark the number of display as 0 in case we fail below, * so that we don't try again later. */ data->nr_display = 0; for (i = 0; i < HWLOC_GL_SERVER_MAX; ++i) { Display* display; char displayName[10]; int opcode, event, error; /* open X server */ snprintf(displayName, sizeof(displayName), ":%u", i); display = XOpenDisplay(displayName); if (!display) continue; /* Check for NV-CONTROL extension (it's per server) */ if(!XQueryExtension(display, "NV-CONTROL", &opcode, &event, &error)) { XCloseDisplay(display); continue; } for (j = 0; j < (unsigned) ScreenCount(display) && j < HWLOC_GL_SCREEN_MAX; j++) { struct hwloc_gl_display_info_s *info = &data->display[data->nr_display]; const int screen = j; unsigned int *ptr_binary_data; int data_length; int gpu_number; int nv_ctrl_pci_bus; int nv_ctrl_pci_device; int nv_ctrl_pci_domain; int nv_ctrl_pci_func; char *productname; /* the server supports NV-CONTROL but it may contain non-NVIDIA screen that don't support it */ if (!XNVCTRLIsNvScreen(display, screen)) continue; /* Gets the GPU number attached to the default screen. */ /* For further details, see the <NVCtrl/NVCtrlLib.h> */ err = XNVCTRLQueryTargetBinaryData (display, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0, NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN, (unsigned char **) &ptr_binary_data, &data_length); if (!err) continue; gpu_number = ptr_binary_data[1]; free(ptr_binary_data); #ifdef NV_CTRL_PCI_DOMAIN /* Gets the ID's of the GPU defined by gpu_number * For further details, see the <NVCtrl/NVCtrlLib.h> */ err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_DOMAIN, &nv_ctrl_pci_domain); if (!err) continue; #else nv_ctrl_pci_domain = 0; #endif err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_BUS, &nv_ctrl_pci_bus); if (!err) continue; err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_DEVICE, &nv_ctrl_pci_device); if (!err) continue; err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_FUNCTION, &nv_ctrl_pci_func); if (!err) continue; productname = NULL; err = XNVCTRLQueryTargetStringAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_STRING_PRODUCT_NAME, &productname); snprintf(info->name, sizeof(info->name), ":%u.%u", i, j); info->port = i; info->device = j; info->pcidomain = nv_ctrl_pci_domain; info->pcibus = nv_ctrl_pci_bus; info->pcidevice = nv_ctrl_pci_device; info->pcifunc = nv_ctrl_pci_func; info->productname = productname; hwloc_debug("GL device %s (product %s) on PCI 0000:%02x:%02x.%u\n", info->name, productname, nv_ctrl_pci_domain, nv_ctrl_pci_bus, nv_ctrl_pci_device, nv_ctrl_pci_func); /* validate this device */ data->nr_display++; } XCloseDisplay(display); } }
int GetNvidiaRates(t_screenrate& screenmap) { #ifdef USING_XRANDR MythXDisplay *d = OpenMythXDisplay(); if (!d) { return -1; } Display *dpy; bool ret; int screen, display_devices, mask, major, minor, len, j; char *str, *start; int nDisplayDevice; char *pMetaModes, *pModeLines[8], *tmp, *modeString; char *modeLine, *modeName; int MetaModeLen, ModeLineLen[8]; int thisMask; int id; int twinview = 0; map<int, map<int,bool> > maprate; memset(pModeLines, 0, sizeof(pModeLines)); memset(ModeLineLen, 0, sizeof(ModeLineLen)); /* * Open a display connection, and make sure the NV-CONTROL X * extension is present on the screen we want to use. */ dpy = d->GetDisplay(); screen = d->GetScreen(); if (!XNVCTRLIsNvScreen(dpy, screen)) { LOG(VB_PLAYBACK, LOG_INFO, QString("The NV-CONTROL X extension is not available on screen %1 " "of '%2'.") .arg(screen) .arg(XDisplayName(NULL))); delete d; return -1; } ret = XNVCTRLQueryVersion(dpy, &major, &minor); if (ret != True) { LOG(VB_PLAYBACK, LOG_INFO, QString("The NV-CONTROL X extension does not exist on '%1'.") .arg(XDisplayName(NULL))); delete d; return -1; } ret = XNVCTRLQueryAttribute(dpy, screen, 0, NV_CTRL_DYNAMIC_TWINVIEW, &twinview); if (!ret) { LOG(VB_PLAYBACK, LOG_ERR, "Failed to query if Dynamic Twinview is enabled"); XCloseDisplay(dpy); return -1; } if (!twinview) { LOG(VB_PLAYBACK, LOG_ERR, "Dynamic Twinview not enabled, ignoring"); delete d; return 0; } /* * query the connected display devices on this X screen and print * basic information about each X screen */ ret = XNVCTRLQueryAttribute(dpy, screen, 0, NV_CTRL_CONNECTED_DISPLAYS, &display_devices); if (!ret) { LOG(VB_PLAYBACK, LOG_ERR, "Failed to query the enabled Display Devices."); delete d; return -1; } /* first, we query the MetaModes on this X screen */ ret = XNVCTRLQueryBinaryData(dpy, screen, 0, // n/a NV_CTRL_BINARY_DATA_METAMODES, (unsigned char **)&pMetaModes, &MetaModeLen); if (!ret) { LOG(VB_PLAYBACK, LOG_ERR, "Failed to query the metamode on selected display device."); delete d; return -1; } /* * then, we query the ModeLines for each display device on * this X screen; we'll need these later */ nDisplayDevice = 0; for (mask = 1; mask < (1 << 24); mask <<= 1) { if (!(display_devices & mask)) continue; ret = XNVCTRLQueryBinaryData(dpy, screen, mask, NV_CTRL_BINARY_DATA_MODELINES, (unsigned char **)&str, &len); if (!ret) { LOG(VB_PLAYBACK, LOG_ERR, "Unknown error. Failed to query the enabled Display Devices."); // Free Memory currently allocated for (j=0; j < nDisplayDevice; ++j) { free(pModeLines[j]); } delete d; return -1; } pModeLines[nDisplayDevice] = str; ModeLineLen[nDisplayDevice] = len; nDisplayDevice++; } /* now, parse each MetaMode */ str = start = pMetaModes; for (j = 0; j < MetaModeLen - 1; ++j) { /* * if we found the end of a line, treat the string from * start to str[j] as a MetaMode */ if ((str[j] == '\0') && (str[j+1] != '\0')) { id = extract_id_string(start); /* * the MetaMode may be preceded with "token=value" * pairs, separated by the main MetaMode with "::"; if * "::" exists in the string, skip past it */ tmp = strstr(start, "::"); if (tmp) { tmp += 2; } else { tmp = start; } /* split the MetaMode string by comma */ char *strtok_state = NULL; for (modeString = strtok_r(tmp, ",", &strtok_state); modeString; modeString = strtok_r(NULL, ",", &strtok_state)) { /* * retrieve the modeName and display device mask * for this segment of the Metamode */ parse_mode_string(modeString, &modeName, &thisMask); /* lookup the modeline that matches */ nDisplayDevice = 0; if (thisMask) { for (mask = 1; mask < (1 << 24); mask <<= 1) { if (!(display_devices & mask)) continue; if (thisMask & mask) break; nDisplayDevice++; } } modeLine = find_modeline(modeName, pModeLines[nDisplayDevice], ModeLineLen[nDisplayDevice]); if (modeLine && !modeline_is_interlaced(modeLine)) { int w, h, vfl, hfl, i, irate; double dcl, r; char *buf[256]; uint64_t key, key2; // skip name tmp = strchr(modeLine, '"'); tmp = strchr(tmp+1, '"') +1 ; while (*tmp == ' ') tmp++; i = 0; for (modeString = strtok_r(tmp, " ", &strtok_state); modeString; modeString = strtok_r(NULL, " ", &strtok_state)) { buf[i++] = modeString; } w = strtol(buf[1], NULL, 10); h = strtol(buf[5], NULL, 10); vfl = strtol(buf[8], NULL, 10); hfl = strtol(buf[4], NULL, 10); h = strtol(buf[5], NULL, 10); istringstream istr(buf[0]); istr.imbue(locale("C")); istr >> dcl; r = (dcl * 1000000.0) / (vfl * hfl); irate = (int) round(r * 1000.0); key = DisplayResScreen::CalcKey(w, h, (double) id); key2 = DisplayResScreen::CalcKey(w, h, 0.0); // We need to eliminate duplicates, giving priority to the first entries found if (maprate.find(key2) == maprate.end()) { // First time we see this resolution, create a map for it maprate[key2] = map<int, bool>(); } if ((maprate[key2].find(irate) == maprate[key2].end()) && (screenmap.find(key) == screenmap.end())) { screenmap[key] = r; maprate[key2][irate] = true; } } free(modeName); } /* move to the next MetaMode */ start = &str[j+1]; }
int main(void) { Display *dpy; Bool ret; int event_base, error_base, major, minor, screens, i; char *str; /* * open a connection to the X server indicated by the DISPLAY * environment variable */ dpy = XOpenDisplay(NULL); if (!dpy) { fprintf(stderr, "Cannot open display '%s'.\n", XDisplayName(NULL)); return 1; } /* * check if the NV-CONTROL X extension is present on this X server */ ret = XNVCTRLQueryExtension(dpy, &event_base, &error_base); if (ret != True) { fprintf(stderr, "The NV-CONTROL X extension does not exist on '%s'.\n", XDisplayName(NULL)); return 1; } /* * query the major and minor extension version */ ret = XNVCTRLQueryVersion(dpy, &major, &minor); if (ret != True) { fprintf(stderr, "The NV-CONTROL X extension does not exist on '%s'.\n", XDisplayName(NULL)); return 1; } /* * print statistics thus far */ printf("NV-CONTROL X extension present\n"); printf(" version : %d.%d\n", major, minor); printf(" event base : %d\n", event_base); printf(" error base : %d\n", error_base); /* * loop over each screen, and determine if each screen is * controlled by the NVIDIA X driver (and thus supports the * NV-CONTROL X extension); then, query the string attributes on * the screen. */ screens = ScreenCount(dpy); for (i = 0; i < screens; i++) { if (XNVCTRLIsNvScreen(dpy, i)) { printf("Screen %d supports the NV-CONTROL X extension\n", i); ret = XNVCTRLQueryStringAttribute(dpy, i, 0, /* XXX not curently used */ NV_CTRL_STRING_PRODUCT_NAME, &str); if (ret) { printf(" GPU : %s\n", str); XFree(str); } ret = XNVCTRLQueryStringAttribute(dpy, i, 0, /* XXX not curently used */ NV_CTRL_STRING_VBIOS_VERSION, &str); if (ret) { printf(" VideoBIOS : %s\n", str); XFree(str); } ret = XNVCTRLQueryStringAttribute(dpy, i, 0, /* XXX not curently used */ NV_CTRL_STRING_NVIDIA_DRIVER_VERSION, &str); if (ret) { printf(" Driver version : %s\n", str); XFree(str); } } } /* * print attribute permission and type information. */ printf("Attributes (Integers):\n"); for (i = 0; i < NV_CTRL_LAST_ATTRIBUTE; i++) { const char *name = attr2str(i, attr_int_table); if (name) { NVCTRLAttributePermissionsRec perms; printf(" (%3d) [Perms: ", i); memset(&perms, 0, sizeof(NVCTRLAttributePermissionsRec)); XNVCTRLQueryAttributePermissions(dpy, i, &perms); print_perms(&perms); printf("] [ "); printf("%-32s", GetAttrTypeName(perms.type)); printf("] - %s\n", name); } } printf("Attributes (Strings):\n"); for (i = 0; i < NV_CTRL_STRING_LAST_ATTRIBUTE; i++) { const char *name = attr2str(i, attr_str_table); if (name) { NVCTRLAttributePermissionsRec perms; printf(" (%3d) [Perms: ", i); memset(&perms, 0, sizeof(NVCTRLAttributePermissionsRec)); XNVCTRLQueryStringAttributePermissions(dpy, i, &perms); print_perms(&perms); printf("] [ "); printf("%-32s", GetAttrTypeName(perms.type)); printf("] - %s\n", name); } } printf("Attributes (Binary Data):\n"); for (i = 0; i < NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE; i++) { const char *name = attr2str(i, attr_bin_table); if (name) { NVCTRLAttributePermissionsRec perms; printf(" (%3d) [Perms: ", i); memset(&perms, 0, sizeof(NVCTRLAttributePermissionsRec)); XNVCTRLQueryBinaryDataAttributePermissions(dpy, i, &perms); print_perms(&perms); printf("] [ "); printf("%-32s", GetAttrTypeName(perms.type)); printf("] - %s\n", name); } } printf("Attributes (String Operations):\n"); for (i = 0; i < NV_CTRL_STRING_OPERATION_LAST_ATTRIBUTE; i++) { const char *name = attr2str(i, attr_strop_table); if (name) { NVCTRLAttributePermissionsRec perms; printf(" (%3d) [Perms: ", i); memset(&perms, 0, sizeof(NVCTRLAttributePermissionsRec)); XNVCTRLQueryStringOperationAttributePermissions(dpy, i, &perms); print_perms(&perms); printf("] [ "); printf("%-32s", GetAttrTypeName(perms.type)); printf("] - %s\n", name); } } /* * close the display connection */ XCloseDisplay(dpy); return 0; }
static int hwloc_gl_discover(struct hwloc_backend *backend) { struct hwloc_topology *topology = backend->topology; unsigned i, res = 0; int err; if (!(hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO))) return 0; if (!hwloc_topology_is_thissystem(topology)) { hwloc_debug("%s", "\nno GL detection (not thissystem)\n"); return 0; } for (i = 0; i < HWLOC_GL_SERVER_MAX; ++i) { Display* display; char displayName[10]; int opcode, event, error; unsigned j; /* open X server */ snprintf(displayName, sizeof(displayName), ":%u", i); display = XOpenDisplay(displayName); if (!display) continue; /* Check for NV-CONTROL extension (it's per server) */ if(!XQueryExtension(display, "NV-CONTROL", &opcode, &event, &error)) { XCloseDisplay(display); continue; } for (j = 0; j < (unsigned) ScreenCount(display) && j < HWLOC_GL_SCREEN_MAX; j++) { hwloc_obj_t osdev, parent; const int screen = j; unsigned int *ptr_binary_data; int data_length; int gpu_number; int nv_ctrl_pci_bus; int nv_ctrl_pci_device; int nv_ctrl_pci_domain; int nv_ctrl_pci_func; char *productname; char name[64]; /* the server supports NV-CONTROL but it may contain non-NVIDIA screen that don't support it */ if (!XNVCTRLIsNvScreen(display, screen)) continue; /* Gets the GPU number attached to the default screen. */ /* For further details, see the <NVCtrl/NVCtrlLib.h> */ err = XNVCTRLQueryTargetBinaryData (display, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0, NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN, (unsigned char **) &ptr_binary_data, &data_length); if (!err) continue; gpu_number = ptr_binary_data[1]; free(ptr_binary_data); #ifdef NV_CTRL_PCI_DOMAIN /* Gets the ID's of the GPU defined by gpu_number * For further details, see the <NVCtrl/NVCtrlLib.h> */ err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_DOMAIN, &nv_ctrl_pci_domain); if (!err) continue; #else nv_ctrl_pci_domain = 0; #endif err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_BUS, &nv_ctrl_pci_bus); if (!err) continue; err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_DEVICE, &nv_ctrl_pci_device); if (!err) continue; err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_FUNCTION, &nv_ctrl_pci_func); if (!err) continue; productname = NULL; err = XNVCTRLQueryTargetStringAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_STRING_PRODUCT_NAME, &productname); snprintf(name, sizeof(name), ":%u.%u", i, j); osdev = hwloc_alloc_setup_object(HWLOC_OBJ_OS_DEVICE, -1); osdev->name = strdup(name); osdev->logical_index = -1; osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_GPU; hwloc_obj_add_info(osdev, "Backend", "GL"); hwloc_obj_add_info(osdev, "GPUVendor", "NVIDIA Corporation"); if (productname) hwloc_obj_add_info(osdev, "GPUModel", productname); parent = hwloc_pci_belowroot_find_by_busid(topology, nv_ctrl_pci_domain, nv_ctrl_pci_bus, nv_ctrl_pci_device, nv_ctrl_pci_func); if (!parent) parent = hwloc_pci_find_busid_parent(topology, nv_ctrl_pci_domain, nv_ctrl_pci_bus, nv_ctrl_pci_device, nv_ctrl_pci_func); if (!parent) parent = hwloc_get_root_obj(topology); hwloc_insert_object_by_parent(topology, parent, osdev); hwloc_debug("GL device %s (product %s) on PCI 0000:%02x:%02x.%u\n", name, productname, nv_ctrl_pci_domain, nv_ctrl_pci_bus, nv_ctrl_pci_device, nv_ctrl_pci_func); res++; } XCloseDisplay(display); } return res; }
void UINVControl::InitialiseMetaModes(Display *XDisplay, int Screen) { if (!NVControlAvailable(XDisplay)) return; QMutexLocker locker(gNVCtrlLock); gMetaModeMap.clear(); if (!XNVCTRLIsNvScreen(XDisplay, Screen)) { LOG(VB_GENERAL, LOG_ERR, QString("NV-CONTROL is not available on screen %1 of display '%2'") .arg(Screen).arg(XDisplayName(NULL))); return; } int displays = 0; Bool ok = XNVCTRLQueryAttribute(XDisplay, Screen, 0, NV_CTRL_CONNECTED_DISPLAYS, &displays); if (ok != True) { LOG(VB_GENERAL, LOG_ERR, "Failed to retrieve display list"); return; } int displaycount = ListDisplays(displays); if (displaycount != 1) { LOG(VB_GENERAL, LOG_WARNING, "There is more than one physical display attached to this screen. Ignoring metamodes"); return; } // retrieve a list of refresh rates by mode name QMap<QString,double> rates; QStringList interlacedrates; unsigned char* modelines = NULL; int modelinelength = 0; if (XNVCTRLQueryBinaryData(XDisplay, Screen, displays, NV_CTRL_BINARY_DATA_MODELINES, &modelines, &modelinelength)) { QByteArray data((const char*)modelines, modelinelength); QList<QByteArray> lines = data.split('\0'); foreach (QByteArray line, lines) { QString modeline = QString::fromLatin1(line.data()).simplified(); LOG(VB_GUI, LOG_DEBUG, QString("Modeline: %1").arg(modeline)); QStringList parts = modeline.split("::", QString::SkipEmptyParts); if (parts.size() < 1) continue; modeline = parts.last(); parts = modeline.split(" ", QString::SkipEmptyParts); if (parts.size() < 10) continue; QString name = parts[0].replace("\"", ""); double rate = parts[5].toInt() * parts[9].toInt(); double clock = parts[1].toDouble(); if (rate > 0.0 && clock > 0.0f) { rate = (clock * 1000000) / rate; bool interlaced = false; if (modeline.contains("interlace", Qt::CaseInsensitive)) { rate *= 2.0f; interlaced = true; } if (rate > 20.0f && rate < 121.0f) { rates.insert(name, rate); if (interlaced) interlacedrates.append(name); } } }
/* ================ Sys_GetVideoRam returns in megabytes open your own display connection for the query and close it using the one shared with GLimp_Init is not stable ================ */ int Sys_GetVideoRam( void ) { #ifdef USE_SDL return 128; #else static int run_once = 0; int major, minor, value; Display *l_dpy; int l_scrnum; if ( run_once ) { return run_once; } if ( sys_videoRam.GetInteger() ) { run_once = sys_videoRam.GetInteger(); return sys_videoRam.GetInteger(); } // try a few strategies to guess the amount of video ram common->Printf( "guessing video ram ( use +set sys_videoRam to force ) ..\n" ); if ( !GLimp_OpenDisplay( ) ) { run_once = 64; return run_once; } l_dpy = dpy; l_scrnum = scrnum; // go for nvidia ext first if ( XNVCTRLQueryVersion( l_dpy, &major, &minor ) ) { common->Printf( "found XNVCtrl extension %d.%d\n", major, minor ); if ( XNVCTRLIsNvScreen( l_dpy, l_scrnum ) ) { if ( XNVCTRLQueryAttribute( l_dpy, l_scrnum, 0, NV_CTRL_VIDEO_RAM, &value ) ) { run_once = value / 1024; return run_once; } else { common->Printf( "XNVCtrlQueryAttribute NV_CTRL_VIDEO_RAM failed\n" ); } } else { common->Printf( "default screen %d is not controlled by NVIDIA driver\n", l_scrnum ); } } // try ATI /proc read ( for the lack of a better option ) int fd; if ( ( fd = open( "/proc/dri/0/umm", O_RDONLY ) ) != -1 ) { int len; char umm_buf[ 1024 ]; char *line; if ( ( len = read( fd, umm_buf, 1024 ) ) != -1 ) { // should be way enough to get the full file // grab "free LFB = " line and "free Inv = " lines umm_buf[ len-1 ] = '\0'; line = umm_buf; line = strtok( umm_buf, "\n" ); int total = 0; while ( line ) { if ( strlen( line ) >= 13 && strstr( line, "max LFB =" ) == line ) { total += atoi( line + 12 ); } else if ( strlen( line ) >= 13 && strstr( line, "max Inv =" ) == line ) { total += atoi( line + 12 ); } line = strtok( NULL, "\n" ); } if ( total ) { run_once = total / 1048576; // round to the lower 16Mb run_once &= ~15; return run_once; } } else { common->Printf( "read /proc/dri/0/umm failed: %s\n", strerror( errno ) ); } } common->Printf( "guess failed, return default low-end VRAM setting ( 64MB VRAM )\n" ); run_once = 64; return run_once; #endif }