From d5ab243d5a5bacbd2ba615d40f13c8ab37364745 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 29 Jun 2010 14:58:33 +0800 Subject: st/egl: Move module loading code to targets. Several changes are made. libegl.a no longer defines _eglMain. It defines functions to create and destroy a _EGLDriver instead. The creation function is called by the targets. It takes an egl_g3d_loader as its argument. The loader is defined by the targets and is in charge of creating st_api and pipe_screen. This allows us to move the module loading code to targets. Lastly, the modules are now loaded as the respective contexts are created. --- src/gallium/targets/egl/Makefile | 51 ++++-- src/gallium/targets/egl/SConscript | 2 +- src/gallium/targets/egl/egl.c | 305 +++++++++++++++++++++++++++++++++ src/gallium/targets/egl/pipe_i965.c | 4 - src/gallium/targets/egl/pipe_nouveau.c | 4 - src/gallium/targets/egl/pipe_radeon.c | 4 - src/gallium/targets/egl/pipe_swrast.c | 4 - src/gallium/targets/egl/pipe_vmwgfx.c | 4 - 8 files changed, 343 insertions(+), 35 deletions(-) create mode 100644 src/gallium/targets/egl/egl.c (limited to 'src/gallium/targets') diff --git a/src/gallium/targets/egl/Makefile b/src/gallium/targets/egl/Makefile index 364a31dc45..80f9c60559 100644 --- a/src/gallium/targets/egl/Makefile +++ b/src/gallium/targets/egl/Makefile @@ -15,6 +15,9 @@ TOP = ../../../.. include $(TOP)/configs/current +ST_PREFIX := st_ +PIPE_PREFIX := egl_gallium_ + common_CPPFLAGS := \ -I$(TOP)/src/gallium/auxiliary \ -I$(TOP)/src/gallium/drivers \ @@ -30,7 +33,8 @@ common_LIBS := \ # EGL driver egl_CPPFLAGS := \ -I$(TOP)/src/gallium/state_trackers/egl \ - -I$(TOP)/src/egl/main + -I$(TOP)/src/egl/main \ + -DST_PREFIX=\"$(ST_PREFIX)\" egl_SYS := -lm -ldl -lEGL egl_LIBS := \ $(TOP)/src/gallium/state_trackers/egl/libegl.a \ @@ -47,6 +51,22 @@ ifneq ($(findstring fbdev, $(EGL_PLATFORMS)),) egl_LIBS += $(TOP)/src/gallium/winsys/sw/fbdev/libfbdev.a endif +# EGL_RENDERABLE_TYPE is a compile time attribute +egl_CPPFLAGS += $(API_DEFINES) +ifneq ($(filter $(GL_LIB), $(EGL_CLIENT_APIS)),) +egl_CPPFLAGS += -DFEATURE_GL=1 +endif +ifneq ($(filter $(GLESv1_CM_LIB), $(EGL_CLIENT_APIS)),) +egl_CPPFLAGS += -DFEATURE_ES1=1 +endif +ifneq ($(filter $(GLESv2_LIB), $(EGL_CLIENT_APIS)),) +egl_CPPFLAGS += -DFEATURE_ES2=1 +endif +ifneq ($(filter $(VG_LIB), $(EGL_CLIENT_APIS)),) +egl_CPPFLAGS += -DFEATURE_VG=1 +endif +egl_CPPFLAGS := $(sort $(egl_CPPFLAGS)) + # LLVM ifeq ($(MESA_LLVM),1) common_SYS += $(LLVM_LIBS) @@ -136,10 +156,10 @@ ifneq ($(findstring svga,$(GALLIUM_WINSYS_DIRS)),) OUTPUTS += vmwgfx endif OUTPUTS += swrast -OUTPUTS := $(addprefix egl_gallium_, $(OUTPUTS)) +OUTPUTS := $(addprefix $(PIPE_PREFIX), $(OUTPUTS)) # state trackers -OUTPUTS += $(addprefix st_, $(EGL_CLIENT_APIS)) +OUTPUTS += $(addprefix $(ST_PREFIX), $(EGL_CLIENT_APIS)) OUTPUTS := $(addsuffix .so, $(OUTPUTS)) OUTPUTS := $(addprefix $(OUTPUT_PATH)/, $(OUTPUTS)) @@ -148,7 +168,7 @@ default: $(OUTPUTS) define mklib-egl $(MKLIB) -o $(notdir $@) -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \ - -install $(OUTPUT_PATH) $(MKLIB_OPTIONS) $< \ + -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 @@ -161,37 +181,40 @@ $(MKLIB) -o $(notdir $@) -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \ endef # EGL drivers -$(OUTPUT_PATH)/egl_gallium_i915.so: pipe_i915.o $(egl_LIBS) $(i915_LIBS) +$(OUTPUT_PATH)/$(PIPE_PREFIX)i915.so: pipe_i915.o egl.o $(egl_LIBS) $(i915_LIBS) $(call mklib-egl,i915) -$(OUTPUT_PATH)/egl_gallium_i965.so: pipe_i965.o $(egl_LIBS) $(i965_LIBS) +$(OUTPUT_PATH)/$(PIPE_PREFIX)i965.so: pipe_i965.o egl.o $(egl_LIBS) $(i965_LIBS) $(call mklib-egl,i965) -$(OUTPUT_PATH)/egl_gallium_nouveau.so: pipe_nouveau.o $(egl_LIBS) $(nouveau_LIBS) +$(OUTPUT_PATH)/$(PIPE_PREFIX)nouveau.so: pipe_nouveau.o egl.o $(egl_LIBS) $(nouveau_LIBS) $(call mklib-egl,nouveau) -$(OUTPUT_PATH)/egl_gallium_radeon.so: pipe_radeon.o $(egl_LIBS) $(radeon_LIBS) +$(OUTPUT_PATH)/$(PIPE_PREFIX)radeon.so: pipe_radeon.o egl.o $(egl_LIBS) $(radeon_LIBS) $(call mklib-egl,radeon) -$(OUTPUT_PATH)/egl_gallium_vmwgfx.so: pipe_vmwgfx.o $(egl_LIBS) $(vmwgfx_LIBS) +$(OUTPUT_PATH)/$(PIPE_PREFIX)vmwgfx.so: pipe_vmwgfx.o egl.o $(egl_LIBS) $(vmwgfx_LIBS) $(call mklib-egl,vmwgfx) -$(OUTPUT_PATH)/egl_gallium_swrast.so: pipe_swrast.o $(egl_LIBS) $(swrast_LIBS) +$(OUTPUT_PATH)/$(PIPE_PREFIX)swrast.so: pipe_swrast.o egl.o $(egl_LIBS) $(swrast_LIBS) $(call mklib-egl,swrast) # state trackers -$(OUTPUT_PATH)/st_$(GL_LIB).so: st_GL.o $(GL_LIBS) +$(OUTPUT_PATH)/$(ST_PREFIX)$(GL_LIB).so: st_GL.o $(GL_LIBS) $(call mklib,GL) -$(OUTPUT_PATH)/st_$(GLESv1_CM_LIB).so: st_GLESv1_CM.o $(GLESv1_CM_LIBS) +$(OUTPUT_PATH)/$(ST_PREFIX)$(GLESv1_CM_LIB).so: st_GLESv1_CM.o $(GLESv1_CM_LIBS) $(call mklib,GLESv1_CM) -$(OUTPUT_PATH)/st_$(GLESv2_LIB).so: st_GLESv2.o $(GLESv2_LIBS) +$(OUTPUT_PATH)/$(ST_PREFIX)$(GLESv2_LIB).so: st_GLESv2.o $(GLESv2_LIBS) $(call mklib,GLESv2) -$(OUTPUT_PATH)/st_$(VG_LIB).so: st_OpenVG.o $(OpenVG_LIBS) +$(OUTPUT_PATH)/$(ST_PREFIX)$(VG_LIB).so: st_OpenVG.o $(OpenVG_LIBS) $(call mklib,OpenVG) +egl.o: egl.c + $(CC) -c -o $@ $< $(common_CPPFLAGS) $(egl_CPPFLAGS) $(DEFINES) $(CFLAGS) + pipe_%.o: pipe_%.c $(CC) -c -o $@ $< $(common_CPPFLAGS) $($*_CPPFLAGS) $(DEFINES) $(CFLAGS) diff --git a/src/gallium/targets/egl/SConscript b/src/gallium/targets/egl/SConscript index c743c26cf6..f2bcb6e684 100644 --- a/src/gallium/targets/egl/SConscript +++ b/src/gallium/targets/egl/SConscript @@ -27,7 +27,7 @@ if env['platform'] == 'windows': egl_gallium_swrast = env.SharedLibrary( target ='egl_gallium_swrast', - source = 'pipe_swrast.c', + source = ['egl.c', 'pipe_swrast.c'], LIBS = st_egl_gdi + ws_gdi + drivers + gallium + egl + env['LIBS'], ) diff --git a/src/gallium/targets/egl/egl.c b/src/gallium/targets/egl/egl.c new file mode 100644 index 0000000000..831adf7c76 --- /dev/null +++ b/src/gallium/targets/egl/egl.c @@ -0,0 +1,305 @@ +/* + * 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; +} diff --git a/src/gallium/targets/egl/pipe_i965.c b/src/gallium/targets/egl/pipe_i965.c index d19c83a47d..cf96214e83 100644 --- a/src/gallium/targets/egl/pipe_i965.c +++ b/src/gallium/targets/egl/pipe_i965.c @@ -28,7 +28,3 @@ create_screen(int fd) } DRM_DRIVER_DESCRIPTOR("i965", "i965", create_screen) - -/* A poor man's --whole-archive for EGL drivers */ -void *_eglMain(void *); -void *_eglWholeArchive = (void *) _eglMain; diff --git a/src/gallium/targets/egl/pipe_nouveau.c b/src/gallium/targets/egl/pipe_nouveau.c index cf569ea62c..e725a4d9b7 100644 --- a/src/gallium/targets/egl/pipe_nouveau.c +++ b/src/gallium/targets/egl/pipe_nouveau.c @@ -18,7 +18,3 @@ create_screen(int fd) } DRM_DRIVER_DESCRIPTOR("nouveau", "nouveau", create_screen) - -/* A poor man's --whole-archive for EGL drivers */ -void *_eglMain(void *); -void *_eglWholeArchive = (void *) _eglMain; diff --git a/src/gallium/targets/egl/pipe_radeon.c b/src/gallium/targets/egl/pipe_radeon.c index ce07327b8f..5a0a8dc573 100644 --- a/src/gallium/targets/egl/pipe_radeon.c +++ b/src/gallium/targets/egl/pipe_radeon.c @@ -24,7 +24,3 @@ create_screen(int fd) } DRM_DRIVER_DESCRIPTOR("radeon", "radeon", create_screen) - -/* A poor man's --whole-archive for EGL drivers */ -void *_eglMain(void *); -void *_eglWholeArchive = (void *) _eglMain; diff --git a/src/gallium/targets/egl/pipe_swrast.c b/src/gallium/targets/egl/pipe_swrast.c index d8205c158e..1ad4e25a6e 100644 --- a/src/gallium/targets/egl/pipe_swrast.c +++ b/src/gallium/targets/egl/pipe_swrast.c @@ -2,7 +2,3 @@ #include "state_tracker/drm_driver.h" DRM_DRIVER_DESCRIPTOR("swrast", NULL, NULL) - -/* A poor man's --whole-archive for EGL drivers */ -void *_eglMain(void *); -void *_eglWholeArchive = (void *) _eglMain; diff --git a/src/gallium/targets/egl/pipe_vmwgfx.c b/src/gallium/targets/egl/pipe_vmwgfx.c index 4e9f51c5dc..15089d6db2 100644 --- a/src/gallium/targets/egl/pipe_vmwgfx.c +++ b/src/gallium/targets/egl/pipe_vmwgfx.c @@ -24,7 +24,3 @@ create_screen(int fd) } DRM_DRIVER_DESCRIPTOR("vmwgfx", "vmwgfx", create_screen) - -/* A poor man's --whole-archive for EGL drivers */ -void *_eglMain(void *); -void *_eglWholeArchive = (void *) _eglMain; -- cgit v1.2.3