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