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