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