Browse Source

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.
tags/mesa-7.9-rc1
Chia-I Wu 15 years ago
parent
commit
a81ef14228

+ 3
- 82
src/egl/main/egldriver.c View File



/* XXX Need to decide how to do dynamic name lookup on Windows */ /* XXX Need to decide how to do dynamic name lookup on Windows */
static const char *DefaultDriverNames[] = { static const char *DefaultDriverNames[] = {
"egl_gallium_swrast"
"egl_gallium"
}; };


typedef HMODULE lib_handle; typedef HMODULE lib_handle;




static const char *DefaultDriverNames[] = { static const char *DefaultDriverNames[] = {
"egl_gallium",
"egl_dri2", "egl_dri2",
"egl_glx" "egl_glx"
}; };
} }




/**
* 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 * Run the preload function on each driver directory and return the number of
* drivers loaded. * drivers loaded.
} }




/**
* 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. * Preload drivers.
* *
return EGL_TRUE; return EGL_TRUE;
} }


loaded = (_eglPreloadUserDriver() ||
_eglPreloadGalliumDrivers());
loaded = _eglPreloadUserDriver();


_eglUnlockMutex(_eglGlobal.Mutex); _eglUnlockMutex(_eglGlobal.Mutex);



+ 2
- 74
src/gallium/state_trackers/egl/x11/native_x11.c View File



#include "state_tracker/drm_driver.h" #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 * static struct native_display *
native_create_display(void *dpy, struct native_event_handler *event_handler, native_create_display(void *dpy, struct native_event_handler *event_handler,
void *user_data) void *user_data)


static const struct native_platform x11_platform = { static const struct native_platform x11_platform = {
"X11", /* name */ "X11", /* name */
x11_create_probe,
x11_get_probe_result,
NULL, /* create_probe */
NULL, /* get_probe_result */
native_create_display native_create_display
}; };



+ 36
- 39
src/gallium/targets/egl/Makefile View File

# #
# This is the Makefile for EGL Gallium driver package. The package consists of # 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 # The following variables are examined
# #
include $(TOP)/configs/current include $(TOP)/configs/current


ST_PREFIX := st_ ST_PREFIX := st_
PIPE_PREFIX := egl_gallium_
PIPE_PREFIX := pipe_


common_CPPFLAGS := \ common_CPPFLAGS := \
-I$(TOP)/src/gallium/auxiliary \ -I$(TOP)/src/gallium/auxiliary \
egl_CPPFLAGS := \ egl_CPPFLAGS := \
-I$(TOP)/src/gallium/state_trackers/egl \ -I$(TOP)/src/gallium/state_trackers/egl \
-I$(TOP)/src/egl/main \ -I$(TOP)/src/egl/main \
-DST_PREFIX=\"$(ST_PREFIX)\"
-DPIPE_PREFIX=\"$(PIPE_PREFIX)\" -DST_PREFIX=\"$(ST_PREFIX)\"
egl_SYS := -lm -ldl -lEGL 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)),) ifneq ($(findstring x11, $(EGL_PLATFORMS)),)
egl_SYS += -lX11 -lXext -lXfixes egl_SYS += -lX11 -lXext -lXfixes
endif endif
egl_CPPFLAGS := $(sort $(egl_CPPFLAGS)) 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 pipe driver
i915_CPPFLAGS := i915_CPPFLAGS :=
i915_SYS := -ldrm_intel i915_SYS := -ldrm_intel
$(TOP)/src/gallium/drivers/svga/libsvga.a $(TOP)/src/gallium/drivers/svga/libsvga.a


# swrast (pseudo) pipe driver # 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 # OpenGL state tracker
GL_CPPFLAGS := -I$(TOP)/src/mesa $(API_DEFINES) GL_CPPFLAGS := -I$(TOP)/src/mesa $(API_DEFINES)
OUTPUTS += swrast OUTPUTS += swrast
OUTPUTS := $(addprefix $(PIPE_PREFIX), $(OUTPUTS)) 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 := $(addsuffix .so, $(OUTPUTS))
OUTPUTS := $(addprefix $(OUTPUT_PATH)/, $(OUTPUTS)) OUTPUTS := $(addprefix $(OUTPUT_PATH)/, $(OUTPUTS))


