summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2010-01-27 18:16:41 -0800
committerAaron Plattner <aplattner@nvidia.com>2010-01-28 09:49:15 -0800
commit3c02e5c68ef9480a0f9e5c3af5b09e6b3dcd981d (patch)
treee163c005591962d3cf6cc4324487fce20b82b783
parenta9c69d294ae41fffadb432caa66917a4e7d107a8 (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.ac17
-rw-r--r--src/Makefile.am15
-rw-r--r--src/mesa_dri2.c163
-rw-r--r--src/mesa_dri2.h50
-rw-r--r--src/vdpau_wrapper.c53
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();