wl_surface.attach with NULL wl_buffer behaviour

Jasper St. Pierre jstpierre at mecheye.net
Wed Sep 2 11:40:22 PDT 2015


Destroying the xdg_surface is absolutely OK. I'm not sure why the Qt
people consider it wrong.

On Wed, Sep 2, 2015 at 11:38 AM, Prabhu S <prabhusundar at gmail.com> wrote:
> With the below change in simple-shm.c, weston+fbdev backend will be stuck
> and other compositors may work. It depends on compositor implementation and
> the actual behavior supposed to be is not clearly defined. I'm still trying
> to identify fix in weston, it looks like state information is overwritten
> before idle_repaint is being called.
>
>     window->callback = wl_surface_frame(window->surface);
>     wl_callback_add_listener(window->callback, &frame_listener, window);
>     wl_surface_commit(window->surface);
>
>    + wl_surface_attach(window->surface, 0, 0, 0);
>     +wl_surface_damage(window->surface,
>               0, 0, 0, 0);
>    + wl_surface_commit(window->surface);
>
> But the cause is wl_buffer set to null from the client and as per
> discussions it is not recommended. So we are trying to get this issue fixed
> in the QTWayland plugin.
> https://bugreports.qt.io/browse/QTBUG-47902
>
> Some proposal to hide the surface would be greatly appreciated.
> Below the discussion in the thread.
>
> "I did a quick check on gtk+ and it seems that in:
> gdk_wayland_window_hide_surface (GdkWindow *window)
> they actually destroy* the surface ... which sounds wrong as well?
>
> I tried to dig into EFL code as well .. but gave up due to not finding the
> implementation of efl_gfx_visible_set (if someone can either point to that
> or find the actual function to look at, that would be nice)"
>
>
>
> On Mon, Aug 24, 2015 at 4:35 AM, Pekka Paalanen <ppaalanen at gmail.com> wrote:
>>
>> On Fri, 21 Aug 2015 19:04:11 -0500
>> Prabhu S <prabhusundar at gmail.com> wrote:
>>
>> > Below is the case where I'm getting stuck with the actual test case.
>> > Wondering why there is no callback wl_callback at 25.done or
>> > wl_buffer at 29.release
>> > The EGL implementation depends on these callback/buffer release.
>>
>> You will not get wl_callback at 25.done, because the NULL wl_buffer has
>> overwritten the other wl_buffer, leaving the wl_surface without any
>> content, which makes it disappear from screen. Frame callbacks are not
>> intended to be posted for non-visible wl_surfaces.
>>
>> You should get wl_buffer at 29.release though. I bet you actually do get
>> it, but something else is stopping the incoming Wayland events from
>> being dispatched. See:
>> http://lists.freedesktop.org/archives/wayland-devel/2014-April/014121.html
>> and "protocol dumpers" on:
>> http://wayland.freedesktop.org/extras.html
>>
>> My wild guess would be that something is blocking, waiting on the frame
>> callback, likely EGL. It's not really EGL's bug but the application's
>> (or Qt).
>>
>> > Also noticed if the valid buffer is attached immediately after null
>> > buffer,
>> > everything is fine, so most of the time it is unnoticed. If the frame is
>>
>> Hmm, no, things should not be fine in that case. Well, it depends on
>> what role the wl_surface you are committing on has, but the very least
>> it may cause flicker.
>>
>> You definetely want to get rid of that null attach. You do not want to
>> just ignore it.
>>
>> > complex, egl will attach after null frame.
>> >
>>
>> It sounds like your application is committing to the wl_surface behind
>> Qt's back somehow, and it only works occasionally by luck.
>>
>> > I will keep debug if any other race conditions in my implementation.
>> >
>> > [3741557.293]  -> wl_surface at 20.frame(new id wl_callback at 25)
>> > [3741557.476]  -> wl_surface at 20.attach(wl_buffer at 29, 0, 0)
>> > [3741557.676]  -> wl_surface at 20.damage(0, 0, 800, 480)
>> > [3741557.906]  -> wl_surface at 20.commit() <=EGL
>> > [3741558.500]  -> wl_surface at 20.attach(nil, 0, 0) <=QTWayland
>> > [3741558.604]  -> wl_surface at 20.commit() <=QTWayland
>> > stuck
>> >
>> >
>> > On Fri, Aug 21, 2015 at 12:16 PM, Jasper St. Pierre
>> > <jstpierre at mecheye.net>
>> > wrote:
>>
>> ...
>>
>> > > However crazy it is, the logic sort of makes sense -- the "frame"
>> > > event is guaranteed to be called once a frame when the surface content
>> > > is painted and shown on the screen. When there's no surface content,
>> > > it isn't painted, so the frame event isn't called.
>> > >
>> > > I'm not sure what you mean about a buffer release event -- you never
>> > > attached a buffer to begin with, so I can't imagine how you'll get an
>> > > event on it.
>> > >
>> > > On Fri, Aug 21, 2015 at 10:03 AM, Prabhu S <prabhusundar at gmail.com>
>> > > wrote:
>> > > > Hi,
>> > > > Based on the wayland protocol specification for wl_surface::attach
>> > > >>>If wl_surface.attach is sent with a NULL wl_buffer, the following
>> > > >>> wl_surface.commit will remove the surface content.
>> > > >
>> > > > Wondering if wl_surface_attach called with wl_buffer=NULL, will
>> > > > there be
>> > > any
>> > > > wl_buffer release event or frame callbacks?
>> > > >
>> > > > Modified the redraw in simple-shm.c as below and not receiving any
>> > > callback
>> > > > or buffer release. It just got stuck.
>> > > > The same thing is being done in qtwayland to hide the surface and it
>> > > > is
>> > > > getting stuck. Some help to check this case would be helpful.
>> > > >
>> > > > static int odd = 1;
>> > > > if(odd == 1){
>> > > >         wl_surface_attach(window->surface, buffer->buffer, 0, 0);
>> > > >         wl_surface_damage(window->surface,
>> > > >                           20, 20, window->width - 40, window->height
>> > > > -
>> > > 40);
>> > > >         odd = 0;
>> > > >     }
>> > > >     else{
>> > > >             wl_surface_attach(window->surface, 0, 0, 0);
>> > > >             wl_surface_damage(window->surface,
>> > > >                           0, 0, 0, 0);
>> > > >             odd=1;
>> > > >     }
>> > > >
>> > > >
>> > > >
>> > > > [823379.816]  -> wl_compositor at 4.create_surface(new id wl_surface at 3)
>> > > > [823379.949]  -> xdg_shell at 6.get_xdg_surface(new id xdg_surface at 7,
>> > > > wl_surface at 3)
>> > > > [823380.120]  -> xdg_surface at 7.set_title("simple-shm")
>> > > > [823380.244]  -> wl_surface at 3.damage(0, 0, 250, 250)
>> > > > [823381.333]  -> wl_shm at 5.create_pool(new id wl_shm_pool at 8, fd 5,
>> > > 250000)
>> > > > [823381.561]  -> wl_shm_pool at 8.create_buffer(new id wl_buffer at 9, 0,
>> > > > 250,
>> > > > 250, 1000, 1)
>> > > > [823381.870]  -> wl_shm_pool at 8.destroy()
>> > > > [823384.880]  -> wl_surface at 3.attach(wl_buffer at 9, 0, 0)
>> > > > [823385.095]  -> wl_surface at 3.damage(20, 20, 210, 210)
>> > > > [823385.317]  -> wl_surface at 3.frame(new id wl_callback at 10)
>> > > > [823385.443]  -> wl_surface at 3.commit()
>> > > > [823388.852] wl_display at 1.delete_id(8)
>> > > > [823388.979] xdg_surface at 7.configure(0, 0, array, 4)
>> > > > [823389.238]  -> xdg_surface at 7.ack_configure(4)
>> > > > [823401.773] wl_display at 1.delete_id(10)
>> > > > [823401.908] wl_buffer at 9.release()
>>
>> This is the buffer release you expected. Note, that release can come
>> before the next buffer is attached, like here. This is typical for a
>> compositor using GL while the client is using software rendering
>> (wl_shm). Things can differ if the client is using GL or if the
>> compositor is not using GL.
>>
>> > > > [823401.991] wl_callback at 10.done(4056537)
>> > > > [823404.239]  -> wl_surface at 3.attach(nil, 0, 0)
>> > > > [823404.442]  -> wl_surface at 3.damage(0, 0, 0, 0)
>> > > > [823404.663]  -> wl_surface at 3.frame(new id wl_callback at 10)
>> > > > [823404.792]  -> wl_surface at 3.commit()
>> > > > [823406.292] xdg_surface at 7.configure(0, 0, array, 5)
>> > > > [823406.524]  -> xdg_surface at 7.ack_configure(5)
>>
>> Just like Jasper explained, wl_callback at 10 will not be signalled until
>> the surface is composited the next time. Without a wl_buffer, it won't
>> get composited. The spec for wl_surface.frame says:
>>
>>         "A server should avoid signalling the frame callbacks if the
>>         surface is not visible in any way"
>>
>> Committing a NULL wl_buffer causes the wl_surface to be not visible.
>>
>>
>> Thanks,
>> pq
>
>



-- 
  Jasper


More information about the wayland-devel mailing list