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