From 07b8cc331f9eb6c53cd32d4eeaff1c12f4685203 Mon Sep 17 00:00:00 2001 From: Courtney Goeltzenleuchter Date: Fri, 27 Feb 2015 15:19:33 -0700 Subject: loader: Merge extensions and layers Update loader so that it extensions and layers work in same basic fashion. That is, application can query for extension/layer support by calling GetExtensionSupport. The loader will then query the available drivers AND layers for that support. Likewise, when the application does CreateDevice the list of "extensions" can be both layers and extensions and the loader will figure out the right thing to do. Conflicts: loader/loader.c xgl-generate.py --- loader/loader.c | 180 +++++++++++++++++++++++++++++++++++--------------------- xgl-generate.py | 2 +- 2 files changed, 113 insertions(+), 69 deletions(-) diff --git a/loader/loader.c b/loader/loader.c index 4dafc223..556c2b3c 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -83,6 +83,7 @@ struct loader_scanned_icds { xglCreateInstanceType CreateInstance; xglDestroyInstanceType DestroyInstance; xglEnumerateGpusType EnumerateGpus; + xglGetExtensionSupportType GetExtensionSupport; XGL_INSTANCE instance; struct loader_scanned_icds *next; }; @@ -262,7 +263,7 @@ static struct loader_icd *loader_icd_add(struct loader_instance *ptr_inst, static void loader_scanned_icd_add(const char *filename) { loader_platform_dl_handle handle; - void *fp_gpa, *fp_enumerate, *fp_create_inst, *fp_destroy_inst; + void *fp_gpa, *fp_enumerate, *fp_create_inst, *fp_destroy_inst, *fp_get_extension_support; struct loader_scanned_icds *new_node; // Used to call: dlopen(filename, RTLD_LAZY); @@ -284,6 +285,7 @@ static void loader_scanned_icd_add(const char *filename) LOOKUP(fp_create_inst, CreateInstance); LOOKUP(fp_destroy_inst, DestroyInstance); LOOKUP(fp_enumerate, EnumerateGpus); + LOOKUP(fp_get_extension_support, GetExtensionSupport); #undef LOOKUP new_node = (struct loader_scanned_icds *) malloc(sizeof(struct loader_scanned_icds)); @@ -297,6 +299,7 @@ static void loader_scanned_icd_add(const char *filename) new_node->CreateInstance = fp_create_inst; new_node->DestroyInstance = fp_destroy_inst; new_node->EnumerateGpus = fp_enumerate; + new_node->GetExtensionSupport = fp_get_extension_support; new_node->next = loader.scanned_icd_list; loader.scanned_icd_list = new_node; } @@ -575,52 +578,77 @@ static void loader_init_layer_libs(struct loader_icd *icd, uint32_t gpu_index, s } } -static bool find_layer_name(struct loader_icd *icd, uint32_t gpu_index, const char * layer_name, const char **lib_name) +static XGL_RESULT find_layer_extension(struct loader_icd *icd, uint32_t gpu_index, const char *pExtName, const char **lib_name) { + XGL_RESULT err; + char *search_name; loader_platform_dl_handle handle; - xglEnumerateLayersType fpEnumerateLayers; - char layer_buf[16][256]; - char * layers[16]; - - for (int i = 0; i < 16; i++) - layers[i] = &layer_buf[i][0]; + xglGetExtensionSupportType fpGetExtensionSupport; + + /* + * The loader provides the abstraction that make layers and extensions work via + * the currently defined extension mechanism. That is, when app queries for an extension + * via xglGetExtensionSupport, the loader will call both the driver as well as any layers + * to see who implements that extension. Then, if the app enables the extension during + * xglCreateDevice the loader will find and load any layers that implement that extension. + */ + + // TODO: What if extension is in multiple places? + + // TODO: Who should we ask first? Driver or layers? Do driver for now. + err = icd->scanned_icds[gpu_index].GetExtensionSupport((XGL_PHYSICAL_GPU) (icd->gpus[gpu_index].nextObject), pExtName); + if (err == XGL_SUCCESS) { + if (lib_name) { + *lib_name = NULL; + } + return XGL_SUCCESS; + } for (unsigned int j = 0; j < loader.scanned_layer_count; j++) { - *lib_name = loader.scanned_layer_names[j]; - // Used to call: dlopen(*lib_name, RTLD_LAZY) - if ((handle = loader_platform_open_library(*lib_name)) == NULL) + search_name = loader.scanned_layer_names[j]; + + if ((handle = loader_platform_open_library(search_name)) == NULL) continue; - if ((fpEnumerateLayers = (xglEnumerateLayersType) loader_platform_get_proc_address(handle, "xglEnumerateLayers")) == NULL) { - char * lib_str = malloc(strlen(*lib_name) + 1 + strlen(layer_name)); - //use default layer name - snprintf(lib_str, strlen(*lib_name) + strlen(layer_name), - XGL_LAYER_LIBRARY_PREFIX "%s" XGL_LIBRARY_SUFFIX, - layer_name); + + fpGetExtensionSupport = loader_platform_get_proc_address(handle, "xglGetExtensionSupport"); + + if (fpGetExtensionSupport != NULL) { + // Found layer's GetExtensionSupport call + err = fpGetExtensionSupport((XGL_PHYSICAL_GPU) (icd->gpus + gpu_index), pExtName); + loader_platform_close_library(handle); - if (!strcmp(*lib_name, lib_str)) { - free(lib_str); - return true; - } - else { - free(lib_str); - continue; - } - } - else { - size_t cnt; - fpEnumerateLayers(NULL, 16, 256, &cnt, layers, (char *) icd->gpus + gpu_index); - for (unsigned int i = 0; i < cnt; i++) { - if (!strcmp((char *) layers[i], layer_name)) { - loader_platform_close_library(handle); - return true; + + if (err == XGL_SUCCESS) { + if (lib_name) { + *lib_name = loader.scanned_layer_names[j]; } + return XGL_SUCCESS; } + } else { + loader_platform_close_library(handle); } - loader_platform_close_library(handle); - } + // No GetExtensionSupport or GetExtensionSupport returned invalid extension + // for the layer, so test the layer name as if it is an extension name + // use default layer name based on library name XGL_LAYER_LIBRARY_PREFIX.XGL_LIBRARY_SUFFIX + char *pEnd; + size_t siz; + + search_name = basename(search_name); + search_name += strlen(XGL_LAYER_LIBRARY_PREFIX); + pEnd = strrchr(search_name, '.'); + siz = (int) (pEnd - search_name); + if (siz != strlen(pExtName)) + continue; - return false; + if (strncmp(search_name, pExtName, siz) == 0) { + if (lib_name) { + *lib_name = loader.scanned_layer_names[j]; + } + return XGL_SUCCESS; + } + } + return XGL_ERROR_INVALID_EXTENSION; } static uint32_t loader_get_layer_env(struct loader_icd *icd, uint32_t gpu_index, struct layer_name_pair *pLayerNames) @@ -657,14 +685,13 @@ static uint32_t loader_get_layer_env(struct loader_icd *icd, uint32_t gpu_index, if (next == NULL) { len = (uint32_t) strlen(p); next = p + len; - } - else { + } else { len = (uint32_t) (next - p); *(char *) next = '\0'; next++; } name = basename(p); - if (!find_layer_name(icd, gpu_index, name, &lib_name)) { + if (find_layer_extension(icd, gpu_index, name, &lib_name) != XGL_SUCCESS) { p = next; continue; } @@ -681,7 +708,7 @@ static uint32_t loader_get_layer_env(struct loader_icd *icd, uint32_t gpu_index, count++; p = next; - }; + } free(pOrig); return count; @@ -690,39 +717,46 @@ static uint32_t loader_get_layer_env(struct loader_icd *icd, uint32_t gpu_index, static uint32_t loader_get_layer_libs(struct loader_icd *icd, uint32_t gpu_index, const XGL_DEVICE_CREATE_INFO* pCreateInfo, struct layer_name_pair **ppLayerNames) { static struct layer_name_pair layerNames[MAX_LAYER_LIBRARIES]; - int env_layer_count = 0; + const char *lib_name = NULL; + uint32_t count = 0; *ppLayerNames = &layerNames[0]; /* Load any layers specified in the environment first */ - env_layer_count = loader_get_layer_env(icd, gpu_index, layerNames); - - const XGL_LAYER_CREATE_INFO *pCi = - (const XGL_LAYER_CREATE_INFO *) pCreateInfo->pNext; - - while (pCi) { - if (pCi->sType == XGL_STRUCTURE_TYPE_LAYER_CREATE_INFO) { - const char *name; - uint32_t len, j = 0; - for (uint32_t i = env_layer_count; i < (env_layer_count + pCi->layerCount); i++) { - const char * lib_name = NULL; - name = *(pCi->ppActiveLayerNames + j); - if (!find_layer_name(icd, gpu_index, name, &lib_name)) { - return i; + count = loader_get_layer_env(icd, gpu_index, layerNames); + + for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) { + const char *pExtName = pCreateInfo->ppEnabledExtensionNames[i]; + + if (find_layer_extension(icd, gpu_index, pExtName, &lib_name) == XGL_SUCCESS) { + uint32_t len; + + /* + * the library name is NULL if the driver supports this + * extension and thus no layer to load. + */ + if (lib_name == NULL) + continue; + + len = (uint32_t) strlen(pExtName); + for (uint32_t j = 0; j < count; j++) { + if (len == strlen(layerNames[j].layer_name) && + strncmp(pExtName, layerNames[j].layer_name, len) == 0) { + // Extension / Layer already on the list + continue; } - len = (uint32_t) strlen(name); - layerNames[i].layer_name = malloc(len + 1); - if (!layerNames[i].layer_name) - return i; - strncpy((char *) layerNames[i].layer_name, name, len); - layerNames[i].layer_name[len] = '\0'; - layerNames[i].lib_name = lib_name; - j++; } - return pCi->layerCount + env_layer_count; + + layerNames[count].layer_name = malloc(len + 1); + if (!layerNames[count].layer_name) + return count; + strncpy((char *) layerNames[count].layer_name, pExtName, len); + layerNames[count].layer_name[len] = '\0'; + layerNames[count].lib_name = lib_name; + count++; } - pCi = pCi->pNext; } - return env_layer_count; + + return count; } static void loader_deactivate_layer(const struct loader_instance *instance) @@ -1013,6 +1047,17 @@ LOADER_EXPORT void * XGLAPI xglGetProcAddr(XGL_PHYSICAL_GPU gpu, const char * pN } } +LOADER_EXPORT XGL_RESULT XGLAPI xglGetExtensionSupport(XGL_PHYSICAL_GPU gpu, const char *pExtName) +{ + uint32_t gpu_index; + struct loader_icd *icd = loader_get_icd((const XGL_BASE_LAYER_OBJECT *) gpu, &gpu_index); + + if (!icd) + return XGL_ERROR_UNAVAILABLE; + + return find_layer_extension(icd, gpu_index, pExtName, NULL); +} + LOADER_EXPORT XGL_RESULT XGLAPI xglEnumerateLayers(XGL_PHYSICAL_GPU gpu, size_t maxLayerCount, size_t maxStringSize, size_t* pOutLayerCount, char* const* pOutLayers, void* pReserved) { uint32_t gpu_index; @@ -1061,8 +1106,7 @@ LOADER_EXPORT XGL_RESULT XGLAPI xglEnumerateLayers(XGL_PHYSICAL_GPU gpu, size_t pOutLayers[count][siz - 1] = '\0'; count++; free(cpyStr); - } - else { + } else { size_t cnt; uint32_t n; XGL_RESULT res; diff --git a/xgl-generate.py b/xgl-generate.py index 55371ab1..e76b1658 100755 --- a/xgl-generate.py +++ b/xgl-generate.py @@ -102,7 +102,7 @@ class LoaderEntrypointsSubcommand(Subcommand): def _is_dispatchable(self, proto): if proto.name in ["GetProcAddr", "DestroyInstance", "EnumerateGpus", - "EnumerateLayers", "DbgRegisterMsgCallback", + "EnumerateLayers", "DbgRegisterMsgCallback", "GetExtensionSupport", "DbgUnregisterMsgCallback", "DbgSetGlobalOption"]: return False -- cgit v1.2.3