+#endif
+
+static bool
+pipe_loader_sw_probe_init_common(struct pipe_loader_sw_device *sdev)
+{
+ sdev->base.type = PIPE_LOADER_DEVICE_SOFTWARE;
+ sdev->base.driver_name = "swrast";
+ sdev->base.ops = &pipe_loader_sw_ops;
+ sdev->fd = -1;
+
+#ifdef GALLIUM_STATIC_TARGETS
+ sdev->dd = &driver_descriptors;
+ if (!sdev->dd)
+ return false;
+#else
+ sdev->lib = pipe_loader_find_module("swrast", PIPE_SEARCH_DIR);
+ if (!sdev->lib)
+ return false;
+
+ sdev->dd = (const struct sw_driver_descriptor *)
+ util_dl_get_proc_address(sdev->lib, "swrast_driver_descriptor");
+
+ if (!sdev->dd){
+ util_dl_close(sdev->lib);
+ sdev->lib = NULL;
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+static void
+pipe_loader_sw_probe_teardown_common(struct pipe_loader_sw_device *sdev)
+{
+#ifndef GALLIUM_STATIC_TARGETS
+ if (sdev->lib)
+ util_dl_close(sdev->lib);
+#endif
+}
+
+#ifdef HAVE_PIPE_LOADER_DRI
+bool
+pipe_loader_sw_probe_dri(struct pipe_loader_device **devs, struct drisw_loader_funcs *drisw_lf)
+{
+ struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
+ int i;
+
+ if (!sdev)
+ return false;
+
+ if (!pipe_loader_sw_probe_init_common(sdev))
+ goto fail;
+
+ for (i = 0; sdev->dd->winsys[i].name; i++) {
+ if (strcmp(sdev->dd->winsys[i].name, "dri") == 0) {
+ sdev->ws = sdev->dd->winsys[i].create_winsys(drisw_lf);
+ break;
+ }
+ }
+ if (!sdev->ws)
+ goto fail;
+
+ *devs = &sdev->base;
+ return true;
+
+fail:
+ pipe_loader_sw_probe_teardown_common(sdev);
+ FREE(sdev);
+ return false;
+}
+#endif
+
+#ifdef HAVE_PIPE_LOADER_KMS
+bool
+pipe_loader_sw_probe_kms(struct pipe_loader_device **devs, int fd)
+{
+ struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
+ int i;
+
+ if (!sdev)
+ return false;
+
+ if (!pipe_loader_sw_probe_init_common(sdev))
+ goto fail;
+
+ sdev->fd = fd;
+
+ for (i = 0; sdev->dd->winsys[i].name; i++) {
+ if (strcmp(sdev->dd->winsys[i].name, "kms_dri") == 0) {
+ sdev->ws = sdev->dd->winsys[i].create_winsys(fd);
+ break;
+ }
+ }
+ if (!sdev->ws)
+ goto fail;
+
+ *devs = &sdev->base;
+ return true;
+
+fail:
+ pipe_loader_sw_probe_teardown_common(sdev);
+ FREE(sdev);
+ return false;
+}
+#endif
+
+bool
+pipe_loader_sw_probe_null(struct pipe_loader_device **devs)
+{
+ struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
+ int i;
+
+ if (!sdev)
+ return false;
+
+ if (!pipe_loader_sw_probe_init_common(sdev))
+ goto fail;
+
+ for (i = 0; sdev->dd->winsys[i].name; i++) {
+ if (strcmp(sdev->dd->winsys[i].name, "null") == 0) {
+ sdev->ws = sdev->dd->winsys[i].create_winsys();
+ break;
+ }
+ }
+ if (!sdev->ws)
+ goto fail;
+
+ *devs = &sdev->base;
+ return true;
+
+fail:
+ pipe_loader_sw_probe_teardown_common(sdev);
+ FREE(sdev);
+ return false;
+}