• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_DRISW_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 "target-helpers/inline_debug_helper.h"
43 #include "frontend/drisw_api.h"
44 #include "frontend/sw_driver.h"
45 #include "frontend/sw_winsys.h"
46 #include "util/driconf.h"
47 
48 struct pipe_loader_sw_device {
49    struct pipe_loader_device base;
50    const struct sw_driver_descriptor *dd;
51 #ifndef GALLIUM_STATIC_TARGETS
52    struct util_dl_library *lib;
53 #endif
54    struct sw_winsys *ws;
55    int fd;
56 };
57 
58 #define pipe_loader_sw_device(dev) ((struct pipe_loader_sw_device *)dev)
59 
60 static const struct pipe_loader_ops pipe_loader_sw_ops;
61 #if defined(HAVE_DRI) && defined(HAVE_ZINK)
62 static const struct pipe_loader_ops pipe_loader_vk_ops;
63 #endif
64 
65 #ifdef GALLIUM_STATIC_TARGETS
66 static const struct sw_driver_descriptor driver_descriptors = {
67    .create_screen = sw_screen_create_vk,
68    .winsys = {
69 #ifdef HAVE_DRI
70       {
71          .name = "dri",
72          .create_winsys = dri_create_sw_winsys,
73       },
74 #endif
75 #ifdef HAVE_DRISW_KMS
76       {
77          .name = "kms_dri",
78          .create_winsys = kms_dri_create_winsys,
79       },
80 #endif
81 #ifndef __ANDROID__
82       {
83          .name = "null",
84          .create_winsys = null_sw_create,
85       },
86       {
87          .name = "wrapped",
88          .create_winsys = wrapper_sw_winsys_wrap_pipe_screen,
89       },
90 #endif
91       { 0 },
92    }
93 };
94 #endif
95 
96 #if defined(GALLIUM_STATIC_TARGETS) && defined(HAVE_ZINK) && defined(HAVE_DRI)
97 static const struct sw_driver_descriptor kopper_driver_descriptors = {
98    .create_screen = sw_screen_create_zink,
99    .winsys = {
100       {
101          .name = "dri",
102          .create_winsys = dri_create_sw_winsys,
103       },
104 #ifdef HAVE_DRISW_KMS
105       {
106          .name = "kms_dri",
107          .create_winsys = kms_dri_create_winsys,
108       },
109 #endif
110 #ifndef __ANDROID__
111       {
112          .name = "null",
113          .create_winsys = null_sw_create,
114       },
115       {
116          .name = "wrapped",
117          .create_winsys = wrapper_sw_winsys_wrap_pipe_screen,
118       },
119 #endif
120       { 0 },
121    }
122 };
123 #endif
124 
125 static bool
pipe_loader_sw_probe_init_common(struct pipe_loader_sw_device * sdev)126 pipe_loader_sw_probe_init_common(struct pipe_loader_sw_device *sdev)
127 {
128    sdev->base.type = PIPE_LOADER_DEVICE_SOFTWARE;
129    sdev->base.driver_name = "swrast";
130    sdev->base.ops = &pipe_loader_sw_ops;
131    sdev->fd = -1;
132 
133 #ifdef GALLIUM_STATIC_TARGETS
134    sdev->dd = &driver_descriptors;
135    if (!sdev->dd)
136       return false;
137 #else
138    const char *search_dir = getenv("GALLIUM_PIPE_SEARCH_DIR");
139    if (search_dir == NULL)
140       search_dir = PIPE_SEARCH_DIR;
141 
142    sdev->lib = pipe_loader_find_module("swrast", search_dir);
143    if (!sdev->lib)
144       return false;
145 
146    sdev->dd = (const struct sw_driver_descriptor *)
147       util_dl_get_proc_address(sdev->lib, "swrast_driver_descriptor");
148 
149    if (!sdev->dd){
150       util_dl_close(sdev->lib);
151       sdev->lib = NULL;
152       return false;
153    }
154 #endif
155 
156    return true;
157 }
158 
159 #if defined(HAVE_DRI) && defined(HAVE_ZINK)
160 static bool
pipe_loader_vk_probe_init_common(struct pipe_loader_sw_device * sdev)161 pipe_loader_vk_probe_init_common(struct pipe_loader_sw_device *sdev)
162 {
163    sdev->base.type = PIPE_LOADER_DEVICE_PLATFORM;
164    sdev->base.driver_name = "kopper";
165    sdev->base.ops = &pipe_loader_vk_ops;
166    sdev->fd = -1;
167 
168 #ifdef GALLIUM_STATIC_TARGETS
169    sdev->dd = &kopper_driver_descriptors;
170    if (!sdev->dd)
171       return false;
172 #else
173    const char *search_dir = getenv("GALLIUM_PIPE_SEARCH_DIR");
174    if (search_dir == NULL)
175       search_dir = PIPE_SEARCH_DIR;
176 
177    sdev->lib = pipe_loader_find_module("swrast", search_dir);
178    if (!sdev->lib)
179       return false;
180 
181    sdev->dd = (const struct sw_driver_descriptor *)
182       util_dl_get_proc_address(sdev->lib, "swrast_driver_descriptor");
183 
184    if (!sdev->dd){
185       util_dl_close(sdev->lib);
186       sdev->lib = NULL;
187       return false;
188    }
189 #endif
190 
191    return true;
192 }
193 #endif
194 
195 static void
pipe_loader_sw_probe_teardown_common(struct pipe_loader_sw_device * sdev)196 pipe_loader_sw_probe_teardown_common(struct pipe_loader_sw_device *sdev)
197 {
198 #ifndef GALLIUM_STATIC_TARGETS
199    if (sdev->lib)
200       util_dl_close(sdev->lib);
201 #endif
202 }
203 
204 #ifdef HAVE_DRI
205 bool
pipe_loader_sw_probe_dri(struct pipe_loader_device ** devs,const struct drisw_loader_funcs * drisw_lf)206 pipe_loader_sw_probe_dri(struct pipe_loader_device **devs, const struct drisw_loader_funcs *drisw_lf)
207 {
208    struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
209    int i;
210 
211    if (!sdev)
212       return false;
213 
214    if (!pipe_loader_sw_probe_init_common(sdev))
215       goto fail;
216 
217    for (i = 0; sdev->dd->winsys[i].name; i++) {
218       if (strcmp(sdev->dd->winsys[i].name, "dri") == 0) {
219          sdev->ws = sdev->dd->winsys[i].create_winsys(drisw_lf);
220          break;
221       }
222    }
223    if (!sdev->ws)
224       goto fail;
225 
226    *devs = &sdev->base;
227    return true;
228 
229 fail:
230    pipe_loader_sw_probe_teardown_common(sdev);
231    FREE(sdev);
232    return false;
233 }
234 #ifdef HAVE_ZINK
235 bool
pipe_loader_vk_probe_dri(struct pipe_loader_device ** devs,const struct drisw_loader_funcs * drisw_lf)236 pipe_loader_vk_probe_dri(struct pipe_loader_device **devs, const struct drisw_loader_funcs *drisw_lf)
237 {
238    struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
239    int i;
240 
241    if (!sdev)
242       return false;
243 
244    if (!pipe_loader_vk_probe_init_common(sdev))
245       goto fail;
246 
247    for (i = 0; sdev->dd->winsys[i].name; i++) {
248       if (strcmp(sdev->dd->winsys[i].name, "dri") == 0) {
249          sdev->ws = sdev->dd->winsys[i].create_winsys(drisw_lf);
250          break;
251       }
252    }
253    if (!sdev->ws)
254       goto fail;
255 
256    *devs = &sdev->base;
257    return true;
258 
259 fail:
260    pipe_loader_sw_probe_teardown_common(sdev);
261    FREE(sdev);
262    return false;
263 }
264 #endif
265 #endif
266 
267 #ifdef HAVE_DRISW_KMS
268 bool
pipe_loader_sw_probe_kms(struct pipe_loader_device ** devs,int fd)269 pipe_loader_sw_probe_kms(struct pipe_loader_device **devs, int fd)
270 {
271    struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
272    int i;
273 
274    if (!sdev)
275       return false;
276 
277    if (!pipe_loader_sw_probe_init_common(sdev))
278       goto fail;
279 
280    if (fd < 0 || (sdev->fd = os_dupfd_cloexec(fd)) < 0)
281       goto fail;
282 
283    for (i = 0; sdev->dd->winsys[i].name; i++) {
284       if (strcmp(sdev->dd->winsys[i].name, "kms_dri") == 0) {
285          sdev->ws = sdev->dd->winsys[i].create_winsys(sdev->fd);
286          break;
287       }
288    }
289    if (!sdev->ws)
290       goto fail;
291 
292    *devs = &sdev->base;
293    return true;
294 
295 fail:
296    pipe_loader_sw_probe_teardown_common(sdev);
297    if (sdev->fd != -1)
298       close(sdev->fd);
299    FREE(sdev);
300    return false;
301 }
302 #endif
303 
304 bool
pipe_loader_sw_probe_null(struct pipe_loader_device ** devs)305 pipe_loader_sw_probe_null(struct pipe_loader_device **devs)
306 {
307    struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
308    int i;
309 
310    if (!sdev)
311       return false;
312 
313    if (!pipe_loader_sw_probe_init_common(sdev))
314       goto fail;
315 
316    for (i = 0; sdev->dd->winsys[i].name; i++) {
317       if (strcmp(sdev->dd->winsys[i].name, "null") == 0) {
318          sdev->ws = sdev->dd->winsys[i].create_winsys();
319          break;
320       }
321    }
322    if (!sdev->ws)
323       goto fail;
324 
325    *devs = &sdev->base;
326    return true;
327 
328 fail:
329    pipe_loader_sw_probe_teardown_common(sdev);
330    FREE(sdev);
331    return false;
332 }
333 
334 int
pipe_loader_sw_probe(struct pipe_loader_device ** devs,int ndev)335 pipe_loader_sw_probe(struct pipe_loader_device **devs, int ndev)
336 {
337    int i = 1;
338 
339    if (i <= ndev) {
340       if (!pipe_loader_sw_probe_null(devs)) {
341          i--;
342       }
343    }
344 
345    return i;
346 }
347 
348 boolean
pipe_loader_sw_probe_wrapped(struct pipe_loader_device ** dev,struct pipe_screen * screen)349 pipe_loader_sw_probe_wrapped(struct pipe_loader_device **dev,
350                              struct pipe_screen *screen)
351 {
352    struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
353    int i;
354 
355    if (!sdev)
356       return false;
357 
358    if (!pipe_loader_sw_probe_init_common(sdev))
359       goto fail;
360 
361    for (i = 0; sdev->dd->winsys[i].name; i++) {
362       if (strcmp(sdev->dd->winsys[i].name, "wrapped") == 0) {
363          sdev->ws = sdev->dd->winsys[i].create_winsys(screen);
364          break;
365       }
366    }
367    if (!sdev->ws)
368       goto fail;
369 
370    *dev = &sdev->base;
371    return true;
372 
373 fail:
374    pipe_loader_sw_probe_teardown_common(sdev);
375    FREE(sdev);
376    return false;
377 }
378 
379 static void
pipe_loader_sw_release(struct pipe_loader_device ** dev)380 pipe_loader_sw_release(struct pipe_loader_device **dev)
381 {
382    UNUSED struct pipe_loader_sw_device *sdev =
383       pipe_loader_sw_device(*dev);
384 
385 #ifndef GALLIUM_STATIC_TARGETS
386    if (sdev->lib)
387       util_dl_close(sdev->lib);
388 #endif
389 
390 #ifdef HAVE_DRISW_KMS
391    if (sdev->fd != -1)
392       close(sdev->fd);
393 #endif
394 
395    pipe_loader_base_release(dev);
396 }
397 
398 static const struct driOptionDescription *
pipe_loader_sw_get_driconf(struct pipe_loader_device * dev,unsigned * count)399 pipe_loader_sw_get_driconf(struct pipe_loader_device *dev, unsigned *count)
400 {
401    *count = 0;
402    return NULL;
403 }
404 
405 #if defined(HAVE_DRI) && defined(HAVE_ZINK)
406 static const driOptionDescription zink_driconf[] = {
407       #include "gallium/drivers/zink/driinfo_zink.h"
408 };
409 
410 static const struct driOptionDescription *
pipe_loader_vk_get_driconf(struct pipe_loader_device * dev,unsigned * count)411 pipe_loader_vk_get_driconf(struct pipe_loader_device *dev, unsigned *count)
412 {
413    *count = ARRAY_SIZE(zink_driconf);
414    return zink_driconf;
415 }
416 #endif
417 
418 static struct pipe_screen *
pipe_loader_sw_create_screen(struct pipe_loader_device * dev,const struct pipe_screen_config * config,bool sw_vk)419 pipe_loader_sw_create_screen(struct pipe_loader_device *dev,
420                              const struct pipe_screen_config *config, bool sw_vk)
421 {
422    struct pipe_loader_sw_device *sdev = pipe_loader_sw_device(dev);
423    struct pipe_screen *screen;
424 
425    screen = sdev->dd->create_screen(sdev->ws, config, sw_vk);
426    if (!screen)
427       sdev->ws->destroy(sdev->ws);
428 
429    return screen ? debug_screen_wrap(screen) : NULL;
430 }
431 
432 static const struct pipe_loader_ops pipe_loader_sw_ops = {
433    .create_screen = pipe_loader_sw_create_screen,
434    .get_driconf = pipe_loader_sw_get_driconf,
435    .release = pipe_loader_sw_release
436 };
437 
438 #if defined(HAVE_DRI) && defined(HAVE_ZINK)
439 static const struct pipe_loader_ops pipe_loader_vk_ops = {
440    .create_screen = pipe_loader_sw_create_screen,
441    .get_driconf = pipe_loader_vk_get_driconf,
442    .release = pipe_loader_sw_release
443 };
444 #endif
445