[RFC v4] Fullscreen shell protocol

Pekka Paalanen ppaalanen at gmail.com
Fri Feb 14 23:12:09 PST 2014


On Fri, 14 Feb 2014 11:11:33 -0600
Jason Ekstrand <jason at jlekstrand.net> wrote:

> Hi Pekka!  Thanks for the review.  Comments follow.
> 
> 
> On Fri, Feb 14, 2014 at 1:14 AM, Pekka Paalanen
> <ppaalanen at gmail.com> wrote:
> 
> > Hi Jason
> >
> > On Thu, 13 Feb 2014 22:37:53 -0600
> > Jason Ekstrand <jason at jlekstrand.net> wrote:
> >
> > > The following is yet another take on the fullscreen shell
> > > protocol. Previous versions more-or-less followed the
> > > approach taken in wl_shell. This version completely reworks
> > > the concept.  In particular, the protocol is split into two
> > > use-cases.  The first is that of a simple client that wants
> > > to present a surface or set of surfaces possibly with some
> > > scaling. This happens through the present_surface request
> > > which looks similar to that of wl_shell only without the
> > > modesetting.
> > >
> > > The second use-case is of a client that wants more control
> > > over the outputs.  In this case, the client uses the
> > > present_surface_for_mode request to present the surface at a
> > > particular output mode.  This request provides a more-or-less
> > > atomic modeset operation.  If the compositor can satisfy the
> > > requested mode, then the mode is changed and the new surface
> > is
> > > presented.  Otherwise, the compositor harmlessly falls back
> > > to the previously presented surface and the client is
> > > informed that the switch failed.  This way, the surface is
> > > either displayed correctly or not at
> > all.
> > > Of course, a client is free to call present_surface_for_mode
> > > with the currently presented surface and hope for the best.
> > > However, this may result in strange behavior and there is no
> > > reliable fallback if the mode switch fails.
> > >
> > > In particular, I would like feedback on the modesetting
> > > portion of this protocol.  This is particularly targetted at
> > > compositors that want to run inside weston or some other
> > > fullscreen compositor.  In the next week or
> > so,
> > > I will attempt to implement all this in weston and see how
> > > well it works. However, I would also like to know how well
> > > this will work for other compositors such as KWin or Hawaii.
> > >
> > > Thanks for your feedback,
> > > --Jason Ekstrand
> > >
> > > ===== Protocol follows: =====
> > >
> > > <protocol name="fullscreen_shell">
> > >   <interface name="wl_fullscreen_shell" version="1">
> >
> > This interface should have a destructor request IMO. It's not
> > stricly required, but I think it would be consistent (I think
> > all global interfaces need an explicit destructor request) and
> > more future-proof.
> >
> 
> Thanks for reminding me.  I'll get one added.
> 
> 
> >
> > >     <description summary="Displays a single surface per
> > > output"> Displays a single surface per output.
> > >
> > >       This interface provides a mechanism for a single client
> > > to display simple full-screen surfaces.  While there
> > > technically may be
> > multiple
> > >       clients bound to this interface, only one of those
> > > clients should
> > be
> > >       shown at a time.
> > >
> > >       To present a surface, the client uses either the
> > > present_surface or present_surface_for_mode requests.
> > > Presenting a surface takes
> > effect
> > >       on the next wl_surface.commit.  See the individual
> > > requests for details about scaling and mode switches.
> > >
> > >       The client can have at most one surface per output at
> > > any time. Requesting a surface be presented on an output that
> > > already has a surface replaces the previously presented
> > > surface.  Presenting a
> > null
> > >       surface removes its content and effectively disables
> > > the output. Exactly what happens when an output is "disabled"
> > > is compositor-specific.  The same surface may be presented
> > > multiple outputs simultaneously.
> >
> > If the same surface is presented on multiple outputs, should
> > the client have a way to say which output is to be considered
> > the surface's main output, where e.g. presentation feedback is
> > synced to?
> >
> 
> That's a good question.  Simple clients probably don't care.
> More complex clients such as compositors probably will.  However,
> I'd expect them to have one surface per output most of the time
> anyway.  I'll give that some thought.
> 
> 
> > Maybe also note explicitly, that once a surface has been
> > presented on an output, it stays on that output until
> > explicitly removed, or output is unplugged? So that simple
> > attach+damage+commit can be used to update the content, if that
> > is the intention.
> >
> 
> Yes, that's a good point.  And I do intend to provide that
> guarantee.
> 
> 
> >
> > >     </description>
> > >
> > >     <enum name="present_method">
> > >       <description summary="different method to set the
> > > surface
> > fullscreen">
> > >       Hints to indicate to the compositor how to deal with a
> > > conflict between the dimensions of the surface and the
> > > dimensions of the output. The compositor is free to ignore
> > > this parameter. </description>
> > >       <entry name="default" value="0" summary="no preference,
> > > apply
> > default policy"/>
> > >       <entry name="center" value="1" summary="center the
> > > surface on the
> > output"/>
> > >       <entry name="zoom" value="2" summary="scale the surface,
> > preserving aspect ratio, to the largest size that will fit on
> > the output" />
> > >       <entry name="zoom_crop" value="3" summary="scale the
> > > surface,
> > preserving aspect ratio, to fully fill the output cropping if
> > needed" />
> > >       <entry name="stretch" value="4" summary="scale the
> > > surface to the
> > size of the output ignoring aspect ratio" />
> > >     </enum>
> > >
> > >     <request name="present_surface">
> > >       <description summary="present surface for display">
> > >       Present a surface on the given output.
> > >
> > >       If the output is null, the compositor will present the
> > > surface on whatever display (or displays) it thinks best.  In
> > > particular, this may replace any or all surfaces currently
> > > presented so it should not be used in combination with
> > > placing surfaces on specific outputs.
> > >
> > >       The method parameter is a hit to the compositor for how
> > > the surface
> >
> > *hint
> >
> 
> Thanks
> 
> 
> >
> > >       is to be presented.  In particular, it tells the
> > > compostior how to handle a size mismatch between the
> > > presented surface and the output.  The compositor is free to
> > > ignore this parameter.
> > >
> > >       The "zoom", "zoom_crop", and "stretch" methods imply a
> > > scaling operation on the surface.  This will override any
> > > kind of output scaling, so the buffer_scale property of the
> > > surface is effectively ignored.
> > >       </description>
> > >       <arg name="surface" type="object"
> > > interface="wl_surface"/> <arg name="method" type="uint"/>
> > >       <arg name="output" type="object" interface="wl_output"
> > allow-null="true"/>
> > >     </request>
> > >
> > >     <request name="present_surface_for_mode">
> > >       <description summary="present surface for display at a
> > > particular
> > mode">
> > >       Presents a surface on the given output for a particular
> > > mode.
> > >
> > >       If the current size of the output differs from that of
> > > the surface, the compositor will attempt to change the size
> > > of the output to match the surface.  The result of the
> > > mode-swith operation will be returned via the provided
> > > wl_fullscreen_shell_mode_feedback object.
> >
> > Is it sufficient to infer the mode from the buffer size, or
> > could there be use cases for forcing a particular mode and
> > scaling a buffer from a different size?
> >
> > If you had a separate "set_mode" request, you could do with
> > only the "present_surface" request for setting the surface.
> >
> 
> Hehe.  That was my original thought on the matter.  Later, I
> thought better of it.  I'll have more comments on the matter at
> the end.
> 
> 
> > Taking this idea further, like atomic mode setting over all
> > outputs, we're getting pretty close to the DRM KMS APIs. Would
> > it make sense to model these interfaces according to the KMS
> > APIs but sanitized to offer all the modern features like atomic
> > modeset and planes in a clean uniform way, or do you
> > intentionally want to keep this protocol interface simple and
> > not e.g. consider planes explicitly?
> >
> 
> I'll take a look at KMS.  However, I think planes are better left
> to subsurfaces.  More on that below.
> 
> 
> > >       If the current output mode matches the one requested or
> > > if the compositor successfully switches the mode to match the
> > > surface, then the mode_successfull event will be sent and the
> > > output will contain the contents of the given surface.  If
> > > the compositor cannot match the output size to the surface
> > > size, the mode_failed will be sent and the output will
> > > contain the contents of the previously presented surface (if
> > > any).  If another surface is presented on the given output
> > > before either of these has a chance to happen, the
> > > present_canceled event will be sent.
> > >
> > >       If the size of the presented surface changes, the
> > > resulting output is undefined.  The compositor may attempt to
> > > change the output mode to compensate.  However, there is no
> > > guarantee that a suitable mode will be found and the client
> > > has no way to be notified of success or failure.
> >
> > The above sounds to me like you want the client be in explicit
> > control of the video mode when it asks one, without the server
> > fuzzing in between with scaling.
> >
> > With an explicit "set_mode" request, I think you could make the
> > above cases defined.
> >
> > How much control do you want to give to the client? Apparently
> > you want the two different cases: simple client, smart server;
> > and smart client with explicit mode setting, simple server just
> > obeying or refusing without any fuzz.
> >
> 
> Pretty much.   Again, read below.
> 
> 
> >
> > >       The framerate parameter specifies the target framerate
> > > for the output.  The compositor is free to ignore this
> > > parameter.  A value of 0 indicates that the client has no
> > > preference.
> > >
> > >       If the surface has a buffer_scale greater than 1, the
> > > compositor may choose a mode that matches either the buffer
> > > size or the surface size.  In either case, the surface will
> > > fill the output. </description>
> > >       <arg name="surface" type="object"
> > > interface="wl_surface"/> <arg name="output" type="object"
> > > interface="wl_output"/> <arg name="framerate" type="int"/>
> > >       <arg name="feedback" type="new_id"
> > interface="wl_fullscreen_shell_mode_feedback"/>
> > >     </request>
> > >
> > >     <enum name="error">
> > >       <description summary="wl_fullscreen_shell error values">
> > >       These errors can be emitted in response to
> > > wl_fullscreen_shell
> > requests
> > >       </description>
> > >       <entry name="invalid_method" value="0"
> > > summary="present_method is
> > not known"/>
> > >     </enum>
> > >   </interface>
> > >
> > >   <interface name="wl_fullscreen_shell_mode_feedback"
> > > version="1"> <event name="mode_successful">
> > >       <description summary="mode switch succeeded">
> > >       This event indicates that the attempted mode switch
> > > operation was successful.  A surface of the size requested in
> > > the mode switch will fill the output without scaling.
> > >
> > >       Upon recieving this event, the client should destroy the
> > >       wl_fullscreen_shell_mode_feedback object.
> > >       </description>
> > >     </event>
> > >     <event name="mode_failed">
> > >       <description summary="mode switch succeeded">
> > >       This event indicates that the attempted mode switch
> > > operation failed. This may be because the requested output
> > > mode is not possible or it may mean that the compositor does
> > > not want to allow mode switches at this time.
> > >
> > >       Upon recieving this event, the client should destroy the
> > >       wl_fullscreen_shell_mode_feedback object.
> > >       </description>
> > >     </event>
> > >     <event name="present_canceled">
> > >       <description summary="mode switch succeeded">
> > >       This event indicates that the attempted mode switch
> > > operation was canceled.  Most likely this is because the
> > > client requested a second mode switch before the first one
> > > completed.
> > >
> > >       Upon recieving this event, the client should destroy the
> > >       wl_fullscreen_shell_mode_feedback object.
> > >       </description>
> > >     </event>
> >
> > This interface has no destructor protocol, so the server cannot
> > know when it gets destroyed by the client. I'm always a bit
> > wary of that, but here it seems ok, since this is a one-shot
> > feedback object without any requests. It is short-lived,
> > doesn't take resources in the server much nor bandwidth when it
> > triggers, so there's no need to ever be able to cancel it.
> >
> 
> Yeah, I thought about having a destructor but it's intentionally
> a one-shot and that just adds more protocol noise for little
> benefit. Maybe it's a good idea, but I don't think it's needed.
> 
> Ok, now for the promised "more detail"...
> 
> When designing this interface, I have three primary use-cases in
> mind:
> 
> 1) Simple clients such as splash screens and terminal emulators.
> These would rather not mess with KMS and, in a world without
> VT's, need some way to get to the screen.  I want to provide a
> simple but powerful enough interface to serve these clients.
> 
> 2) Full compositors such as KWin that would rather not deal with
> KMS themselves but would prefer to let Weston or some other
> implementation handle it.  In this case, we want more
> fine-grained control and we want things like planes, cursors, etc.
> 
> 3) Other non-KMS "backends" such as VNC/RDP servers, screen
> recorders, or anything else where it may not be practical to
> implement full DRM/KMS.
> 
> As you surmised, the first request is to handle the first of these
> use-cases and the second request is for the other two.  Breaking
> it into two completely separate cases was a deliberate decision.
> Maybe not the right one, but deliberate none the less.  Allow me
> to explain.
> 
> First, I think that planes and the like are already pretty-well
> covered by wl_subsurface and wl_viewport.  There's no reason for
> me to duplicate that protocol here if it's already covered by
> those.  This may not map perfectly, but I think it will cover
> well enough for most cases.  Axel, this also covers cursors and
> the like.

