This lets the egl_dri2 driver initialize on just a DRM fd. --- configs/autoconf.in | 6 +- configure.ac | 15 ++- src/egl/drivers/dri2/Makefile | 6 +- src/egl/drivers/dri2/egl_dri2.c | 240 +++++++++++++++++++++++++++++++++------ 4 files changed, 227 insertions(+), 40 deletions(-)
diff --git a/configs/autoconf.in b/configs/autoconf.in index b7e8d8e..f21f0e1 100644 --- a/configs/autoconf.in +++ b/configs/autoconf.in @@ -179,8 +179,10 @@ EGL_PC_REQ_PRIV = @GL_PC_REQ_PRIV@ EGL_PC_LIB_PRIV = @GL_PC_LIB_PRIV@ EGL_PC_CFLAGS = @GL_PC_CFLAGS@ -EGL_DRI2_CFLAGS = @EGL_DRI2_CFLAGS@ -EGL_DRI2_LIBS = @EGL_DRI2_LIBS@ +XCB_DRI2_CFLAGS = @XCB_DRI2_CFLAGS@ +XCB_DRI2_LIBS = @XCB_DRI2_LIBS@ +LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@ +LIBUDEV_LIBS = @LIBUDEV_LIBS@ MESA_LLVM = @MESA_LLVM@ diff --git a/configure.ac b/configure.ac index c4a4f95..7e39c98 100644 --- a/configure.ac +++ b/configure.ac @@ -1008,11 +1008,22 @@ if test "x$enable_egl" = xyes; then fi # build egl_dri2 when xcb-dri2 is available - PKG_CHECK_MODULES([EGL_DRI2], [x11-xcb xcb-dri2 xcb-xfixes libdrm], + PKG_CHECK_MODULES([XCB_DRI2], [x11-xcb xcb-dri2 xcb-xfixes], [have_xcb_dri2=yes],[have_xcb_dri2=no]) + PKG_CHECK_MODULES([LIBUDEV], [libudev > 150], + [have_libudev=yes],[have_libudev=no]) + if test "$have_xcb_dri2" = yes; then - EGL_DRIVERS_DIRS="$EGL_DRIVERS_DIRS dri2" + EGL_DRIVER_DRI2=dri2 + DEFINES="$DEFINES -DHAVE_XCB_DRI2" + fi + + if test "$have_libudev" = yes; then + EGL_DRIVER_DRI2=dri2 + DEFINES="$DEFINES -DHAVE_LIBUDEV" fi + + EGL_DRIVERS_DIRS="$EGL_DRIVERS_DIRS $EGL_DRIVER_DRI2" fi if test "$with_demos" = yes; then diff --git a/src/egl/drivers/dri2/Makefile b/src/egl/drivers/dri2/Makefile index 4e760ae..8a3c9b6 100644 --- a/src/egl/drivers/dri2/Makefile +++ b/src/egl/drivers/dri2/Makefile @@ -11,8 +11,10 @@ EGL_INCLUDES = \ -I$(TOP)/src/egl/main \ -I$(TOP)/src/mapi \ -DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\" \ - $(EGL_DRI2_CFLAGS) + $(XCB_DRI2_CFLAGS) \ + $(LIBUDEV_CFLAGS) \ + $(LIBDRM_CFLAGS) -EGL_LIBS = $(EGL_DRI2_LIBS) +EGL_LIBS = $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(LIBDRM_LIBS) include ../Makefile.template diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 82aa8bf..f33fa5a 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -40,6 +40,12 @@ #include <xcb/dri2.h> #include <xcb/xfixes.h> #include <X11/Xlib-xcb.h> +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef HAVE_LIBUDEV +#include <libudev.h> +#endif #include <glapi/glapi.h> #include "eglconfig.h" @@ -627,6 +633,106 @@ dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy, return EGL_TRUE; } + +#ifdef HAVE_LIBUDEV + +struct dri2_driver_map { + int vendor_id; + const char *driver; + const int *chip_ids; + int num_chips_ids; +}; + +const int i915_chip_ids[] = { + 0x3577, /* PCI_CHIP_I830_M */ + 0x2562, /* PCI_CHIP_845_G */ + 0x3582, /* PCI_CHIP_I855_GM */ + 0x2572, /* PCI_CHIP_I865_G */ + 0x2582, /* PCI_CHIP_I915_G */ + 0x258a, /* PCI_CHIP_E7221_G */ + 0x2592, /* PCI_CHIP_I915_GM */ + 0x2772, /* PCI_CHIP_I945_G */ + 0x27a2, /* PCI_CHIP_I945_GM */ + 0x27ae, /* PCI_CHIP_I945_GME */ + 0x29b2, /* PCI_CHIP_Q35_G */ + 0x29c2, /* PCI_CHIP_G33_G */ + 0x29d2, /* PCI_CHIP_Q33_G */ +}; + +const int i965_chip_ids[] = { + 0x29a2, /* PCI_CHIP_I965_G */ + 0x2992, /* PCI_CHIP_I965_Q */ + 0x2982, /* PCI_CHIP_I965_G_1 */ + 0x2972, /* PCI_CHIP_I946_GZ */ + 0x2a02, /* PCI_CHIP_I965_GM */ + 0x2a12, /* PCI_CHIP_I965_GME */ + 0x2a42, /* PCI_CHIP_GM45_GM */ + 0x2e02, /* PCI_CHIP_IGD_E_G */ + 0x2e12, /* PCI_CHIP_Q45_G */ + 0x2e22, /* PCI_CHIP_G45_G */ + 0x2e32, /* PCI_CHIP_G41_G */ +}; + +const struct dri2_driver_map driver_map[] = { + { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) }, + { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) }, +}; + +static char * +dri2_get_driver_for_fd(int fd) +{ + struct udev *udev; + struct udev_device *device, *parent; + struct stat buf; + const char *pci_id; + char *driver = NULL; + int vendor_id, chip_id, i, j; + + udev = udev_new(); + if (fstat(fd, &buf) < 0) { + _eglLog(_EGL_WARNING, "DRI2: failed to stat fd %d", fd); + goto out; + } + + device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev); + if (device == NULL) { + _eglLog(_EGL_WARNING, + "DRI2: could not create udev device for fd %d", fd); + goto out; + } + + parent = udev_device_get_parent(device); + if (parent == NULL) { + _eglLog(_EGL_WARNING, "DRI2: could not get parent device"); + goto out; + } + + pci_id = udev_device_get_property_value(parent, "PCI_ID"); + if (pci_id == NULL || sscanf(pci_id, "%x:%x", &vendor_id, &chip_id) != 2) { + _eglLog(_EGL_WARNING, "DRI2: malformed or no PCI ID"); + goto out; + } + + for (i = 0; i < ARRAY_SIZE(driver_map); i++) { + if (vendor_id != driver_map[i].vendor_id) + continue; + for (j = 0; j < driver_map[i].num_chips_ids; j++) + if (driver_map[i].chip_ids[j] == chip_id) { + driver = strdup(driver_map[i].driver); + _eglLog(_EGL_DEBUG, "pci id for %d: %04x:%04x, driver %s", + fd, vendor_id, chip_id, driver); + goto out; + } + } + + out: + udev_device_unref(device); + udev_unref(udev); + + return driver; +} + +#endif static EGLBoolean dri2_load_driver(_EGLDisplay *disp) @@ -690,15 +796,52 @@ dri2_load_driver(_EGLDisplay *disp) return EGL_TRUE; } - static EGLBoolean -dri2_initialize_xcb(_EGLDisplay *disp) +dri2_create_screen(_EGLDisplay *disp) { const __DRIextension **extensions; struct dri2_egl_display *dri2_dpy; unsigned int api_mask; dri2_dpy = disp->DriverData; + dri2_dpy->dri_screen = + dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions, + &dri2_dpy->driver_configs, dri2_dpy); + + if (dri2_dpy->dri_screen == NULL) + return _eglError(EGL_BAD_ALLOC, "DRI2: failed to create dri screen"); + + extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); + if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) + goto cleanup_dri_screen; + + if (dri2_dpy->dri2->base.version >= 2) + api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); + else + api_mask = __DRI_API_OPENGL; + + disp->ClientAPIsMask = 0; + if (api_mask & (1 <<__DRI_API_OPENGL)) + disp->ClientAPIsMask |= EGL_OPENGL_BIT; + if (api_mask & (1 <<__DRI_API_GLES)) + disp->ClientAPIsMask |= EGL_OPENGL_ES_BIT; + if (api_mask & (1 << __DRI_API_GLES2)) + disp->ClientAPIsMask |= EGL_OPENGL_ES2_BIT; + + return EGL_TRUE; + + cleanup_dri_screen: + dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); + + return EGL_FALSE; +} + +static EGLBoolean +dri2_initialize_xcb(_EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy; + + dri2_dpy = disp->DriverData; if (disp->NativeDisplay == NULL) { dri2_dpy->conn = xcb_connect(0, 0); } else { @@ -750,36 +893,11 @@ dri2_initialize_xcb(_EGLDisplay *disp) dri2_dpy->extensions[1] = &dri2_dpy->image_lookup_extension.base; dri2_dpy->extensions[2] = NULL; - dri2_dpy->dri_screen = - dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions, - &dri2_dpy->driver_configs, dri2_dpy); - - if (dri2_dpy->dri_screen == NULL) { - _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen"); + if (!dri2_create_screen(disp)) goto cleanup_fd; - } - extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); - if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) - goto cleanup_dri_screen; - - if (dri2_dpy->dri2->base.version >= 2) - api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); - else - api_mask = __DRI_API_OPENGL; - - disp->ClientAPIsMask = 0; - if (api_mask & (1 <<__DRI_API_OPENGL)) - disp->ClientAPIsMask |= EGL_OPENGL_BIT; - if (api_mask & (1 <<__DRI_API_GLES)) - disp->ClientAPIsMask |= EGL_OPENGL_ES_BIT; - if (api_mask & (1 << __DRI_API_GLES2)) - disp->ClientAPIsMask |= EGL_OPENGL_ES2_BIT; - - if (dri2_dpy->conn) { - if (!dri2_add_configs_for_visuals(dri2_dpy, disp)) - goto cleanup_configs; - } + if (!dri2_add_configs_for_visuals(dri2_dpy, disp)) + goto cleanup_configs; disp->Extensions.KHR_image_base = EGL_TRUE; disp->Extensions.KHR_image_pixmap = EGL_TRUE; @@ -792,7 +910,6 @@ dri2_initialize_xcb(_EGLDisplay *disp) cleanup_configs: _eglCleanupDisplay(disp); - cleanup_dri_screen: dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); cleanup_fd: close(dri2_dpy->fd); @@ -807,6 +924,47 @@ dri2_initialize_xcb(_EGLDisplay *disp) return EGL_FALSE; } +static EGLBoolean +dri2_initialize_drm(_EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy; + + dri2_dpy = disp->DriverData; + dri2_dpy->fd = (int) disp->VoidDisplay; + + dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd); + if (dri2_dpy->driver_name == NULL) + return _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name"); + + if (!dri2_load_driver(disp)) + goto cleanup_driver_name; + + dri2_dpy->image_lookup_extension.base.name = __DRI_IMAGE_LOOKUP; + dri2_dpy->image_lookup_extension.base.version = 1; + dri2_dpy->image_lookup_extension.lookupEGLImage = dri2_lookup_egl_image; + + dri2_dpy->extensions[0] = &dri2_dpy->image_lookup_extension.base; + dri2_dpy->extensions[1] = NULL; + + if (!dri2_create_screen(disp)) + goto cleanup_driver; + + /* FIXME: Visuals */ + + disp->Extensions.KHR_image_base = EGL_TRUE; + disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; + disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; + + return EGL_TRUE; + + cleanup_driver: + dlclose(dri2_dpy->driver); + cleanup_driver_name: + free(dri2_dpy->driver_name); + + return EGL_FALSE; +} + /** * Called via eglInitialize(), GLX_drv->API.Initialize(). */ @@ -827,6 +985,13 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, goto cleanup_dpy; break; +#ifdef HAVE_LIBUDEV + case EGL_DRM_DISPLAY_TYPE_MESA: + if (!dri2_initialize_drm(disp)) + goto cleanup_dpy; + break; +#endif + default: _eglLog(_EGL_WARNING, "DRI2: unknown display type: %d", disp->DisplayType); @@ -857,10 +1022,17 @@ dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) _eglCleanupDisplay(disp); dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); - close(dri2_dpy->fd); + + switch (disp->DisplayType) { + case EGL_X11_DISPLAY_TYPE_MESA: + close(dri2_dpy->fd); + if (disp->NativeDisplay == NULL) + xcb_disconnect(dri2_dpy->conn); + break; + } + + free(dri2_dpy->driver_name); dlclose(dri2_dpy->driver); - if (disp->NativeDisplay == NULL) - xcb_disconnect(dri2_dpy->conn); free(dri2_dpy); disp->DriverData = NULL; -- 1.7.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev