/* * 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 */ #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; }