Decorationless EGL apps are broken in toytoolkit

Pekka Paalanen ppaalanen at gmail.com
Mon Dec 12 05:02:09 PST 2011


On Wed, 30 Nov 2011 13:46:35 +0200
Pekka Paalanen <ppaalanen at gmail.com> wrote:

> Hi,
> 
> as I was working on the screensaver stuff, I found out that EGL
> applications that do not want decorations are broken. This is easy to
> reproduce, just apply the following hunk:
> 
> diff --git a/clients/gears.c b/clients/gears.c
> index bc85f54..4a1d660 100644
> --- a/clients/gears.c
> +++ b/clients/gears.c
> @@ -319,6 +319,7 @@ gears_create(struct display *display)
>         gears->window = window_create(display, width, height);
>         window_set_transparent(gears->window, 0);
>         window_set_title(gears->window, "Wayland Gears");
> +       window_set_decoration(gears->window, 0);
>  
>         gears->display = display_get_egl_display(gears->d);
>         if (gears->display == NULL)
> 
> After that, the gears demo should be decorationless, but instead it
> triggers this error:
> 
> libEGL debug: EGL user error 0x300d (EGL_BAD_SURFACE) in
> eglSwapBuffers
> 
> That's fun, because nowhere in the Wayland demos toytoolkit code we
> call eglSwapBuffers ourselves. The finger points at Cairo-egl.
> 
> I made a hack that makes it work:
> 
> diff --git a/clients/window.c b/clients/window.c
> index 20500b4..8e11892 100644
> --- a/clients/window.c
> +++ b/clients/window.c
> @@ -930,6 +930,20 @@ window_create_surface(struct window *window)
>  }
>  
>  static void
> +window_draw_none(struct window *window)
> +{
> +       cairo_t *cr;
> +
> +       window_create_surface(window);
> +
> +       /* XXX FIXME: what an ugly hack!
> +        * But without this, decorationless EGL apps do not work. */
> +       cr = cairo_create(window->cairo_surface);
> +       cairo_paint(cr);
> +       cairo_destroy(cr);
> +}
> +
> +static void
>  window_draw_menu(struct window *window)
>  {
>         cairo_t *cr;
> @@ -1098,7 +1112,7 @@ window_draw(struct window *window)
>         if (window->parent)
>                 window_draw_menu(window);
>         else if (!window->decoration)
> -               window_create_surface(window);
> +               window_draw_none(window);
>         else
>                 window_draw_decorations(window);
>  }
> 
> I'm using this hack to continue my work, as I have no idea what is
> wrong.
> 
> I am still using the cairo commit 9bdfae6e218185dd9, and have not yet
> tried the current HEAD. There is also this in
> window_draw_decorations():
> 
> 	/* FIXME: this breakes gears, fix cairo? */
> #if 0 
> 	cairo_device_flush (window->display->device);
> #endif
> 
> Maybe it is related?

Seems to be related indeed. Both cairo_device_flush() and by default
after creating the surface, the cairo current target surface is NULL
(cairo_gl_context_t::current_target).

In cairo_gl_surface_swapbuffers(), NULL target causes first
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_ctx) which
succeeds because we have the surfaceless EGL extension. Then it calls
eglSwapBuffers(display, egl_surface) in Cairo _egl_swap_buffers()
and fails.

That is in 9bdfae6e218185dd9, but _egl_swap_buffers() seems to be the
same still in current Cairo HEAD.

Cairo should somehow have the surface as current for swap buffers, as
required in the EGL 1.4 spec, section 3.9.3.

Cairo docs say that cairo_device_flush() must be called before issuing
any native rendering commands, and currently nowhere in any of the demo
clients it is called. I wonder if this causes extra problems with the
current Cairo HEAD.

- pq


More information about the wayland-devel mailing list