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 3c0273a..5bf1df3 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 5fe234d..f7b8d68 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 c4023af..69f3d59 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 56759fc..db97713 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 9d922b5..cbb2482 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 d2e121b..1826594 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 49fe7b0..2559602 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();
-- 
1.8.0

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to