Hi,

the sub-surface approach for planes has one complication. If your
fullscreen-compositor is the one making all decisions about hw
plane usage and never exposing any details of them to the
child-compositor, then the child-compositor must always forward all
surfaces as sub-surfaces to give the fullscreen-compositor a chance
to use all planes. If the child-compositor composites itself, it
excludes some opportunities to use hw planes.

Is the cost of forwarding all surfaces into sub-surfaces
significant? I don't really know. Is it your intended way of
working?

It certainly does make the protocol simple and easy to use.

> Second, I wanted to ensure that things were atomic.  By having
> presentation explicitly tied to mode set, we can ensure this.
> There is the issue of the fallback not being atomic.  One
> solution to this would be to have a fallback mode option so if it
> can't find a mode it will scale or something. However, I would
> rather clients pick one interface and stick with it than
> switching between the two.  I thought about splitting it into a
> set_mode request and a present_surface request.  However, a) it's
> harder (not impossible) to make this atomic and b) it makes the
> compositor's life more difficult (see next paragraph).  If they
> want scaling+modeset, they can just use a wl_viewport.

Sorry, perhaps I wasn't clear. I meant to keep your semantics the
same, mode set being triggered on wl_surface.commit. The set_mode
request would be just the mode set part of your
present_surface_for_mode. Atomicity would be exactly the same. That
way you could replace present_surface_for_mode with a pair of
set_mode and present_surface, and have the very same result.

> Third, I want to allow VNC/RDP-type compositors to be as simple as
> possible.  If they don't provide wl_subsurface and wl_viewport
> then they don't have to do any real composting.  They still have
> to handle the first request but that's easily enough done with
> pixman or similar.  Also, it explicitly states that they can
> ignore the method parameter and just always center the surface or
> something.  For the present_for_mode request, it means that they
> can always do a direct pixel copy from the source to the
> destination (or directly flip in the case of DRM/KMS).  By
> requiring the surface and output size to match, it takes a lot of
> the guesswork out of the mode switches.

You could still keep those semantics too, I guess, but now I
realize that you indeed do not have the "method" argument for
present_surface_for_mode. Yes, your design makes sense.

> I hope that makes my thinking on this whole protocol more clear.
> Thanks for reviewing;  I look forward to any future comments you
> may have! --Jason Ekstrand

Sure!

Thanks,
pq


More information about the wayland-devel mailing list