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 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 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 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 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 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 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 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 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 * 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 * 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