[RFCv3 weston 06/15] protocol: add presentation extension RFC v3

Pekka Paalanen ppaalanen at gmail.com
Fri Mar 7 04:03:54 PST 2014

From: Pekka Paalanen <pekka.paalanen at collabora.co.uk>

Add accurate presentation timing features to Wayland: queueing and

This specification is based on the draft written by Frederic Plourde
<frederic.plourde at collabora.co.uk> and redesigned by Pekka Paalanen.

The RFC v2 version is from

Changes in v3:

* associate presentation time to current surface contents

This implements the suggestion from

which prevents surface content from jumping backwards in time if a
client retroactively queues an update with a target time in the past.

* use 64-bit tv_sec in presentation

The time_t type used in struct timespec could be almost anything. POSIX
probably defines it to be an integer, but not the size. Apparently it is
usually 'long', which makes it 64-bit on x86_64.

To be able to fully represent timespec values returned by clock_gettime,
change the protocol to use 64 bits for the tv_sec part.

* define an error for invalid tv_nsec

This allow us to rely on the normalized timestamp form.

* define some interactions with sub-surfaces

Sub-surface cached state updates (synchronized mode) are designed
especially for resizing. As queued updates are not meant to produce any
resizing-like effects, they also do not trigger any sub-surface

* add sub-headings as xml comments

* queued update cannot map

Because before mapping, the surface has no main output assigned. An
immediate commit is needed anyway, to be able to set all the surface
state, which a queued update cannot touch.

* frame callbacks are not queued

It is not known when queueing frame callbacks would be useful.

Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
 Makefile.am                      |   5 +
 protocol/presentation_timing.xml | 434 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 439 insertions(+)
 create mode 100644 protocol/presentation_timing.xml

diff --git a/Makefile.am b/Makefile.am
index 64d0743..998dc54 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -77,6 +77,8 @@ nodist_weston_SOURCES =					\
 	protocol/input-method-server-protocol.h		\
 	protocol/workspaces-protocol.c			\
 	protocol/workspaces-server-protocol.h		\
+	protocol/presentation_timing-protocol.c		\
+	protocol/presentation_timing-server-protocol.h	\
 	protocol/scaler-protocol.c			\
@@ -416,6 +418,8 @@ nodist_libtoytoolkit_la_SOURCES =			\
 	protocol/scaler-client-protocol.h		\
 	protocol/workspaces-protocol.c			\
 	protocol/workspaces-client-protocol.h		\
+	protocol/presentation_timing-protocol.c		\
+	protocol/presentation_timing-client-protocol.h	\
 	protocol/xdg-shell-protocol.c			\
@@ -911,6 +915,7 @@ EXTRA_DIST +=					\
 	protocol/text-cursor-position.xml	\
 	protocol/wayland-test.xml		\
 	protocol/xdg-shell.xml			\
+	protocol/presentation_timing.xml	\
 man_MANS = weston.1 weston.ini.5
