74329e4cba9ac6f5699553480db5cced7f7a00b3
[mesa.git] / src / gallium / auxiliary / pipe-loader / pipe_loader_sw.c
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 #ifdef HAVE_PIPE_LOADER_KMS
29 #include <fcntl.h>
30 #endif
31
32 #include "pipe_loader_priv.h"
33
34 #include "util/u_memory.h"
35 #include "util/u_dl.h"
36 #include "sw/dri/dri_sw_winsys.h"
37 #include "sw/kms-dri/kms_dri_sw_winsys.h"
38 #include "sw/null/null_sw_winsys.h"
39 #include "sw/wrapper/wrapper_sw_winsys.h"
40 #include "target-helpers/sw_helper_public.h"
41 #include "frontend/drisw_api.h"
42 #include "frontend/sw_driver.h"
43 #include "frontend/sw_winsys.h"
44
45 struct pipe_loader_sw_device {
46 struct pipe_loader_device base;
47 const struct sw_driver_descriptor *dd;
48 #ifndef GALLIUM_STATIC_TARGETS
49 struct util_dl_library *lib;
50 #endif
51 struct sw_winsys *ws;
52 int fd;
53 };
54
55 #define pipe_loader_sw_device(dev) ((struct pipe_loader_sw_device *)dev)
56
57 static const struct pipe_loader_ops pipe_loader_sw_ops;
58
59 #ifdef GALLIUM_STATIC_TARGETS
60 static const struct sw_driver_descriptor driver_descriptors = {
61 .create_screen = sw_screen_create,
62 .winsys = {
63 #ifdef HAVE_PIPE_LOADER_DRI
64 {
65 .name = "dri",
66 .create_winsys = dri_create_sw_winsys,
67 },
68 #endif
69 #ifdef HAVE_PIPE_LOADER_KMS
70 {
71 .name = "kms_dri",
72 .create_winsys = kms_dri_create_winsys,
73 },
74 #endif
75 /**
76 * XXX: Do not include these two for non autotools builds.
77 * They don't have neither opencl nor nine, where these are used.
78 */
79 #ifndef DROP_PIPE_LOADER_MISC
80 {
81 .name = "null",
82 .create_winsys = null_sw_create,
83 },
84 {
85 .name = "wrapped",
86 .create_winsys = wrapper_sw_winsys_wrap_pipe_screen,
87 },
88 #endif
89 { 0 },
90 }
91 };
92 #endif
93
94 static bool
95 pipe_loader_sw_probe_init_common(struct pipe_loader_sw_device *sdev)
96 {
97 sdev->base.type = PIPE_LOADER_DEVICE_SOFTWARE;
98 sdev->base.driver_name = "swrast";
99 sdev->base.ops = &pipe_loader_sw_ops;
100 sdev->fd = -1;
101
102 #ifdef GALLIUM_STATIC_TARGETS
103 sdev->dd = &driver_descriptors;
104 if (!sdev->dd)
105 return false;
106 #else
107 sdev->lib = pipe_loader_find_module("swrast", PIPE_SEARCH_DIR);
108 if (!sdev->lib)
109 return false;
110
111 sdev->dd = (const struct sw_driver_descriptor *)
112 util_dl_get_proc_address(sdev->lib, "swrast_driver_descriptor");
113
114 if (!sdev->dd){
115 util_dl_close(sdev->lib);
116 sdev->lib = NULL;
117 return false;
118 }
119 #endif
120
121 return true;
122 }
123
124 static void
125 pipe_loader_sw_probe_teardown_common(struct pipe_loader_sw_device *sdev)
126 {
127 #ifndef GALLIUM_STATIC_TARGETS
128 if (sdev->lib)
129 util_dl_close(sdev->lib);
130 #endif
131 }
132
133 #ifdef HAVE_PIPE_LOADER_DRI
134 bool
135 pipe_loader_sw_probe_dri(struct pipe_loader_device **devs, const struct drisw_loader_funcs *drisw_lf)
136 {
137 struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
138 int i;
139
140 if (!sdev)
141 return false;
142
143 if (!pipe_loader_sw_probe_init_common(sdev))
144 goto fail;
145
146 for (i = 0; sdev->dd->winsys[i].name; i++) {
147 if (strcmp(sdev->dd->winsys[i].name, "dri") == 0) {
148 sdev->ws = sdev->dd->winsys[i].create_winsys(drisw_lf);
149 break;
150 }
151 }
152 if (!sdev->ws)
153 goto fail;
154
155 *devs = &sdev->base;
156 return true;
157
158 fail:
159 pipe_loader_sw_probe_teardown_common(sdev);
160 FREE(sdev);
161 return false;
162 }
163 #endif
164
165 #ifdef HAVE_PIPE_LOADER_KMS
166 bool
167 pipe_loader_sw_probe_kms(struct pipe_loader_device **devs, int fd)
168 {
169 struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
170 int i;
171
172 if (!sdev)
173 return false;
174
175 if (!pipe_loader_sw_probe_init_common(sdev))
176 goto fail;
177
178 if (fd < 0 || (sdev->fd = fcntl(fd, F_DUPFD_CLOEXEC, 3)) < 0)
179 goto fail;
180
181 for (i = 0; sdev->dd->winsys[i].name; i++) {
182 if (strcmp(sdev->dd->winsys[i].name, "kms_dri") == 0) {
183 sdev->ws = sdev->dd->winsys[i].create_winsys(sdev->fd);
184 break;
185 }
186 }
187 if (!sdev->ws)
188 goto fail;
189
190 *devs = &sdev->base;
191 return true;
192
193 fail:
194 pipe_loader_sw_probe_teardown_common(sdev);
195 if (sdev->fd != -1)
196 close(sdev->fd);
197 FREE(sdev);
198 return false;
199 }
200 #endif
201
202 bool
203 pipe_loader_sw_probe_null(struct pipe_loader_device **devs)
204 {
205 struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
206 int i;
207
208 if (!sdev)
209 return false;
210
211 if (!pipe_loader_sw_probe_init_common(sdev))
212 goto fail;
213
214 for (i = 0; sdev->dd->winsys[i].name; i++) {
215 if (strcmp(sdev->dd->winsys[i].name, "null") == 0) {
216 sdev->ws = sdev->dd->winsys[i].create_winsys();
217 break;
218 }
219 }
220 if (!sdev->ws)
221 goto fail;
222
223 *devs = &sdev->base;
224 return true;
225
226 fail:
227 pipe_loader_sw_probe_teardown_common(sdev);
228 FREE(sdev);
229 return false;
230 }
231
232 int
233 pipe_loader_sw_probe(struct pipe_loader_device **devs, int ndev)
234 {
235 int i = 1;
236
237 if (i <= ndev) {
238 if (!pipe_loader_sw_probe_null(devs)) {
239 i--;
240 }
241 }
242
243 return i;
244 }
245
246 boolean
247 pipe_loader_sw_probe_wrapped(struct pipe_loader_device **dev,
248 struct pipe_screen *screen)
249 {
250 struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
251 int i;
252
253 if (!sdev)
254 return false;
255
256 if (!pipe_loader_sw_probe_init_common(sdev))
257 goto fail;
258
259 for (i = 0; sdev->dd->winsys[i].name; i++) {
260 if (strcmp(sdev->dd->winsys[i].name, "wrapped") == 0) {
261 sdev->ws = sdev->dd->winsys[i].create_winsys(screen);
262 break;
263 }
264 }
265 if (!sdev->ws)
266 goto fail;
267
268 *dev = &sdev->base;
269 return true;
270
271 fail:
272 pipe_loader_sw_probe_teardown_common(sdev);
273 FREE(sdev);
274 return false;
275 }
276
277 static void
278 pipe_loader_sw_release(struct pipe_loader_device **dev)
279 {
280 UNUSED struct pipe_loader_sw_device *sdev =
281 pipe_loader_sw_device(*dev);
282
283 #ifndef GALLIUM_STATIC_TARGETS
284 if (sdev->lib)
285 util_dl_close(sdev->lib);
286 #endif
287
288 #ifdef HAVE_PIPE_LOADER_KMS
289 if (sdev->fd != -1)
290 close(sdev->fd);
291 #endif
292
293 pipe_loader_base_release(dev);
294 }
295
296 static const char *
297 pipe_loader_sw_get_driconf_xml(struct pipe_loader_device *dev)
298 {
299 return NULL;
300 }
301
302 static struct pipe_screen *
303 pipe_loader_sw_create_screen(struct pipe_loader_device *dev,
304 const struct pipe_screen_config *config)
305 {
306 struct pipe_loader_sw_device *sdev = pipe_loader_sw_device(dev);
307 struct pipe_screen *screen;
308
309 screen = sdev->dd->create_screen(sdev->ws);
310 if (!screen)
311 sdev->ws->destroy(sdev->ws);
312
313 return screen;
314 }
315
316 static const struct pipe_loader_ops pipe_loader_sw_ops = {
317 .create_screen = pipe_loader_sw_create_screen,
318 .get_driconf_xml = pipe_loader_sw_get_driconf_xml,
319 .release = pipe_loader_sw_release
320 };