From: Chia-I Wu Date: Wed, 23 Jun 2010 13:36:20 +0000 (+0800) Subject: st/egl: Build a single EGL driver. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a81ef14228c6fe2893527b7b5f12855c90db3f8e;p=mesa.git st/egl: Build a single EGL driver. This change makes st/egl build a single egl_gallium.so and multiple st_.so and pipe_.so. When a display is initialized, the corresponding pipe driver will be loaded. When a context is created, the corresponding state tracker will be loaded. Unlike DRI drivers, no ABI compatibility is maintained. egl_gallium, pipe drivers and state trackers should always be distributed as a single package. As such, there is only a single src/gallium/targets/egl/ that builds everything for the package. --- diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c index c65df286454..71d2ba06d50 100644 --- a/src/egl/main/egldriver.c +++ b/src/egl/main/egldriver.c @@ -39,7 +39,7 @@ /* XXX Need to decide how to do dynamic name lookup on Windows */ static const char *DefaultDriverNames[] = { - "egl_gallium_swrast" + "egl_gallium" }; typedef HMODULE lib_handle; @@ -68,6 +68,7 @@ library_suffix(void) static const char *DefaultDriverNames[] = { + "egl_gallium", "egl_dri2", "egl_glx" }; @@ -294,71 +295,6 @@ _eglLoaderFile(const char *dir, size_t len, void *loader_data) } -/** - * A loader function for use with _eglPreloadForEach. The loader data is the - * pattern (prefix) of the files to look for. - */ -static EGLBoolean -_eglLoaderPattern(const char *dir, size_t len, void *loader_data) -{ -#if defined(_EGL_OS_UNIX) - const char *prefix, *suffix; - size_t prefix_len, suffix_len; - DIR *dirp; - struct dirent *dirent; - char path[1024]; - - if (len + 2 > sizeof(path)) - return EGL_TRUE; - if (len) { - memcpy(path, dir, len); - path[len++] = '/'; - } - path[len] = '\0'; - - dirp = opendir(path); - if (!dirp) - return EGL_TRUE; - - prefix = (const char *) loader_data; - prefix_len = strlen(prefix); - suffix = library_suffix(); - suffix_len = (suffix) ? strlen(suffix) : 0; - - while ((dirent = readdir(dirp))) { - _EGLDriver *drv; - size_t dirent_len = strlen(dirent->d_name); - const char *p; - - /* match the prefix */ - if (strncmp(dirent->d_name, prefix, prefix_len) != 0) - continue; - /* match the suffix */ - if (suffix) { - p = dirent->d_name + dirent_len - suffix_len; - if (p < dirent->d_name || strcmp(p, suffix) != 0) - continue; - } - - /* make a full path and load the driver */ - if (len + dirent_len + 1 <= sizeof(path)) { - strcpy(path + len, dirent->d_name); - drv = _eglLoadDriver(path, NULL); - if (drv) - _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv; - } - } - - closedir(dirp); - - return EGL_TRUE; -#else /* _EGL_OS_UNIX */ - /* stop immediately */ - return EGL_FALSE; -#endif -} - - /** * Run the preload function on each driver directory and return the number of * drivers loaded. @@ -463,20 +399,6 @@ _eglPreloadUserDriver(void) } -/** - * Preload Gallium drivers. - * - * FIXME This makes libEGL a memory hog if an user driver is not specified and - * there are many Gallium drivers - */ -static EGLBoolean -_eglPreloadGalliumDrivers(void) -{ - return (_eglPreloadForEach(_eglGetSearchPath(), - _eglLoaderPattern, (void *) "egl_gallium_") > 0); -} - - /** * Preload drivers. * @@ -497,8 +419,7 @@ _eglPreloadDrivers(void) return EGL_TRUE; } - loaded = (_eglPreloadUserDriver() || - _eglPreloadGalliumDrivers()); + loaded = _eglPreloadUserDriver(); _eglUnlockMutex(_eglGlobal.Mutex); diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c index f0519405d3d..8dc19d0dd9f 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.c +++ b/src/gallium/state_trackers/egl/x11/native_x11.c @@ -33,78 +33,6 @@ #include "state_tracker/drm_driver.h" -#define X11_PROBE_MAGIC 0x11980BE /* "X11PROBE" */ - -static void -x11_probe_destroy(struct native_probe *nprobe) -{ - if (nprobe->data) - FREE(nprobe->data); - FREE(nprobe); -} - -static struct native_probe * -x11_create_probe(void *dpy) -{ - struct native_probe *nprobe; - struct x11_screen *xscr; - int scr; - const char *driver_name = NULL; - Display *xdpy; - - nprobe = CALLOC_STRUCT(native_probe); - if (!nprobe) - return NULL; - - xdpy = dpy; - if (!xdpy) { - xdpy = XOpenDisplay(NULL); - if (!xdpy) { - FREE(nprobe); - return NULL; - } - } - - scr = DefaultScreen(xdpy); - xscr = x11_screen_create(xdpy, scr); - if (xscr) { - if (x11_screen_support(xscr, X11_SCREEN_EXTENSION_DRI2)) { - driver_name = x11_screen_probe_dri2(xscr, NULL, NULL); - if (driver_name) - nprobe->data = strdup(driver_name); - } - - x11_screen_destroy(xscr); - } - - if (xdpy != dpy) - XCloseDisplay(xdpy); - - nprobe->magic = X11_PROBE_MAGIC; - nprobe->display = dpy; - - nprobe->destroy = x11_probe_destroy; - - return nprobe; -} - -static enum native_probe_result -x11_get_probe_result(struct native_probe *nprobe) -{ - if (!nprobe || nprobe->magic != X11_PROBE_MAGIC) - return NATIVE_PROBE_UNKNOWN; - - /* this is a software driver */ - if (!driver_descriptor.create_screen) - return NATIVE_PROBE_SUPPORTED; - - /* the display does not support DRI2 or the driver mismatches */ - if (!nprobe->data || strcmp(driver_descriptor.name, (const char *) nprobe->data) != 0) - return NATIVE_PROBE_FALLBACK; - - return NATIVE_PROBE_EXACT; -} - static struct native_display * native_create_display(void *dpy, struct native_event_handler *event_handler, void *user_data) @@ -131,8 +59,8 @@ native_create_display(void *dpy, struct native_event_handler *event_handler, static const struct native_platform x11_platform = { "X11", /* name */ - x11_create_probe, - x11_get_probe_result, + NULL, /* create_probe */ + NULL, /* get_probe_result */ native_create_display }; diff --git a/src/gallium/targets/egl/Makefile b/src/gallium/targets/egl/Makefile index 80f9c605599..b9db6bc2c9f 100644 --- a/src/gallium/targets/egl/Makefile +++ b/src/gallium/targets/egl/Makefile @@ -2,8 +2,9 @@ # # This is the Makefile for EGL Gallium driver package. The package consists of # -# egl_gallium_.so - EGL drivers -# st_.so - client API state trackers +# egl_gallium.so - EGL driver +# pipe_.so - pipe drivers +# st_.so - client API state trackers # # The following variables are examined # @@ -16,7 +17,7 @@ TOP = ../../../.. include $(TOP)/configs/current ST_PREFIX := st_ -PIPE_PREFIX := egl_gallium_ +PIPE_PREFIX := pipe_ common_CPPFLAGS := \ -I$(TOP)/src/gallium/auxiliary \ @@ -34,11 +35,9 @@ common_LIBS := \ egl_CPPFLAGS := \ -I$(TOP)/src/gallium/state_trackers/egl \ -I$(TOP)/src/egl/main \ - -DST_PREFIX=\"$(ST_PREFIX)\" + -DPIPE_PREFIX=\"$(PIPE_PREFIX)\" -DST_PREFIX=\"$(ST_PREFIX)\" egl_SYS := -lm -ldl -lEGL -egl_LIBS := \ - $(TOP)/src/gallium/state_trackers/egl/libegl.a \ - $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a +egl_LIBS := $(TOP)/src/gallium/state_trackers/egl/libegl.a ifneq ($(findstring x11, $(EGL_PLATFORMS)),) egl_SYS += -lX11 -lXext -lXfixes @@ -67,13 +66,6 @@ egl_CPPFLAGS += -DFEATURE_VG=1 endif egl_CPPFLAGS := $(sort $(egl_CPPFLAGS)) -# LLVM -ifeq ($(MESA_LLVM),1) -common_SYS += $(LLVM_LIBS) -egl_LIBS += $(TOP)/src/gallium/drivers/llvmpipe/libllvmpipe.a -LDFLAGS += $(LLVM_LDFLAGS) -endif - # i915 pipe driver i915_CPPFLAGS := i915_SYS := -ldrm_intel @@ -112,9 +104,17 @@ vmwgfx_LIBS := \ $(TOP)/src/gallium/drivers/svga/libsvga.a # swrast (pseudo) pipe driver -swrast_CPPFLAGS := -swrast_SYS := -swrast_LIBS := +swrast_CPPFLAGS := -DGALLIUM_SOFTPIPE -DGALLIUM_RBUG -DGALLIUM_TRACE +swrast_SYS := -lm +swrast_LIBS := $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a + +# LLVM +ifeq ($(MESA_LLVM),1) +common_SYS += $(LLVM_LIBS) +swrast_CPPFLAGS += -DGALLIUM_LLVMPIPE +swrast_LIBS += $(TOP)/src/gallium/drivers/llvmpipe/libllvmpipe.a +LDFLAGS += $(LLVM_LDFLAGS) +endif # OpenGL state tracker GL_CPPFLAGS := -I$(TOP)/src/mesa $(API_DEFINES) @@ -158,21 +158,14 @@ endif OUTPUTS += swrast OUTPUTS := $(addprefix $(PIPE_PREFIX), $(OUTPUTS)) -# state trackers -OUTPUTS += $(addprefix $(ST_PREFIX), $(EGL_CLIENT_APIS)) +# EGL driver and state trackers +OUTPUTS += egl_gallium $(addprefix $(ST_PREFIX), $(EGL_CLIENT_APIS)) OUTPUTS := $(addsuffix .so, $(OUTPUTS)) OUTPUTS := $(addprefix $(OUTPUT_PATH)/, $(OUTPUTS)) default: $(OUTPUTS) -define mklib-egl -$(MKLIB) -o $(notdir $@) -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \ - -install $(OUTPUT_PATH) $(MKLIB_OPTIONS) $< egl.o \ - -Wl,--start-group $(common_LIBS) $(egl_LIBS) $($(1)_LIBS) -Wl,--end-group \ - $(common_SYS) $(egl_SYS) $($(1)_SYS) -endef - define mklib $(MKLIB) -o $(notdir $@) -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \ -install $(OUTPUT_PATH) $(MKLIB_OPTIONS) $< \ @@ -180,24 +173,28 @@ $(MKLIB) -o $(notdir $@) -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \ $(common_SYS) $($(1)_SYS) endef -# EGL drivers -$(OUTPUT_PATH)/$(PIPE_PREFIX)i915.so: pipe_i915.o egl.o $(egl_LIBS) $(i915_LIBS) - $(call mklib-egl,i915) +# EGL driver +$(OUTPUT_PATH)/egl_gallium.so: egl.o $(egl_LIBS) + $(call mklib,egl) + +# pipe drivers +$(OUTPUT_PATH)/$(PIPE_PREFIX)i915.so: pipe_i915.o $(i915_LIBS) + $(call mklib,i915) -$(OUTPUT_PATH)/$(PIPE_PREFIX)i965.so: pipe_i965.o egl.o $(egl_LIBS) $(i965_LIBS) - $(call mklib-egl,i965) +$(OUTPUT_PATH)/$(PIPE_PREFIX)i965.so: pipe_i965.o $(i965_LIBS) + $(call mklib,i965) -$(OUTPUT_PATH)/$(PIPE_PREFIX)nouveau.so: pipe_nouveau.o egl.o $(egl_LIBS) $(nouveau_LIBS) - $(call mklib-egl,nouveau) +$(OUTPUT_PATH)/$(PIPE_PREFIX)nouveau.so: pipe_nouveau.o $(nouveau_LIBS) + $(call mklib,nouveau) -$(OUTPUT_PATH)/$(PIPE_PREFIX)radeon.so: pipe_radeon.o egl.o $(egl_LIBS) $(radeon_LIBS) - $(call mklib-egl,radeon) +$(OUTPUT_PATH)/$(PIPE_PREFIX)radeon.so: pipe_radeon.o $(radeon_LIBS) + $(call mklib,radeon) -$(OUTPUT_PATH)/$(PIPE_PREFIX)vmwgfx.so: pipe_vmwgfx.o egl.o $(egl_LIBS) $(vmwgfx_LIBS) - $(call mklib-egl,vmwgfx) +$(OUTPUT_PATH)/$(PIPE_PREFIX)vmwgfx.so: pipe_vmwgfx.o $(vmwgfx_LIBS) + $(call mklib,vmwgfx) -$(OUTPUT_PATH)/$(PIPE_PREFIX)swrast.so: pipe_swrast.o egl.o $(egl_LIBS) $(swrast_LIBS) - $(call mklib-egl,swrast) +$(OUTPUT_PATH)/$(PIPE_PREFIX)swrast.so: pipe_swrast.o $(swrast_LIBS) + $(call mklib,swrast) # state trackers $(OUTPUT_PATH)/$(ST_PREFIX)$(GL_LIB).so: st_GL.o $(GL_LIBS) diff --git a/src/gallium/targets/egl/SConscript b/src/gallium/targets/egl/SConscript index f2bcb6e684f..1643867f605 100644 --- a/src/gallium/targets/egl/SConscript +++ b/src/gallium/targets/egl/SConscript @@ -25,13 +25,13 @@ if env['platform'] == 'windows': drivers += [llvmpipe] drivers += [identity, trace, rbug] - egl_gallium_swrast = env.SharedLibrary( - target ='egl_gallium_swrast', + egl_gallium = env.SharedLibrary( + target ='egl_gallium', source = ['egl.c', 'pipe_swrast.c'], LIBS = st_egl_gdi + ws_gdi + drivers + gallium + egl + env['LIBS'], ) - env.InstallSharedLibrary(egl_gallium_swrast) + env.InstallSharedLibrary(egl_gallium) api_libs = { 'OpenVG': vgapi + st_vega, diff --git a/src/gallium/targets/egl/egl.c b/src/gallium/targets/egl/egl.c index 831adf7c765..d9d89485c3c 100644 --- a/src/gallium/targets/egl/egl.c +++ b/src/gallium/targets/egl/egl.c @@ -34,21 +34,38 @@ #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" +#include "common/egl_g3d_loader.h" struct egl_g3d_loader egl_g3d_loader; static struct st_module { boolean initialized; - const char *name; + char *name; struct util_dl_library *lib; struct st_api *stapi; } st_modules[ST_API_COUNT]; +static struct pipe_module { + boolean initialized; + char *name; + struct util_dl_library *lib; + const struct drm_driver_descriptor *drmdd; + struct pipe_screen *(*swrast_create_screen)(struct sw_winsys *); +} pipe_modules[16]; + +static char * +loader_strdup(const char *s) +{ + size_t len = (s) ? strlen(s) : 0; + char *t = MALLOC(len + 1); + if (t) { + memcpy(t, s, len); + t[len] = '\0'; + } + return t; +} + static EGLBoolean dlopen_st_module_cb(const char *dir, size_t len, void *callback_data) { @@ -81,7 +98,7 @@ load_st_module(struct st_module *stmod, { struct st_api *(*create_api)(void); - stmod->name = name; + stmod->name = loader_strdup(name); if (stmod->name) _eglSearchPathForEach(dlopen_st_module_cb, (void *) stmod); else @@ -99,12 +116,77 @@ load_st_module(struct st_module *stmod, } } - if (!stmod->stapi) + if (!stmod->stapi) { + FREE(stmod->name); stmod->name = NULL; + } return (stmod->stapi != NULL); } +static EGLBoolean +dlopen_pipe_module_cb(const char *dir, size_t len, void *callback_data) +{ + struct pipe_module *pmod = (struct pipe_module *) callback_data; + char path[1024]; + int ret; + + if (len) { + ret = util_snprintf(path, sizeof(path), + "%.*s/" PIPE_PREFIX "%s" UTIL_DL_EXT, len, dir, pmod->name); + } + else { + ret = util_snprintf(path, sizeof(path), + PIPE_PREFIX "%s" UTIL_DL_EXT, pmod->name); + } + if (ret > 0 && ret < sizeof(path)) { + pmod->lib = util_dl_open(path); + if (pmod->lib) + _eglLog(_EGL_DEBUG, "loaded %s", path); + } + + return !(pmod->lib); +} + +static boolean +load_pipe_module(struct pipe_module *pmod, const char *name) +{ + pmod->name = loader_strdup(name); + if (!pmod->name) + return FALSE; + + _eglSearchPathForEach(dlopen_pipe_module_cb, (void *) pmod); + if (pmod->lib) { + pmod->drmdd = (const struct drm_driver_descriptor *) + util_dl_get_proc_address(pmod->lib, "driver_descriptor"); + if (pmod->drmdd) { + if (pmod->drmdd->driver_name) { + /* driver name mismatch */ + if (strcmp(pmod->drmdd->driver_name, pmod->name) != 0) + pmod->drmdd = NULL; + } + else { + /* swrast */ + pmod->swrast_create_screen = + (struct pipe_screen *(*)(struct sw_winsys *)) + util_dl_get_proc_address(pmod->lib, "swrast_create_screen"); + if (!pmod->swrast_create_screen) + pmod->drmdd = NULL; + } + } + + if (!pmod->drmdd) { + util_dl_close(pmod->lib); + pmod->lib = NULL; + } + } + + if (!pmod->drmdd) + pmod->name = NULL; + + return (pmod->drmdd != NULL); +} + static struct st_api * get_st_api(enum st_api_type api) { @@ -206,27 +288,47 @@ guess_gl_api(void) return stapi; } +static struct pipe_module * +get_pipe_module(const char *name) +{ + struct pipe_module *pmod = NULL; + int i; + + if (!name) + return NULL; + + for (i = 0; i < Elements(pipe_modules); i++) { + if (!pipe_modules[i].initialized || + strcmp(pipe_modules[i].name, name) == 0) { + pmod = &pipe_modules[i]; + break; + } + } + if (!pmod) + return NULL; + + if (!pmod->initialized) { + load_pipe_module(pmod, name); + pmod->initialized = TRUE; + } + + return pmod; +} + 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; + struct pipe_module *pmod = get_pipe_module(name); + return (pmod && pmod->drmdd->create_screen) ? + pmod->drmdd->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; + struct pipe_module *pmod = get_pipe_module("swrast"); + return (pmod && pmod->swrast_create_screen) ? + pmod->swrast_create_screen(ws) : NULL; } static const struct egl_g3d_loader * @@ -273,9 +375,30 @@ loader_fini(void) util_dl_close(stmod->lib); stmod->lib = NULL; } - stmod->name = NULL; + if (stmod->name) { + FREE(stmod->name); + stmod->name = NULL; + } stmod->initialized = FALSE; } + for (i = 0; i < Elements(pipe_modules); i++) { + struct pipe_module *pmod = &pipe_modules[i]; + + if (!pmod->initialized) + break; + + pmod->drmdd = NULL; + pmod->swrast_create_screen = NULL; + if (pmod->lib) { + util_dl_close(pmod->lib); + pmod->lib = NULL; + } + if (pmod->name) { + FREE(pmod->name); + pmod->name = NULL; + } + pmod->initialized = FALSE; + } } static void diff --git a/src/gallium/targets/egl/pipe_i965.c b/src/gallium/targets/egl/pipe_i965.c index cf96214e83e..43bf646e825 100644 --- a/src/gallium/targets/egl/pipe_i965.c +++ b/src/gallium/targets/egl/pipe_i965.c @@ -27,4 +27,5 @@ create_screen(int fd) return screen; } +PUBLIC DRM_DRIVER_DESCRIPTOR("i965", "i965", create_screen) diff --git a/src/gallium/targets/egl/pipe_nouveau.c b/src/gallium/targets/egl/pipe_nouveau.c index e725a4d9b7a..0c9081bc713 100644 --- a/src/gallium/targets/egl/pipe_nouveau.c +++ b/src/gallium/targets/egl/pipe_nouveau.c @@ -17,4 +17,5 @@ create_screen(int fd) return screen; } +PUBLIC DRM_DRIVER_DESCRIPTOR("nouveau", "nouveau", create_screen) diff --git a/src/gallium/targets/egl/pipe_radeon.c b/src/gallium/targets/egl/pipe_radeon.c index 5a0a8dc5738..35550bcb263 100644 --- a/src/gallium/targets/egl/pipe_radeon.c +++ b/src/gallium/targets/egl/pipe_radeon.c @@ -23,4 +23,5 @@ create_screen(int fd) return screen; } +PUBLIC DRM_DRIVER_DESCRIPTOR("radeon", "radeon", create_screen) diff --git a/src/gallium/targets/egl/pipe_swrast.c b/src/gallium/targets/egl/pipe_swrast.c index 1ad4e25a6eb..b2e3289c5d3 100644 --- a/src/gallium/targets/egl/pipe_swrast.c +++ b/src/gallium/targets/egl/pipe_swrast.c @@ -1,4 +1,22 @@ +#include "target-helpers/inline_sw_helper.h" +#include "target-helpers/inline_debug_helper.h" #include "state_tracker/drm_driver.h" +PUBLIC struct pipe_screen * +swrast_create_screen(struct sw_winsys *ws); + +PUBLIC DRM_DRIVER_DESCRIPTOR("swrast", NULL, NULL) + +struct pipe_screen * +swrast_create_screen(struct sw_winsys *ws) +{ + struct pipe_screen *screen; + + screen = sw_screen_create(ws); + if (screen) + screen = debug_screen_wrap(screen); + + return screen; +} diff --git a/src/gallium/targets/egl/pipe_vmwgfx.c b/src/gallium/targets/egl/pipe_vmwgfx.c index 15089d6db26..22a28fa858a 100644 --- a/src/gallium/targets/egl/pipe_vmwgfx.c +++ b/src/gallium/targets/egl/pipe_vmwgfx.c @@ -23,4 +23,5 @@ create_screen(int fd) return screen; } +PUBLIC DRM_DRIVER_DESCRIPTOR("vmwgfx", "vmwgfx", create_screen)