diff --git a/src/setup.py b/src/setup.py index 8657516c0c..1b9013e151 100755 --- a/src/setup.py +++ b/src/setup.py @@ -154,6 +154,7 @@ def is_msvc(): WIN32_BUILD_LIB_PREFIX = os.environ.get("XPRA_WIN32_BUILD_LIB_PREFIX", "C:\\") nvenc4_sdk = WIN32_BUILD_LIB_PREFIX + "nvenc_4.0.0_sdk" nvenc5_sdk = WIN32_BUILD_LIB_PREFIX + "nvenc_5.0.1_sdk" + nvapi_path = WIN32_BUILD_LIB_PREFIX + "NVAPI" try: import pycuda except: @@ -880,6 +881,7 @@ def pkgconfig(*pkgs_options, **ekw): "xpra/codecs/csc_cython/colorspace_converter.c", "xpra/codecs/xor/cyxor.c", "xpra/codecs/argb/argb.c", + "xpra/codecs/nvapi_version.c", "xpra/server/stats/cystats.c", "xpra/server/region.c", "etc/xpra/xpra.conf", @@ -1500,6 +1502,17 @@ def add_keywords(path_dirs=[], inc_dirs=[], lib_dirs=[], libs=[], noref=True, no #assume 32-bit for now: #add_data_files('', ["C:\\Windows\System32\nvcuda.dll"]) #add_data_files('', ["%s/nvencodeapi.dll" % nvenc_bin_dir]) + elif "nvapi" in pkgs_options[0]: + nvapi_include_dir = nvapi_path + import struct + if struct.calcsize("P")==4: + nvapi_lib_names = ["nvapi"] + nvapi_lib_dir = os.path.join(nvapi_path, "x86") + else: + nvapi_lib_names = ["nvapi64"] + nvapi_lib_dir = os.path.join(nvapi_path, "amd64") + + add_keywords([], [nvapi_include_dir], [nvapi_lib_dir], nvapi_lib_names) elif "pygobject-2.0" in pkgs_options[0]: dirs = (python_include_path, pygtk_include_dir, atk_include_dir, gtk2_include_dir, @@ -1877,6 +1890,12 @@ def cython_add(*args, **kwargs): toggle_packages(nvenc4_ENABLED, "xpra.codecs.nvenc4") toggle_packages(nvenc5_ENABLED, "xpra.codecs.nvenc5") toggle_packages(nvenc4_ENABLED or nvenc5_ENABLED, "xpra.codecs.cuda_common", "xpra.codecs.nv_util") +if (nvenc4_ENABLED or nvenc5_ENABLED) and WIN32: + cython_add(Extension("xpra.codecs.nvapi_version", + ["xpra/codecs/nvapi_version.pyx"], + **pkgconfig("nvapi") + )) + if nvenc4_ENABLED or nvenc5_ENABLED: #find nvcc: nvcc = None diff --git a/src/xpra/codecs/nv_util.py b/src/xpra/codecs/nv_util.py index 3878077b2e..2e58005eba 100644 --- a/src/xpra/codecs/nv_util.py +++ b/src/xpra/codecs/nv_util.py @@ -7,25 +7,45 @@ import os from xpra.log import Logger log = Logger("encoder", "nvenc") +from xpra.util import pver def identify_nvidia_module_version(): if os.name!="posix": - return None - from xpra.os_util import load_binary_file - v = load_binary_file("/proc/driver/nvidia/version") - if not v: - log.warn("Nvidia kernel module not installed?") - return [] - KSTR = "Kernel Module" - p = v.find(KSTR) - if not p: - log.warn("unknown Nvidia kernel module version") - return [] - v = v[p+len(KSTR):].strip().split(" ")[0] + if not sys.platform.startswith("win"): + log.warn("Warning: unable to identify the NVidia driver version on this platform") + return None + #try the nvapi call: + try: + from xpra.codecs.nvapi_version import get_driver_version #@UnresolvedImport + v = get_driver_version() + log("NVAPI get_driver_version()=%s", v) + except Exception as e: + log.warn("failed to get the driver version through NVAPI:") + log.warn(" %s", e) + else: + from xpra.os_util import load_binary_file + v = load_binary_file("/proc/driver/nvidia/version") + if not v: + log.warn("Nvidia kernel module not installed?") + return [] + KSTR = "Kernel Module" + p = v.find(KSTR) + if not p: + log.warn("unknown Nvidia kernel module version") + return [] + v = v[p+len(KSTR):].strip().split(" ")[0] + v = v.split(".") + #only keep numeric values: + numver = [] try: - numver = [int(x) for x in v.split(".")] - log.info("Nvidia kernel module version %s", v) + for x in v: + try: + numver.append(int(x)) + except ValueError: + if len(numver)==0: + raise + log.info("Nvidia driver version %s", pver(numver)) return numver except Exception as e: log.warn("failed to parse Nvidia kernel module version '%s': %s", v, e) diff --git a/src/xpra/codecs/nvapi_version.pyx b/src/xpra/codecs/nvapi_version.pyx new file mode 100644 index 0000000000..f5d61fd51b --- /dev/null +++ b/src/xpra/codecs/nvapi_version.pyx @@ -0,0 +1,66 @@ +# This file is part of Xpra. +# Copyright (C) 2015 Antoine Martin +# Xpra is released under the terms of the GNU GPL v2, or, at your option, any +# later version. See the file COPYING for details. + +import sys +import os +from xpra.log import Logger +log = Logger("encoder", "nvenc") + +from libc.stdint cimport uint32_t + + +cdef extern from "nvapi.h": + #define NVAPI_SHORT_STRING_MAX 64 + int NVAPI_SHORT_STRING_MAX + ctypedef uint32_t NvU32 + ctypedef char[64] NvAPI_ShortString + ctypedef uint32_t NVAPI_INTERFACE + ctypedef uint32_t NvAPI_Status + + ctypedef struct NV_DISPLAY_DRIVER_VERSION: + NvU32 version # Structure version + NvU32 drvVersion + NvU32 bldChangeListNum + NvAPI_ShortString szBuildBranchString + NvAPI_ShortString szAdapterString + + NvAPI_Status NvAPI_Initialize() + NvAPI_Status NvAPI_Unload() + NvAPI_Status NvAPI_GetErrorMessage(NvAPI_Status nr,NvAPI_ShortString szDesc) + NvAPI_Status NvAPI_SYS_GetDriverAndBranchVersion(NvU32* pDriverVersion, NvAPI_ShortString szBuildBranchString) + +def raiseNVAPI(r, msg): + if r!=0: + raise Exception("error %s %s" % (r, msg)) + +def get_driver_version(): + cdef NvAPI_Status r + r = NvAPI_Initialize() + raiseNVAPI(r, "NvAPI_Initialize") + cdef NvU32 driverVersion + cdef NvAPI_ShortString buildBranch + try: + r = NvAPI_SYS_GetDriverAndBranchVersion(&driverVersion, buildBranch) + raiseNVAPI(r, "NvAPI_SYS_GetDriverAndBranchVersion") + log("DriverVersion: %s", driverVersion) + log("Build Branch: %s", buildBranch) + return [driverVersion//100, driverVersion%100, str(buildBranch)] + finally: + r = NvAPI_Unload() + raiseNVAPI(r, "NvAPI_Unload") + +def main(): + if "-v" in sys.argv or "--verbose" in sys.argv: + log.enable_debug() + + from xpra.platform import init, clean + try: + init("Nvidia-Info", "Nvidia Info") + log.info("%s", get_driver_version()) + finally: + clean() + +if __name__ == "__main__": + main()