[PATCH v2] gles2-renderer: Provide an API for backends to use.

John Kåre Alsaker john.kare.alsaker at gmail.com
Fri Oct 26 13:51:58 PDT 2012


Actually moving the GL and EGL state is done in a separate commit in
the interest of clarity and reducing conflicts.

This commit enables 3 EGL fields to be moved into gles2-renderer, of
which only 1 field is required to move.

I suggest one of the following options to continue:
- Backport the moving of the two other EGL fields which this commit
enabled to move or more, so you feel like the changes are more
justified.
- Split the commit in two so the EGL refactorings and output API
addition is on separate commits. Perhaps in combination with
backporting on the EGL refactorings part.
- Submit the entire patch set which moves all GL and EGL state into
gles2-renderer, which gets treated as one patch.
- Submit the patch set as one patch (That'll be fun to review).

On Fri, Oct 26, 2012 at 8:56 PM, Kristian Høgsberg <hoegsberg at gmail.com> wrote:
> On Fri, Oct 26, 2012 at 02:39:24PM -0400, Kristian Høgsberg wrote:
>> On Fri, Oct 26, 2012 at 06:06:15PM +0200, John Kåre Alsaker wrote:
>> > On Fri, Oct 26, 2012 at 3:59 PM, Kristian Høgsberg <hoegsberg at gmail.com> wrote:
>> > > On Thu, Oct 25, 2012 at 10:53:20PM +0200, John Kåre Alsaker wrote:
>> > >> 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.
>> > >
>> > > I read the patch and Pekka has a lot of good points, both stylistic
>> > > and regarding the actual code changes.  However, I don't agree with
>> > > the direction of the patch.  It's *ok* for a backend to know and
>> > > depend on EGL or some other rendering API (say pixman or a custom
>> > > compositing API or whatever).  It can even depend on multiple such
>> > > APIs (for example both pixman and EGL).  A backend will always have to
>> > > do some render API specific initialization, where the backend API and
>> > > rendering API intersects.  Like eglGetDisplay, which requires backend
>> > > specific knowledge (X display, gbm device or such) and rendering API
>> > > knowledge (it's an EGL call).
>> > What parts don't you agree with?
>> > - Refactoring common EGL code into gles2-renderer.
>> > - Providing a way for gles2-renderer to have output specific state.
>> > - Moving EGL state from the compositor into gles2-renderer, which is
>> > enabled by the above changes and happens to minimize code where the
>> > backend API and rendering API intersects.
>> >
>> > >
>> > > The next small, self-contained step forward from where the renderer
>> > > abstraction is now, is to move the EGL types out of the core structs
>> > > and header files (that is, just compositor.h).  First step: move the
>> > > shaders out of weston_compositor.h.  Let's do that and take the rest
>> > > from there.
>> > I could rebase out some smaller changes, but it's just more work and
>> > wouldn't delay this patch by much.
>>
>> I guess we're at a stalemate then.
>
> To elaborate, I don't think my suggestion was any kind of ambiguous.
> I don't want to see new patches that introduce 10 new interal API
> entrypoints without even moving the EGL types out of compositor.h.
>
> Kristian
>
>>
>> > Let's ignore the entry points catering to the Android hack and the
>> > helper function and gles2_renderer_outputs_ready, all of which can go
>> > away.
>> >
>> > int
>> > gles2_renderer_create(struct weston_compositor *ec,
>> > EGLNativeDisplayType display, int alpha);
>> > void
>> > gles2_renderer_destroy(struct weston_compositor *ec);
>> >
>> > 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 *go);
>> >
>> > void
>> > gles2_renderer_output_bind(struct weston_output *output, struct
>> > gles2_output_state *go);
>> > void
>> > gles2_renderer_output_unbind(struct weston_output *output);
>> >
>> > pq complained about the naming on bind/unbind. output_bind and
>> > output_unbind binds the gl-renderer to an output, which is why the
>> > renderer frees the state on unbind, since it no longer needs it.
>> > gl_renderer_output_bind can never fail, that is why the output_state
>> > has to be create and passed to it since creating an output_state can
>> > fail. It's probably not the best naming, but I didn't come up with
>> > anything better. They do not represent adding/removal of outputs as
>> > the backends will do unbind followed by bind on mode switching.
>> >
>> > As you can see, this API does depend on EGL so Kristian doesn't have
>> > to worry that the backends are becoming EGL independent :)
>> >
>> > >
>> > > Kristian
>> > >
>> > >> ---
>> > >>  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
>> > >>
>> > >> _______________________________________________
>> > >> wayland-devel mailing list
>> > >> wayland-devel at lists.freedesktop.org
>> > >> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list