summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPekka Paalanen <pekka.paalanen@collabora.com>2020-01-16 17:44:51 +0200
committerPekka Paalanen <pq@iki.fi>2020-01-27 12:14:14 +0000
commit9dccfd1ef3f0d20b4ec4ca62703e3aa618f09596 (patch)
treee02d7bce6f6efc8b19b3ecf154aa77c1b7c2adc4
parent1f3615f3cce1f71144e7bb606f95c0f2e87cd3b4 (diff)
doc: output management sequence diagrams
When we were designing the libweston output API, I wrote a design document as a Phabricator wiki page. Phabricator is no longer accessible so that information needs to be migrated to a new place. Here I am converting most of it into libweston Sphinx documentation, particularly pulling in the sequence diagrams I drew. This should help people understand how libweston output configuration works. The diagrams are committed as both MSC source files and rendered PNG files. I did not bother tinkering with the build to run mscgen automatically and then with the CI images to install the tool. The Sphinx configuration need numref explicitly enabled so that figures are automatically numbered and can be referenced by their number rather than their whole caption text(!). The document structure is changed a little better flowing with Output Management being the overview page and the Heads and Outputs being the API pages. First I wrote the struct weston_output and weston_head descriptions in Doxygen comments in libweston.h, but then in the API page that text would have been buried somewhere towards the end of the page. So I put that text in ReST instead where it comes as first on the pages as it should. The doc for the structs only contain a link to the top of the page. Yes, the comment style in libweston.h is a little broken. If I left the asterisk there it would show up as a bullet point in Sphinx. OTOH putting everything from \rst in a single line did not produce anything. Because Sphinx cannot look in two places, the images need to be copied into the build dir too. mscgen: http://www.mcternan.me.uk/mscgen/ Fixes: https://gitlab.freedesktop.org/wayland/weston/issues/25 Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
-rw-r--r--doc/sphinx/conf.py.in3
-rw-r--r--doc/sphinx/toc/libweston.rst3
-rw-r--r--doc/sphinx/toc/libweston/head.rst40
-rw-r--r--doc/sphinx/toc/libweston/images/create_output.msc31
-rw-r--r--doc/sphinx/toc/libweston/images/create_output.pngbin0 -> 39923 bytes
-rw-r--r--doc/sphinx/toc/libweston/images/destroy-output.msc29
-rw-r--r--doc/sphinx/toc/libweston/images/destroy-output.pngbin0 -> 30249 bytes
-rw-r--r--doc/sphinx/toc/libweston/images/head-destroyed.msc26
-rw-r--r--doc/sphinx/toc/libweston/images/head-destroyed.pngbin0 -> 28457 bytes
-rw-r--r--doc/sphinx/toc/libweston/images/initial-heads.msc35
-rw-r--r--doc/sphinx/toc/libweston/images/initial-heads.pngbin0 -> 37770 bytes
-rw-r--r--doc/sphinx/toc/libweston/images/meson.build13
-rw-r--r--doc/sphinx/toc/libweston/images/react-to-heads-changed.msc24
-rw-r--r--doc/sphinx/toc/libweston/images/react-to-heads-changed.pngbin0 -> 27241 bytes
-rw-r--r--doc/sphinx/toc/libweston/meson.build10
-rw-r--r--doc/sphinx/toc/libweston/output-management.rst104
-rw-r--r--doc/sphinx/toc/libweston/output.rst22
-rw-r--r--include/libweston/libweston.h11
18 files changed, 330 insertions, 21 deletions
diff --git a/doc/sphinx/conf.py.in b/doc/sphinx/conf.py.in
index 6ec48e0f..ab8f9bf1 100644
--- a/doc/sphinx/conf.py.in
+++ b/doc/sphinx/conf.py.in
@@ -84,6 +84,9 @@ pygments_style = None
# default domain
primary_domain = 'cpp'
+# To automatically number figures, tables, etc. and be able to reference them.
+numfig = True
+
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
diff --git a/doc/sphinx/toc/libweston.rst b/doc/sphinx/toc/libweston.rst
index c339d2b5..c8a2e62d 100644
--- a/doc/sphinx/toc/libweston.rst
+++ b/doc/sphinx/toc/libweston.rst
@@ -6,8 +6,7 @@ Libweston
:caption: Contents:
libweston/compositor.rst
- libweston/head.rst
- libweston/output.rst
+ libweston/output-management.rst
libweston/log.rst
`Libweston` is an effort to separate the re-usable parts of Weston into a
diff --git a/doc/sphinx/toc/libweston/head.rst b/doc/sphinx/toc/libweston/head.rst
index 14686ffe..7bcd5e4a 100644
--- a/doc/sphinx/toc/libweston/head.rst
+++ b/doc/sphinx/toc/libweston/head.rst
@@ -1,24 +1,44 @@
-Head
-====
+.. _libweston-head:
-A head usually refers to a monitor, but it can also refer to an output window
-in case of a nested compositor. A :type:`weston_output` is responsible for
-driving a :type:`weston_head`. :type:`weston_head` should be initialized using
-:func:`weston_head_init`, and shall be released using
-:func:`weston_head_release`.
+Heads
+=====
+
+A head is represented by a :type:`weston_head` object.
+
+A head refers to a monitor when driving hardware, but it can also be a window
+in another window system, or a virtual concept. Essentially a head is a place
+where you could present an image. The image will be produced by a weston_output
+where the head is attached to.
+
+In display hardware, a head represents a display connector in a computer
+system, not the actual monitor connected to the connector. A head carries
+monitor information, if present, like make and model, EDID and possible video
+modes. Other properties are DPMS mode and backlight control.
+
+In terms of Wayland protocol, a head corresponds to a wl_output. If one
+:type:`weston_output` has several heads, meaning that the heads are cloned,
+each head is represented as a separate wl_output global in wl_registry. Only
+the heads of an enabled output are exposed as wl_outputs.
+
+Heads can appear and disappear dynamically, mainly because of DisplayPort
+Multi-Stream Transport where connecting a new monitor may expose new
+connectors. Window and virtual outputs are often dynamic as well.
+
+Heads are always owned by libweston which dictates their lifetimes. Some
+backends may offer specific API to create and destroy heads, but hardware
+backends like DRM-backend create and destroy heads on their own.
.. note::
:func:`weston_head_init` and :func:`weston_head_release` belong to the
private/internal backend API and should be moved accordingly once that
- section has been created.
+ section has been created. There are many other functions as well that are
+ intended only for backends.
A :type:`weston_head` must be attached/detached from a :type:`weston_output`.
To that purpose you can use :func:`weston_output_attach_head`, respectively
:func:`weston_head_detach`.
-Head API
---------
.. doxygengroup:: head
:content-only:
diff --git a/doc/sphinx/toc/libweston/images/create_output.msc b/doc/sphinx/toc/libweston/images/create_output.msc
new file mode 100644
index 00000000..f20cdb4e
--- /dev/null
+++ b/doc/sphinx/toc/libweston/images/create_output.msc
@@ -0,0 +1,31 @@
+#!/usr/bin/mscgen -Tpng
+
+msc {
+ hscale="1.5";
+
+ c [label = "compositor"], w [label = "libweston core"],
+ b [label = "backend"];
+
+ |||;
+
+ --- [label = "Compositor creates an output for a head"];
+
+ c box c [label = "Have an existing head to process."];
+ c => w [label = "weston_compositor_create_output_with_head()"];
+ w => b [label = "weston_backend::create_output()"];
+ w << b [label = "an empty output, no hw resources"];
+ w => b [label = "weston_output::attach_head()"];
+ w << b [label = "success"];
+ c << w [label = "success"];
+
+ c abox c [label = "optionally more heads with weston_output_attach_head() for hardware clone mode."];
+
+ c :> w [label = "weston_output_set_scale()"];
+ c :> w [label = "weston_output_set_transform()"];
+ c :> b [label = "backend specific settings via plugin API"];
+ c => w [label = "weston_output_enable()"];
+ w => b [label = "weston_output::enable()"];
+ b box b [label = "hw resource allocation"];
+ w << b [label = "success"];
+ c << w [label = "success"];
+}
diff --git a/doc/sphinx/toc/libweston/images/create_output.png b/doc/sphinx/toc/libweston/images/create_output.png
new file mode 100644
index 00000000..1573072d
--- /dev/null
+++ b/doc/sphinx/toc/libweston/images/create_output.png
Binary files differ
diff --git a/doc/sphinx/toc/libweston/images/destroy-output.msc b/doc/sphinx/toc/libweston/images/destroy-output.msc
new file mode 100644
index 00000000..fc477fff
--- /dev/null
+++ b/doc/sphinx/toc/libweston/images/destroy-output.msc
@@ -0,0 +1,29 @@
+#!/usr/bin/mscgen -Tpng
+
+msc {
+ hscale="1.5";
+
+ c [label = "compositor"], w [label = "libweston core"],
+ b [label = "backend"];
+
+ |||;
+
+ --- [label = "Compositor destroys an output for a head"];
+
+ c box c [label = "A head is found disconnected, is being destroyed, or something else needs it disabled."];
+
+ c => w [label = "weston_head_get_output()"];
+ c << w [label = "weston_output"];
+
+ c box c [label = "decide the output needs to be destroyed"];
+
+ c => w [label = "weston_output_destroy()"];
+ w => b [label = "weston_output::destroy()"];
+ w <= b [label = "weston_output_release()"];
+ w <= w [label = "weston_head_detach()"];
+ w :> b [label = "weston_output::detach_head()"];
+ w >> b [label = "release return"];
+ b box b [label = "free(output)"];
+ w << b;
+ c << w;
+}
diff --git a/doc/sphinx/toc/libweston/images/destroy-output.png b/doc/sphinx/toc/libweston/images/destroy-output.png
new file mode 100644
index 00000000..6b6bfe50
--- /dev/null
+++ b/doc/sphinx/toc/libweston/images/destroy-output.png
Binary files differ
diff --git a/doc/sphinx/toc/libweston/images/head-destroyed.msc b/doc/sphinx/toc/libweston/images/head-destroyed.msc
new file mode 100644
index 00000000..ab261650
--- /dev/null
+++ b/doc/sphinx/toc/libweston/images/head-destroyed.msc
@@ -0,0 +1,26 @@
+#!/usr/bin/mscgen -Tpng
+
+msc {
+ hscale="1.5";
+
+ c [label = "compositor"], w [label = "libweston core"],
+ b [label = "backend"];
+
+ |||;
+
+ --- [label = "Head is destroyed for an enabled output"];
+
+ b box b [label = "A head disappears, e.g. MST connector is removed, not just disconnected"];
+
+ w <= b [label = "weston_head_release()"];
+ c x- w [label = "head->destroy_signal"];
+ w => w [label = "weston_head_detach()"];
+ w :> b [label = "weston_output::detach_head()"];
+ w note w [label = "No heads left in the output."];
+ w => w [label = "weston_output_disable()"];
+ w :> b [label = "weston_output::disable()"];
+ w >> b [label = "release return"];
+ b box b [label = "free(head)"];
+
+ --- [label = "The output is left disabled."];
+}
diff --git a/doc/sphinx/toc/libweston/images/head-destroyed.png b/doc/sphinx/toc/libweston/images/head-destroyed.png
new file mode 100644
index 00000000..053c1eae
--- /dev/null
+++ b/doc/sphinx/toc/libweston/images/head-destroyed.png
Binary files differ
diff --git a/doc/sphinx/toc/libweston/images/initial-heads.msc b/doc/sphinx/toc/libweston/images/initial-heads.msc
new file mode 100644
index 00000000..45d47914
--- /dev/null
+++ b/doc/sphinx/toc/libweston/images/initial-heads.msc
@@ -0,0 +1,35 @@
+#!/usr/bin/mscgen -Tpng
+
+msc {
+ hscale="1.5";
+
+ c [label = "compositor"], w [label = "libweston core"],
+ b [label = "backend"];
+
+ |||;
+
+ c => w [label = "weston_compositor_load_backend()"];
+ w => b [label = "init"];
+
+ --- [label = "Create initial heads"];
+ b box b [label = "Backend discovers an entity to create a head for."];
+
+ w <: b [label = "weston_head_init()"];
+ b box b [label = "assign hw resource to head"];
+ w <: b [label = "weston_head_set_monitor_strings()"];
+ w <: b [label = "weston_head_set_physical_size()"];
+ w <: b [label = "weston_head_set_subpixel()"];
+ w <: b [label = "weston_head_set_connection_status()"];
+ w <= b [label = "weston_compositor_add_head()"];
+ w <= w [label = "schedule heads_changed"];
+ w << b [label = "init success"];
+ c << w [label = "load success"];
+
+ |||;
+
+ --- [label = "Compositor start-up"];
+
+ c => w [label = "weston_compositor_flush_heads_changed()"];
+ c <<= w [label = "heads_changed callback"];
+
+}
diff --git a/doc/sphinx/toc/libweston/images/initial-heads.png b/doc/sphinx/toc/libweston/images/initial-heads.png
new file mode 100644
index 00000000..96b55152
--- /dev/null
+++ b/doc/sphinx/toc/libweston/images/initial-heads.png
Binary files differ
diff --git a/doc/sphinx/toc/libweston/images/meson.build b/doc/sphinx/toc/libweston/images/meson.build
new file mode 100644
index 00000000..d4c6c5e8
--- /dev/null
+++ b/doc/sphinx/toc/libweston/images/meson.build
@@ -0,0 +1,13 @@
+# Sphinx does not know look for these files in the source directory, so
+# they must be copied to the build directory.
+files = [
+ 'create_output.png',
+ 'destroy-output.png',
+ 'head-destroyed.png',
+ 'initial-heads.png',
+ 'react-to-heads-changed.png',
+]
+
+foreach file : files
+ configure_file(input: file, output: file, copy: true)
+endforeach
diff --git a/doc/sphinx/toc/libweston/images/react-to-heads-changed.msc b/doc/sphinx/toc/libweston/images/react-to-heads-changed.msc
new file mode 100644
index 00000000..4f39e492
--- /dev/null
+++ b/doc/sphinx/toc/libweston/images/react-to-heads-changed.msc
@@ -0,0 +1,24 @@
+#!/usr/bin/mscgen -Tpng
+
+msc {
+ hscale="1.5";
+
+ c [label = "compositor"], w [label = "libweston core"],
+ b [label = "backend"];
+
+ |||;
+
+ --- [label = "Compositor reacts to heads_changed"];
+
+ c <<= w [label = "heads_changed callback"];
+ c box c [label = "Iterate with weston_compositor_iterate_heads(), for each head"];
+ c => w [label = "weston_head_is_connected()"];
+ c << w [label = "bool"];
+ c => w [label = "weston_head_is_enabled()"];
+ c << w [label = "bool"];
+ c => w [label = "weston_head_is_device_changed()"];
+ c << w [label = "bool"];
+ c abox c [label = "If the head needs enabling, create an output."];
+ c abox c [label = "If the head needs disabling, disable the output or destroy the output."];
+ c >> w;
+}
diff --git a/doc/sphinx/toc/libweston/images/react-to-heads-changed.png b/doc/sphinx/toc/libweston/images/react-to-heads-changed.png
new file mode 100644
index 00000000..ba1b8132
--- /dev/null
+++ b/doc/sphinx/toc/libweston/images/react-to-heads-changed.png
Binary files differ
diff --git a/doc/sphinx/toc/libweston/meson.build b/doc/sphinx/toc/libweston/meson.build
index 9de61635..9fdd59f4 100644
--- a/doc/sphinx/toc/libweston/meson.build
+++ b/doc/sphinx/toc/libweston/meson.build
@@ -1,6 +1,14 @@
# you need to add here any files you add to the toc directory as well
-files = [ 'compositor.rst', 'head.rst', 'output.rst', 'log.rst' ]
+files = [
+ 'compositor.rst',
+ 'head.rst',
+ 'log.rst',
+ 'output.rst',
+ 'output-management.rst',
+]
foreach file : files
configure_file(input: file, output: file, copy: true)
endforeach
+
+subdir('images')
diff --git a/doc/sphinx/toc/libweston/output-management.rst b/doc/sphinx/toc/libweston/output-management.rst
new file mode 100644
index 00000000..8e763095
--- /dev/null
+++ b/doc/sphinx/toc/libweston/output-management.rst
@@ -0,0 +1,104 @@
+Output management
+=================
+
+Libweston output API revolves around two main concepts: :type:`weston_head` and
+:type:`weston_output`. A head represents a connector or a monitor (a sink)
+while an output represents the compositing state machine that produces content
+(a source) to be presented on a head. If a backend allows it, it is possible to
+attach more than one head to an output, in which case all those heads will have
+identical timings and contents (they share framebuffers if applicable).
+
+Heads are created and destroyed automatically by libweston according to e.g.
+hardware features like the existence of physical connectors. Creation, hotplug
+events and other changes to heads are notified with
+:func:`weston_compositor_add_heads_changed_listener`. Head destruction is
+communicated via :func:`weston_head_add_destroy_listener`. Note that
+disconnecting a connector does not mean the head is destroyed. A head is
+destroyed when the connector itself disappears.
+
+Some backends, mainly virtual and nested ones, may offer backend-specific API
+to create and destroy heads at will. In these cases a head does not represent
+anything physical but can be e.g. a window in another window system.
+
+Outputs are explicitly created and destroyed by the libweston user at will. To
+make a new output or to light up a head, you create an output, attach the
+head(s) to it, configure it, and finally :func:`weston_output_enable` it to
+make it live.
+
+An enabled output cannot be reconfigured, but this is intended to change in the
+future. You can use :func:`weston_output_disable` to disable an output and then
+reconfigure it, but this will cause visible glitches.
+
+.. toctree::
+ :caption: API
+
+ head.rst
+ output.rst
+
+The following sequence diagrams show the function calls for various actions.
+:numref:`libweston-initial-heads` shows how DRM-backend creates and configures
+heads on compositor start-up.
+:numref:`libweston-react-to-heads-changed` shows the principle of a compositor
+reacting to initial heads discovered and hotplug events.
+
+When a compositor wants to light up a monitor, it creates an output as in
+:numref:`libweston-create-output`. Attaching more than one head to an output
+requires specific hardware support in the case of DRM-backend. Other backends
+are unlikely to support multiple heads per output.
+
+A connector becoming disconnected is a common reason to destroy an output.
+This happens in :numref:`libweston-destroy-output`.
+
+Heads can also disappear. This is not due to normal monitor unplug but refers
+to the connector itself disappearing. This is particularly possible with
+DisplayPort Multi-Stream Transport, where unplugging a monitor will literally
+remove a connector from the system as that connector was provided by the
+monitor for daisy-chaining. One scenario of handling that is presented in
+:numref:`libweston-head-destroyed`.
+
+
+.. _libweston-initial-heads:
+
+.. figure:: images/initial-heads.png
+ :alt: Sequence diagram of creating heads initially.
+
+ Heads are being created on compositor start-up with a backend that manages
+ head lifetimes completely on its own, e.g. DRM-backend.
+
+
+.. _libweston-react-to-heads-changed:
+
+.. figure:: images/react-to-heads-changed.png
+ :alt: Sequence diagram of reacting to head changes.
+
+ A compositor handles libweston notification of something with heads having
+ changed. This happens on both compositor start-up and later due to hotplug.
+
+
+.. _libweston-create-output:
+
+.. figure:: images/create_output.png
+ :alt: Sequence diagram for creating an output.
+
+ A compositor creates and configures an output for a head or heads it wants
+ to light up.
+
+
+.. _libweston-destroy-output:
+
+.. figure:: images/destroy-output.png
+ :alt: Sequence diagram of compositor destroying an output.
+
+ A compositor finds out a head has been disconnected and proceeds to
+ destroy the corresponding output.
+
+
+.. _libweston-head-destroyed:
+
+.. figure:: images/head-destroyed.png
+ :alt: Sequence diagram of a head being destroyed.
+
+ The backend realises that a piece of hardware has disappeared and needs to
+ destroy the corresponding head. The head is released, and even when the
+ compositor is not listening for head destroy signal, the output gets
+ automatically disabled, though not destroyed.
diff --git a/doc/sphinx/toc/libweston/output.rst b/doc/sphinx/toc/libweston/output.rst
index a89132ae..6bd4bf96 100644
--- a/doc/sphinx/toc/libweston/output.rst
+++ b/doc/sphinx/toc/libweston/output.rst
@@ -1,5 +1,21 @@
-Output
-======
+.. _libweston-output:
+
+Outputs
+=======
+
+A :type:`weston_output` determines what part of the global compositor
+coordinate space will be composited into an image and when. That image is
+presented on the attached heads (weston_head).
+
+An output object is resposible for the framebuffer management, damage tracking,
+display timings, and the repaint state machine. Video mode, output scale and
+output transform are properties of an output.
+
+In display hardware, a weston_output represents a CRTC, but only if it has been
+successfully enabled. The CRTC may be switched to another during an output's
+lifetime.
+
+The lifetime of a weston_output is controlled by the libweston user.
With at least a :type:`weston_head` attached, you can construct a
:type:`weston_output` object which can be used by the compositor, by enabling
@@ -9,8 +25,6 @@ already enabled.
The reverse operation, :func:`weston_output_disable`, should be used when there's
a need to reconfigure the output or it will be destroyed.
-Output API
-----------
.. doxygengroup:: output
:content-only:
diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h
index dc54b170..ab2be42d 100644
--- a/include/libweston/libweston.h
+++ b/include/libweston/libweston.h
@@ -185,10 +185,10 @@ enum weston_hdcp_protection {
WESTON_HDCP_ENABLE_TYPE_1
};
-/** Represents a monitor
+/** Represents a head, usually a display connector
*
- * This object represents a monitor (hardware backends like DRM) or a window
- * (windowed nested backends).
+ * \rst
+ See :ref:`libweston-head`. \endrst
*
* \ingroup head
*/
@@ -222,7 +222,10 @@ struct weston_head {
enum weston_hdcp_protection current_protection;
};
-/** Represents an output
+/** Content producer for heads
+ *
+ * \rst
+ See :ref:`libweston-output`. \endrst
*
* \ingroup output
*/