I feel configure events and requests are messed up
krh at bitplanet.net
Thu Sep 8 13:32:22 PDT 2011
2011/9/8 Giovanni Campagna <scampa.giovanni at gmail.com>:
> Il giorno gio, 08/09/2011 alle 14.31 -0400, Kristian Høgsberg ha
>> 2011/9/7 Giovanni Campagna <scampa.giovanni at gmail.com>:
>> > [...]
>> > You say it: "it's more important that clients always know exactly that
>> > the buffer size of the EGLSurface they're rendering to corresponds to
>> > the size of the window". If you don't resize the buffer as soon as the
>> > window is resized server-side, you end with the client drawing a buffer
>> > of the wrong size, at which point either the compositor bows to the
>> > client and draws the entire buffer, or the buffer is clipped.
>> > The only way to control rogue clients is to ensure that the
>> > implementation, at the either side of the socket, agrees and enforces
>> > the same limits - and since policy should not be in the hands of
>> > low-level libraries, it flows naturally that whatever the compositor
>> > says, they client must obey.
>> > A great, positive advantage X11 has, compared to other windowing system,
>> > is the window manager, that ensures consistent behavior and policy
>> > across all applications, irrespective of the toolkit used or the Human
>> > Interface Guidelines of the originating project. xterm resizes like
>> > konsole, like gnome-terminal, like xfce4-terminal, despite being all
>> > completely different code bases, and this only thanks to window manager.
>> > Consistency is what I want to achieve (or rather, to preserve, as this
>> > is already in X11) - by centralizing all decisions.
>> I dont see anything in what you say here that argues against the way
>> Wayland works today.
> Yes, because you are letting applications call gdk_window_move_resize()
> and the compositor has no way to prevent the effects.
I don't understand what you mean here. I don't control what GTK/GDK
API is available to applications.
> I have nothing
> against having GDK calling wl_egl_window_resize,
> cairo_gl_surface_set_size, cogl_onscreen_update_size, etc. as part of
> interactive resizing, and I have nothing against the compositor
> accepting any buffer in that time. But outside of that, I want
> applications to respect the given size.
> It's like a widget system: from a widget implementation, you can ask a
> bigger size, but you cannot actually draw at the new size until you're
> allocated again, and you have no guarantee that you'll be actually given
> the preferred size.
Ah, but you *can* actually draw before you get the size. The idea is
also to reduce roundtrips between the compositor and client. The
client isn't messing up anything for anybody else by assuming it will
be allowed to resize and drawing at the new size. And there is really
no point in asking the compositor "can I be this size" and then
waiting for "yes you can" before drawing. We can just resize and draw
at the size we want and present the end result to the compositor. We
should probably add an event for the case when the compositor rejects
the new size, but there's really no need to add a
configure_request/configure_notify roundtrip when pretty much all apps
will behave well and resize to a size that will accepted by the
>> > You want a concrete example? Consider edge tiling: in that mode, the
>> > window is not resizable, and attempts to programmatically resize it
>> > should be cached and reapplied when the window is desnapped. Shall we
>> > tell the client it is edge tiled? If we go that road, we end up with
>> > EMWH, trying to specify all possible window states...
>> Yes, the client needs to know that it can't resize at that time. You
>> can't force clients to behave a certain way by just clamping their
>> size, they have to understand that they're being displayed in a
>> certain way that means they can't currently resize freely. Maybe
>> we'll need a flag in the configiure event that tells the client "be
>> this exact size" or maybe the client just needs to know that it's edge
>> tiled and cant try to resize.
> I disagree. There are two paths here: one is programmatical resize, for
> example because the logical contents (the widgets, that is) of the
> window changed, and the other is interactive resize.
> The former should be preceded by a constraint change (so if the
> egde-tiled size is no longer possible, the compositor automatically
> de-tiles), but should be vetted by the wm before it actually happens.
> This is not a problem for flashes, as it will happen only once in a
> The latter instead should be always initiated by the compositor, using
> keybindings or server-side frames. There is no need for the client to
> know if the window is resizable by the user or not, as UI hints will be
> placed by the compositor.
> The middle ground is animating a programmatical resize, and this is
> where wayland works well, as the buffer is first prepared at the new
> size and then immediately composited. We can still let the compositor
> have a say in this with a flow similar to this:
> - the higher level toolkit notices that the window should change size,
> and invokes gdk_window_resize with the target size
> - GDK asks the compositor if this is OK
> - the compositor replies with a configure_notify event with the target
> size, essentially saying "go ahead", and enters a special "animated
> resizing" mode
> - the higher level toolkit animates the resizing by issuing a redraw at
> a fixed interval and asking GDK for a buffer of the interpolated size;
> the redraw function invoked by the higher level toolkit is given the
> interpolated size, rather than the value of gdk_window_get_size()
> - once each buffer is complete, libEGL attaches it and the compositor
> blits it on screen, until it receives a buffer of the target size, at
> which point the animated resize is over and the compositor goes back to
> normal policy of wrongly sized buffers
>> > And that's my problem with it: toolkits needs to be mixed. I'm not
>> > saying mixing Qt and GDK (although Qt wants to load Gtk to render GNOME
>> > themes...), but of GDK, Cairo and Cogl. You don't want Cairo to depend
>> > on Gdk or Cogl (one of the maintainers already told me that this is not
>> > acceptable, as Cairo wants the maximum portability),
>> Did you notice cairo_xlib_surface_set_size()? Cairo doesn't magically
>> listen for X events and resizes the cairo surface behind the toolkits
>> back. Cairo works the same way.
> True, but the only place that wants to call
> cairo_xlib_surface_set_size() is Gdk (or whoever created the surface in
> the first place). Bad things happen if application code invokes it, and
> I consider it cleaner if we can prevent it from the very beginning, by
> not having a cairo_wayland_surface_set_size().
It's already there, it's cairo_gl_surface_set_size(). And why do you
think wl_egl_surface_resize() is different from
cairo_xlib_surface_set_size() in terms of who calls it? If you're
using cairo-gl, that will call wl_egl_surface_resize(), if you're
using clutter, cogl will call wl_egl_surface_resize(). It's not an
application level API.
> But anyway, this is not important, as long as it updates only cairo
> internal state, and not actually resize the window on screen.
>> > and neither Cogl
>> > probably wants to depend on GDK; but on the other hand, the window
>> > should be created by GDK and handled by GDK (as most of non-rendering
>> > stuff, like events, drags and management must be handed by GDK, if not
>> > by the upper layers), so there should be a way for GDK to hand out some
>> > sort of "window object" down to Cogl and Cairo, with all necessary state
>> > and change notifications. And then there is the problem of libEGL, as it
>> > can't of course depend on any toolkit, but must still preserve state and
>> > receive notifications.
>> There is no window object other than GdkWindow in GTK. Gdk manages
>> the event for the underlying window, and creates a cairo surface at
>> the size it things the window is. I don't know the details of Clutter
>> and GDK integration, but I understand you know that area pretty well.
>> However, in that case, GDK is still going to handle resizing and can
>> just push the size down to cogl, which then calls
>> wl_egl_window_resize(). In that way, cogl would work much like cairo.
> GdkWindow is not a window object, or at least not what I mean with
> window object. GdkWindow is an abstraction over window objects provided
> by the native system (Window XID, HWND), and shares state with the
> underlying objects, allowing a different library that only implements
> the native system.
> This is what allows for example Gdk and Cogl to work together, without
> Cogl knowing about Gdk or Gdk knowing about Cogl: all they know about,
> and the only interface for them is libX11. Resizing is just part of the
> picture: if all events and client state changes need to be pushed down
> by an integrating library, I imagine things will get messy as soon as
> wayland becomes more complex.
>> > In X11, handling a Window XID plus a set of XEvents is enough;
>> No, in X11 there is a different event stream for resizing the
>> underlying GLX/EGL surface. In DRI1 it was really bad, since we used
>> a bit in a shared memory area to notify libGL that the window had
>> changed and libGL would then do a roundtrip to the server to get the
>> new size. In DRI2 we're now using a DRI2 invalidate event that
>> triggers libGL to go out and do a roundtrip to ask for a new set of
>> buffers in the size that X thinks the window is. X, the wm and the
>> client are all different processes. At any given time during
>> interactive or animated resizing, the toolkits idea of size, libGL
>> idea and the X servers idea is likely to be out of sync.
>> We don't want the EGL buffers to match the latest size from the
>> server, we want them to match the size that the client saw when it
>> scheduled its redraw. Wayland resizing is designed so that there's
>> one predictable flow or pipeline of resize events instead of hitting
>> different parts of the stack with different resize events at different
>> times: The new size comes from the compositor (in case of interactive
>> resizing) or the clients animation framework (in case of animated
>> resizing). The toolkit receives that size and relayouts widgets and
>> schedules a redraw. The redraw triggers and tells the rendering
>> library what size we want the surface to be, renders the frame and
>> then finally presents the frame to the compositor, which atomically
>> updates the contents, size and position of the surface.
> You don't want EGL buffers to match the size when the client scheduled
> the redraw, you want them to match the size that will be drawn on the
Sure, but then when you start drawing, GL will do a roundtrip behind
your back and get a different size anyway. Rendering APIs that change
the surface size autonomously and unpredictable behind your back are
> Since you first create a buffer and then draw on it, the
> application can query (or obtain) the buffer size at the beginning of
> redraw procedure, so if the compositor in the mean time comes in and
> says "no, this size is not good for you", the application won't map the
> wrong buffer.
>> And I suspect this talk about "letting the toolkit have the final say"
>> is what is making you see red, but realize I'm not arguing that we
>> should let clients go crazy. Well behaved clients will allocate the
>> size they're asked to, render a new frame and send that back to the
>> compositor. That's what pretty much what all clients will do and
>> that's the case we have to optimize for. The case where a badly
>> behaved client tries to use a wrong size is going to look bad when we
>> clip it, whether we do it in client side EGL or in the compositor.
> Yes, but in the middle of this is policy. If the originator of a resize
> is not the user, how the application can know that the new size is good?
> We need some way for central policy to kick in, and that's what I'm
> asking for with the explicit "configure" request. All the rest,
> including buffer sizes, is tangential and a big misunderstanding caused
> by my original email.
More information about the wayland-devel