The goal is to have a uniform interface to create winsys and pipe_screen instances for any driver, exposing the device enumeration capabilities that might be supported by the operating system (for now there's a "drm" back-end using udev and a "sw" back-end that always returns the same built-in devices).
The typical use case of this library will be: > > struct ws_loader_device devs[n]; > struct pipe_screen *screen; > > ws_loader_probe(&devs, n); >[pick some device from the array...] > > screen = ws_loader_create_screen(dev, library_search_path); >[do something with screen...] > > screen->destroy(screen); > ws_loader_release(&devs, N); > A part of the code was taken from targets/gbm/pipe_loader.c, which will be removed and replaced with calls into this library by a future commit. --- configure.ac | 7 + src/gallium/winsys/loader/Makefile.am | 34 +++++ src/gallium/winsys/loader/ws_loader.c | 102 +++++++++++++ src/gallium/winsys/loader/ws_loader.h | 136 +++++++++++++++++ src/gallium/winsys/loader/ws_loader_drm.c | 218 ++++++++++++++++++++++++++++ src/gallium/winsys/loader/ws_loader_priv.h | 47 ++++++ src/gallium/winsys/loader/ws_loader_sw.c | 107 ++++++++++++++ 7 files changed, 651 insertions(+) create mode 100644 src/gallium/winsys/loader/Makefile.am create mode 100644 src/gallium/winsys/loader/ws_loader.c create mode 100644 src/gallium/winsys/loader/ws_loader.h create mode 100644 src/gallium/winsys/loader/ws_loader_drm.c create mode 100644 src/gallium/winsys/loader/ws_loader_priv.h create mode 100644 src/gallium/winsys/loader/ws_loader_sw.c diff --git a/configure.ac b/configure.ac index bf5330d..a28052c 100644 --- a/configure.ac +++ b/configure.ac @@ -1936,6 +1936,10 @@ if test "x$NEED_G3DVL_DRI" = xyes; then GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS g3dvl/dri" fi +if test "x$enable_gallium_loader" = xyes; then + GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS loader/" +fi + dnl Tell Automake which drivers to build for driver in $GALLIUM_DRIVERS_DIRS; do case "x$driver" in @@ -1957,6 +1961,8 @@ done AM_CONDITIONAL(HAVE_GALAHAD_GALLIUM, test x$HAVE_GALAHAD_GALLIUM = xyes) AM_CONDITIONAL(HAVE_IDENTITY_GALLIUM, test x$HAVE_IDENTITY_GALLIUM = xyes) AM_CONDITIONAL(HAVE_NOOP_GALLIUM, test x$HAVE_NOOP_GALLIUM = xyes) +AM_CONDITIONAL(HAVE_DRM_LOADER_GALLIUM, test x$enable_gallium_drm_loader = xyes) +AM_CONDITIONAL(HAVE_XLIB_LOADER_GALLIUM, test x$HAVE_WINSYS_XLIB = xyes) AC_SUBST([GALLIUM_MAKE_DIRS]) dnl prepend CORE_DIRS to SRC_DIRS @@ -1974,6 +1980,7 @@ dnl Substitute the config AC_CONFIG_FILES([configs/autoconf src/gallium/winsys/sw/null/Makefile src/gallium/winsys/sw/xlib/Makefile + src/gallium/winsys/loader/Makefile src/gallium/drivers/Makefile src/gallium/drivers/r300/Makefile src/gbm/Makefile diff --git a/src/gallium/winsys/loader/Makefile.am b/src/gallium/winsys/loader/Makefile.am new file mode 100644 index 0000000..45e34da --- /dev/null +++ b/src/gallium/winsys/loader/Makefile.am @@ -0,0 +1,34 @@ +AUTOMAKE_OPTIONS = subdir-objects + +AM_CPPFLAGS = $(DEFINES) \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/gallium/include \ + -I$(top_srcdir)/src/gallium/auxiliary \ + -I$(top_srcdir)/src/gallium/winsys + +AM_CFLAGS = $(PIC_FLAGS) + +noinst_LTLIBRARIES = libws_loader.la + +libws_loader_la_SOURCES = \ + ws_loader.h \ + ws_loader_priv.h \ + ws_loader.c \ + ws_loader_sw.c + +libws_loader_la_LIBADD = \ + $(top_srcdir)/src/gallium/winsys/sw/null/libws_null.la + +if HAVE_XLIB_LOADER_GALLIUM +libws_loader_la_LIBADD += \ + $(top_srcdir)/src/gallium/winsys/sw/xlib/libws_xlib.la +AM_CFLAGS += -DHAVE_WS_LOADER_XLIB +endif + +if HAVE_DRM_LOADER_GALLIUM +libws_loader_la_SOURCES += ws_loader_drm.c +AM_CFLAGS += -DHAVE_WS_LOADER_DRM $(LIBDRM_CFLAGS) +endif + +# FIXME: Remove when the rest of Gallium is converted to automake. +default: all diff --git a/src/gallium/winsys/loader/ws_loader.c b/src/gallium/winsys/loader/ws_loader.c new file mode 100644 index 0000000..7071fc7 --- /dev/null +++ b/src/gallium/winsys/loader/ws_loader.c @@ -0,0 +1,102 @@ +/************************************************************************** + * + * Copyright 2012 Francisco Jerez + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "loader/ws_loader_priv.h" + +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_string.h" +#include "util/u_dl.h" + +#define MODULE_PREFIX "pipe_" + +static int (*backends[])(struct ws_loader_device **, int) = { +#ifdef HAVE_WS_LOADER_DRM + &ws_loader_drm_probe, +#endif + &ws_loader_sw_probe +}; + +int +ws_loader_probe(struct ws_loader_device **devs, int ndev) +{ + int i, n = 0; + + for (i = 0; i < Elements(backends); i++) + n += backends[i](&devs[n], MAX2(0, ndev - n)); + + return n; +} + +void +ws_loader_release(struct ws_loader_device **devs, int ndev) +{ + int i; + + for (i = 0; i < ndev; i++) + devs[i]->ops->release(&devs[i]); +} + +struct pipe_screen * +ws_loader_create_screen(struct ws_loader_device *dev, + const char *library_paths) +{ + return dev->ops->create_screen(dev, library_paths); +} + +struct util_dl_library * +ws_loader_find_module(struct ws_loader_device *dev, + const char *library_paths) +{ + struct util_dl_library *lib; + const char *next; + char path[PATH_MAX]; + int len, ret; + + for (next = library_paths; *next; library_paths = next + 1) { + next = util_strchrnul(library_paths, ':'); + len = next - library_paths; + + if (len) + ret = util_snprintf(path, sizeof(path), "%.*s/%s%s%s", + len, library_paths, + MODULE_PREFIX, dev->driver_name, UTIL_DL_EXT); + else + ret = util_snprintf(path, sizeof(path), "%s%s%s", + MODULE_PREFIX, dev->driver_name, UTIL_DL_EXT); + + if (ret > 0 && ret < sizeof(path)) { + lib = util_dl_open(path); + if (lib) { + debug_printf("loaded %s\n", path); + return lib; + } + } + } + + return NULL; +} diff --git a/src/gallium/winsys/loader/ws_loader.h b/src/gallium/winsys/loader/ws_loader.h new file mode 100644 index 0000000..2554da5 --- /dev/null +++ b/src/gallium/winsys/loader/ws_loader.h @@ -0,0 +1,136 @@ +/************************************************************************** + * + * Copyright 2012 Francisco Jerez + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * \file Winsys that provides device enumeration and multiplexing of + * other winsys. + */ + +#ifndef WS_LOADER_H +#define WS_LOADER_H + +#include "pipe/p_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct pipe_screen; + +enum ws_loader_device_type { + WS_LOADER_DEVICE_SOFTWARE, + WS_LOADER_DEVICE_PCI, + NUM_WS_LOADER_DEVICE_TYPES +}; + +/** + * A device known to the winsys loader. + */ +struct ws_loader_device { + enum ws_loader_device_type type; + + union { + struct { + int vendor_id; + int chip_id; + } pci; + }; /**< Discriminated by \a type */ + + const char *driver_name; + const struct ws_loader_ops *ops; +}; + +/** + * Get a list of known devices. + * + * \param devs Array that will be filled with pointers to the devices + * available in the system. + * \param ndev Maximum number of devices to return. + * \return Number of devices available in the system. + */ +int +ws_loader_probe(struct ws_loader_device **devs, int ndev); + +/** + * Create a pipe_screen for the specified device. + * + * \param dev Device the screen will be created for. + * \param library_paths Colon-separated list of filesystem paths that + * will be used to look for the pipe driver + * module that handles this device. + */ +struct pipe_screen * +ws_loader_create_screen(struct ws_loader_device *dev, + const char *library_paths); + +/** + * Release resources allocated for a list of devices. + * + * Should be called when the specified devices are no longer in use to + * release any resources allocated by ws_loader_probe. + * + * \param devs Devices to release. + * \param ndev Number of devices to release. + */ +void +ws_loader_release(struct ws_loader_device **devs, int ndev); + +/** + * Get a list of known software devices. + * + * This function is platform-specific. + * + * \sa ws_loader_probe + */ +int +ws_loader_sw_probe(struct ws_loader_device **devs, int ndev); + +/** + * Get a list of known DRM devices. + * + * This function is platform-specific. + * + * \sa ws_loader_probe + */ +int +ws_loader_drm_probe(struct ws_loader_device **devs, int ndev); + +/** + * Initialize a DRM device in an already opened fd. + * + * This function is platform-specific. + * + * \sa ws_loader_probe + */ +boolean +ws_loader_drm_probe_fd(struct ws_loader_device **dev, int fd); + +#ifdef __cplusplus +} +#endif + +#endif /* WS_LOADER_H */ diff --git a/src/gallium/winsys/loader/ws_loader_drm.c b/src/gallium/winsys/loader/ws_loader_drm.c new file mode 100644 index 0000000..817872b --- /dev/null +++ b/src/gallium/winsys/loader/ws_loader_drm.c @@ -0,0 +1,218 @@ +/************************************************************************** + * + * Copyright 2011 Intel Corporation + * Copyright 2012 Francisco Jerez + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kristian Høgsberg <k...@bitplanet.net> + * Benjamin Franzke <benjaminfran...@googlemail.com> + * + **************************************************************************/ + +#include <fcntl.h> +#include <stdio.h> +#include <libudev.h> +#include <xf86drm.h> + +#include "state_tracker/drm_driver.h" +#include "loader/ws_loader_priv.h" + +#include "util/u_memory.h" +#include "util/u_dl.h" +#include "util/u_debug.h" + +#define DRIVER_MAP_GALLIUM_ONLY +#include "pci_ids/pci_id_driver_map.h" + +struct ws_loader_drm_device { + struct ws_loader_device base; + struct util_dl_library *lib; + int fd; +}; + +#define ws_loader_drm_device(dev) ((struct ws_loader_drm_device *)dev) + +static boolean +find_drm_pci_id(struct ws_loader_drm_device *ddev) +{ + struct udev *udev = NULL; + struct udev_device *parent, *device = NULL; + struct stat stat; + const char *pci_id; + + if (fstat(ddev->fd, &stat) < 0) + goto fail; + + udev = udev_new(); + if (!udev) + goto fail; + + device = udev_device_new_from_devnum(udev, 'c', stat.st_rdev); + if (!device) + goto fail; + + parent = udev_device_get_parent(device); + if (!parent) + goto fail; + + pci_id = udev_device_get_property_value(parent, "PCI_ID"); + if (!pci_id || + sscanf(pci_id, "%x:%x", &ddev->base.pci.vendor_id, + &ddev->base.pci.chip_id) != 2) + goto fail; + + return TRUE; + + fail: + if (device) + udev_device_unref(device); + if (udev) + udev_unref(udev); + + debug_printf("pci id for fd %d not found\n", ddev->fd); + return FALSE; +} + +static boolean +find_drm_driver_name(struct ws_loader_drm_device *ddev) +{ + struct ws_loader_device *dev = &ddev->base; + int i, j; + + for (i = 0; driver_map[i].driver; i++) { + if (dev->pci.vendor_id != driver_map[i].vendor_id) + continue; + + if (driver_map[i].num_chips_ids == -1) { + dev->driver_name = driver_map[i].driver; + goto found; + } + + for (j = 0; j < driver_map[i].num_chips_ids; j++) { + if (dev->pci.chip_id == driver_map[i].chip_ids[j]) { + dev->driver_name = driver_map[i].driver; + goto found; + } + } + } + + return FALSE; + + found: + debug_printf("driver for %04x:%04x: %s\n", dev->pci.vendor_id, + dev->pci.chip_id, dev->driver_name); + return TRUE; +} + +static struct ws_loader_ops ws_loader_drm_ops; + +boolean +ws_loader_drm_probe_fd(struct ws_loader_device **dev, int fd) +{ + struct ws_loader_drm_device *ddev = CALLOC_STRUCT(ws_loader_drm_device); + + ddev->base.type = WS_LOADER_DEVICE_PCI; + ddev->base.ops = &ws_loader_drm_ops; + ddev->fd = fd; + + if (!find_drm_pci_id(ddev)) + goto fail; + + if (!find_drm_driver_name(ddev)) + goto fail; + + *dev = &ddev->base; + return TRUE; + + fail: + FREE(ddev); + return FALSE; +} + +static int +open_drm_minor(int minor) +{ + char path[PATH_MAX]; + snprintf(path, sizeof(path), DRM_DEV_NAME, DRM_DIR_NAME, minor); + return open(path, O_RDWR, 0); +} + +int +ws_loader_drm_probe(struct ws_loader_device **devs, int ndev) +{ + int i, j, fd; + + for (i = 0, j = 0; i < DRM_MAX_MINOR; i++) { + fd = open_drm_minor(i); + if (fd < 0) + continue; + + if (j >= ndev || !ws_loader_drm_probe_fd(&devs[j], fd)) + close(fd); + + j++; + } + + return j; +} + +static void +ws_loader_drm_release(struct ws_loader_device **dev) +{ + struct ws_loader_drm_device *ddev = ws_loader_drm_device(*dev); + + if (ddev->lib) + util_dl_close(ddev->lib); + + close(ddev->fd); + FREE(ddev); + *dev = NULL; +} + +static struct pipe_screen * +ws_loader_drm_create_screen(struct ws_loader_device *dev, + const char *library_paths) +{ + struct ws_loader_drm_device *ddev = ws_loader_drm_device(dev); + const struct drm_driver_descriptor *dd; + + if (!ddev->lib) + ddev->lib = ws_loader_find_module(dev, library_paths); + if (!ddev->lib) + return NULL; + + dd = (const struct drm_driver_descriptor *) + util_dl_get_proc_address(ddev->lib, "driver_descriptor"); + + /* sanity check on the name */ + if (!dd || strcmp(dd->name, ddev->base.driver_name) != 0) + return NULL; + + return dd->create_screen(ddev->fd); +} + +static struct ws_loader_ops ws_loader_drm_ops = { + .create_screen = ws_loader_drm_create_screen, + .release = ws_loader_drm_release +}; diff --git a/src/gallium/winsys/loader/ws_loader_priv.h b/src/gallium/winsys/loader/ws_loader_priv.h new file mode 100644 index 0000000..0de33d7 --- /dev/null +++ b/src/gallium/winsys/loader/ws_loader_priv.h @@ -0,0 +1,47 @@ +/************************************************************************** + * + * Copyright 2012 Francisco Jerez + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef WS_LOADER_PRIV_H +#define WS_LOADER_PRIV_H + +#include "ws_loader.h" + +struct ws_loader_ops { + struct pipe_screen *(*create_screen)(struct ws_loader_device *dev, + const char *library_paths); + + void (*release)(struct ws_loader_device **dev); +}; + +/** + * Open the pipe driver module that handles a specified device. + */ +struct util_dl_library * +ws_loader_find_module(struct ws_loader_device *dev, + const char *library_paths); + +#endif /* WS_LOADER_PRIV_H */ diff --git a/src/gallium/winsys/loader/ws_loader_sw.c b/src/gallium/winsys/loader/ws_loader_sw.c new file mode 100644 index 0000000..b3f925e --- /dev/null +++ b/src/gallium/winsys/loader/ws_loader_sw.c @@ -0,0 +1,107 @@ +/************************************************************************** + * + * Copyright 2012 Francisco Jerez + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "loader/ws_loader_priv.h" + +#include "util/u_memory.h" +#include "util/u_dl.h" +#include "sw/null/null_sw_winsys.h" +#include "target-helpers/inline_sw_helper.h" +#include "state_tracker/xlib_sw_winsys.h" + +struct ws_loader_sw_device { + struct ws_loader_device base; + struct util_dl_library *lib; + struct sw_winsys *ws; +}; + +#define ws_loader_sw_device(dev) ((struct ws_loader_sw_device *)dev) + +static struct ws_loader_ops ws_loader_sw_ops; + +static struct sw_winsys *(*backends[])() = { +#ifdef HAVE_WINSYS_XLIB + x11_sw_create, +#endif + null_sw_create +}; + +int +ws_loader_sw_probe(struct ws_loader_device **devs, int ndev) +{ + int i; + + for (i = 0; i < Elements(backends); i++) { + if (i < ndev) { + struct ws_loader_sw_device *sdev = CALLOC_STRUCT(ws_loader_sw_device); + + sdev->base.type = WS_LOADER_DEVICE_SOFTWARE; + sdev->base.driver_name = "swrast"; + sdev->base.ops = &ws_loader_sw_ops; + sdev->ws = backends[i](); + devs[i] = &sdev->base; + } + } + + return i; +} + +static void +ws_loader_sw_release(struct ws_loader_device **dev) +{ + struct ws_loader_sw_device *sdev = ws_loader_sw_device(*dev); + + if (sdev->lib) + util_dl_close(sdev->lib); + + FREE(sdev); + *dev = NULL; +} + +static struct pipe_screen * +ws_loader_sw_create_screen(struct ws_loader_device *dev, + const char *library_paths) +{ + struct ws_loader_sw_device *sdev = ws_loader_sw_device(dev); + struct pipe_screen *(*init)(struct sw_winsys *); + + if (!sdev->lib) + sdev->lib = ws_loader_find_module(dev, library_paths); + if (!sdev->lib) + return NULL; + + init = (void *)util_dl_get_proc_address(sdev->lib, "swrast_create_screen"); + if (!init) + return NULL; + + return init(sdev->ws); +} + +static struct ws_loader_ops ws_loader_sw_ops = { + .create_screen = ws_loader_sw_create_screen, + .release = ws_loader_sw_release +}; -- 1.7.9.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev