pipe_loader_sw.c revision 46991ab9aac99c5ba55b735396f32447e75a6320
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   struct util_dl_library *lib;
44   struct sw_winsys *ws;
45};
46
47#define pipe_loader_sw_device(dev) ((struct pipe_loader_sw_device *)dev)
48
49static struct pipe_loader_ops pipe_loader_sw_ops;
50
51static bool
52pipe_loader_sw_probe_init_common(struct pipe_loader_sw_device *sdev)
53{
54   sdev->base.type = PIPE_LOADER_DEVICE_SOFTWARE;
55   sdev->base.driver_name = "swrast";
56   sdev->base.ops = &pipe_loader_sw_ops;
57
58   sdev->lib = pipe_loader_find_module(&sdev->base, PIPE_SEARCH_DIR);
59   if (!sdev->lib)
60      return false;
61
62   sdev->dd = (const struct sw_driver_descriptor *)
63      util_dl_get_proc_address(sdev->lib, "swrast_driver_descriptor");
64
65   if (!sdev->dd){
66      util_dl_close(sdev->lib);
67      sdev->lib = NULL;
68      return false;
69   }
70
71   return true;
72}
73
74static void
75pipe_loader_sw_probe_teardown_common(struct pipe_loader_sw_device *sdev)
76{
77   if (sdev->lib)
78      util_dl_close(sdev->lib);
79}
80
81#ifdef HAVE_PIPE_LOADER_DRI
82bool
83pipe_loader_sw_probe_dri(struct pipe_loader_device **devs, struct drisw_loader_funcs *drisw_lf)
84{
85   struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
86   int i;
87
88   if (!sdev)
89      return false;
90
91   if (!pipe_loader_sw_probe_init_common(sdev))
92      goto fail;
93
94   for (i = 0; sdev->dd->winsys; i++) {
95      if (strcmp(sdev->dd->winsys[i].name, "dri") == 0) {
96         sdev->ws = sdev->dd->winsys[i].create_winsys(drisw_lf);
97         break;
98      }
99   }
100   if (!sdev->ws)
101      goto fail;
102
103   *devs = &sdev->base;
104   return true;
105
106fail:
107   pipe_loader_sw_probe_teardown_common(sdev);
108   FREE(sdev);
109   return false;
110}
111#endif
112
113#ifdef HAVE_PIPE_LOADER_KMS
114bool
115pipe_loader_sw_probe_kms(struct pipe_loader_device **devs, int fd)
116{
117   struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
118   int i;
119
120   if (!sdev)
121      return false;
122
123   if (!pipe_loader_sw_probe_init_common(sdev))
124      goto fail;
125
126   for (i = 0; sdev->dd->winsys; i++) {
127      if (strcmp(sdev->dd->winsys[i].name, "kms_dri") == 0) {
128         sdev->ws = sdev->dd->winsys[i].create_winsys(fd);
129         break;
130      }
131   }
132   if (!sdev->ws)
133      goto fail;
134
135   *devs = &sdev->base;
136   return true;
137
138fail:
139   pipe_loader_sw_probe_teardown_common(sdev);
140   FREE(sdev);
141   return false;
142}
143#endif
144
145bool
146pipe_loader_sw_probe_null(struct pipe_loader_device **devs)
147{
148   struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
149   int i;
150
151   if (!sdev)
152      return false;
153
154   if (!pipe_loader_sw_probe_init_common(sdev))
155      goto fail;
156
157   for (i = 0; sdev->dd->winsys; i++) {
158      if (strcmp(sdev->dd->winsys[i].name, "null") == 0) {
159         sdev->ws = sdev->dd->winsys[i].create_winsys();
160         break;
161      }
162   }
163   if (!sdev->ws)
164      goto fail;
165
166   *devs = &sdev->base;
167   return true;
168
169fail:
170   pipe_loader_sw_probe_teardown_common(sdev);
171   FREE(sdev);
172   return false;
173}
174
175int
176pipe_loader_sw_probe(struct pipe_loader_device **devs, int ndev)
177{
178   int i = 1;
179
180   if (i < ndev) {
181      if (!pipe_loader_sw_probe_null(devs)) {
182         i--;
183      }
184   }
185
186   return i;
187}
188
189boolean
190pipe_loader_sw_probe_wrapped(struct pipe_loader_device **dev,
191                             struct pipe_screen *screen)
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, "wrapped") == 0) {
204         sdev->ws = sdev->dd->winsys[i].create_winsys(screen);
205         break;
206      }
207   }
208   if (!sdev->ws)
209      goto fail;
210
211   *dev = &sdev->base;
212   return true;
213
214fail:
215   pipe_loader_sw_probe_teardown_common(sdev);
216   FREE(sdev);
217   return false;
218}
219
220static void
221pipe_loader_sw_release(struct pipe_loader_device **dev)
222{
223   struct pipe_loader_sw_device *sdev = pipe_loader_sw_device(*dev);
224
225   if (sdev->lib)
226      util_dl_close(sdev->lib);
227
228   FREE(sdev);
229   *dev = NULL;
230}
231
232static const struct drm_conf_ret *
233pipe_loader_sw_configuration(struct pipe_loader_device *dev,
234                             enum drm_conf conf)
235{
236   return NULL;
237}
238
239static struct pipe_screen *
240pipe_loader_sw_create_screen(struct pipe_loader_device *dev)
241{
242   struct pipe_loader_sw_device *sdev = pipe_loader_sw_device(dev);
243   struct pipe_screen *screen;
244
245   screen = sdev->dd->create_screen(sdev->ws);
246   if (!screen)
247      sdev->ws->destroy(sdev->ws);
248
249   return screen;
250}
251
252static struct pipe_loader_ops pipe_loader_sw_ops = {
253   .create_screen = pipe_loader_sw_create_screen,
254   .configuration = pipe_loader_sw_configuration,
255   .release = pipe_loader_sw_release
256};
257