pipe_loader_sw.c revision 459cc94507071eec18b746f57a4ec82578a38b54
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 41struct 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 53static const struct pipe_loader_ops pipe_loader_sw_ops; 54 55#ifdef GALLIUM_STATIC_TARGETS 56static 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 90static bool 91pipe_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 120static void 121pipe_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 130bool 131pipe_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 154fail: 155 pipe_loader_sw_probe_teardown_common(sdev); 156 FREE(sdev); 157 return false; 158} 159#endif 160 161#ifdef HAVE_PIPE_LOADER_KMS 162bool 163pipe_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 188fail: 189 pipe_loader_sw_probe_teardown_common(sdev); 190 FREE(sdev); 191 return false; 192} 193#endif 194 195bool 196pipe_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 219fail: 220 pipe_loader_sw_probe_teardown_common(sdev); 221 FREE(sdev); 222 return false; 223} 224 225int 226pipe_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 239boolean 240pipe_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 264fail: 265 pipe_loader_sw_probe_teardown_common(sdev); 266 FREE(sdev); 267 return false; 268} 269 270static void 271pipe_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 if (sdev->fd != -1) 281 close(sdev->fd); 282 283 FREE(sdev); 284 *dev = NULL; 285} 286 287static const struct drm_conf_ret * 288pipe_loader_sw_configuration(struct pipe_loader_device *dev, 289 enum drm_conf conf) 290{ 291 return NULL; 292} 293 294static struct pipe_screen * 295pipe_loader_sw_create_screen(struct pipe_loader_device *dev) 296{ 297 struct pipe_loader_sw_device *sdev = pipe_loader_sw_device(dev); 298 struct pipe_screen *screen; 299 300 screen = sdev->dd->create_screen(sdev->ws); 301 if (!screen) 302 sdev->ws->destroy(sdev->ws); 303 304 return screen; 305} 306 307static const struct pipe_loader_ops pipe_loader_sw_ops = { 308 .create_screen = pipe_loader_sw_create_screen, 309 .configuration = pipe_loader_sw_configuration, 310 .release = pipe_loader_sw_release 311}; 312