Commit 97f2952b authored by Ander Conselvan de Oliveira's avatar Ander Conselvan de Oliveira Committed by Kristian H. Kristensen

gl-renderer: Build as a loadable module

The time spent loading EGL and GLES libraries from disk can be a
considerable hit in some embedded use cases. If Weston is compiled
with EGL support, the binary will depend on those libraries, even if
a software renderer is in use.

This patch splits the GL renderer into a separate loadable module,
and moves the dependency on EGL and GLES to it. The backends still
need the EGL headers for the native types and EGLint. The function
load_module() is renamed to weston_load_module() and exported, so
that it can be used by the backends.

The gl renderer interface is changed so that there is only one symbol
that needs to be dlsym()'d. This symbol contains pointers to all the
functions and data necessary to interact with the renderer. As a side
effect, this change simplifies gl-renderer.h a great deal.
parent 70e2e684
......@@ -62,7 +62,7 @@ AC_ARG_ENABLE(egl, [ --disable-egl],,
AM_CONDITIONAL(ENABLE_EGL, test x$enable_egl = xyes)
if test x$enable_egl = xyes; then
AC_DEFINE([ENABLE_EGL], [1], [Build Weston with EGL support])
COMPOSITOR_MODULES="$COMPOSITOR_MODULES egl >= 7.10 glesv2"
PKG_CHECK_MODULES(EGL, [egl >= 7.10 glesv2])
fi
AC_ARG_ENABLE(xkbcommon,
......
......@@ -40,7 +40,6 @@ weston_SOURCES = \
subsurface-server-protocol.h \
bindings.c \
animation.c \
gl-renderer.h \
noop-renderer.c \
pixman-renderer.c \
pixman-renderer.h \
......@@ -50,13 +49,6 @@ weston_SOURCES = \
weston-launch.h \
weston-egl-ext.h
if ENABLE_EGL
weston_SOURCES += \
gl-renderer.c \
vertex-clipping.c \
vertex-clipping.h
endif
git-version.h : .FORCE
$(AM_V_GEN)(echo "#define BUILD_ID \"$(shell git --git-dir=$(top_srcdir)/.git describe --always --dirty) $(shell git --git-dir=$(top_srcdir)/.git log -1 --format='%s (%ci)')\"" > $@-new; \
cmp -s $@ $@-new || cp $@-new $@; \
......@@ -104,6 +96,7 @@ module_LTLIBRARIES = \
$(tablet_shell) \
$(cms_static) \
$(cms_colord) \
$(gl_renderer) \
$(x11_backend) \
$(drm_backend) \
$(wayland_backend) \
......@@ -119,6 +112,21 @@ else
noinst_LTLIBRARIES += $(rpi_backend)
endif
if ENABLE_EGL
gl_renderer = gl-renderer.la
gl_renderer_la_LDFLAGS = -module -avoid-version
gl_renderer_la_LIBADD = $(COMPOSITOR_LIBS) $(EGL_LIBS)
gl_renderer_la_CFLAGS = \
$(COMPOSITOR_CFLAGS) \
$(EGL_CFLAGS) \
$(GCC_CFLAGS)
gl_renderer_la_SOURCES = \
gl-renderer.h \
gl-renderer.c \
vertex-clipping.c \
vertex-clipping.h
endif
if ENABLE_X11_COMPOSITOR
x11_backend = x11-backend.la
x11_backend_la_LDFLAGS = -module -avoid-version
......@@ -126,6 +134,7 @@ x11_backend_la_LIBADD = $(COMPOSITOR_LIBS) $(X11_COMPOSITOR_LIBS) \
../shared/libshared-cairo.la
x11_backend_la_CFLAGS = \
$(COMPOSITOR_CFLAGS) \
$(EGL_CFLAGS) \
$(PIXMAN_CFLAGS) \
$(CAIRO_CFLAGS) \
$(X11_COMPOSITOR_CFLAGS) \
......@@ -140,6 +149,7 @@ drm_backend_la_LIBADD = $(COMPOSITOR_LIBS) $(DRM_COMPOSITOR_LIBS) \
../shared/libshared.la -lrt
drm_backend_la_CFLAGS = \
$(COMPOSITOR_CFLAGS) \
$(EGL_CFLAGS) \
$(DRM_COMPOSITOR_CFLAGS) \
$(GCC_CFLAGS)
drm_backend_la_SOURCES = \
......@@ -168,6 +178,7 @@ wayland_backend_la_LIBADD = $(COMPOSITOR_LIBS) $(WAYLAND_COMPOSITOR_LIBS) \
../shared/libshared-cairo.la
wayland_backend_la_CFLAGS = \
$(COMPOSITOR_CFLAGS) \
$(EGL_CFLAGS) \
$(PIXMAN_CFLAGS) \
$(CAIRO_CFLAGS) \
$(WAYLAND_COMPOSITOR_CFLAGS) \
......@@ -219,6 +230,7 @@ fbdev_backend_la_LIBADD = \
../shared/libshared.la
fbdev_backend_la_CFLAGS = \
$(COMPOSITOR_CFLAGS) \
$(EGL_CFLAGS) \
$(FBDEV_COMPOSITOR_CFLAGS) \
$(PIXMAN_CFLAGS) \
$(GCC_CFLAGS)
......
......@@ -33,6 +33,7 @@
#include <linux/vt.h>
#include <assert.h>
#include <sys/mman.h>
#include <dlfcn.h>
#include <time.h>
#include <xf86drm.h>
......@@ -194,6 +195,8 @@ struct drm_sprite {
uint32_t formats[];
};
static struct gl_renderer_interface *gl_renderer;
static const char default_seat[] = "seat0";
static void
......@@ -1101,7 +1104,7 @@ drm_output_destroy(struct weston_output *output_base)
if (c->use_pixman) {
drm_output_fini_pixman(output);
} else {
gl_renderer_output_destroy(output_base);
gl_renderer->output_destroy(output_base);
gbm_surface_destroy(output->surface);
}
......@@ -1192,7 +1195,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
return -1;
}
} else {
gl_renderer_output_destroy(&output->base);
gl_renderer->output_destroy(&output->base);
gbm_surface_destroy(output->surface);
if (drm_output_init_egl(output, ec) < 0) {
......@@ -1262,14 +1265,26 @@ init_egl(struct drm_compositor *ec)
{
EGLint format;
gl_renderer = weston_load_module("gl-renderer.so",
"gl_renderer_interface");
if (!gl_renderer)
return -1;
/* GBM will load a dri driver, but even though they need symbols from
* libglapi, in some version of Mesa they are not linked to it. Since
* only the gl-renderer module links to it, the call above won't make
* these symbols globally available, and loading the DRI driver fails.
* Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */
dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
ec->gbm = gbm_create_device(ec->drm.fd);
if (!ec->gbm)
return -1;
format = ec->format;
if (gl_renderer_create(&ec->base, ec->gbm,
gl_renderer_opaque_attribs, &format) < 0) {
if (gl_renderer->create(&ec->base, ec->gbm,
gl_renderer->opaque_attribs, &format) < 0) {
gbm_device_destroy(ec->gbm);
return -1;
}
......@@ -1471,7 +1486,7 @@ drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec)
return -1;
}
if (gl_renderer_output_create(&output->base, output->surface) < 0) {
if (gl_renderer->output_create(&output->base, output->surface) < 0) {
weston_log("failed to create gl renderer output state\n");
gbm_surface_destroy(output->surface);
return -1;
......
......@@ -95,6 +95,8 @@ struct fbdev_parameters {
int use_gl;
};
struct gl_renderer_interface *gl_renderer;
static const char default_seat[] = "seat0";
static inline struct fbdev_output *
......@@ -623,7 +625,7 @@ fbdev_output_create(struct fbdev_compositor *compositor,
goto out_shadow_surface;
} else {
setenv("HYBRIS_EGLPLATFORM", "wayland", 1);
if (gl_renderer_output_create(&output->base,
if (gl_renderer->output_create(&output->base,
(EGLNativeWindowType)NULL) < 0) {
weston_log("gl_renderer_output_create failed.\n");
goto out_shadow_surface;
......@@ -684,7 +686,7 @@ fbdev_output_destroy(struct weston_output *base)
output->shadow_buf = NULL;
}
} else {
gl_renderer_output_destroy(base);
gl_renderer->output_destroy(base);
}
/* Remove the output. */
......@@ -923,8 +925,16 @@ fbdev_compositor_create(struct wl_display *display, int *argc, char *argv[],
if (pixman_renderer_init(&compositor->base) < 0)
goto out_launcher;
} else {
if (gl_renderer_create(&compositor->base, EGL_DEFAULT_DISPLAY,
gl_renderer_opaque_attribs, NULL) < 0) {
gl_renderer = weston_load_module("gl-renderer.so",
"gl_renderer_interface");
if (!gl_renderer) {
weston_log("could not load gl renderer\n");
goto out_launcher;
}
if (gl_renderer->create(&compositor->base, EGL_DEFAULT_DISPLAY,
gl_renderer->opaque_attribs,
NULL) < 0) {
weston_log("gl_renderer_create failed.\n");
goto out_launcher;
}
......
......@@ -89,6 +89,8 @@ struct wayland_input {
struct wayland_output *output;
};
struct gl_renderer_interface *gl_renderer;
static void
create_border(struct wayland_compositor *c)
{
......@@ -106,7 +108,7 @@ create_border(struct wayland_compositor *c)
edges[2] = c->border.top;
edges[3] = c->border.bottom;
gl_renderer_set_border(&c->base, pixman_image_get_width(image),
gl_renderer->set_border(&c->base, pixman_image_get_width(image),
pixman_image_get_height(image),
pixman_image_get_data(image), edges);
......@@ -233,7 +235,7 @@ wayland_output_destroy(struct weston_output *output_base)
{
struct wayland_output *output = (struct wayland_output *) output_base;
gl_renderer_output_destroy(output_base);
gl_renderer->output_destroy(output_base);
wl_egl_window_destroy(output->parent.egl_window);
free(output);
......@@ -283,7 +285,7 @@ wayland_compositor_create_output(struct wayland_compositor *c,
goto cleanup_output;
}
if (gl_renderer_output_create(&output->base,
if (gl_renderer->output_create(&output->base,
output->parent.egl_window) < 0)
goto cleanup_window;
......@@ -742,8 +744,14 @@ wayland_compositor_create(struct wl_display *display,
wl_display_dispatch(c->parent.wl_display);
c->base.wl_display = display;
if (gl_renderer_create(&c->base, c->parent.wl_display,
gl_renderer_alpha_attribs,
gl_renderer = weston_load_module("gl-renderer.so",
"gl_renderer_interface");
if (!gl_renderer)
goto err_display;
if (gl_renderer->create(&c->base, c->parent.wl_display,
gl_renderer->alpha_attribs,
NULL) < 0)
goto err_display;
......@@ -759,7 +767,7 @@ wayland_compositor_create(struct wl_display *display,
if (wayland_compositor_create_output(c, width, height) < 0)
goto err_gl;
/* requires gl_renderer_output_state_create called
/* requires gl_renderer->output_state_create called
* by wayland_compositor_create_output */
create_border(c);
......
......@@ -115,6 +115,8 @@ struct x11_output {
int32_t scale;
};
struct gl_renderer_interface *gl_renderer;
static struct xkb_keymap *
x11_compositor_get_keymap(struct x11_compositor *c)
{
......@@ -519,7 +521,7 @@ x11_output_destroy(struct weston_output *output_base)
pixman_renderer_output_destroy(output_base);
x11_output_deinit_shm(compositor, output);
} else
gl_renderer_output_destroy(output_base);
gl_renderer->output_destroy(output_base);
xcb_destroy_window(compositor->conn, output->window);
......@@ -785,6 +787,7 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
struct wm_normal_hints normal_hints;
struct wl_event_loop *loop;
int output_width, output_height;
int ret;
uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
xcb_atom_t atom_list[1];
uint32_t values[2] = {
......@@ -905,7 +908,9 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
return NULL;
}
} else {
if (gl_renderer_output_create(&output->base, (EGLNativeWindowType)output->window) < 0)
ret = gl_renderer->output_create(&output->base,
(EGLNativeWindowType) output->window);
if (ret < 0)
return NULL;
}
......@@ -1441,6 +1446,21 @@ parse_transform(const char *transform, const char *output_name)
return WL_OUTPUT_TRANSFORM_NORMAL;
}
static int
init_gl_renderer(struct x11_compositor *c)
{
int ret;
gl_renderer = weston_load_module("gl-renderer.so",
"gl_renderer_interface");
if (!gl_renderer)
return -1;
ret = gl_renderer->create(&c->base, (EGLNativeDisplayType) c->dpy,
gl_renderer->opaque_attribs, NULL);
return ret;
}
static struct weston_compositor *
x11_compositor_create(struct wl_display *display,
int fullscreen,
......@@ -1497,10 +1517,8 @@ x11_compositor_create(struct wl_display *display,
if (pixman_renderer_init(&c->base) < 0)
goto err_xdisplay;
}
else {
if (gl_renderer_create(&c->base, (EGLNativeDisplayType)c->dpy, gl_renderer_opaque_attribs,
NULL) < 0)
goto err_xdisplay;
else if (init_gl_renderer(c) < 0) {
goto err_xdisplay;
}
weston_log("Using %s renderer\n", use_pixman ? "pixman" : "gl");
......
......@@ -3224,8 +3224,8 @@ on_caught_signal(int s, siginfo_t *siginfo, void *context)
raise(SIGTRAP);
}
static void *
load_module(const char *name, const char *entrypoint)
WL_EXPORT void *
weston_load_module(const char *name, const char *entrypoint)
{
char path[PATH_MAX];
void *module, *init;
......@@ -3275,7 +3275,7 @@ load_modules(struct weston_compositor *ec, const char *modules,
while (*p) {
end = strchrnul(p, ',');
snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p);
module_init = load_module(buffer, "module_init");
module_init = weston_load_module(buffer, "module_init");
if (module_init)
module_init(ec, argc, argv);
p = end;
......@@ -3509,7 +3509,7 @@ int main(int argc, char *argv[])
section = weston_config_get_section(config, "core", NULL, NULL);
weston_config_section_get_string(section, "modules", &modules, "");
backend_init = load_module(backend, "backend_init");
backend_init = weston_load_module(backend, "backend_init");
if (!backend_init)
exit(EXIT_FAILURE);
......
......@@ -1256,6 +1256,9 @@ weston_transformed_rect(int width, int height,
int32_t scale,
pixman_box32_t rect);
void *
weston_load_module(const char *name, const char *entrypoint);
#ifdef __cplusplus
}
#endif
......
......@@ -170,7 +170,7 @@ egl_error_string(EGLint code)
#undef MYERRCODE
}
WL_EXPORT void
static void
gl_renderer_print_egl_error_state(void)
{
EGLint code;
......@@ -1440,7 +1440,7 @@ output_apply_border(struct weston_output *output, struct gl_renderer *gr)
output->border.right = gr->border.right;
}
WL_EXPORT void
static void
gl_renderer_set_border(struct weston_compositor *ec, int32_t width, int32_t height, void *data,
int32_t *edges)
{
......@@ -1475,7 +1475,7 @@ gl_renderer_set_border(struct weston_compositor *ec, int32_t width, int32_t heig
static int
gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
WL_EXPORT int
static int
gl_renderer_output_create(struct weston_output *output,
EGLNativeWindowType window)
{
......@@ -1514,7 +1514,7 @@ gl_renderer_output_create(struct weston_output *output,
return 0;
}
WL_EXPORT void
static void
gl_renderer_output_destroy(struct weston_output *output)
{
struct gl_renderer *gr = get_renderer(output->compositor);
......@@ -1529,7 +1529,7 @@ gl_renderer_output_destroy(struct weston_output *output)
free(go);
}
WL_EXPORT EGLSurface
static EGLSurface
gl_renderer_output_surface(struct weston_output *output)
{
return get_output_state(output)->egl_surface;
......@@ -1602,7 +1602,7 @@ out:
return -1;
}
WL_EXPORT const EGLint gl_renderer_opaque_attribs[] = {
static const EGLint gl_renderer_opaque_attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 1,
EGL_GREEN_SIZE, 1,
......@@ -1612,7 +1612,7 @@ WL_EXPORT const EGLint gl_renderer_opaque_attribs[] = {
EGL_NONE
};
WL_EXPORT const EGLint gl_renderer_alpha_attribs[] = {
static const EGLint gl_renderer_alpha_attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 1,
EGL_GREEN_SIZE, 1,
......@@ -1622,7 +1622,7 @@ WL_EXPORT const EGLint gl_renderer_alpha_attribs[] = {
EGL_NONE
};
WL_EXPORT int
static int
gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
const EGLint *attribs, const EGLint *visual_id)
{
......@@ -1673,7 +1673,7 @@ err_egl:
return -1;
}
WL_EXPORT EGLDisplay
static EGLDisplay
gl_renderer_display(struct weston_compositor *ec)
{
return get_renderer(ec)->egl_display;
......@@ -1863,3 +1863,16 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
return 0;
}
WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
.opaque_attribs = gl_renderer_opaque_attribs,
.alpha_attribs = gl_renderer_alpha_attribs,
.create = gl_renderer_create,
.display = gl_renderer_display,
.output_create = gl_renderer_output_create,
.output_destroy = gl_renderer_output_destroy,
.output_surface = gl_renderer_output_surface,
.set_border = gl_renderer_set_border,
.print_egl_error_state = gl_renderer_print_egl_error_state
};
......@@ -28,27 +28,6 @@
#include <EGL/egl.h>
extern const EGLint gl_renderer_opaque_attribs[];
extern const EGLint gl_renderer_alpha_attribs[];
int
gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
const EGLint *attribs, const EGLint *visual_id);
EGLDisplay
gl_renderer_display(struct weston_compositor *ec);
int
gl_renderer_output_create(struct weston_output *output,
EGLNativeWindowType window);
void
gl_renderer_output_destroy(struct weston_output *output);
EGLSurface
gl_renderer_output_surface(struct weston_output *output);
void
gl_renderer_set_border(struct weston_compositor *ec, int32_t width, int32_t height, void *data,
int32_t *edges);
void
gl_renderer_print_egl_error_state(void);
#else
typedef int EGLint;
......@@ -58,49 +37,31 @@ typedef intptr_t EGLNativeDisplayType;
typedef intptr_t EGLNativeWindowType;
#define EGL_DEFAULT_DISPLAY NULL
static const EGLint gl_renderer_opaque_attribs[];
static const EGLint gl_renderer_alpha_attribs[];
inline static int
gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
const EGLint *attribs, const EGLint *visual_id)
{
return -1;
}
inline static EGLDisplay
gl_renderer_display(struct weston_compositor *ec)
{
return 0;
}
inline static int
gl_renderer_output_create(struct weston_output *output,
EGLNativeWindowType window)
{
return -1;
}
inline static void
gl_renderer_output_destroy(struct weston_output *output)
{
}
inline static EGLSurface
gl_renderer_output_surface(struct weston_output *output)
{
return 0;
}
inline static void
gl_renderer_set_border(struct weston_compositor *ec, int32_t width, int32_t height, void *data,
int32_t *edges)
{
}
inline static void
gl_renderer_print_egl_error_state(void)
{
}
#endif
struct gl_renderer_interface {
const EGLint *opaque_attribs;
const EGLint *alpha_attribs;
int (*create)(struct weston_compositor *ec,
EGLNativeDisplayType display,
const EGLint *attribs,
const EGLint *visual_id);
EGLDisplay (*display)(struct weston_compositor *ec);
int (*output_create)(struct weston_output *output,
EGLNativeWindowType window);
void (*output_destroy)(struct weston_output *output);
EGLSurface (*output_surface)(struct weston_output *output);
void (*set_border)(struct weston_compositor *ec,
int32_t width, int32_t height,
void *data, int32_t *edges);
void (*print_egl_error_state)(void);
};
struct gl_renderer_interface gl_renderer_interface;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment