diff options
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 Binary files differnew file mode 100644 index 00000000..1573072d --- /dev/null +++ b/doc/sphinx/toc/libweston/images/create_output.png 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 Binary files differnew file mode 100644 index 00000000..6b6bfe50 --- /dev/null +++ b/doc/sphinx/toc/libweston/images/destroy-output.png 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 Binary files differnew file mode 100644 index 00000000..053c1eae --- /dev/null +++ b/doc/sphinx/toc/libweston/images/head-destroyed.png 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 Binary files differnew file mode 100644 index 00000000..96b55152 --- /dev/null +++ b/doc/sphinx/toc/libweston/images/initial-heads.png 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 Binary files differnew file mode 100644 index 00000000..ba1b8132 --- /dev/null +++ b/doc/sphinx/toc/libweston/images/react-to-heads-changed.png 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 */ |