diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2010-01-27 18:16:41 -0800 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2010-01-28 09:49:15 -0800 |
commit | 3c02e5c68ef9480a0f9e5c3af5b09e6b3dcd981d (patch) | |
tree | e163c005591962d3cf6cc4324487fce20b82b783 | |
parent | a9c69d294ae41fffadb432caa66917a4e7d107a8 (diff) |
Query DRI2 for the driver name.
If the VDPAU_DRIVER environment variable is not set, use DRI2Connect to query
the VDPAU driver name from the X server.
Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
Reviewed-by: Stephen Warren <swarren@nvidia.com>
-rw-r--r-- | configure.ac | 17 | ||||
-rw-r--r-- | src/Makefile.am | 15 | ||||
-rw-r--r-- | src/mesa_dri2.c | 163 | ||||
-rw-r--r-- | src/mesa_dri2.h | 50 | ||||
-rw-r--r-- | src/vdpau_wrapper.c | 53 |
5 files changed, 294 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac index 00e8ac1..24e958d 100644 --- a/configure.ac +++ b/configure.ac @@ -20,6 +20,23 @@ PKG_CHECK_MODULES(X11, x11) AC_SUBST(X11_CFLAGS) AC_SUBST(X11_LIBS) +# Check for optional dependencies. +AC_ARG_ENABLE(dri2, AS_HELP_STRING([--disable-dri2], [Disable driver name query through DRI2 (default: auto)]), [DRI2=$enableval], [DRI2=auto]) +PKG_CHECK_MODULES(dri2proto, dri2proto >= 2.2, [HAVE_DRI2PROTO=yes], [HAVE_DRI2PROTO=no]) +case "$DRI2,$HAVE_DRI2PROTO" in + yes,no) + AC_MSG_ERROR([DRI2 queries require dri2proto >= 2.2]) + ;; + yes,yes | auto,yes) + AC_DEFINE(DRI2, 1, [Request driver name from DRI2]) + DRI2=yes + PKG_CHECK_MODULES(XEXT, xext) + AC_SUBST([XEXT_CFLAGS]) + AC_SUBST([XEXT_LIBS]) + ;; +esac +AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes) + dnl Check to see if dlopen is in default libraries (like Solaris, which dnl has it in libc), or if libdl is needed to get it. AC_CHECK_FUNC([dlopen], [], diff --git a/src/Makefile.am b/src/Makefile.am index 923eaac..48e69a7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,15 +1,24 @@ AM_CFLAGS = \ -I$(top_srcdir)/include \ -DVDPAU_MODULEDIR="\"$(moduledir)\"" \ - $(X11_CFLAGS) + $(X11_CFLAGS) \ + $(XEXT_CFLAGS) lib_LTLIBRARIES = libvdpau.la libvdpau_la_SOURCES = \ - vdpau_wrapper.c + vdpau_wrapper.c \ + $(DRI2_SOURCES) + +if DRI2 + DRI2_SOURCES = \ + mesa_dri2.c \ + mesa_dri2.h +endif libvdpau_la_LIBADD = \ - $(DLOPEN_LIBS) + $(DLOPEN_LIBS) \ + $(XEXT_LIBS) libvdpau_la_LDFLAGS = -version-info 1:0:0 -no-undefined diff --git a/src/mesa_dri2.c b/src/mesa_dri2.c new file mode 100644 index 0000000..dbf9aa8 --- /dev/null +++ b/src/mesa_dri2.c @@ -0,0 +1,163 @@ +/* + * Copyright © 2008 Red Hat, Inc. + * Copyright © 2010 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Soft- + * ware"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, provided that the above copyright + * notice(s) and this permission notice appear in all copies of the Soft- + * ware and that both the above copyright notice(s) and this permission + * notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- + * MANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization of + * the copyright holder. + * + * Authors: + * Kristian Høgsberg (krh@redhat.com) + * Modified for VDPAU by Aaron Plattner (aplattner@nvidia.com) + */ + + +#define NEED_REPLIES +#include <X11/Xlibint.h> +#include <X11/extensions/Xext.h> +#include <X11/extensions/extutil.h> +#include <X11/extensions/dri2proto.h> +#include "mesa_dri2.h" + +static char dri2ExtensionName[] = DRI2_NAME; +static XExtensionInfo *dri2Info; +static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info) + +static /* const */ XExtensionHooks dri2ExtensionHooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + DRI2CloseDisplay, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, + dri2Info, + dri2ExtensionName, + &dri2ExtensionHooks, + 0, NULL) + +Bool +_vdp_DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + + if (XextHasExtension(info)) { + *eventBase = info->codes->first_event; + *errorBase = info->codes->first_error; + return True; + } + + return False; +} + +Bool +_vdp_DRI2QueryVersion(Display * dpy, int *major, int *minor) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2QueryVersionReply rep; + xDRI2QueryVersionReq *req; + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2QueryVersion, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2QueryVersion; + req->majorVersion = DRI2_MAJOR; + req->minorVersion = DRI2_MINOR; + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *major = rep.majorVersion; + *minor = rep.minorVersion; + UnlockDisplay(dpy); + SyncHandle(); + + return True; +} + +Bool +_vdp_DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2ConnectReply rep; + xDRI2ConnectReq *req; + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2Connect, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2Connect; + req->window = window; + req->driverType = DRI2DriverVDPAU; + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *driverName = Xmalloc(rep.driverNameLength + 1); + if (*driverName == NULL) { + _XEatData(dpy, + ((rep.driverNameLength + 3) & ~3) + + ((rep.deviceNameLength + 3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + _XReadPad(dpy, *driverName, rep.driverNameLength); + (*driverName)[rep.driverNameLength] = '\0'; + + *deviceName = Xmalloc(rep.deviceNameLength + 1); + if (*deviceName == NULL) { + Xfree(*driverName); + _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + _XReadPad(dpy, *deviceName, rep.deviceNameLength); + (*deviceName)[rep.deviceNameLength] = '\0'; + + UnlockDisplay(dpy); + SyncHandle(); + + return True; +} diff --git a/src/mesa_dri2.h b/src/mesa_dri2.h new file mode 100644 index 0000000..5c5fb12 --- /dev/null +++ b/src/mesa_dri2.h @@ -0,0 +1,50 @@ +/* + * Copyright © 2007,2008 Red Hat, Inc. + * Copyright © 2010 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Soft- + * ware"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, provided that the above copyright + * notice(s) and this permission notice appear in all copies of the Soft- + * ware and that both the above copyright notice(s) and this permission + * notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- + * MANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization of + * the copyright holder. + * + * Authors: + * Kristian Høgsberg (krh@redhat.com) + * Modified for VDPAU by Aaron Plattner (aplattner@nvidia.com) + */ + +#ifndef _VDP_DRI2_H_ +#define _VDP_DRI2_H_ + +#include <X11/extensions/dri2tokens.h> + +extern Bool +_vdp_DRI2QueryExtension(Display * display, int *eventBase, int *errorBase); + +extern Bool +_vdp_DRI2QueryVersion(Display * display, int *major, int *minor); + +extern Bool +_vdp_DRI2Connect(Display * display, XID window, char **driverName, + char **deviceName); + +#endif diff --git a/src/vdpau_wrapper.c b/src/vdpau_wrapper.c index a635f6c..f504775 100644 --- a/src/vdpau_wrapper.c +++ b/src/vdpau_wrapper.c @@ -21,12 +21,20 @@ * SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <dlfcn.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <vdpau/vdpau_x11.h> +#if DRI2 +#include "mesa_dri2.h" +#include <X11/Xlib.h> +#endif typedef void SetDllHandle( void * driver_dll_handle @@ -49,6 +57,36 @@ static void _vdp_wrapper_error_breakpoint(char const * file, int line, char cons #define DRIVER_LIB_FORMAT "%slibvdpau_%s.so%s" +static char * _vdp_get_driver_name_from_dri2( + Display * display, + int screen +) +{ + char * driver_name = NULL; +#if DRI2 + Window root = RootWindow(display, screen); + int event_base, error_base; + int major, minor; + char * device_name; + + if (!_vdp_DRI2QueryExtension(display, &event_base, &error_base)) { + return NULL; + } + + if (!_vdp_DRI2QueryVersion(display, &major, &minor) || + (major < 1 || (major == 1 && minor < 2))) { + return NULL; + } + + if (!_vdp_DRI2Connect(display, root, &driver_name, &device_name)) { + return NULL; + } + + XFree(device_name); +#endif /* DRI2 */ + return driver_name; +} + VdpStatus vdp_device_create_x11( Display * display, int screen, @@ -58,6 +96,7 @@ VdpStatus vdp_device_create_x11( ) { char const * vdpau_driver; + char * vdpau_driver_dri2 = NULL; char vdpau_driver_lib[PATH_MAX]; void * backend_dll; char const * vdpau_trace; @@ -65,9 +104,12 @@ VdpStatus vdp_device_create_x11( VdpDeviceCreateX11 * vdp_imp_device_create_x11; - /* FIXME: Determine driver name using an X extension */ vdpau_driver = getenv("VDPAU_DRIVER"); if (!vdpau_driver) { + vdpau_driver = vdpau_driver_dri2 = + _vdp_get_driver_name_from_dri2(display, screen); + } + if (!vdpau_driver) { vdpau_driver = "nvidia"; } @@ -75,6 +117,10 @@ VdpStatus vdp_device_create_x11( VDPAU_MODULEDIR "/", vdpau_driver, ".1") >= sizeof(vdpau_driver_lib)) { fprintf(stderr, "Failed to construct driver path: path too long\n"); + if (vdpau_driver_dri2) { + XFree(vdpau_driver_dri2); + vdpau_driver_dri2 = NULL; + } _VDP_ERROR_BREAKPOINT(); return VDP_STATUS_NO_IMPLEMENTATION; } @@ -88,6 +134,11 @@ VdpStatus vdp_device_create_x11( backend_dll = dlopen(vdpau_driver_lib, RTLD_NOW | RTLD_GLOBAL); } + if (vdpau_driver_dri2) { + XFree(vdpau_driver_dri2); + vdpau_driver_dri2 = NULL; + } + if (!backend_dll) { fprintf(stderr, "Failed to open VDPAU backend %s\n", dlerror()); _VDP_ERROR_BREAKPOINT(); |