| /* |
| * Mesa 3-D graphics library |
| * Version: 7.9 |
| * |
| * Copyright (C) 2010 LunarG Inc. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| * DEALINGS IN THE SOFTWARE. |
| * |
| * Authors: |
| * Chia-I Wu <olv@lunarg.com> |
| */ |
| |
| #include "util/u_debug.h" |
| #include "util/u_string.h" |
| #include "util/u_memory.h" |
| #include "util/u_dl.h" |
| #include "egldriver.h" |
| #include "egllog.h" |
| |
| #include "state_tracker/st_api.h" |
| #include "softpipe/sp_public.h" |
| #include "llvmpipe/lp_public.h" |
| #include "target-helpers/wrap_screen.h" |
| #include "common/egl_g3d_loader.h" |
| #include "state_tracker/drm_driver.h" |
| |
| struct egl_g3d_loader egl_g3d_loader; |
| |
| static struct st_module { |
| boolean initialized; |
| const char *name; |
| struct util_dl_library *lib; |
| struct st_api *stapi; |
| } st_modules[ST_API_COUNT]; |
| |
| static EGLBoolean |
| dlopen_st_module_cb(const char *dir, size_t len, void *callback_data) |
| { |
| struct st_module *stmod = |
| (struct st_module *) callback_data; |
| char path[1024]; |
| int ret; |
| |
| if (len) { |
| ret = util_snprintf(path, sizeof(path), |
| "%.*s/" ST_PREFIX "%s" UTIL_DL_EXT, len, dir, stmod->name); |
| } |
| else { |
| ret = util_snprintf(path, sizeof(path), |
| ST_PREFIX "%s" UTIL_DL_EXT, stmod->name); |
| } |
| |
| if (ret > 0 && ret < sizeof(path)) { |
| stmod->lib = util_dl_open(path); |
| if (stmod->lib) |
| _eglLog(_EGL_DEBUG, "loaded %s", path); |
| } |
| |
| return !(stmod->lib); |
| } |
| |
| static boolean |
| load_st_module(struct st_module *stmod, |
| const char *name, const char *procname) |
| { |
| struct st_api *(*create_api)(void); |
| |
| stmod->name = name; |
| if (stmod->name) |
| _eglSearchPathForEach(dlopen_st_module_cb, (void *) stmod); |
| else |
| stmod->lib = util_dl_open(NULL); |
| |
| if (stmod->lib) { |
| create_api = (struct st_api *(*)(void)) |
| util_dl_get_proc_address(stmod->lib, procname); |
| if (create_api) |
| stmod->stapi = create_api(); |
| |
| if (!stmod->stapi) { |
| util_dl_close(stmod->lib); |
| stmod->lib = NULL; |
| } |
| } |
| |
| if (!stmod->stapi) |
| stmod->name = NULL; |
| |
| return (stmod->stapi != NULL); |
| } |
| |
| static struct st_api * |
| get_st_api(enum st_api_type api) |
| { |
| struct st_module *stmod = &st_modules[api]; |
| const char *names[8], *symbol; |
| int i, count = 0; |
| |
| if (stmod->initialized) |
| return stmod->stapi; |
| |
| switch (api) { |
| case ST_API_OPENGL: |
| symbol = ST_CREATE_OPENGL_SYMBOL; |
| names[count++] = "GL"; |
| break; |
| case ST_API_OPENGL_ES1: |
| symbol = ST_CREATE_OPENGL_ES1_SYMBOL; |
| names[count++] = "GLESv1_CM"; |
| names[count++] = "GL"; |
| break; |
| case ST_API_OPENGL_ES2: |
| symbol = ST_CREATE_OPENGL_ES2_SYMBOL; |
| names[count++] = "GLESv2"; |
| names[count++] = "GL"; |
| break; |
| case ST_API_OPENVG: |
| symbol = ST_CREATE_OPENVG_SYMBOL; |
| names[count++] = "OpenVG"; |
| break; |
| default: |
| symbol = NULL; |
| assert(!"Unknown API Type\n"); |
| break; |
| } |
| |
| /* NULL means the process itself */ |
| names[count++] = NULL; |
| |
| for (i = 0; i < count; i++) { |
| if (load_st_module(stmod, names[i], symbol)) |
| break; |
| } |
| |
| if (!stmod->stapi) { |
| EGLint level = (egl_g3d_loader.api_mask & (1 << api)) ? |
| _EGL_WARNING : _EGL_DEBUG; |
| _eglLog(level, "unable to load " ST_PREFIX "%s" UTIL_DL_EXT, names[0]); |
| } |
| |
| stmod->initialized = TRUE; |
| |
| return stmod->stapi; |
| } |
| |
| static struct st_api * |
| guess_gl_api(void) |
| { |
| struct st_api *stapi; |
| int gl_apis[] = { |
| ST_API_OPENGL, |
| ST_API_OPENGL_ES1, |
| ST_API_OPENGL_ES2, |
| -1 |
| }; |
| int i, api = -1; |
| |
| /* determine the api from the loaded libraries */ |
| for (i = 0; gl_apis[i] != -1; i++) { |
| if (st_modules[gl_apis[i]].stapi) { |
| api = gl_apis[i]; |
| break; |
| } |
| } |
| /* determine the api from the linked libraries */ |
| if (api == -1) { |
| struct util_dl_library *self = util_dl_open(NULL); |
| |
| if (self) { |
| if (util_dl_get_proc_address(self, "glColor4d")) |
| api = ST_API_OPENGL; |
| else if (util_dl_get_proc_address(self, "glColor4x")) |
| api = ST_API_OPENGL_ES1; |
| else if (util_dl_get_proc_address(self, "glShaderBinary")) |
| api = ST_API_OPENGL_ES2; |
| util_dl_close(self); |
| } |
| } |
| |
| stapi = (api != -1) ? get_st_api(api) : NULL; |
| if (!stapi) { |
| for (i = 0; gl_apis[i] != -1; i++) { |
| api = gl_apis[i]; |
| stapi = get_st_api(api); |
| if (stapi) |
| break; |
| } |
| } |
| |
| return stapi; |
| } |
| |
| static struct pipe_screen * |
| create_drm_screen(const char *name, int fd) |
| { |
| return (driver_descriptor.driver_name && name && |
| strcmp(driver_descriptor.driver_name, name) == 0) ? |
| driver_descriptor.create_screen(fd) : NULL; |
| } |
| |
| static struct pipe_screen * |
| create_sw_screen(struct sw_winsys *ws) |
| { |
| struct pipe_screen *screen = NULL; |
| |
| #if defined(GALLIUM_LLVMPIPE) |
| if (!screen && !debug_get_bool_option("GALLIUM_NO_LLVM", FALSE)) |
| screen = llvmpipe_create_screen(ws); |
| #endif |
| if (!screen) |
| screen = softpipe_create_screen(ws); |
| |
| return (screen) ? gallium_wrap_screen(screen) : NULL; |
| } |
| |
| static const struct egl_g3d_loader * |
| loader_init(void) |
| { |
| uint api_mask = 0x0; |
| |
| /* TODO detect at runtime? */ |
| #if FEATURE_GL |
| api_mask |= 1 << ST_API_OPENGL; |
| #endif |
| #if FEATURE_ES1 |
| api_mask |= 1 << ST_API_OPENGL_ES1; |
| #endif |
| #if FEATURE_ES2 |
| api_mask |= 1 << ST_API_OPENGL_ES2; |
| #endif |
| #if FEATURE_VG |
| api_mask |= 1 << ST_API_OPENVG; |
| #endif |
| |
| egl_g3d_loader.api_mask = api_mask; |
| egl_g3d_loader.get_st_api = get_st_api; |
| egl_g3d_loader.guess_gl_api = guess_gl_api; |
| egl_g3d_loader.create_drm_screen = create_drm_screen; |
| egl_g3d_loader.create_sw_screen = create_sw_screen; |
| |
| return &egl_g3d_loader; |
| } |
| |
| static void |
| loader_fini(void) |
| { |
| int i; |
| |
| for (i = 0; i < ST_API_COUNT; i++) { |
| struct st_module *stmod = &st_modules[i]; |
| |
| if (stmod->stapi) { |
| stmod->stapi->destroy(stmod->stapi); |
| stmod->stapi = NULL; |
| } |
| if (stmod->lib) { |
| util_dl_close(stmod->lib); |
| stmod->lib = NULL; |
| } |
| stmod->name = NULL; |
| stmod->initialized = FALSE; |
| } |
| } |
| |
| static void |
| egl_g3d_unload(_EGLDriver *drv) |
| { |
| egl_g3d_destroy_driver(drv); |
| loader_fini(); |
| } |
| |
| _EGLDriver * |
| _eglMain(const char *args) |
| { |
| const struct egl_g3d_loader *loader; |
| _EGLDriver *drv; |
| |
| loader = loader_init(); |
| drv = egl_g3d_create_driver(loader); |
| if (!drv) { |
| loader_fini(); |
| return NULL; |
| } |
| |
| drv->Name = "Gallium"; |
| drv->Unload = egl_g3d_unload; |
| |
| return drv; |
| } |