From 94659274b4f315783d6480c51d1efde9963ed3ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 13 Nov 2012 19:10:18 +0100 Subject: [PATCH] Move weston_output EGL state into gles2-renderer. This introduces callbacks for output creation and destruction for the gles2-renderer. This enables the gles2-renderer to have per-output state. EGL surface creation is now done by the output_create callback and the EGL surface is stored in the new per-output gles2-renderer state. On the first output_create call, the gles2-renderer will setup it's GL context. This is because EGL requires a EGL surface to be able to use the GL context. --- src/compositor-android.c | 16 ++------ src/compositor-drm.c | 50 +++++++++---------------- src/compositor-rpi.c | 52 +++++++++----------------- src/compositor-wayland.c | 16 ++------ src/compositor-x11.c | 25 ++++--------- src/compositor.h | 10 ++++- src/gles2-renderer.c | 80 +++++++++++++++++++++++++++++++++++----- 7 files changed, 130 insertions(+), 119 deletions(-) diff --git a/src/compositor-android.c b/src/compositor-android.c index 3c0273a1..5bf1df3f 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_destroy(base); + android_framebuffer_destroy(output->fb); free(output); @@ -406,16 +408,9 @@ android_init_egl(struct android_compositor *compositor, 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(); + if (gles2_renderer_output_create(&output->base, + output->fb->native_window) < 0) return -1; - } return 0; } @@ -478,9 +473,6 @@ 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; - compositor->seat = android_seat_create(compositor); if (!compositor->seat) goto err_egl; diff --git a/src/compositor-drm.c b/src/compositor-drm.c index 5fe234d1..f7b8d68e 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -829,7 +829,8 @@ 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_destroy(output_base); + gbm_surface_destroy(output->surface); weston_plane_release(&output->fb_plane); @@ -875,7 +876,6 @@ 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; if (output_base == NULL) { weston_log("output is NULL.\n"); @@ -935,14 +935,11 @@ 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); + gles2_renderer_output_destroy(&output->base); - if (egl_surface == EGL_NO_SURFACE) { - weston_log("failed to create egl surface\n"); - goto err; + if (!gles2_renderer_output_create(&output->base, surface)) { + weston_log("failed to create renderer output\n"); + goto err_gbm; } ret = drmModeSetCrtc(ec->drm.fd, @@ -951,7 +948,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. */ @@ -973,9 +970,7 @@ 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); gbm_surface_destroy(output->surface); - output->base.egl_surface = egl_surface; output->surface = surface; /*update output*/ @@ -984,8 +979,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_destroy(&output->base); +err_gbm: gbm_surface_destroy(surface); return -1; } @@ -1387,15 +1383,12 @@ 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); + + if (gles2_renderer_output_create(&output->base, output->surface) < 0) + goto err_output; output->cursor_bo[0] = gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888, @@ -1415,10 +1408,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; @@ -1445,7 +1434,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, @@ -2227,9 +2217,6 @@ drm_compositor_create(struct wl_display *display, goto err_sprite; } - if (gles2_renderer_init(&ec->base) < 0) - goto err_egl; - path = NULL; evdev_input_create(&ec->base, ec->udev, seat); @@ -2270,7 +2257,6 @@ err_drm_source: wl_event_source_remove(ec->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); diff --git a/src/compositor-rpi.c b/src/compositor-rpi.c index c4023afb..69f3d591 100644 --- a/src/compositor-rpi.c +++ b/src/compositor-rpi.c @@ -970,8 +970,7 @@ rpi_output_destroy(struct weston_output *base) vc_dispmanx_element_remove(update, output->egl_element); vc_dispmanx_update_submit_sync(update); - eglDestroySurface(output->compositor->base.egl_display, - output->base.egl_surface); + gles2_renderer_output_destroy(base); wl_list_for_each_safe(element, tmp, &output->element_list, link) rpi_element_destroy(element); @@ -1050,25 +1049,6 @@ rpi_output_create(struct rpi_compositor *compositor) output->egl_window.width = modeinfo.width; output->egl_window.height = modeinfo.height; - output->base.egl_surface = - eglCreateWindowSurface(compositor->base.egl_display, - compositor->base.egl_config, - (EGLNativeWindowType)&output->egl_window, - NULL); - if (output->base.egl_surface == EGL_NO_SURFACE) { - print_egl_error_state(); - weston_log("Failed to create output surface.\n"); - goto out_dmx; - } - - if (!eglSurfaceAttrib(compositor->base.egl_display, - output->base.egl_surface, - EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) { - print_egl_error_state(); - weston_log("Failed to set swap behaviour to preserved.\n"); - goto out_surface; - } - output->base.repaint = rpi_output_repaint; output->base.destroy = rpi_output_destroy; if (compositor->max_planes > 0) @@ -1104,6 +1084,19 @@ rpi_output_create(struct rpi_compositor *compositor) weston_output_init(&output->base, &compositor->base, 0, 0, round(mm_width), round(mm_height), WL_OUTPUT_TRANSFORM_NORMAL); + + if (gles2_renderer_output_create(&output->base, + (EGLNativeWindowType)&output->egl_window) < 0) + goto out_output; + + if (!eglSurfaceAttrib(compositor->base.egl_display, + gles2_renderer_output_surface(&output->base), + EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) { + print_egl_error_state(); + weston_log("Failed to set swap behaviour to preserved.\n"); + goto out_gles2; + } + wl_list_insert(compositor->base.output_list.prev, &output->base.link); weston_log("Raspberry Pi HDMI output %dx%d px\n", @@ -1113,11 +1106,10 @@ rpi_output_create(struct rpi_compositor *compositor) return 0; -out_surface: - eglDestroySurface(compositor->base.egl_display, - output->base.egl_surface); - -out_dmx: +out_gles2: + gles2_renderer_output_destroy(&output->base); +out_output: + weston_output_destroy(&output->base); update = vc_dispmanx_update_start(0); vc_dispmanx_element_remove(update, output->egl_element); vc_dispmanx_update_submit_sync(update); @@ -1512,7 +1504,6 @@ rpi_compositor_create(struct wl_display *display, int argc, char *argv[], const char *config_file, struct rpi_parameters *param) { struct rpi_compositor *compositor; - struct weston_output *output; const char *seat = default_seat; uint32_t key; @@ -1571,17 +1562,10 @@ rpi_compositor_create(struct wl_display *display, int argc, char *argv[], if (rpi_output_create(compositor) < 0) goto out_egl; - if (gles2_renderer_init(&compositor->base) < 0) - goto out_output; - evdev_input_create(&compositor->base, compositor->udev, seat); return &compositor->base; -out_output: - wl_list_for_each(output, &compositor->base.output_list, link) - rpi_output_destroy(output); - out_egl: rpi_fini_egl(compositor); diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index 56759fc0..db977133 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -317,9 +317,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_destroy(output_base); + wl_egl_window_destroy(output->parent.egl_window); free(output); @@ -373,13 +373,9 @@ 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_create(&output->base, + output->parent.egl_window) < 0) goto cleanup_window; - } output->parent.shell_surface = wl_shell_get_shell_surface(c->parent.shell, @@ -846,10 +842,6 @@ wayland_compositor_create(struct wl_display *display, if (wayland_compositor_create_output(c, width, height) < 0) goto err_display; - /* requires wayland_compositor_create_output */ - if (gles2_renderer_init(&c->base) < 0) - goto err_display; - /* requires gles2_renderer_init */ create_border(c); diff --git a/src/compositor-x11.c b/src/compositor-x11.c index 9d922b53..cbb24829 100644 --- a/src/compositor-x11.c +++ b/src/compositor-x11.c @@ -390,8 +390,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_destroy(output_base); xcb_destroy_window(compositor->conn, output->window); @@ -607,18 +606,6 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y, x11_output_wait_for_map(c, output); - 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"); - return NULL; - } - - loop = wl_display_get_event_loop(c->base.wl_display); - output->finish_frame_timer = - wl_event_loop_add_timer(loop, finish_frame_handler, output); - output->base.origin = output->base.current; output->base.repaint = x11_output_repaint; output->base.destroy = x11_output_destroy; @@ -632,6 +619,13 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y, weston_output_init(&output->base, &c->base, x, y, width, height, transform); + if (gles2_renderer_output_create(&output->base, output->window) < 0) + return NULL; + + loop = wl_display_get_event_loop(c->base.wl_display); + output->finish_frame_timer = + wl_event_loop_add_timer(loop, finish_frame_handler, output); + wl_list_insert(c->base.output_list.prev, &output->base.link); weston_log("x11 output %dx%d, window id %d\n", @@ -1247,9 +1241,6 @@ 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; - c->xcb_source = wl_event_loop_add_fd(c->base.input_loop, xcb_get_file_descriptor(c->conn), diff --git a/src/compositor.h b/src/compositor.h index d2e121b1..18265949 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; @@ -838,7 +839,12 @@ int weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode); int -gles2_renderer_init(struct weston_compositor *ec); +gles2_renderer_output_create(struct weston_output *output, + EGLNativeWindowType window); +void +gles2_renderer_output_destroy(struct weston_output *output); +EGLSurface +gles2_renderer_output_surface(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 49fe7b04..2559602b 100644 --- a/src/gles2-renderer.c +++ b/src/gles2-renderer.c @@ -36,6 +36,17 @@ struct gles2_renderer { int fragment_shader_debug; }; +struct gles2_output_state { + EGLSurface egl_surface; +}; + + +static inline struct gles2_output_state * +get_output_state(struct weston_output *output) +{ + return (struct gles2_output_state *)output->renderer_state; +} + static const char * egl_error_string(EGLint code) { @@ -706,6 +717,7 @@ static void gles2_renderer_repaint_output(struct weston_output *output, pixman_region32_t *output_damage) { + struct gles2_output_state *go = get_output_state(output); struct weston_compositor *compositor = output->compositor; EGLBoolean ret; static int errored; @@ -718,8 +730,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, go->egl_surface, + go->egl_surface, compositor->egl_context); if (ret == EGL_FALSE) { if (errored) return; @@ -755,7 +767,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, go->egl_surface); if (ret == EGL_FALSE && !errored) { errored = 1; weston_log("Failed in eglSwapBuffers.\n"); @@ -1213,6 +1225,57 @@ log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig) weston_log_continue(" unknown\n"); } +static int +gles2_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface); + +WL_EXPORT int +gles2_renderer_output_create(struct weston_output *output, + EGLNativeWindowType window) +{ + struct weston_compositor *ec = output->compositor; + struct gles2_output_state *go = calloc(1, sizeof *go); + + if (!go) + return -1; + + go->egl_surface = + eglCreateWindowSurface(ec->egl_display, + ec->egl_config, + window, NULL); + + if (go->egl_surface == EGL_NO_SURFACE) { + weston_log("failed to create egl surface\n"); + free(go); + return -1; + } + + if (ec->egl_context == NULL) + if (gles2_renderer_setup(ec, go->egl_surface) < 0) { + free(go); + return -1; + } + + output->renderer_state = go; + + return 0; +} + +WL_EXPORT void +gles2_renderer_output_destroy(struct weston_output *output) +{ + struct gles2_output_state *go = get_output_state(output); + + eglDestroySurface(output->compositor->egl_display, go->egl_surface); + + free(go); +} + +WL_EXPORT EGLSurface +gles2_renderer_output_surface(struct weston_output *output) +{ + return get_output_state(output)->egl_surface; +} + WL_EXPORT void gles2_renderer_destroy(struct weston_compositor *ec) { @@ -1274,12 +1337,11 @@ fragment_debug_binding(struct wl_seat *seat, uint32_t time, uint32_t key, weston_output_damage(output); } -WL_EXPORT int -gles2_renderer_init(struct weston_compositor *ec) +static int +gles2_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface) { struct gles2_renderer *renderer; const char *extensions; - struct weston_output *output; EGLBoolean ret; static const EGLint context_attribs[] = { @@ -1307,10 +1369,8 @@ gles2_renderer_init(struct weston_compositor *ec) return -1; } - output = container_of(ec->output_list.next, - struct weston_output, link); - ret = eglMakeCurrent(ec->egl_display, output->egl_surface, - output->egl_surface, ec->egl_context); + ret = eglMakeCurrent(ec->egl_display, egl_surface, + egl_surface, ec->egl_context); if (ret == EGL_FALSE) { weston_log("Failed to make EGL context current.\n"); print_egl_error_state();