diff options
author | Chia-I Wu <olv@lunarg.com> | 2010-06-29 14:58:33 +0800 |
---|---|---|
committer | Chia-I Wu <olv@lunarg.com> | 2010-06-29 17:16:20 +0800 |
commit | d5ab243d5a5bacbd2ba615d40f13c8ab37364745 (patch) | |
tree | bbf3c92d3c512e0d12eab3a7036c60c8e2cf7171 | |
parent | d8e0e114567ec19fd59f974080a418dc959cc9b6 (diff) |
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.
26 files changed, 556 insertions, 424 deletions
diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile index e117f15d93..9e9e479e7e 100644 --- a/src/gallium/state_trackers/egl/Makefile +++ b/src/gallium/state_trackers/egl/Makefile @@ -5,14 +5,12 @@ common_INCLUDES = \ -I. \ -I$(TOP)/src/gallium/include \ -I$(TOP)/src/gallium/auxiliary \ - -I$(TOP)/src/gallium/drivers \ -I$(TOP)/src/egl/main \ -I$(TOP)/include common_SOURCES = $(wildcard common/*.c) common_OBJECTS = $(common_SOURCES:.c=.o) - x11_INCLUDES = \ -I$(TOP)/src/gallium/drivers \ -I$(TOP)/src/glx \ @@ -31,7 +29,7 @@ kms_SOURCES = $(wildcard kms/*.c) kms_OBJECTS = $(kms_SOURCES:.c=.o) -fbdev_INCLUDES = -I$(TOP)/src/gallium/winsys/sw -I$(TOP)/src/gallium/drivers +fbdev_INCLUDES = -I$(TOP)/src/gallium/winsys/sw fbdev_SOURCES = $(wildcard fbdev/*.c) fbdev_OBJECTS = $(fbdev_SOURCES:.c=.o) @@ -40,7 +38,7 @@ ALL_INCLUDES = $(common_INCLUDES) $(x11_INCLUDES) $(kms_INCLUDES) $(fbdev_INCLUD ALL_SOURCES = $(common_SOURCES) $(x11_SOURCES) $(kms_SOURCES) $(fbdev_SOURCES) EGL_OBJECTS = $(common_OBJECTS) -EGL_CPPFLAGS = $(common_INCLUDES) -DST_MODULE_PREFIX=\"st_\" +EGL_CPPFLAGS = $(common_INCLUDES) # add backends ifneq ($(findstring x11, $(EGL_PLATFORMS)),) diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index 36354dd42e..494d6dd8b6 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -35,34 +35,10 @@ #include "egl_g3d.h" #include "egl_g3d_api.h" #include "egl_g3d_st.h" +#include "egl_g3d_loader.h" #include "native.h" /** - * Initialize the state trackers. - */ -static void -egl_g3d_init_st(_EGLDriver *drv) -{ - struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); - EGLint i; - - /* already initialized */ - if (gdrv->api_mask) - return; - - egl_g3d_init_st_apis(gdrv->stapis); - for (i = 0; i < ST_API_COUNT; i++) { - if (gdrv->stapis[i]) - gdrv->api_mask |= egl_g3d_st_api_bit(i); - } - - if (gdrv->api_mask) - _eglLog(_EGL_DEBUG, "Driver API mask: 0x%x", gdrv->api_mask); - else - _eglLog(_EGL_WARNING, "No supported client API"); -} - -/** * Get the native platform. */ static const struct native_platform * @@ -323,7 +299,6 @@ egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const struct native_config *nconf, enum pipe_format depth_stencil_format) { - struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); struct egl_g3d_config *gconf = egl_g3d_config(conf); EGLint buffer_mask, api_mask; EGLBoolean valid; @@ -347,7 +322,7 @@ egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ? ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT; - api_mask = gdrv->api_mask;; + api_mask = dpy->ClientAPIsMask; /* this is required by EGL, not by OpenGL ES */ if (nconf->window_bit && gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT) @@ -472,8 +447,26 @@ egl_g3d_invalid_surface(struct native_display *ndpy, gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi); } +static struct pipe_screen * +egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd) +{ + _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + return gdpy->loader->create_drm_screen(name, fd); +} + +static struct pipe_screen * +egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws) +{ + _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + return gdpy->loader->create_sw_screen(ws); +} + static struct native_event_handler egl_g3d_native_event_handler = { - egl_g3d_invalid_surface + egl_g3d_invalid_surface, + egl_g3d_new_drm_screen, + egl_g3d_new_sw_screen }; static EGLBoolean @@ -529,20 +522,25 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, _eglError(EGL_BAD_ALLOC, "eglInitialize"); goto fail; } + gdpy->loader = gdrv->loader; dpy->DriverData = gdpy; _eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay); gdpy->native = nplat->create_display(dpy->PlatformDisplay, - &egl_g3d_native_event_handler); + &egl_g3d_native_event_handler, (void *) dpy); if (!gdpy->native) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); goto fail; } - gdpy->native->user_data = (void *) dpy; - - egl_g3d_init_st(&gdrv->base); - dpy->ClientAPIsMask = gdrv->api_mask; + if (gdpy->loader->api_mask & (1 << ST_API_OPENGL)) + dpy->ClientAPIsMask |= EGL_OPENGL_BIT; + if (gdpy->loader->api_mask & (1 << ST_API_OPENGL_ES1)) + dpy->ClientAPIsMask |= EGL_OPENGL_ES_BIT; + if (gdpy->loader->api_mask & (1 << ST_API_OPENGL_ES2)) + dpy->ClientAPIsMask |= EGL_OPENGL_ES2_BIT; + if (gdpy->loader->api_mask & (1 << ST_API_OPENVG)) + dpy->ClientAPIsMask |= EGL_OPENVG_BIT; gdpy->smapi = egl_g3d_create_st_manager(dpy); if (!gdpy->smapi) { @@ -583,22 +581,15 @@ static _EGLProc egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) { struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); - _EGLProc proc; - EGLint i; + struct st_api *stapi = NULL; - /* in case this is called before a display is initialized */ - egl_g3d_init_st(&gdrv->base); - - for (i = 0; i < ST_API_COUNT; i++) { - struct st_api *stapi = gdrv->stapis[i]; - if (stapi) { - proc = (_EGLProc) stapi->get_proc_address(stapi, procname); - if (proc) - return proc; - } - } + if (procname && procname[0] == 'v' && procname[1] == 'g') + stapi = gdrv->loader->get_st_api(ST_API_OPENVG); + else if (procname && procname[0] == 'g' && procname[1] == 'l') + stapi = gdrv->loader->guess_gl_api(); - return (_EGLProc) NULL; + return (_EGLProc) ((stapi) ? + stapi->get_proc_address(stapi, procname) : NULL); } static EGLint @@ -628,18 +619,8 @@ egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy) return score; } -static void -egl_g3d_unload(_EGLDriver *drv) -{ - struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); - - egl_g3d_destroy_st_apis(); - egl_g3d_destroy_probe(drv, NULL); - FREE(gdrv); -} - _EGLDriver * -_eglMain(const char *args) +egl_g3d_create_driver(const struct egl_g3d_loader *loader) { struct egl_g3d_driver *gdrv; @@ -647,17 +628,28 @@ _eglMain(const char *args) if (!gdrv) return NULL; + gdrv->loader = loader; + egl_g3d_init_driver_api(&gdrv->base); gdrv->base.API.Initialize = egl_g3d_initialize; gdrv->base.API.Terminate = egl_g3d_terminate; gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address; - gdrv->base.Name = "Gallium"; gdrv->base.Probe = egl_g3d_probe; - gdrv->base.Unload = egl_g3d_unload; /* the key is " EGL G3D" */ gdrv->probe_key = 0x0E61063D; + /* to be filled by the caller */ + gdrv->base.Name = NULL; + gdrv->base.Unload = NULL; + return &gdrv->base; } + +void +egl_g3d_destroy_driver(_EGLDriver *drv) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + FREE(gdrv); +} diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h index a498dcf6f6..d9ecb208e0 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d.h @@ -41,12 +41,11 @@ #include "native.h" #include "egl_g3d_st.h" +#include "egl_g3d_loader.h" struct egl_g3d_driver { _EGLDriver base; - struct st_api *stapis[ST_API_COUNT]; - EGLint api_mask; - + const struct egl_g3d_loader *loader; const struct native_platform *platforms[_EGL_NUM_PLATFORMS]; EGLint probe_key; }; @@ -54,6 +53,7 @@ struct egl_g3d_driver { struct egl_g3d_display { struct native_display *native; + const struct egl_g3d_loader *loader; struct st_manager *smapi; struct pipe_context *pipe; }; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c index 255a1fb730..308fa96d99 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c @@ -35,6 +35,7 @@ #include "egl_g3d_api.h" #include "egl_g3d_image.h" #include "egl_g3d_st.h" +#include "egl_g3d_loader.h" #include "native.h" /** @@ -44,7 +45,6 @@ static struct st_api * egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) { struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); - struct st_api *stapi; EGLint idx = -1; switch (ctx->ClientAPI) { @@ -73,8 +73,7 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) break; } - stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL; - return stapi; + return (idx >= 0) ? gdrv->loader->get_st_api(idx) : NULL; } static _EGLContext * diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_loader.h b/src/gallium/state_trackers/egl/common/egl_g3d_loader.h new file mode 100644 index 0000000000..c9141f8ad4 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_loader.h @@ -0,0 +1,54 @@ +/* + * 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 <olv@lunarg.com> + */ + +#ifndef _EGL_G3D_LOADER_H_ +#define _EGL_G3D_LOADER_H_ + +#include "pipe/p_compiler.h" +#include "state_tracker/st_api.h" +#include "egltypedefs.h" + +struct pipe_screen; +struct sw_winsys; + +struct egl_g3d_loader { + uint api_mask; + struct st_api *(*get_st_api)(enum st_api_type api); + struct st_api *(*guess_gl_api)(void); + + struct pipe_screen *(*create_drm_screen)(const char *name, int fd); + struct pipe_screen *(*create_sw_screen)(struct sw_winsys *ws); +}; + +_EGLDriver * +egl_g3d_create_driver(const struct egl_g3d_loader *loader); + +void +egl_g3d_destroy_driver(_EGLDriver *drv); + +#endif /* _EGL_G3D_LOADER_H_ */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.c b/src/gallium/state_trackers/egl/common/egl_g3d_st.c index 0668f5c91a..05cdb0d421 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_st.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.c @@ -49,173 +49,6 @@ egl_g3d_st_manager(struct st_manager *smapi) return (struct egl_g3d_st_manager *) smapi; } -static struct egl_g3d_st_module { - const char *filename; - struct util_dl_library *lib; - struct st_api *stapi; -} egl_g3d_st_modules[ST_API_COUNT]; - -static EGLBoolean -egl_g3d_search_path_callback(const char *dir, size_t len, void *callback_data) -{ - struct egl_g3d_st_module *stmod = - (struct egl_g3d_st_module *) callback_data; - char path[1024]; - int ret; - - if (!len) { - stmod->lib = util_dl_open(stmod->filename); - return !(stmod->lib); - } - - ret = util_snprintf(path, sizeof(path), - "%.*s/%s", len, dir, stmod->filename); - if (ret > 0 && ret < sizeof(path)) - stmod->lib = util_dl_open(path); - - return !(stmod->lib); -} - -static boolean -egl_g3d_load_st_module(struct egl_g3d_st_module *stmod, - const char *filename, const char *procname) -{ - struct st_api *(*create_api)(void); - - stmod->filename = filename; - if (stmod->filename) - _eglSearchPathForEach(egl_g3d_search_path_callback, (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) { - return TRUE; - } - else { - stmod->filename = NULL; - return FALSE; - } -} - -#ifdef PIPE_OS_WINDOWS -#define ST_MODULE_SUFFIX ".dll" -#else -#define ST_MODULE_SUFFIX ".so" -#endif - -void -egl_g3d_init_st_apis(struct st_api *stapis[ST_API_COUNT]) -{ - const char *skip_checks[ST_API_COUNT], *symbols[ST_API_COUNT]; - const char *filenames[ST_API_COUNT][4]; - struct util_dl_library *self; - int num_needed = 0, api; - - self = util_dl_open(NULL); - - /* collect the necessary data for loading modules */ - for (api = 0; api < ST_API_COUNT; api++) { - int count = 0; - - switch (api) { - case ST_API_OPENGL: - skip_checks[api] = "glColor4d"; - symbols[api] = ST_CREATE_OPENGL_SYMBOL; - filenames[api][count++] = ST_MODULE_PREFIX "GL" ST_MODULE_SUFFIX; - break; - case ST_API_OPENGL_ES1: - skip_checks[api] = "glColor4x"; - symbols[api] = ST_CREATE_OPENGL_ES1_SYMBOL; - filenames[api][count++] = ST_MODULE_PREFIX "GLESv1_CM" ST_MODULE_SUFFIX; - filenames[api][count++] = ST_MODULE_PREFIX "GL" ST_MODULE_SUFFIX; - break; - case ST_API_OPENGL_ES2: - skip_checks[api] = "glShaderBinary"; - symbols[api] = ST_CREATE_OPENGL_ES2_SYMBOL; - filenames[api][count++] = ST_MODULE_PREFIX "GLESv2" ST_MODULE_SUFFIX; - filenames[api][count++] = ST_MODULE_PREFIX "GL" ST_MODULE_SUFFIX; - break; - case ST_API_OPENVG: - skip_checks[api] = "vgClear"; - symbols[api] = ST_CREATE_OPENVG_SYMBOL; - filenames[api][count++]= ST_MODULE_PREFIX "OpenVG" ST_MODULE_SUFFIX; - break; - default: - assert(!"Unknown API Type\n"); - skip_checks[api] = NULL; - symbols[api] = NULL; - break; - } - filenames[api][count++]= NULL; - assert(count < Elements(filenames[api])); - - /* heuristicically decide if the module is needed */ - if (!self || !skip_checks[api] || - util_dl_get_proc_address(self, skip_checks[api])) { - /* unset so the module is not skipped */ - skip_checks[api] = NULL; - num_needed++; - } - } - /* mark all moudles needed if we wrongly decided that none is needed */ - if (!num_needed) - memset(skip_checks, 0, sizeof(skip_checks)); - - if (self) - util_dl_close(self); - - for (api = 0; api < ST_API_COUNT; api++) { - struct egl_g3d_st_module *stmod = &egl_g3d_st_modules[api]; - const char **p; - - /* skip the module */ - if (skip_checks[api]) - continue; - - /* try all filenames, including NULL */ - for (p = filenames[api]; *p; p++) { - if (egl_g3d_load_st_module(stmod, *p, symbols[api])) - break; - } - if (!stmod->stapi) - egl_g3d_load_st_module(stmod, NULL, symbols[api]); - - stapis[api] = stmod->stapi; - } -} - -void -egl_g3d_destroy_st_apis(void) -{ - int api; - - for (api = 0; api < ST_API_COUNT; api++) { - struct egl_g3d_st_module *stmod = &egl_g3d_st_modules[api]; - - if (stmod->stapi) { - stmod->stapi->destroy(stmod->stapi); - stmod->stapi = NULL; - } - if (stmod->lib) { - util_dl_close(stmod->lib); - stmod->lib = NULL; - } - stmod->filename = NULL; - } -} - static boolean egl_g3d_st_manager_get_egl_image(struct st_manager *smapi, struct st_context_iface *stctx, diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.h b/src/gallium/state_trackers/egl/common/egl_g3d_st.h index ee53799b02..aa25cc042d 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_st.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.h @@ -33,12 +33,6 @@ #include "state_tracker/st_api.h" #include "egltypedefs.h" -void -egl_g3d_init_st_apis(struct st_api *stapis[ST_API_COUNT]); - -void -egl_g3d_destroy_st_apis(void); - struct st_manager * egl_g3d_create_st_manager(_EGLDisplay *dpy); diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h index c4d23bf541..7e84d74ea7 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -32,6 +32,7 @@ #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "state_tracker/sw_winsys.h" #include "native_probe.h" #include "native_modeset.h" @@ -196,6 +197,11 @@ struct native_event_handler { void (*invalid_surface)(struct native_display *ndpy, struct native_surface *nsurf, unsigned int seq_num); + + struct pipe_screen *(*new_drm_screen)(struct native_display *ndpy, + const char *name, int fd); + struct pipe_screen *(*new_sw_screen)(struct native_display *ndpy, + struct sw_winsys *ws); }; /** @@ -225,7 +231,8 @@ struct native_platform { enum native_probe_result (*get_probe_result)(struct native_probe *nprobe); struct native_display *(*create_display)(void *dpy, - struct native_event_handler *handler); + struct native_event_handler *handler, + void *user_data); }; const struct native_platform * diff --git a/src/gallium/state_trackers/egl/common/native_helper.c b/src/gallium/state_trackers/egl/common/native_helper.c index 206817ed66..7832b2b693 100644 --- a/src/gallium/state_trackers/egl/common/native_helper.c +++ b/src/gallium/state_trackers/egl/common/native_helper.c @@ -31,9 +31,6 @@ #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "pipe/p_state.h" -#include "softpipe/sp_public.h" -#include "llvmpipe/lp_public.h" -#include "target-helpers/wrap_screen.h" #include "native_helper.h" @@ -236,18 +233,3 @@ resource_surface_present(struct resource_surface *rsurf, return TRUE; } - -struct pipe_screen * -native_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; -} diff --git a/src/gallium/state_trackers/egl/common/native_helper.h b/src/gallium/state_trackers/egl/common/native_helper.h index bdb9629466..d1569ac3ea 100644 --- a/src/gallium/state_trackers/egl/common/native_helper.h +++ b/src/gallium/state_trackers/egl/common/native_helper.h @@ -69,6 +69,3 @@ boolean resource_surface_present(struct resource_surface *rsurf, enum native_attachment which, void *winsys_drawable_handle); - -struct pipe_screen * -native_create_sw_screen(struct sw_winsys *ws); diff --git a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c index c0bc7b2462..7c276c22f8 100644 --- a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c +++ b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c @@ -386,8 +386,10 @@ fbdev_display_init(struct native_display *ndpy) return FALSE; ws = fbdev_create_sw_winsys(fbdpy->fd, fbdpy->config.color_format); - if (ws) - fbdpy->base.screen = native_create_sw_screen(ws); + if (ws) { + fbdpy->base.screen = + fbdpy->event_handler->new_sw_screen(&fbdpy->base, ws); + } if (fbdpy->base.screen) { if (!fbdpy->base.screen->is_format_supported(fbdpy->base.screen, @@ -402,7 +404,8 @@ fbdev_display_init(struct native_display *ndpy) } static struct native_display * -fbdev_display_create(int fd, struct native_event_handler *event_handler) +fbdev_display_create(int fd, struct native_event_handler *event_handler, + void *user_data) { struct fbdev_display *fbdpy; @@ -412,6 +415,7 @@ fbdev_display_create(int fd, struct native_event_handler *event_handler) fbdpy->fd = fd; fbdpy->event_handler = event_handler; + fbdpy->base.user_data = user_data; if (!fbdev_display_init(&fbdpy->base)) { FREE(fbdpy); @@ -428,7 +432,8 @@ fbdev_display_create(int fd, struct native_event_handler *event_handler) } 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) { struct native_display *ndpy; int fd; @@ -443,7 +448,7 @@ native_create_display(void *dpy, struct native_event_handler *event_handler) if (fd < 0) return NULL; - ndpy = fbdev_display_create(fd, event_handler); + ndpy = fbdev_display_create(fd, event_handler, user_data); if (!ndpy) close(fd); diff --git a/src/gallium/state_trackers/egl/gdi/native_gdi.c b/src/gallium/state_trackers/egl/gdi/native_gdi.c index 4ec229a3f2..ed955c4132 100644 --- a/src/gallium/state_trackers/egl/gdi/native_gdi.c +++ b/src/gallium/state_trackers/egl/gdi/native_gdi.c @@ -343,10 +343,11 @@ gdi_display_destroy(struct native_display *ndpy) } static struct native_display * -gdi_create_display(HDC hDC, struct pipe_screen *screen, - struct native_event_handler *event_handler) +gdi_create_display(HDC hDC, struct native_event_handler *event_handler, + void *user_data) { struct gdi_display *gdpy; + struct sw_winsys *winsys; gdpy = CALLOC_STRUCT(gdi_display); if (!gdpy) @@ -354,8 +355,21 @@ gdi_create_display(HDC hDC, struct pipe_screen *screen, gdpy->hDC = hDC; gdpy->event_handler = event_handler; + gdpy->base.user_data = user_data; + + winsys = gdi_create_sw_winsys(); + if (!winsys) { + FREE(gdpy); + return NULL; + } - gdpy->base.screen = screen; + gdpy->base.screen = gdpy->event_handler->create_sw_screen(winsys); + if (!gdpy->base.screen) { + if (winsys->destroy) + winsys->destroy(winsys); + FREE(gdpy); + return NULL; + } gdpy->base.destroy = gdi_display_destroy; gdpy->base.get_param = gdi_display_get_param; @@ -367,23 +381,10 @@ gdi_create_display(HDC hDC, struct pipe_screen *screen, } 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) { - struct sw_winsys *winsys; - struct pipe_screen *screen; - - winsys = gdi_create_sw_winsys(); - if (!winsys) - return NULL; - - screen = native_create_sw_screen(winsys); - if (!screen) { - if (winsys->destroy) - winsys->destroy(winsys); - return NULL; - } - - return gdi_create_display((HDC) dpy, screen, event_handler); + return gdi_create_display((HDC) dpy, event_handler, user_data); } static const struct native_platform gdi_platform = { diff --git a/src/gallium/state_trackers/egl/kms/native_kms.c b/src/gallium/state_trackers/egl/kms/native_kms.c index dd4ea71140..5833d27a25 100644 --- a/src/gallium/state_trackers/egl/kms/native_kms.c +++ b/src/gallium/state_trackers/egl/kms/native_kms.c @@ -23,6 +23,10 @@ * DEALINGS IN THE SOFTWARE. */ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "util/u_debug.h" @@ -33,7 +37,6 @@ #include "egllog.h" #include "native_kms.h" -#include "state_tracker/drm_driver.h" static boolean kms_surface_validate(struct native_surface *nsurf, uint attachment_mask, @@ -656,7 +659,7 @@ kms_display_destroy(struct native_display *ndpy) kdpy->base.screen->destroy(kdpy->base.screen); if (kdpy->fd >= 0) - drmClose(kdpy->fd); + close(kdpy->fd); FREE(kdpy); } @@ -668,50 +671,23 @@ static boolean kms_display_init_screen(struct native_display *ndpy) { struct kms_display *kdpy = kms_display(ndpy); - int fd; - - fd = kdpy->fd; - if (fd >= 0) { - drmVersionPtr version = drmGetVersion(fd); - if (!version || strcmp(version->name, driver_descriptor.driver_name)) { - if (version) { - _eglLog(_EGL_WARNING, "unknown driver name %s", version->name); - drmFreeVersion(version); - } - else { - _eglLog(_EGL_WARNING, "invalid fd %d", fd); - } - - return FALSE; - } + drmVersionPtr version; - drmFreeVersion(version); - } - else { - fd = drmOpen(driver_descriptor.driver_name, NULL); - } - - if (fd < 0) { - _eglLog(_EGL_WARNING, "failed to open DRM device"); + version = drmGetVersion(kdpy->fd); + if (!version) { + _eglLog(_EGL_WARNING, "invalid fd %d", kdpy->fd); return FALSE; } -#if 0 - if (drmSetMaster(fd)) { - _eglLog(_EGL_WARNING, "failed to become DRM master"); - return FALSE; - } -#endif + kdpy->base.screen = kdpy->event_handler->new_drm_screen(&kdpy->base, + version->name, kdpy->fd);; + drmFreeVersion(version); - kdpy->base.screen = driver_descriptor.create_screen(fd); if (!kdpy->base.screen) { _eglLog(_EGL_WARNING, "failed to create DRM screen"); - drmClose(fd); return FALSE; } - kdpy->fd = fd; - return TRUE; } @@ -723,7 +699,8 @@ static struct native_display_modeset kms_display_modeset = { }; static struct native_display * -kms_create_display(int fd, struct native_event_handler *event_handler) +kms_create_display(int fd, struct native_event_handler *event_handler, + void *user_data) { struct kms_display *kdpy; @@ -731,8 +708,10 @@ kms_create_display(int fd, struct native_event_handler *event_handler) if (!kdpy) return NULL; - kdpy->event_handler = event_handler; kdpy->fd = fd; + kdpy->event_handler = event_handler; + kdpy->base.user_data = user_data; + if (!kms_display_init_screen(&kdpy->base)) { kms_display_destroy(&kdpy->base); return NULL; @@ -769,39 +748,32 @@ kms_create_display(int fd, struct native_event_handler *event_handler) } 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) { - struct native_display *ndpy; int fd; - /* well, this makes fd 0 being ignored */ - fd = (dpy) ? (int) pointer_to_intptr(dpy) : -1; - ndpy = kms_create_display(fd, event_handler); - - return ndpy; -} - -static void -kms_init_platform(struct native_platform *nplat) -{ - static char kms_name[32]; - - if (nplat->name) - return; - - util_snprintf(kms_name, sizeof(kms_name), "KMS/%s", driver_descriptor.name); + if (dpy) { + fd = dup((int) pointer_to_intptr(dpy)); + } + else { + fd = open("/dev/dri/card0", O_RDWR); + } + if (fd < 0) + return NULL; - nplat->name = kms_name; - nplat->create_probe = NULL; - nplat->get_probe_result = NULL; - nplat->create_display = native_create_display; + return kms_create_display(fd, event_handler, user_data); } -static struct native_platform kms_platform; +static const struct native_platform kms_platform = { + "KMS", /* name */ + NULL, /* create_probe */ + NULL, /* get_probe_result */ + native_create_display +}; const struct native_platform * native_get_kms_platform(void) { - kms_init_platform(&kms_platform); return &kms_platform; } diff --git a/src/gallium/state_trackers/egl/kms/native_kms.h b/src/gallium/state_trackers/egl/kms/native_kms.h index 14cf5a641a..cd8e4ff0b2 100644 --- a/src/gallium/state_trackers/egl/kms/native_kms.h +++ b/src/gallium/state_trackers/egl/kms/native_kms.h @@ -32,6 +32,7 @@ #include "pipe/p_compiler.h" #include "util/u_format.h" #include "pipe/p_state.h" +#include "state_tracker/drm_driver.h" #include "common/native.h" #include "common/native_helper.h" diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c index 7464354fe6..1bef59d864 100644 --- a/src/gallium/state_trackers/egl/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -692,7 +692,6 @@ static boolean dri2_display_init_screen(struct native_display *ndpy) { struct dri2_display *dri2dpy = dri2_display(ndpy); - const char *driver = driver_descriptor.name; int fd; if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) || @@ -703,19 +702,15 @@ dri2_display_init_screen(struct native_display *ndpy) dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr, &dri2dpy->dri_major, &dri2dpy->dri_minor); - if (!dri2dpy->dri_driver || !driver || - strcmp(dri2dpy->dri_driver, driver) != 0) { - _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s", - dri2dpy->dri_driver, driver); - return FALSE; - } fd = x11_screen_enable_dri2(dri2dpy->xscr, dri2_display_invalidate_buffers, &dri2dpy->base); if (fd < 0) return FALSE; - dri2dpy->base.screen = driver_descriptor.create_screen(fd); + dri2dpy->base.screen = + dri2dpy->event_handler->new_drm_screen(&dri2dpy->base, + dri2dpy->dri_driver, fd); if (!dri2dpy->base.screen) { _eglLog(_EGL_WARNING, "failed to create DRM screen"); return FALSE; @@ -739,7 +734,8 @@ dri2_display_hash_table_compare(void *key1, void *key2) struct native_display * x11_create_dri2_display(Display *dpy, - struct native_event_handler *event_handler) + struct native_event_handler *event_handler, + void *user_data) { struct dri2_display *dri2dpy; @@ -748,6 +744,7 @@ x11_create_dri2_display(Display *dpy, return NULL; dri2dpy->event_handler = event_handler; + dri2dpy->base.user_data = user_data; dri2dpy->dpy = dpy; if (!dri2dpy->dpy) { diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c index 7eec563bdf..f0519405d3 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.c +++ b/src/gallium/state_trackers/egl/x11/native_x11.c @@ -23,7 +23,6 @@ * DEALINGS IN THE SOFTWARE. */ -#include <string.h> #include "util/u_debug.h" #include "util/u_memory.h" #include "util/u_string.h" @@ -107,50 +106,38 @@ x11_get_probe_result(struct native_probe *nprobe) } 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) { struct native_display *ndpy = NULL; boolean force_sw; force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE); - if (!driver_descriptor.create_screen) - force_sw = TRUE; - if (!force_sw) { - ndpy = x11_create_dri2_display((Display *) dpy, event_handler); + ndpy = x11_create_dri2_display((Display *) dpy, + event_handler, user_data); } if (!ndpy) { EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING; _eglLog(level, "use software fallback"); - ndpy = x11_create_ximage_display((Display *) dpy, event_handler); + ndpy = x11_create_ximage_display((Display *) dpy, + event_handler, user_data); } return ndpy; } -static void -x11_init_platform(struct native_platform *nplat) -{ - static char x11_name[32]; - - if (nplat->name) - return; - - util_snprintf(x11_name, sizeof(x11_name), "X11/%s", driver_descriptor.name); - - nplat->name = x11_name; - nplat->create_probe = x11_create_probe; - nplat->get_probe_result = x11_get_probe_result; - nplat->create_display = native_create_display; -} - -static struct native_platform x11_platform; +static const struct native_platform x11_platform = { + "X11", /* name */ + x11_create_probe, + x11_get_probe_result, + native_create_display +}; const struct native_platform * native_get_x11_platform(void) { - x11_init_platform(&x11_platform); return &x11_platform; } diff --git a/src/gallium/state_trackers/egl/x11/native_x11.h b/src/gallium/state_trackers/egl/x11/native_x11.h index a1c32c3455..0b47837e1b 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.h +++ b/src/gallium/state_trackers/egl/x11/native_x11.h @@ -30,10 +30,12 @@ struct native_display * x11_create_ximage_display(Display *dpy, - struct native_event_handler *event_handler); + struct native_event_handler *event_handler, + void *user_data); struct native_display * x11_create_dri2_display(Display *dpy, - struct native_event_handler *event_handler); + struct native_event_handler *event_handler, + void *user_data); #endif /* _NATIVE_X11_H_ */ diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c index ee10a04cfb..4b32f6e36e 100644 --- a/src/gallium/state_trackers/egl/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl/x11/native_ximage.c @@ -442,7 +442,8 @@ ximage_display_destroy(struct native_display *ndpy) struct native_display * x11_create_ximage_display(Display *dpy, - struct native_event_handler *event_handler) + struct native_event_handler *event_handler, + void *user_data) { struct ximage_display *xdpy; struct sw_winsys *winsys = NULL; @@ -462,6 +463,7 @@ x11_create_ximage_display(Display *dpy, } xdpy->event_handler = event_handler; + xdpy->base.user_data = user_data; xdpy->xscr_number = DefaultScreen(xdpy->dpy); xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number); @@ -472,7 +474,8 @@ x11_create_ximage_display(Display *dpy, if (!winsys) goto fail; - xdpy->base.screen = native_create_sw_screen(winsys); + xdpy->base.screen = + xdpy->event_handler->new_sw_screen(&xdpy->base, winsys); if (!xdpy->base.screen) goto fail; 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 <olv@lunarg.com> + */ + +#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; |