[PATCH v2] gles2-renderer: Provide an API for backends to use.
John Kåre Alsaker
john.kare.alsaker at gmail.com
Thu Oct 25 13:53:20 PDT 2012
This provides an new API for gles2-renderer. It allows to move most EGL initialization code and EGL surface creation into gles2-renderer, which makes compositor backends less dependent on gles2-renderer. As a side effect weston_output gets a per-renderer state which gles2-renderer uses to store the EGL surface.
---
src/compositor-android.c | 72 +++++++----------
src/compositor-drm.c | 87 ++++++---------------
src/compositor-wayland.c | 58 +++-----------
src/compositor-x11.c | 71 +++--------------
src/compositor.h | 23 +++++-
src/gles2-renderer.c | 197 ++++++++++++++++++++++++++++++++++++++++++-----
6 files changed, 265 insertions(+), 243 deletions(-)
diff --git a/src/compositor-android.c b/src/compositor-android.c
index 3c0273a..bf14910 100644
--- a/src/compositor-android.c
+++ b/src/compositor-android.c
@@ -145,6 +145,8 @@ android_output_destroy(struct weston_output *base)
wl_list_remove(&output->base.link);
weston_output_destroy(&output->base);
+ gles2_renderer_output_unbind(base);
+
android_framebuffer_destroy(output->fb);
free(output);
@@ -319,6 +321,8 @@ android_seat_create(struct android_compositor *compositor)
static int
android_egl_choose_config(struct android_compositor *compositor,
struct android_framebuffer *fb,
+ EGLDisplay egl_display,
+ EGLConfig *egl_config,
const EGLint *attribs)
{
EGLBoolean ret;
@@ -332,9 +336,9 @@ android_egl_choose_config(struct android_compositor *compositor,
* surfaceflinger/DisplayHardware/DisplayHardware.cpp
*/
- compositor->base.egl_config = NULL;
+ *egl_config = NULL;
- ret = eglGetConfigs(compositor->base.egl_display, NULL, 0, &count);
+ ret = eglGetConfigs(egl_display, NULL, 0, &count);
if (ret == EGL_FALSE || count < 1)
return -1;
@@ -342,27 +346,27 @@ android_egl_choose_config(struct android_compositor *compositor,
if (!configs)
return -1;
- ret = eglChooseConfig(compositor->base.egl_display, attribs, configs,
+ ret = eglChooseConfig(egl_display, attribs, configs,
count, &matched);
if (ret == EGL_FALSE || matched < 1)
goto out;
for (i = 0; i < matched; ++i) {
EGLint id;
- ret = eglGetConfigAttrib(compositor->base.egl_display,
+ ret = eglGetConfigAttrib(egl_display,
configs[i], EGL_NATIVE_VISUAL_ID,
&id);
if (ret == EGL_FALSE)
continue;
if (id > 0 && fb->format == id) {
- compositor->base.egl_config = configs[i];
+ *egl_config = configs[i];
break;
}
}
out:
free(configs);
- if (!compositor->base.egl_config)
+ if (!*egl_config)
return -1;
return 0;
@@ -372,7 +376,8 @@ static int
android_init_egl(struct android_compositor *compositor,
struct android_output *output)
{
- EGLint eglmajor, eglminor;
+ EGLDisplay egl_display;
+ EGLConfig egl_config;
int ret;
static const EGLint config_attrs[] = {
@@ -385,66 +390,41 @@ android_init_egl(struct android_compositor *compositor,
EGL_NONE
};
- compositor->base.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (compositor->base.egl_display == EGL_NO_DISPLAY) {
- weston_log("Failed to create EGL display.\n");
- print_egl_error_state();
- return -1;
- }
+ egl_display = gles2_renderer_init_without_config(&compositor->base, EGL_DEFAULT_DISPLAY);
- ret = eglInitialize(compositor->base.egl_display, &eglmajor, &eglminor);
- if (!ret) {
- weston_log("Failed to initialise EGL.\n");
+ if (egl_display == EGL_NO_DISPLAY) {
+ weston_log("Failed to create EGL display.\n");
print_egl_error_state();
return -1;
}
- ret = android_egl_choose_config(compositor, output->fb, config_attrs);
+ ret = android_egl_choose_config(compositor, output->fb, egl_display, &egl_config, config_attrs);
if (ret < 0) {
weston_log("Failed to find an EGL config.\n");
print_egl_error_state();
return -1;
}
- output->base.egl_surface =
- eglCreateWindowSurface(compositor->base.egl_display,
- compositor->base.egl_config,
- output->fb->native_window,
- NULL);
- if (output->base.egl_surface == EGL_NO_SURFACE) {
- weston_log("Failed to create FB EGLSurface.\n");
- print_egl_error_state();
+ gles2_renderer_select_config(&compositor->base, egl_config);
+
+ if (gles2_renderer_output_state_create_and_bind(&output->base, output->fb->native_window) < 0)
return -1;
- }
return 0;
}
static void
-android_fini_egl(struct android_compositor *compositor)
-{
- gles2_renderer_destroy(&compositor->base);
-
- eglMakeCurrent(compositor->base.egl_display,
- EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
-
- eglTerminate(compositor->base.egl_display);
- eglReleaseThread();
-}
-
-static void
android_compositor_destroy(struct weston_compositor *base)
{
struct android_compositor *compositor = to_android_compositor(base);
android_seat_destroy(compositor->seat);
+ gles2_renderer_destroy(base);
+
/* destroys outputs, too */
weston_compositor_shutdown(&compositor->base);
- android_fini_egl(compositor);
-
free(compositor);
}
@@ -478,17 +458,17 @@ android_compositor_create(struct wl_display *display, int argc, char *argv[],
android_compositor_add_output(compositor, output);
- if (gles2_renderer_init(&compositor->base) < 0)
- goto err_egl;
+ if (gles2_renderer_outputs_ready(&compositor->base) < 0)
+ goto err_gles2;
compositor->seat = android_seat_create(compositor);
if (!compositor->seat)
- goto err_egl;
+ goto err_gles2;
return &compositor->base;
-err_egl:
- android_fini_egl(compositor);
+err_gles2:
+ gles2_renderer_destroy(&compositor->base);
err_output:
android_output_destroy(&output->base);
err_compositor:
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 3e75387..96a206e 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -861,7 +861,7 @@ drm_output_destroy(struct weston_output *output_base)
c->crtc_allocator &= ~(1 << output->crtc_id);
c->connector_allocator &= ~(1 << output->connector_id);
- eglDestroySurface(c->base.egl_display, output->base.egl_surface);
+ gles2_renderer_output_unbind(output_base);
gbm_surface_destroy(output->surface);
weston_plane_release(&output->fb_plane);
@@ -907,7 +907,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
int ret;
struct drm_compositor *ec;
struct gbm_surface *surface;
- EGLSurface egl_surface;
+ struct gles2_output_state *state;
if (output_base == NULL) {
weston_log("output is NULL.\n");
@@ -967,15 +967,10 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
return -1;
}
- egl_surface =
- eglCreateWindowSurface(ec->base.egl_display,
- ec->base.egl_config,
- surface, NULL);
+ state = gles2_renderer_output_state_create(&ec->base, surface);
- if (egl_surface == EGL_NO_SURFACE) {
- weston_log("failed to create egl surface\n");
- goto err;
- }
+ if (!state)
+ goto err_gbm;
ret = drmModeSetCrtc(ec->drm.fd,
output->crtc_id,
@@ -983,7 +978,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
&output->connector_id, 1, &drm_mode->mode_info);
if (ret) {
weston_log("failed to set mode\n");
- goto err;
+ goto err_gles2;
}
/* reset rendering stuff. */
@@ -1005,10 +1000,10 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
}
output->next = NULL;
- eglDestroySurface(ec->base.egl_display, output->base.egl_surface);
+ gles2_renderer_output_unbind(output_base);
gbm_surface_destroy(output->surface);
- output->base.egl_surface = egl_surface;
output->surface = surface;
+ gles2_renderer_output_bind(&output->base, state);
/*update output*/
output->base.current = &drm_mode->base;
@@ -1016,8 +1011,9 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
weston_output_move(&output->base, output->base.x, output->base.y);
return 0;
-err:
- eglDestroySurface(ec->base.egl_display, egl_surface);
+err_gles2:
+ gles2_renderer_output_state_destroy(&ec->base, state);
+err_gbm:
gbm_surface_destroy(surface);
return -1;
}
@@ -1039,18 +1035,8 @@ on_drm_input(int fd, uint32_t mask, void *data)
static int
init_egl(struct drm_compositor *ec, struct udev_device *device)
{
- EGLint major, minor, n;
const char *filename, *sysnum;
int fd;
- static const EGLint config_attribs[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RED_SIZE, 1,
- EGL_GREEN_SIZE, 1,
- EGL_BLUE_SIZE, 1,
- EGL_ALPHA_SIZE, 0,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_NONE
- };
sysnum = udev_device_get_sysnum(device);
if (sysnum)
@@ -1073,22 +1059,9 @@ init_egl(struct drm_compositor *ec, struct udev_device *device)
ec->drm.fd = fd;
ec->gbm = gbm_create_device(ec->drm.fd);
- ec->base.egl_display = eglGetDisplay(ec->gbm);
- if (ec->base.egl_display == NULL) {
- weston_log("failed to create display\n");
- return -1;
- }
-
- if (!eglInitialize(ec->base.egl_display, &major, &minor)) {
- weston_log("failed to initialize display\n");
- return -1;
- }
- if (!eglChooseConfig(ec->base.egl_display, config_attribs,
- &ec->base.egl_config, 1, &n) || n != 1) {
- weston_log("failed to choose config: %d\n", n);
+ if (gles2_renderer_init(&ec->base, ec->gbm, 0) < 0)
return -1;
- }
return 0;
}
@@ -1445,15 +1418,13 @@ create_output_for_connector(struct drm_compositor *ec,
goto err_free;
}
- output->base.egl_surface =
- eglCreateWindowSurface(ec->base.egl_display,
- ec->base.egl_config,
- output->surface,
- NULL);
- if (output->base.egl_surface == EGL_NO_SURFACE) {
- weston_log("failed to create egl surface\n");
- goto err_surface;
- }
+ weston_output_init(&output->base, &ec->base, x, y,
+ connector->mmWidth, connector->mmHeight,
+ o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL);
+
+ /* this requires output->base.compositor to be initialized */
+ if (gles2_renderer_output_state_create_and_bind(&output->base, output->surface) < 0)
+ goto err_output;
output->cursor_bo[0] =
gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888,
@@ -1473,10 +1444,6 @@ create_output_for_connector(struct drm_compositor *ec,
output->base.backlight_current = drm_get_backlight(output);
}
- weston_output_init(&output->base, &ec->base, x, y,
- connector->mmWidth, connector->mmHeight,
- o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL);
-
wl_list_insert(ec->base.output_list.prev, &output->base.link);
output->base.origin = output->base.current;
@@ -1503,7 +1470,8 @@ create_output_for_connector(struct drm_compositor *ec,
return 0;
-err_surface:
+err_output:
+ weston_output_destroy(&output->base);
gbm_surface_destroy(output->surface);
err_free:
wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
@@ -2039,12 +2007,6 @@ drm_destroy(struct weston_compositor *ec)
gles2_renderer_destroy(ec);
- /* Work around crash in egl_dri2.c's dri2_make_current() */
- eglMakeCurrent(ec->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
- eglTerminate(ec->egl_display);
- eglReleaseThread();
-
gbm_device_destroy(d->gbm);
destroy_sprites(d);
if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0)
@@ -2238,7 +2200,7 @@ drm_compositor_create(struct wl_display *display,
goto err_sprite;
}
- if (gles2_renderer_init(&ec->base) < 0)
+ if (gles2_renderer_outputs_ready(&ec->base) < 0)
goto err_egl;
path = NULL;
@@ -2280,10 +2242,7 @@ err_drm_source:
wl_list_for_each_safe(weston_seat, next, &ec->base.seat_list, link)
evdev_input_destroy(weston_seat);
err_egl:
- eglMakeCurrent(ec->base.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
- eglTerminate(ec->base.egl_display);
- eglReleaseThread();
+ gles2_renderer_destroy(&ec->base);
gbm_device_destroy(ec->gbm);
err_sprite:
destroy_sprites(ec);
diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index 56759fc..1e60d0f 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -241,41 +241,6 @@ create_border(struct wayland_compositor *c)
pixman_image_unref(image);
}
-static int
-wayland_compositor_init_egl(struct wayland_compositor *c)
-{
- EGLint major, minor;
- EGLint n;
- EGLint config_attribs[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RED_SIZE, 1,
- EGL_GREEN_SIZE, 1,
- EGL_BLUE_SIZE, 1,
- EGL_ALPHA_SIZE, 1,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_NONE
- };
-
- c->base.egl_display = eglGetDisplay(c->parent.wl_display);
- if (c->base.egl_display == NULL) {
- weston_log("failed to create display\n");
- return -1;
- }
-
- if (!eglInitialize(c->base.egl_display, &major, &minor)) {
- weston_log("failed to initialize display\n");
- return -1;
- }
-
- if (!eglChooseConfig(c->base.egl_display, config_attribs,
- &c->base.egl_config, 1, &n) || n == 0) {
- weston_log("failed to choose config: %d\n", n);
- return -1;
- }
-
- return 0;
-}
-
static void
frame_done(void *data, struct wl_callback *callback, uint32_t time)
{
@@ -317,9 +282,9 @@ static void
wayland_output_destroy(struct weston_output *output_base)
{
struct wayland_output *output = (struct wayland_output *) output_base;
- struct weston_compositor *ec = output->base.compositor;
- eglDestroySurface(ec->egl_display, output->base.egl_surface);
+ gles2_renderer_output_unbind(output_base);
+
wl_egl_window_destroy(output->parent.egl_window);
free(output);
@@ -373,13 +338,8 @@ wayland_compositor_create_output(struct wayland_compositor *c,
goto cleanup_output;
}
- output->base.egl_surface =
- eglCreateWindowSurface(c->base.egl_display, c->base.egl_config,
- output->parent.egl_window, NULL);
- if (!output->base.egl_surface) {
- weston_log("failed to create window surface\n");
+ if (gles2_renderer_output_state_create_and_bind(&output->base, output->parent.egl_window) < 0)
goto cleanup_window;
- }
output->parent.shell_surface =
wl_shell_get_shell_surface(c->parent.shell,
@@ -831,7 +791,7 @@ wayland_compositor_create(struct wl_display *display,
wl_display_dispatch(c->parent.wl_display);
c->base.wl_display = display;
- if (wayland_compositor_init_egl(c) < 0)
+ if (gles2_renderer_init(&c->base, c->parent.wl_display, 1) < 0)
goto err_display;
c->base.destroy = wayland_destroy;
@@ -844,11 +804,11 @@ wayland_compositor_create(struct wl_display *display,
/* requires border fields */
if (wayland_compositor_create_output(c, width, height) < 0)
- goto err_display;
+ goto err_gles2;
/* requires wayland_compositor_create_output */
- if (gles2_renderer_init(&c->base) < 0)
- goto err_display;
+ if (gles2_renderer_outputs_ready(&c->base) < 0)
+ goto err_gles2;
/* requires gles2_renderer_init */
create_border(c);
@@ -860,12 +820,14 @@ wayland_compositor_create(struct wl_display *display,
wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
wayland_compositor_handle_event, c);
if (c->parent.wl_source == NULL)
- goto err_display;
+ goto err_gles2;
wl_event_source_check(c->parent.wl_source);
return &c->base;
+err_gles2:
+ gles2_renderer_destroy(&c->base);
err_display:
wl_display_disconnect(c->parent.wl_display);
err_compositor:
diff --git a/src/compositor-x11.c b/src/compositor-x11.c
index e616f45..80c28b0 100644
--- a/src/compositor-x11.c
+++ b/src/compositor-x11.c
@@ -239,53 +239,6 @@ x11_input_destroy(struct x11_compositor *compositor)
weston_seat_release(&compositor->core_seat);
}
-static int
-x11_compositor_init_egl(struct x11_compositor *c)
-{
- EGLint major, minor;
- EGLint n;
- EGLint config_attribs[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RED_SIZE, 1,
- EGL_GREEN_SIZE, 1,
- EGL_BLUE_SIZE, 1,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_NONE
- };
-
- c->base.egl_display = eglGetDisplay(c->dpy);
- if (c->base.egl_display == NULL) {
- weston_log("failed to create display\n");
- return -1;
- }
-
- if (!eglInitialize(c->base.egl_display, &major, &minor)) {
- weston_log("failed to initialize display\n");
- return -1;
- }
-
- if (!eglChooseConfig(c->base.egl_display, config_attribs,
- &c->base.egl_config, 1, &n) || n == 0) {
- weston_log("failed to choose config: %d\n", n);
- return -1;
- }
-
- return 0;
-}
-
-static void
-x11_compositor_fini_egl(struct x11_compositor *compositor)
-{
- gles2_renderer_destroy(&compositor->base);
-
- eglMakeCurrent(compositor->base.egl_display,
- EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
-
- eglTerminate(compositor->base.egl_display);
- eglReleaseThread();
-}
-
static void
x11_output_repaint(struct weston_output *output_base,
pixman_region32_t *damage)
@@ -322,8 +275,7 @@ x11_output_destroy(struct weston_output *output_base)
wl_list_remove(&output->base.link);
wl_event_source_remove(output->finish_frame_timer);
- eglDestroySurface(compositor->base.egl_display,
- output->base.egl_surface);
+ gles2_renderer_output_unbind(output_base);
xcb_destroy_window(compositor->conn, output->window);
@@ -529,13 +481,8 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
x11_output_change_state(output, 1,
c->atom.net_wm_state_fullscreen);
- output->base.egl_surface =
- eglCreateWindowSurface(c->base.egl_display, c->base.egl_config,
- output->window, NULL);
- if (!output->base.egl_surface) {
- weston_log("failed to create window surface\n");
+ if (gles2_renderer_output_state_create_and_bind(&output->base, output->window) < 0)
return NULL;
- }
loop = wl_display_get_event_loop(c->base.wl_display);
output->finish_frame_timer =
@@ -1085,7 +1032,7 @@ x11_destroy(struct weston_compositor *ec)
weston_compositor_shutdown(ec); /* destroys outputs, too */
- x11_compositor_fini_egl(compositor);
+ gles2_renderer_destroy(ec);
XCloseDisplay(compositor->dpy);
free(ec);
@@ -1133,14 +1080,14 @@ x11_compositor_create(struct wl_display *display,
x11_compositor_get_resources(c);
c->base.wl_display = display;
- if (x11_compositor_init_egl(c) < 0)
+ if (gles2_renderer_init(&c->base, c->dpy, 0) < 0)
goto err_xdisplay;
c->base.destroy = x11_destroy;
c->base.restore = x11_restore;
if (x11_input_create(c, no_input) < 0)
- goto err_egl;
+ goto err_gles2;
width = option_width ? option_width : 1024;
height = option_height ? option_height : 640;
@@ -1173,8 +1120,8 @@ x11_compositor_create(struct wl_display *display,
x = pixman_region32_extents(&output->base.region)->x2;
}
- if (gles2_renderer_init(&c->base) < 0)
- goto err_egl;
+ if (gles2_renderer_outputs_ready(&c->base) < 0)
+ goto err_x11_input;
c->xcb_source =
wl_event_loop_add_fd(c->base.input_loop,
@@ -1187,8 +1134,8 @@ x11_compositor_create(struct wl_display *display,
err_x11_input:
x11_input_destroy(c);
-err_egl:
- x11_compositor_fini_egl(c);
+err_gles2:
+ gles2_renderer_destroy(&c->base);
err_xdisplay:
XCloseDisplay(c->dpy);
err_free:
diff --git a/src/compositor.h b/src/compositor.h
index 3176bfd..59eb4bf 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -154,7 +154,8 @@ enum dpms_enum {
struct weston_output {
uint32_t id;
- EGLSurface egl_surface;
+ void *renderer_state;
+
struct wl_list link;
struct wl_list resource_list;
struct wl_global *global;
@@ -822,8 +823,26 @@ weston_surface_destroy(struct weston_surface *surface);
int
weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode);
+struct gles2_output_state;
+
+int
+gles2_renderer_init(struct weston_compositor *ec, EGLNativeDisplayType display, int alpha);
+EGLDisplay
+gles2_renderer_init_without_config(struct weston_compositor *ec, EGLNativeDisplayType display);
+void
+gles2_renderer_select_config(struct weston_compositor *ec, EGLConfig config);
int
-gles2_renderer_init(struct weston_compositor *ec);
+gles2_renderer_outputs_ready(struct weston_compositor *ec);
+int
+gles2_renderer_output_state_create_and_bind(struct weston_output *output, EGLNativeWindowType window);
+struct gles2_output_state *
+gles2_renderer_output_state_create(struct weston_compositor *ec, EGLNativeWindowType window);
+void
+gles2_renderer_output_state_destroy(struct weston_compositor *ec, struct gles2_output_state *state);
+void
+gles2_renderer_output_bind(struct weston_output *output, struct gles2_output_state *state);
+void
+gles2_renderer_output_unbind(struct weston_output *output);
void
gles2_renderer_destroy(struct weston_compositor *ec);
diff --git a/src/gles2-renderer.c b/src/gles2-renderer.c
index 544cc15..a03a7dd 100644
--- a/src/gles2-renderer.c
+++ b/src/gles2-renderer.c
@@ -30,6 +30,26 @@
#include "compositor.h"
+struct gles2_output_state {
+ EGLSurface egl_surface;
+};
+
+struct gles2_renderer {
+ struct weston_renderer base;
+};
+
+static inline struct gles2_output_state *
+get_output_state(struct weston_output *output)
+{
+ return (struct gles2_output_state *)output->renderer_state;
+}
+
+static inline struct gles2_renderer *
+get_renderer(struct weston_compositor *ec)
+{
+ return (struct gles2_renderer *)ec->renderer;
+}
+
static const char *
egl_error_string(EGLint code)
{
@@ -700,6 +720,7 @@ static void
gles2_renderer_repaint_output(struct weston_output *output,
pixman_region32_t *output_damage)
{
+ struct gles2_output_state *output_state = get_output_state(output);
struct weston_compositor *compositor = output->compositor;
EGLBoolean ret;
static int errored;
@@ -712,8 +733,8 @@ gles2_renderer_repaint_output(struct weston_output *output,
glViewport(0, 0, width, height);
- ret = eglMakeCurrent(compositor->egl_display, output->egl_surface,
- output->egl_surface, compositor->egl_context);
+ ret = eglMakeCurrent(compositor->egl_display, output_state->egl_surface,
+ output_state->egl_surface, compositor->egl_context);
if (ret == EGL_FALSE) {
if (errored)
return;
@@ -749,7 +770,7 @@ gles2_renderer_repaint_output(struct weston_output *output,
wl_signal_emit(&output->frame_signal, output);
- ret = eglSwapBuffers(compositor->egl_display, output->egl_surface);
+ ret = eglSwapBuffers(compositor->egl_display, output_state->egl_surface);
if (ret == EGL_FALSE && !errored) {
errored = 1;
weston_log("Failed in eglSwapBuffers.\n");
@@ -1157,24 +1178,167 @@ log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
weston_log_continue(" unknown\n");
}
-struct gles2_renderer {
- struct weston_renderer base;
-};
+static int
+create_renderer(struct weston_compositor *ec)
+{
+ struct gles2_renderer *renderer = malloc(sizeof *renderer);
+
+ if (renderer == NULL)
+ return -1;
+
+ renderer->base.repaint_output = gles2_renderer_repaint_output;
+ renderer->base.flush_damage = gles2_renderer_flush_damage;
+ renderer->base.attach = gles2_renderer_attach;
+ renderer->base.destroy_surface = gles2_renderer_destroy_surface;
+
+ ec->renderer = &renderer->base;
+
+ return 0;
+}
+
+static int
+init_display(struct weston_compositor *ec, EGLNativeDisplayType display)
+{
+ EGLint major, minor;
+
+ if (create_renderer(ec) < 0)
+ return -1;
+
+ ec->egl_display = eglGetDisplay(display);
+ if (ec->egl_display == NULL) {
+ weston_log("failed to create display\n");
+ print_egl_error_state();
+ return -1;
+ }
+
+ if (!eglInitialize(ec->egl_display, &major, &minor)) {
+ weston_log("failed to initialize display\n");
+ print_egl_error_state();
+ return -1;
+ }
+
+ return 0;
+}
+
+WL_EXPORT int
+gles2_renderer_output_state_create_and_bind(struct weston_output *output, EGLNativeWindowType window)
+{
+ struct gles2_output_state *state = gles2_renderer_output_state_create(output->compositor, window);
+
+ if (!state)
+ return -1;
+
+ gles2_renderer_output_bind(output, state);
+
+ return 0;
+}
+
+WL_EXPORT struct gles2_output_state *
+gles2_renderer_output_state_create(struct weston_compositor *ec, EGLNativeWindowType window)
+{
+ struct gles2_output_state *state = calloc(1, sizeof *state);
+
+ if (!state)
+ return NULL;
+
+ state->egl_surface =
+ eglCreateWindowSurface(ec->egl_display,
+ ec->egl_config,
+ window, NULL);
+
+ if (state->egl_surface == EGL_NO_SURFACE) {
+ weston_log("failed to create egl surface\n");
+ free(state);
+ return NULL;
+ }
+
+ return state;
+}
+
+WL_EXPORT void
+gles2_renderer_output_state_destroy(struct weston_compositor *ec, struct gles2_output_state *state)
+{
+ eglDestroySurface(ec->egl_display, state->egl_surface);
+
+ free(state);
+}
+
+WL_EXPORT void
+gles2_renderer_output_bind(struct weston_output *output, struct gles2_output_state *state)
+{
+ output->renderer_state = state;
+}
+
+WL_EXPORT void
+gles2_renderer_output_unbind(struct weston_output *output)
+{
+ gles2_renderer_output_state_destroy(output->compositor, get_output_state(output));
+}
WL_EXPORT void
gles2_renderer_destroy(struct weston_compositor *ec)
{
if (ec->has_bind_display)
ec->unbind_display(ec->egl_display, ec->wl_display);
+
+ /* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */
+ eglMakeCurrent(ec->egl_display,
+ EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+
+ eglTerminate(ec->egl_display);
+ eglReleaseThread();
+}
+
+WL_EXPORT int
+gles2_renderer_init(struct weston_compositor *ec, EGLNativeDisplayType display, int alpha)
+{
+ EGLint n;
+
+ const EGLint config_attribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RED_SIZE, 1,
+ EGL_GREEN_SIZE, 1,
+ EGL_BLUE_SIZE, 1,
+ EGL_ALPHA_SIZE, alpha ? 1 : 0,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_NONE
+ };
+
+ if (init_display(ec, display) < 0)
+ return -1;
+
+ if (!eglChooseConfig(ec->egl_display, config_attribs,
+ &ec->egl_config, 1, &n) || n != 1) {
+ weston_log("failed to choose config: %d\n", n);
+ print_egl_error_state();
+ return -1;
+ }
+
+ return 0;
+}
+
+WL_EXPORT EGLDisplay
+gles2_renderer_init_without_config(struct weston_compositor *ec, EGLNativeDisplayType display)
+{
+ if (init_display(ec, display) < 0)
+ return EGL_NO_DISPLAY;
+ else
+ return ec->egl_display;
+}
+
+void
+gles2_renderer_select_config(struct weston_compositor *ec, EGLConfig config)
+{
+ ec->egl_config = config;
}
WL_EXPORT int
-gles2_renderer_init(struct weston_compositor *ec)
+gles2_renderer_outputs_ready(struct weston_compositor *ec)
{
- struct gles2_renderer *renderer;
const char *extensions;
int has_egl_image_external = 0;
- struct weston_output *output;
+ struct gles2_output_state *output;
EGLBoolean ret;
static const EGLint context_attribs[] = {
@@ -1182,10 +1346,6 @@ gles2_renderer_init(struct weston_compositor *ec)
EGL_NONE
};
- renderer = malloc(sizeof *renderer);
- if (renderer == NULL)
- return -1;
-
if (!eglBindAPI(EGL_OPENGL_ES_API)) {
weston_log("failed to bind EGL_OPENGL_ES_API\n");
print_egl_error_state();
@@ -1202,8 +1362,8 @@ gles2_renderer_init(struct weston_compositor *ec)
return -1;
}
- output = container_of(ec->output_list.next,
- struct weston_output, link);
+ output = get_output_state(container_of(ec->output_list.next,
+ struct weston_output, link));
ret = eglMakeCurrent(ec->egl_display, output->egl_surface,
output->egl_surface, ec->egl_context);
if (ret == EGL_FALSE) {
@@ -1289,12 +1449,6 @@ gles2_renderer_init(struct weston_compositor *ec)
vertex_shader, solid_fragment_shader) < 0)
return -1;
- renderer->base.repaint_output = gles2_renderer_repaint_output;
- renderer->base.flush_damage = gles2_renderer_flush_damage;
- renderer->base.attach = gles2_renderer_attach;
- renderer->base.destroy_surface = gles2_renderer_destroy_surface;
- ec->renderer = &renderer->base;
-
weston_log("GL ES 2 renderer features:\n");
weston_log_continue(STAMP_SPACE "read-back format: %s\n",
ec->read_format == GL_BGRA_EXT ? "BGRA" : "RGBA");
@@ -1303,5 +1457,6 @@ gles2_renderer_init(struct weston_compositor *ec)
weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n",
ec->has_bind_display ? "yes" : "no");
+
return 0;
}
--
1.7.12.4
More information about the wayland-devel
mailing list