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