diff --git a/protocol/presentation_timing.xml b/protocol/presentation_timing.xml
new file mode 100644
index 0000000..e191b87
--- /dev/null
+++ b/protocol/presentation_timing.xml
@@ -0,0 +1,434 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="presentation_timing">
+<!-- wrap:70 -->
+  <copyright>
+    Copyright © 2013-2014 Collabora, Ltd.
+    Permission to use, copy, modify, distribute, and sell this
+    software and its documentation for any purpose is hereby granted
+    without fee, provided that the above copyright notice appear in
+    all copies and that both that copyright notice and this permission
+    notice appear in supporting documentation, and that the name of
+    the copyright holders not be used in advertising or publicity
+    pertaining to distribution of the software without specific,
+    written prior permission.  The copyright holders make no
+    representations about the suitability of this software for any
+    purpose.  It is provided "as is" without express or implied
+    warranty.
+  </copyright>
+  <interface name="presentation" version="1">
+    <description summary="timed presentation related wl_surface requests">
+<!-- Introduction -->
+      The main features of this interface are accurate presentation
+      timing feedback, and queued wl_surface content updates to ensure
+      smooth video playback while maintaining audio/video
+      synchronization. Some features use the concept of a presentation
+      clock, which is defined in presentation.clock_id event.
+      Requests 'feedback' and 'queue' can be regarded as additional
+      wl_surface methods. They are part of the double-buffered surface
+      state update mechanism, where other requests first set up the
+      state and then wl_surface.commit atomically applies the state
+      into use. In other words, wl_surface.commit submits a content
+      update.
+<!-- Surface state vs. buffer state -->
+      Interface wl_surface has requests to set surface related state
+      and buffer related state, because there is no separate interface
+      for buffer state alone. Queueing requires separating the surface
+      from buffer state, and buffer state can be queued while surface
+      state cannot.
+      Buffer state includes the wl_buffer from wl_surface.attach, the
+      state assigned by wl_surface requests
+      set_buffer_transform and set_buffer_scale, and any
+      buffer-related state from extensions, for instance
+      wl_viewport.set_source. This state is inherent to the buffer and
+      the content update, rather than the surface.
+      Surface state includes all other state associated with
+      wl_surfaces, like the x,y arguments of wl_surface.attach, input
+      and opaque regions, damage, frame callbacks, and extension state like
+      wl_viewport.destination. In general, anything expressed in
+      surface local coordinates is better as surface state.
+<!-- Posting: immediate and queued -->
+      The standard way of posting new content to a surface using the
+      wl_surface requests 'damage', 'attach', and 'commit' is called
+      immediate content submission. This happens when a
+      presentation.queue request has not been sent since the last
+      wl_surface.commit.
+      The new way of posting a content update is a queued content
+      update submission. This happens on a wl_surface.commit when a
+      presentation.queue request has been sent since the last
+      wl_surface.commit. This does not trigger the application of
+      cached state of (synchronized) sub-surfaces. This also cannot be
+      used to map a surface or window, mapping must be done with an
+      immediate commit.
+<!-- Queueing updates -->
+      Queued content updates do not get applied immediately in the
+      compositor but are pushed to a queue on receiving the
+      wl_surface.commit. The queue is ordered by the submission target
+      timestamp. Each item in the queue contains the wl_buffer, the
+      target timestamp, and all the buffer state as defined above. All
+      the queued state is taken from the pending wl_surface state at
+      the time of the commit, exactly like an immediate commit would
+      have taken it.
+      For instance on a queueing commit, the pending buffer is queued
+      and no buffer is pending afterwards. The stored values of the
+      x,y parameters of wl_surface.attach are reset to zero, but they
+      also are not queued; queued content updates do not carry the
+      attach offsets. All other surface state (that is not queued),
+      e.g. damage, is not applied nor reset.
+      Issuing a queueing commit without a wl_surface.attach is
+      undefined. However, queueing a commit with explicitly attached
+      NULL wl_buffer works; when and if the content update is
+      executed, the surface content is removed as defined for
+      wl_surface.attach.
+      If a queued content update has been submitted, and the wl_buffer
+      used in the update is destroyed before the wl_buffer.release
+      event, the results are undefined. The compositor may or may not
+      have executed the update, therefore the surface contents become
+      undefined as explained in wl_surface.attach. The result of
+      presentation feedback is undefined, but some feedback event
+      is guaranteed to be sent at some point if it was requested.
+<!-- Compositor prepares to repaint -->
+      For each surface, the compositor maintains an association to a
+      single output that is considered as the main output for the
+      surface. Queued content updates are synchronized to the
+      surface's main output, to provide a consistent and meaningful
+      definition of the moment the update is displayed to the user.
+      When a compositor updates an output, it processes only the
+      queues of the surfaces whose main output is the one being
+      updated. The queues of other surfaces, even if they are part of
+      the redrawing, are not processed at that time.
+      When a compositor chooses to update an output, it must predict
+      the presentation clock value when the display update will occur.
+      For the definition of the moment of display update, see
+      presentation_feedback.presented. Therefore if the prediction is
+      absolutely perfect, presentation_feedback.presented will carry
+      the same clock value.
+<!-- Picking an update from a queue -->
+      For each surface with queued content updates and matching main
+      output, the compositor picks the update with the highest
+      timestamp no later than a half frame period after the predicted
+      presentation time. The intent is to pick the content update
+      whose target timestamp as rounded to the output refresh period
+      granularity matches the same display update as the compositor is
+      targeting, while not displaying any content update more than a
+      half frame period too early. If all the updates in the queue are
+      already late, the highest timestamp update is taken regardless
+      of how late it is. Once an update in a queue has been chosen,
+      all remaining updates with an earlier timestamp in the queue are
+      discarded.
+      The surface's current timestamp is the realized presentation
+      time of the update that gave the surface its current content. If
+      the presentation has been programmed, but not realized yet, the
+      surface's current timestamp is the predicted presentation time.
+      If the update chosen from the queue has a target time earlier
+      than the surface's current timestamp, the update is discarded
+      instead of applied.
+<!-- Applying queued updates -->
+      The compositor applies the chosen update to the wl_surface,
+      regardless of possible wl_subsurface.set_sync mode. This allows
+      e.g. a video to continue running in a sub-surface also during
+      window resizing. It is assumed that buffer state updates do not
+      cause visual disruption to the window like surface state updates
+      can. Support for wl_viewport is needed for glitch-free resizing
+      if the resizing involves changing the (sub-)surface size.
+      When the chosen update is applied, damage for the whole surface
+      is assumed, as damage is not explicitly queued with buffer
+      state. Applying queued updates does not trigger the application
+      of cached state of (synchronized) sub-surfaces.
+<!-- Completing presentation -->
+      When the final realized presentation time is available, e.g.
+      after a framebuffer flip completes, the requested
+      presentation_feedback.presented events are sent. The final
+      presentation time can differ from the compositor's predicted
+      display update time and the update's target time, especially
+      when the compositor misses its target vertical blanking period.
+<!-- Discarding updates -->
+      When updates from the queue are discarded, the
+      presentation_feedback.discarded event is delivered if feedback
+      was requested.
+      An immediate content update with an attach request automatically
+      discards the whole queue just before the update gets applied. If
+      wl_surface.attach has not been sent for an immediate content
+      submission, the queue is not discarded, and the content update
+      applies only the surface state, but no buffer state.
+      If a wl_surface has queued content updates when it is destroyed,
+      the whole queue is implicitly discarded as if
+      presentation.discard_queue was sent immediately prior to the
+      destroy request.
+    </description>
+    <enum name="error">
+      <description summary="fatal presentation errors">
+        These fatal protocol errors may be emitted in response to
+        illegal presentation requests.
+      </description>
+      <entry name="invalid_timestamp" value="0"
+             summary="invalid value in tv_nsec"/>
+    </enum>
+    <request name="destroy" type="destructor">
+      <description summary="unbind from the presentation interface">
+        Informs the server that the client will not be using this
+        protocol object anymore. This does not affect any content
+        update queues nor existing objects created by this interface.
+      </description>
+    </request>
+    <request name="feedback">
+      <description summary="request presentation feedback information">
+        With this request, presentation feedback will be provided for
+        the current content submission of the given surface. A new
+        presentation_feedback object is created, and that object will
+        deliver the information once. The object is tied to this
+        content submission only. Multiple presentation_feedback
+        objects may be created for the same submission, and they will
+        all return the same information.
+        For details on what information is returned, see
+        presentation_feedback interface.
+      </description>
+      <arg name="surface" type="object" interface="wl_surface"
+           summary="target surface"/>
+      <arg name="callback" type="new_id" interface="presentation_feedback"
+           summary="new feedback object"/>
+    </request>
+    <request name="queue">
+      <description summary="queue the buffer instead of immediate presentation">
+        This request changes the behaviour of the very next
+        wl_surface.commit of the given wl_surface and that commit
+        only. Instead of immediately applying the pending wl_surface
+        state as defined in wl_surface.commit, the commit will queue a
+        new content update, using the pending buffer state only.
+        For a more detailed description and what is buffer state, see
+        the documentation for presentation interface.
+        The value of the target timestamp is in the presentation clock
+        domain, see presentation.clock_id.
+        If queue request has already been sent for the unfinished
+        content update submission on the given wl_surface, a new queue
+        request will override the previous one.
+        If tv_nsec is not in [0, 999999999], the protocol error
+        'invalid_timestamp' is generated.
+      </description>
+      <arg name="surface" type="object" interface="wl_surface"
+           summary="target surface"/>
+      <arg name="tv_sec_hi" type="uint"
+           summary="high 32 bits of the seconds part of the target timestamp"/>
+      <arg name="tv_sec_lo" type="uint"
+           summary="low 32 bits of the seconds part of the target timestamp"/>
+      <arg name="tv_nsec" type="uint"
+           summary="nanoseconds part of the target timestamp"/>
+    </request>
+    <request name="discard_queue">
+      <description summary="discard the whole queue of the given surface">
+        This request discards the whole remaining content update queue
+        of the given wl_surface. Once the compositor has processed
+        this request, no more queued updates will happen on the
+        surface until the client queues new updates. Discard_queue is
+        processed immediately when the compositor dispatches the
+        request.
+        A client can issue a wl_display.sync after this, and once the
+        sync returns, the client has received all
+        presentation_feedback.discarded events resulting from the
+        discard_queue. However, presentation_feedback.presented events
+        may arrive later if the compositor executed a queued content
+        update before the discard_queue.
+      </description>
+      <arg name="surface" type="object" interface="wl_surface"
+           summary="target surface"/>
+    </request>
+    <event name="clock_id">
+      <description summary="clock ID for timestamps">
+        This event tells the client, in which clock domain the
+        compositor interprets the timestamps used by the presentation
+        extension. This clock is called the presentation clock.
+        The compositor sends this event when the client binds to the
+        presentation interface. The presentation clock does not change
+        during the lifetime of the client connection.
+        The clock identifier is platform dependent. Clients must be
+        able to query the current clock value directly, not by asking
+        the compositor.
+        On Linux/glibc, the identifer value is one of the clockid_t
+        values accepted by clock_gettime(). clock_gettime() is defined
+        by POSIX.1-2001.
+        Compositors should prefer a clock, which does not jump and is
+        not slewed e.g. by NTP. The absolute value of the clock is
+        irrelevant. Precision of one millisecond or better is
+        recommended.
+        Timestamps in this clock domain are expressed as tv_sec_hi,
+        tv_sec_lo, tv_nsec triples, each component being an unsigned
+        32-bit value. Whole seconds are in tv_sec which is a 64-bit
+        value combined from tv_sec_hi and tv_sec_lo, and the
+        additional fractional part in tv_nsec as nanoseconds. Hence,
+        for valid timestamps tv_nsec must be in [0, 999999999].
+        Note, that clock_id applies only to the presentation clock,
+        and implies nothing about e.g. the timestamps used in the
+        Wayland core protocol input events.
+      </description>
+      <arg name="clk_id" type="uint" summary="platform clock identifier"/>
+    </event>
+  </interface>
+  <interface name="presentation_feedback" version="1">
+    <description summary="presentation time feedback event">
+      A presentation_feedback object returns the feedback information
+      about a wl_surface content update becoming visible to the user.
+      One object corresponds to one content update submission
+      (wl_surface.commit), queued or immediate. There are two possible
+      outcomes: the content update may be presented to the user, in
+      which case the presentation timestamp is delivered. Otherwise,
+      the content update is discarded, and the user never had a chance
+      to see it before it was superseded or the surface was destroyed.
+      Once a presentation_feedback object has delivered an event, it
+      becomes inert, and should be destroyed by the client.
+    </description>
+    <request name="destroy" type="destructor">
+      <description summary="destroy presentation feedback object">
+        The object is destroyed. If a feedback event had not been
+        delivered yet, it is cancelled.
+      </description>
+    </request>
+    <event name="sync_output">
+      <description summary="presentation synchronized to this output">
+        As presentation can be synchronized to only one output at a
+        time, this event tells which output it was. This event is only
+        sent prior to the presented event.
+        As clients may bind to the same global wl_output multiple
+        times, this event is sent for each bound instance that matches
+        the synchronized output. If a client has not bound to the
+        right wl_output global at all, this event is not sent.
+      </description>
+      <arg name="output" type="object" interface="wl_output"
+           summary="presentation output"/>
+    </event>
+    <event name="presented">
+      <description summary="the content update was displayed">
+        The associated content update was displayed to the user at the
+        indicated time (tv_sec_hi/lo, tv_nsec). For the interpretation of
+        the timestamp, see presentation.clock_id event.
+        The timestamp corresponds to the time when the content update
+        turned into light the first time on the surface's main output.
+        Compositors may approximate this from the framebuffer flip
+        completion events from the system, and the latency of the
+        physical display path if known.
+        This event is preceeded by all related sync_output events
+        telling which output's refresh cycle the feedback corresponds
+        to, i.e. the main output for the surface. Compositors are
+        recommended to choose to the output containing the largest
+        part of the wl_surface, or keeping the output they previously
+        chose. Having a stable presentation output association helps
+        clients to predict future output refreshes (vblank).
+        Argument 'refresh' gives the compositor's prediction of how
+        many nanoseconds after tv_sec, tv_nsec the very next output
+        refresh may occur. This is to further aid clients in
+        predicting future refreshes, i.e., estimating the timestamps
+        targeting the next few vblanks. If such prediction cannot
+        usefully be done, the argument is zero.
+        The 64-bit value combined from seq_hi and seq_lo is the value
+        of the output's vertical retrace counter when the content
+        update was first scanned out to the display. This value must
+        be compatible with the definition of MSC in
+        GLX_OML_sync_control specification. Note, that if the display
+        path has a non-zero latency, the time instant specified by
+        this counter may differ from the timestamp's.
+        If the output does not have a constant refresh rate, explicit
+        video mode switches excluded, then the refresh argument must
+        be zero.
+        If the output does not have a concept of vertical retrace or a
+        refresh cycle, or the output device is self-refreshing without
+        a way to query the refresh count, then the arguments seq_hi
+        and seq_lo must be zero.
+      </description>
+      <arg name="tv_sec_hi" type="uint"
+           summary="high 32 bits of the seconds part of the presentation timestamp"/>
+      <arg name="tv_sec_lo" type="uint"
+           summary="low 32 bits of the seconds part of the presentation timestamp"/>
+      <arg name="tv_nsec" type="uint"
+           summary="nanoseconds part of the presentation timestamp"/>
+      <arg name="refresh" type="uint" summary="nanoseconds till next refresh"/>
+      <arg name="seq_hi" type="uint"
+           summary="high 32 bits of refresh counter"/>
+      <arg name="seq_lo" type="uint"
+           summary="low 32 bits of refresh counter"/>
+    </event>
+    <event name="discarded">
+      <description summary="the content update was not displayed">
+        The content update was never displayed to the user.
+      </description>
+    </event>
+  </interface>

More information about the wayland-devel mailing list