default: $(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 define mklib
$(MKLIB) -o $(notdir $@) -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \ $(MKLIB) -o $(notdir $@) -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \
-install $(OUTPUT_PATH) $(MKLIB_OPTIONS) $< \ -install $(OUTPUT_PATH) $(MKLIB_OPTIONS) $< \
$(common_SYS) $($(1)_SYS) $(common_SYS) $($(1)_SYS)
endef 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 # state trackers
$(OUTPUT_PATH)/$(ST_PREFIX)$(GL_LIB).so: st_GL.o $(GL_LIBS) $(OUTPUT_PATH)/$(ST_PREFIX)$(GL_LIB).so: st_GL.o $(GL_LIBS)

+ 3
- 3
src/gallium/targets/egl/SConscript View File

drivers += [llvmpipe] drivers += [llvmpipe]
drivers += [identity, trace, rbug] 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'], source = ['egl.c', 'pipe_swrast.c'],
LIBS = st_egl_gdi + ws_gdi + drivers + gallium + egl + env['LIBS'], LIBS = st_egl_gdi + ws_gdi + drivers + gallium + egl + env['LIBS'],
) )


env.InstallSharedLibrary(egl_gallium_swrast)
env.InstallSharedLibrary(egl_gallium)


api_libs = { api_libs = {
'OpenVG': vgapi + st_vega, 'OpenVG': vgapi + st_vega,

+ 144
- 21
src/gallium/targets/egl/egl.c View File

#include "egllog.h" #include "egllog.h"


#include "state_tracker/st_api.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 "state_tracker/drm_driver.h"
#include "common/egl_g3d_loader.h"


struct egl_g3d_loader egl_g3d_loader; struct egl_g3d_loader egl_g3d_loader;


static struct st_module { static struct st_module {
boolean initialized; boolean initialized;
const char *name;
char *name;
struct util_dl_library *lib; struct util_dl_library *lib;
struct st_api *stapi; struct st_api *stapi;
} st_modules[ST_API_COUNT]; } 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 static EGLBoolean
dlopen_st_module_cb(const char *dir, size_t len, void *callback_data) dlopen_st_module_cb(const char *dir, size_t len, void *callback_data)
{ {
{ {
struct st_api *(*create_api)(void); struct st_api *(*create_api)(void);


stmod->name = name;
stmod->name = loader_strdup(name);
if (stmod->name) if (stmod->name)
_eglSearchPathForEach(dlopen_st_module_cb, (void *) stmod); _eglSearchPathForEach(dlopen_st_module_cb, (void *) stmod);
else else
} }
} }


if (!stmod->stapi)
if (!stmod->stapi) {
FREE(stmod->name);
stmod->name = NULL; stmod->name = NULL;
}


return (stmod->stapi != 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 * static struct st_api *
get_st_api(enum st_api_type api) get_st_api(enum st_api_type api)
{ {
return stapi; 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 * static struct pipe_screen *
create_drm_screen(const char *name, int fd) 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 * static struct pipe_screen *
create_sw_screen(struct sw_winsys *ws) 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 * static const struct egl_g3d_loader *
util_dl_close(stmod->lib); util_dl_close(stmod->lib);
stmod->lib = NULL; stmod->lib = NULL;
} }
stmod->name = NULL;
if (stmod->name) {
FREE(stmod->name);
stmod->name = NULL;
}
stmod->initialized = FALSE; 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 static void

+ 1
- 0
src/gallium/targets/egl/pipe_i965.c View File

return screen; return screen;
} }


PUBLIC
DRM_DRIVER_DESCRIPTOR("i965", "i965", create_screen) DRM_DRIVER_DESCRIPTOR("i965", "i965", create_screen)

+ 1
- 0
src/gallium/targets/egl/pipe_nouveau.c View File

return screen; return screen;
} }


PUBLIC
DRM_DRIVER_DESCRIPTOR("nouveau", "nouveau", create_screen) DRM_DRIVER_DESCRIPTOR("nouveau", "nouveau", create_screen)

+ 1
- 0
src/gallium/targets/egl/pipe_radeon.c View File

return screen; return screen;
} }


PUBLIC
DRM_DRIVER_DESCRIPTOR("radeon", "radeon", create_screen) DRM_DRIVER_DESCRIPTOR("radeon", "radeon", create_screen)

+ 18
- 0
src/gallium/targets/egl/pipe_swrast.c View File



#include "target-helpers/inline_sw_helper.h"
#include "target-helpers/inline_debug_helper.h"
#include "state_tracker/drm_driver.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) 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;
}

+ 1
- 0
src/gallium/targets/egl/pipe_vmwgfx.c View File

return screen; return screen;
} }


PUBLIC
DRM_DRIVER_DESCRIPTOR("vmwgfx", "vmwgfx", create_screen) DRM_DRIVER_DESCRIPTOR("vmwgfx", "vmwgfx", create_screen)

Loading…
Cancel
Save