pipe_loader.c revision 361fc4cb
1/**************************************************************************
2 *
3 * Copyright 2012 Francisco Jerez
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include "pipe_loader_priv.h"
29
30#include "util/u_inlines.h"
31#include "util/u_memory.h"
32#include "util/u_string.h"
33#include "util/u_dl.h"
34#include "util/u_file.h"
35#include "util/xmlconfig.h"
36#include "util/xmlpool.h"
37
38#include <string.h>
39
40#ifdef _MSC_VER
41#include <stdlib.h>
42#define PATH_MAX _MAX_PATH
43#endif
44
45#define MODULE_PREFIX "pipe_"
46
47static int (*backends[])(struct pipe_loader_device **, int) = {
48#ifdef HAVE_LIBDRM
49   &pipe_loader_drm_probe,
50#endif
51   &pipe_loader_sw_probe
52};
53
54const char gallium_driinfo_xml[] =
55   DRI_CONF_BEGIN
56#include "driinfo_gallium.h"
57   DRI_CONF_END
58;
59
60int
61pipe_loader_probe(struct pipe_loader_device **devs, int ndev)
62{
63   int i, n = 0;
64
65   for (i = 0; i < ARRAY_SIZE(backends); i++)
66      n += backends[i](&devs[n], MAX2(0, ndev - n));
67
68   return n;
69}
70
71void
72pipe_loader_release(struct pipe_loader_device **devs, int ndev)
73{
74   int i;
75
76   for (i = 0; i < ndev; i++)
77      devs[i]->ops->release(&devs[i]);
78}
79
80void
81pipe_loader_base_release(struct pipe_loader_device **dev)
82{
83   driDestroyOptionCache(&(*dev)->option_cache);
84   driDestroyOptionInfo(&(*dev)->option_info);
85
86   FREE(*dev);
87   *dev = NULL;
88}
89
90void
91pipe_loader_load_options(struct pipe_loader_device *dev)
92{
93   if (dev->option_info.info)
94      return;
95
96   const char *xml_options = dev->ops->get_driconf_xml(dev);
97   if (!xml_options)
98      xml_options = gallium_driinfo_xml;
99
100   driParseOptionInfo(&dev->option_info, xml_options);
101   driParseConfigFiles(&dev->option_cache, &dev->option_info, 0,
102                       dev->driver_name, NULL);
103}
104
105char *
106pipe_loader_get_driinfo_xml(const char *driver_name)
107{
108#ifdef HAVE_LIBDRM
109   char *xml = pipe_loader_drm_get_driinfo_xml(driver_name);
110#else
111   char *xml = NULL;
112#endif
113
114   if (!xml)
115      xml = strdup(gallium_driinfo_xml);
116
117   return xml;
118}
119
120struct pipe_screen *
121pipe_loader_create_screen(struct pipe_loader_device *dev)
122{
123   struct pipe_screen_config config;
124
125   pipe_loader_load_options(dev);
126   config.options = &dev->option_cache;
127
128   return dev->ops->create_screen(dev, &config);
129}
130
131struct util_dl_library *
132pipe_loader_find_module(const char *driver_name,
133                        const char *library_paths)
134{
135   struct util_dl_library *lib;
136   const char *next;
137   char path[PATH_MAX];
138   int len, ret;
139
140   for (next = library_paths; *next; library_paths = next + 1) {
141      next = util_strchrnul(library_paths, ':');
142      len = next - library_paths;
143
144      if (len)
145         ret = util_snprintf(path, sizeof(path), "%.*s/%s%s%s",
146                             len, library_paths,
147                             MODULE_PREFIX, driver_name, UTIL_DL_EXT);
148      else
149         ret = util_snprintf(path, sizeof(path), "%s%s%s",
150                             MODULE_PREFIX, driver_name, UTIL_DL_EXT);
151
152      if (ret > 0 && ret < sizeof(path) && u_file_access(path, 0) != -1) {
153         lib = util_dl_open(path);
154         if (lib) {
155            return lib;
156         }
157         fprintf(stderr, "ERROR: Failed to load pipe driver at `%s': %s\n",
158                         path, util_dl_error());
159      }
160   }
161
162   return NULL;
163}
164