st/egl: Build a single EGL driver.

This change makes st/egl build a single egl_gallium.so and multiple
st_<API>.so and pipe_<HW>.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.
This commit is contained in:
Chia-I Wu 2010-06-23 21:36:20 +08:00
parent d5ab243d5a
commit a81ef14228
10 changed files with 210 additions and 219 deletions

View File

@ -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);

View File

@ -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
};

View File

@ -2,8 +2,9 @@
#
# This is the Makefile for EGL Gallium driver package. The package consists of
#
# egl_gallium_<HW>.so - EGL drivers
# st_<API>.so - client API state trackers
# egl_gallium.so - EGL driver
# pipe_<HW>.so - pipe drivers
# st_<API>.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)
$(OUTPUT_PATH)/$(PIPE_PREFIX)i965.so: pipe_i965.o egl.o $(egl_LIBS) $(i965_LIBS)
$(call mklib-egl,i965)
# pipe drivers
$(OUTPUT_PATH)/$(PIPE_PREFIX)i915.so: pipe_i915.o $(i915_LIBS)
$(call mklib,i915)
$(OUTPUT_PATH)/$(PIPE_PREFIX)nouveau.so: pipe_nouveau.o egl.o $(egl_LIBS) $(nouveau_LIBS)
$(call mklib-egl,nouveau)
$(OUTPUT_PATH)/$(PIPE_PREFIX)i965.so: pipe_i965.o $(i965_LIBS)
$(call mklib,i965)
$(OUTPUT_PATH)/$(PIPE_PREFIX)radeon.so: pipe_radeon.o egl.o $(egl_LIBS) $(radeon_LIBS)
$(call mklib-egl,radeon)
$(OUTPUT_PATH)/$(PIPE_PREFIX)nouveau.so: pipe_nouveau.o $(nouveau_LIBS)
$(call mklib,nouveau)
$(OUTPUT_PATH)/$(PIPE_PREFIX)vmwgfx.so: pipe_vmwgfx.o egl.o $(egl_LIBS) $(vmwgfx_LIBS)
$(call mklib-egl,vmwgfx)
$(OUTPUT_PATH)/$(PIPE_PREFIX)radeon.so: pipe_radeon.o $(radeon_LIBS)
$(call mklib,radeon)
$(OUTPUT_PATH)/$(PIPE_PREFIX)swrast.so: pipe_swrast.o egl.o $(egl_LIBS) $(swrast_LIBS)
$(call mklib-egl,swrast)
$(OUTPUT_PATH)/$(PIPE_PREFIX)vmwgfx.so: pipe_vmwgfx.o $(vmwgfx_LIBS)
$(call mklib,vmwgfx)
$(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)

View File

@ -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,

View File

@ -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

View File

@ -27,4 +27,5 @@ create_screen(int fd)
return screen;
}
PUBLIC
DRM_DRIVER_DESCRIPTOR("i965", "i965", create_screen)

View File

@ -17,4 +17,5 @@ create_screen(int fd)
return screen;
}
PUBLIC
DRM_DRIVER_DESCRIPTOR("nouveau", "nouveau", create_screen)

View File

@ -23,4 +23,5 @@ create_screen(int fd)
return screen;
}
PUBLIC
DRM_DRIVER_DESCRIPTOR("radeon", "radeon", create_screen)

View File

@ -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;
}

View File

@ -23,4 +23,5 @@ create_screen(int fd)
return screen;
}
PUBLIC
DRM_DRIVER_DESCRIPTOR("vmwgfx", "vmwgfx", create_screen)