1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2012 Francisco Jerez 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "pipe_loader_priv.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "util/u_inlines.h" 31bf215546Sopenharmony_ci#include "util/u_memory.h" 32bf215546Sopenharmony_ci#include "util/u_string.h" 33bf215546Sopenharmony_ci#include "util/u_dl.h" 34bf215546Sopenharmony_ci#include "util/u_file.h" 35bf215546Sopenharmony_ci#include "util/xmlconfig.h" 36bf215546Sopenharmony_ci#include "util/driconf.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#include <string.h> 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci#ifdef _MSC_VER 41bf215546Sopenharmony_ci#include <stdlib.h> 42bf215546Sopenharmony_ci#define PATH_MAX _MAX_PATH 43bf215546Sopenharmony_ci#endif 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci#define MODULE_PREFIX "pipe_" 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_cistatic int (*backends[])(struct pipe_loader_device **, int) = { 48bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM 49bf215546Sopenharmony_ci &pipe_loader_drm_probe, 50bf215546Sopenharmony_ci#endif 51bf215546Sopenharmony_ci &pipe_loader_sw_probe 52bf215546Sopenharmony_ci}; 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ciconst driOptionDescription gallium_driconf[] = { 55bf215546Sopenharmony_ci#include "driinfo_gallium.h" 56bf215546Sopenharmony_ci}; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ciint 59bf215546Sopenharmony_cipipe_loader_probe(struct pipe_loader_device **devs, int ndev) 60bf215546Sopenharmony_ci{ 61bf215546Sopenharmony_ci int i, n = 0; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(backends); i++) 64bf215546Sopenharmony_ci n += backends[i](&devs[n], MAX2(0, ndev - n)); 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci return n; 67bf215546Sopenharmony_ci} 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_civoid 70bf215546Sopenharmony_cipipe_loader_release(struct pipe_loader_device **devs, int ndev) 71bf215546Sopenharmony_ci{ 72bf215546Sopenharmony_ci int i; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci for (i = 0; i < ndev; i++) 75bf215546Sopenharmony_ci devs[i]->ops->release(&devs[i]); 76bf215546Sopenharmony_ci} 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_civoid 79bf215546Sopenharmony_cipipe_loader_base_release(struct pipe_loader_device **dev) 80bf215546Sopenharmony_ci{ 81bf215546Sopenharmony_ci driDestroyOptionCache(&(*dev)->option_cache); 82bf215546Sopenharmony_ci driDestroyOptionInfo(&(*dev)->option_info); 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci FREE(*dev); 85bf215546Sopenharmony_ci *dev = NULL; 86bf215546Sopenharmony_ci} 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_cistatic driOptionDescription * 89bf215546Sopenharmony_cimerge_driconf(const driOptionDescription *driver_driconf, unsigned driver_count, 90bf215546Sopenharmony_ci unsigned *merged_count) 91bf215546Sopenharmony_ci{ 92bf215546Sopenharmony_ci unsigned gallium_count = ARRAY_SIZE(gallium_driconf); 93bf215546Sopenharmony_ci driOptionDescription *merged = malloc((driver_count + gallium_count) * 94bf215546Sopenharmony_ci sizeof(*merged)); 95bf215546Sopenharmony_ci if (!merged) { 96bf215546Sopenharmony_ci *merged_count = 0; 97bf215546Sopenharmony_ci return NULL; 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci memcpy(merged, gallium_driconf, sizeof(*merged) * gallium_count); 101bf215546Sopenharmony_ci memcpy(&merged[gallium_count], driver_driconf, sizeof(*merged) * driver_count); 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci *merged_count = driver_count + gallium_count; 104bf215546Sopenharmony_ci return merged; 105bf215546Sopenharmony_ci} 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci/** 108bf215546Sopenharmony_ci * Ensure that dev->option_cache is initialized appropriately for the driver. 109bf215546Sopenharmony_ci * 110bf215546Sopenharmony_ci * This function can be called multiple times. 111bf215546Sopenharmony_ci * 112bf215546Sopenharmony_ci * \param dev Device for which options should be loaded. 113bf215546Sopenharmony_ci */ 114bf215546Sopenharmony_cistatic void 115bf215546Sopenharmony_cipipe_loader_load_options(struct pipe_loader_device *dev) 116bf215546Sopenharmony_ci{ 117bf215546Sopenharmony_ci if (dev->option_info.info) 118bf215546Sopenharmony_ci return; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci unsigned driver_count, merged_count; 121bf215546Sopenharmony_ci const driOptionDescription *driver_driconf = 122bf215546Sopenharmony_ci dev->ops->get_driconf(dev, &driver_count); 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci const driOptionDescription *merged_driconf = 125bf215546Sopenharmony_ci merge_driconf(driver_driconf, driver_count, &merged_count); 126bf215546Sopenharmony_ci driParseOptionInfo(&dev->option_info, merged_driconf, merged_count); 127bf215546Sopenharmony_ci free((void *)merged_driconf); 128bf215546Sopenharmony_ci} 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_civoid 131bf215546Sopenharmony_cipipe_loader_config_options(struct pipe_loader_device *dev) 132bf215546Sopenharmony_ci{ 133bf215546Sopenharmony_ci if (!dev->option_cache.info) { 134bf215546Sopenharmony_ci driParseConfigFiles(&dev->option_cache, &dev->option_info, 0, 135bf215546Sopenharmony_ci dev->driver_name, NULL, NULL, NULL, 0, NULL, 0); 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci} 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_cichar * 140bf215546Sopenharmony_cipipe_loader_get_driinfo_xml(const char *driver_name) 141bf215546Sopenharmony_ci{ 142bf215546Sopenharmony_ci unsigned driver_count = 0; 143bf215546Sopenharmony_ci const driOptionDescription *driver_driconf = NULL; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM 146bf215546Sopenharmony_ci driver_driconf = pipe_loader_drm_get_driconf_by_name(driver_name, 147bf215546Sopenharmony_ci &driver_count); 148bf215546Sopenharmony_ci#endif 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci unsigned merged_count; 151bf215546Sopenharmony_ci const driOptionDescription *merged_driconf = 152bf215546Sopenharmony_ci merge_driconf(driver_driconf, driver_count, &merged_count); 153bf215546Sopenharmony_ci free((void *)driver_driconf); 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci char *xml = driGetOptionsXml(merged_driconf, merged_count); 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci free((void *)merged_driconf); 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci return xml; 160bf215546Sopenharmony_ci} 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_cistruct pipe_screen * 163bf215546Sopenharmony_cipipe_loader_create_screen_vk(struct pipe_loader_device *dev, bool sw_vk) 164bf215546Sopenharmony_ci{ 165bf215546Sopenharmony_ci struct pipe_screen_config config; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci pipe_loader_load_options(dev); 168bf215546Sopenharmony_ci config.options_info = &dev->option_info; 169bf215546Sopenharmony_ci config.options = &dev->option_cache; 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci return dev->ops->create_screen(dev, &config, sw_vk); 172bf215546Sopenharmony_ci} 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_cistruct pipe_screen * 175bf215546Sopenharmony_cipipe_loader_create_screen(struct pipe_loader_device *dev) 176bf215546Sopenharmony_ci{ 177bf215546Sopenharmony_ci return pipe_loader_create_screen_vk(dev, false); 178bf215546Sopenharmony_ci} 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_cistruct util_dl_library * 181bf215546Sopenharmony_cipipe_loader_find_module(const char *driver_name, 182bf215546Sopenharmony_ci const char *library_paths) 183bf215546Sopenharmony_ci{ 184bf215546Sopenharmony_ci struct util_dl_library *lib; 185bf215546Sopenharmony_ci const char *next; 186bf215546Sopenharmony_ci char path[PATH_MAX]; 187bf215546Sopenharmony_ci int len, ret; 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci for (next = library_paths; *next; library_paths = next + 1) { 190bf215546Sopenharmony_ci next = strchrnul(library_paths, ':'); 191bf215546Sopenharmony_ci len = next - library_paths; 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci if (len) 194bf215546Sopenharmony_ci ret = snprintf(path, sizeof(path), "%.*s/%s%s%s", 195bf215546Sopenharmony_ci len, library_paths, 196bf215546Sopenharmony_ci MODULE_PREFIX, driver_name, UTIL_DL_EXT); 197bf215546Sopenharmony_ci else 198bf215546Sopenharmony_ci ret = snprintf(path, sizeof(path), "%s%s%s", 199bf215546Sopenharmony_ci MODULE_PREFIX, driver_name, UTIL_DL_EXT); 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci if (ret > 0 && ret < sizeof(path) && u_file_access(path, 0) != -1) { 202bf215546Sopenharmony_ci lib = util_dl_open(path); 203bf215546Sopenharmony_ci if (lib) { 204bf215546Sopenharmony_ci return lib; 205bf215546Sopenharmony_ci } 206bf215546Sopenharmony_ci fprintf(stderr, "ERROR: Failed to load pipe driver at `%s': %s\n", 207bf215546Sopenharmony_ci path, util_dl_error()); 208bf215546Sopenharmony_ci } 209bf215546Sopenharmony_ci } 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci return NULL; 212bf215546Sopenharmony_ci} 213