diff --git a/doc/publican/Content_Updates.xml b/doc/publican/Content_Updates.xml
new file mode 100644
index 00000000..30c4ed33
--- /dev/null
+++ b/doc/publican/Content_Updates.xml
@@ -0,0 +1,460 @@
+
+
+%BOOK_ENTITIES;
+]>
+
+
+ Content Updates
+
+
+ Overview
+
+
+ In the Wayland protocol, requests are asynchronous but take effect
+ immediately when the compositor receives them. However, some requests on
+ surfaces are not applied immediately but are instead double-buffered to
+ allow atomic changes. These double-buffered changes are committed through
+ the wl_surface.commit request, which creates a Content Update.
+
+
+
+ Content Updates encapsulate all double-buffered state changes and can be
+ applied by the compositor. The complexity arises when considering
+ subsurfaces, which can operate in synchronized mode. When a subsurface is
+ synchronized, its Content Updates must be applied atomically together with
+ the parent surface's state. This synchronization can extend through an
+ entire tree of subsurfaces, where child subsurfaces inherit the
+ synchronized behavior from their parents.
+
+
+
+ Historically, Content Updates from synchronized subsurfaces were merged
+ into the pending state of the parent surface on commit. However, the
+ introduction of constraints—which can defer the application of Content
+ Updates—necessitated a more sophisticated model. This led to the
+ implementation of per-surface queues of Content Updates, with dependencies
+ between Content Updates across different queues. This queuing model
+ maintains backwards compatibility with the earlier approach of merging
+ Content Updates into the parent's pending state on commit.
+
+
+
+ The core protocol defines the semantics of Content Updates using
+ per-surface queues, but compositors that do not need to support constraints
+ may implement the simpler legacy model where synchronized subsurface states
+ are merged directly into the parent's pending state.
+
+
+
+
+ Rules
+
+
+ The core protocol specifies the behavior in wl_subsurface and
+ wl_surface.commit. The behavior can be summarized by the following rules:
+
+
+
+
+
+ Content Updates (CU) contain all double-buffered state of the surface and
+ selected state from their direct children.
+
+
+
+
+ Surfaces which are effectively synchronized create Synchronized
+ Content Updates (SCU), otherwise they create Desync Content Updates
+ (DCU).
+
+
+
+
+ When a CU is created, it gets a dependency on the previous CU of the
+ same queues (if it exists).
+
+
+
+
+ When a CU is created, it gets a dependency on the last SCU of direct
+ child surfaces that are not reachable (if they exists).
+
+
+
+
+ The CUs and their dependencies form a DAG, where CUs are nodes and
+ dependencies are edges.
+
+
+
+
+ All DCUs starting from the front of the queues until the first SCU or
+ the back of the queue is reached are candidates.
+
+
+
+
+ If the maximal DAG that's reachable from a candidate (candidate DAG)
+ does not have any constraints, then this DAG can be applied.
+
+
+
+
+ A DAG is applied atomically by recursively applying a content update
+ without dependencies and removing it from the DAG.
+
+
+
+
+ Surfaces transition from effectively sync to effectively desync after
+ their parents.
+
+
+
+
+ When a surface transitions to effectively desync, all SCUs in its
+ queue which are not reachable by a DCU become DCUs.
+
+
+
+
+
+
+ Examples
+
+
+ These examples should help to build an intuition for how content updates
+ actually behave. They cover the interesting edge cases, such as
+ subsurfaces with constraints, and transitioning from a sync subsurface to
+ a desync one.
+
+
+ In all the examples below, the surface T1 refers to a toplevel surface,
+ SS1 refers to a sub-surface which is a child of T1, and SS2 refers to a
+ sub-surface which is a child of SS1.
+
+
+
+ Legend
+
+
+
+
+
+
+
+
+ Simple Desynchronized Case
+
+
+
+
+
+
+ SS2 is effectively desynchronized and commits. This results in the
+ desynchronized content update (DCU) 1.
+
+
+
+
+
+
+
+
+
+ DCU 1 is a candidate, and the candidate DAG
+ reachable from DCU 1 is only
+ DCU 1 itself. DCU 1 and
+ thus the candidate DAG does not have any constraints and can be
+ applied.
+
+
+
+
+
+
+
+
+
+ The content updates of the candidate DAG get applied to the surface
+ atomically.
+
+
+
+
+
+
+
+
+
+ T1 commits a DCU with a buffer-sync constraint.
+ It is a candidate but its DAG can't be applied because it contains a
+ constraint.
+
+
+
+
+
+
+
+
+
+ T1 commits another CU (DCU 3) which is added at
+ the end of the queue, with a dependency to the previous CU (DCU
+ 2). Both DCU 2 and DCU
+ 3 are candidates, but both DAGs contain DCU
+ 2 with a constraint, and can't be applied.
+
+
+
+
+
+
+
+
+
+ When the constraint gets cleared, both DAGs can be applied to the
+ surface atomitcally (either only 2, or
+ 2 and 3).
+
+
+
+
+
+
+ Simple Synchronized Case
+
+
+
+
+
+
+ SS1 and SS2 are effectively synchronized. SS2 commits SCU 1.
+
+
+
+
+
+
+
+
+
+ SS1 commits SCU 2. The direct child surfaces SS2 has the last SCU 1 in its queue, which is not reachable. This creates a dependency from SCU 2 to SCU 1.
+
+
+
+
+
+
+
+
+
+ SS1 commits SCU 3. The direct child surfaces SS2 has the last SCU 1 in its queue, which is already reachable by SCU 2. No dependency to SCU 1 is created. A dependency to the previous CU of the same queue (SCU 2) is created.
+
+
+
+
+
+
+
+
+
+ T1 commit DCU 4. It is a candidate, its DAG does not contain any constraint and it can be applied.
+
+
+
+
+
+
+
+
+
+ The DAG gets applied to the surfaces atomically.
+
+
+
+ Every DCU (1 and 6) contain
+ CUs with constraints in their candidate DAG
+
+
+
+
+
+
+
+
+
+ Waiting until the buffer-sync constrain on CU
+ 1 is cleared, the candidate DAG of CU
+ 1 does not contain constraints and can be applied
+
+
+
+
+
+
+
+
+
+ That leaves the candidate DAG of CU 6 which still
+ contains another CU with a buffer-sync constrain
+
+
+
+
+
+
+
+
+
+ Waiting until the buffer-sync constrain on CU
+ 6 is cleared, the candidate DAG of
+ 6 does not contain CUs with constraints and can
+ be applied.
+
+
+
+
+
+
+
+
+
+ There is no DCU left and no constraint remaining. Nothing more can be
+ applied without a new CU.
+
+
+
+ There are four SCUs and all surfaces are effectively synchronized.
+
+
+
+
+
+
+
+
+
+ Surface SS1 transitions to effectively
+ desynchronized and SCU 2 becomes a DCU because
+ it is not reachable from a DCU
+
+
+
+
+
+
+
+
+
+ Surface SS2 transitions to effectively
+ desynchronized. SCUs 3 and
+ 4 become DCUs because they are not reachable
+ from a DCU. SCU 1 does not change because it is
+ reachable by DCU 2.
+
+
+
+
+
+
+
diff --git a/doc/publican/Wayland.xml b/doc/publican/Wayland.xml
index 852c2971..f02a97fc 100644
--- a/doc/publican/Wayland.xml
+++ b/doc/publican/Wayland.xml
@@ -11,6 +11,7 @@
+
diff --git a/doc/publican/html/images/content-updates/content-update-legend.png b/doc/publican/html/images/content-updates/content-update-legend.png
new file mode 100644
index 00000000..84f12e76
Binary files /dev/null and b/doc/publican/html/images/content-updates/content-update-legend.png differ
diff --git a/doc/publican/html/images/content-updates/content-updates.drawio b/doc/publican/html/images/content-updates/content-updates.drawio
new file mode 100644
index 00000000..5d780213
--- /dev/null
+++ b/doc/publican/html/images/content-updates/content-updates.drawio
@@ -0,0 +1,1528 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/publican/html/images/content-updates/meson.build b/doc/publican/html/images/content-updates/meson.build
new file mode 100644
index 00000000..850e81ff
--- /dev/null
+++ b/doc/publican/html/images/content-updates/meson.build
@@ -0,0 +1,35 @@
+foreach src : files([
+ 'simple-desynchronized-state-1.png',
+ 'simple-desynchronized-state-2.png',
+ 'simple-desynchronized-state-3.png',
+ 'simple-desynchronized-state-4.png',
+ 'simple-desynchronized-state-5.png',
+ 'simple-desynchronized-state-6.png',
+ 'simple-synchronized-state-1.png',
+ 'simple-synchronized-state-2.png',
+ 'simple-synchronized-state-3.png',
+ 'simple-synchronized-state-4.png',
+ 'simple-synchronized-state-5.png',
+ 'sync-subsurf-case1-1.png',
+ 'sync-subsurf-case1-2.png',
+ 'sync-subsurf-case1-3.png',
+ 'sync-subsurf-case1-4.png',
+ 'sync-subsurf-case1-5.png',
+ 'sync-subsurf-case2-1.png',
+ 'sync-subsurf-case2-2.png',
+ 'sync-subsurf-case2-3.png',
+ 'sync-to-desync-subsurf-1.png',
+ 'sync-to-desync-subsurf-2.png',
+ 'sync-to-desync-subsurf-3.png',
+ 'sync-to-desync-transition-1.png',
+ 'sync-to-desync-transition-2.png',
+ 'sync-to-desync-transition-3.png',
+ 'content-update-legend.png',
+])
+ name = fs.name(src)
+ publican_inputs += fs.copyfile(
+ name,
+ install: true,
+ install_dir: publican_install_prefix + '/html/images/content-updates',
+ )
+endforeach
diff --git a/doc/publican/html/images/content-updates/simple-desynchronized-state-1.png b/doc/publican/html/images/content-updates/simple-desynchronized-state-1.png
new file mode 100644
index 00000000..d319ac25
Binary files /dev/null and b/doc/publican/html/images/content-updates/simple-desynchronized-state-1.png differ
diff --git a/doc/publican/html/images/content-updates/simple-desynchronized-state-2.png b/doc/publican/html/images/content-updates/simple-desynchronized-state-2.png
new file mode 100644
index 00000000..ecd284cd
Binary files /dev/null and b/doc/publican/html/images/content-updates/simple-desynchronized-state-2.png differ
diff --git a/doc/publican/html/images/content-updates/simple-desynchronized-state-3.png b/doc/publican/html/images/content-updates/simple-desynchronized-state-3.png
new file mode 100644
index 00000000..73da57f8
Binary files /dev/null and b/doc/publican/html/images/content-updates/simple-desynchronized-state-3.png differ
diff --git a/doc/publican/html/images/content-updates/simple-desynchronized-state-4.png b/doc/publican/html/images/content-updates/simple-desynchronized-state-4.png
new file mode 100644
index 00000000..83dcc063
Binary files /dev/null and b/doc/publican/html/images/content-updates/simple-desynchronized-state-4.png differ
diff --git a/doc/publican/html/images/content-updates/simple-desynchronized-state-5.png b/doc/publican/html/images/content-updates/simple-desynchronized-state-5.png
new file mode 100644
index 00000000..d4e42d8f
Binary files /dev/null and b/doc/publican/html/images/content-updates/simple-desynchronized-state-5.png differ
diff --git a/doc/publican/html/images/content-updates/simple-desynchronized-state-6.png b/doc/publican/html/images/content-updates/simple-desynchronized-state-6.png
new file mode 100644
index 00000000..ebb88d81
Binary files /dev/null and b/doc/publican/html/images/content-updates/simple-desynchronized-state-6.png differ
diff --git a/doc/publican/html/images/content-updates/simple-desynchronized.drawio b/doc/publican/html/images/content-updates/simple-desynchronized.drawio
new file mode 100644
index 00000000..c1adfd60
--- /dev/null
+++ b/doc/publican/html/images/content-updates/simple-desynchronized.drawio
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/publican/html/images/content-updates/simple-synchronized-state-1.png b/doc/publican/html/images/content-updates/simple-synchronized-state-1.png
new file mode 100644
index 00000000..be101446
Binary files /dev/null and b/doc/publican/html/images/content-updates/simple-synchronized-state-1.png differ
diff --git a/doc/publican/html/images/content-updates/simple-synchronized-state-2.png b/doc/publican/html/images/content-updates/simple-synchronized-state-2.png
new file mode 100644
index 00000000..af6c64ff
Binary files /dev/null and b/doc/publican/html/images/content-updates/simple-synchronized-state-2.png differ
diff --git a/doc/publican/html/images/content-updates/simple-synchronized-state-3.png b/doc/publican/html/images/content-updates/simple-synchronized-state-3.png
new file mode 100644
index 00000000..7ca9ae69
Binary files /dev/null and b/doc/publican/html/images/content-updates/simple-synchronized-state-3.png differ
diff --git a/doc/publican/html/images/content-updates/simple-synchronized-state-4.png b/doc/publican/html/images/content-updates/simple-synchronized-state-4.png
new file mode 100644
index 00000000..e8b9b3db
Binary files /dev/null and b/doc/publican/html/images/content-updates/simple-synchronized-state-4.png differ
diff --git a/doc/publican/html/images/content-updates/simple-synchronized-state-5.png b/doc/publican/html/images/content-updates/simple-synchronized-state-5.png
new file mode 100644
index 00000000..21c3414a
Binary files /dev/null and b/doc/publican/html/images/content-updates/simple-synchronized-state-5.png differ
diff --git a/doc/publican/html/images/content-updates/simple-synchronized.drawio b/doc/publican/html/images/content-updates/simple-synchronized.drawio
new file mode 100644
index 00000000..a478ae02
--- /dev/null
+++ b/doc/publican/html/images/content-updates/simple-synchronized.drawio
@@ -0,0 +1,207 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/publican/html/images/content-updates/sync-subsurf-case1-1.png b/doc/publican/html/images/content-updates/sync-subsurf-case1-1.png
new file mode 100644
index 00000000..1f7ff8e4
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-subsurf-case1-1.png differ
diff --git a/doc/publican/html/images/content-updates/sync-subsurf-case1-2.png b/doc/publican/html/images/content-updates/sync-subsurf-case1-2.png
new file mode 100644
index 00000000..6839b679
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-subsurf-case1-2.png differ
diff --git a/doc/publican/html/images/content-updates/sync-subsurf-case1-3.png b/doc/publican/html/images/content-updates/sync-subsurf-case1-3.png
new file mode 100644
index 00000000..9810a028
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-subsurf-case1-3.png differ
diff --git a/doc/publican/html/images/content-updates/sync-subsurf-case1-4.png b/doc/publican/html/images/content-updates/sync-subsurf-case1-4.png
new file mode 100644
index 00000000..bf3c04bc
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-subsurf-case1-4.png differ
diff --git a/doc/publican/html/images/content-updates/sync-subsurf-case1-5.png b/doc/publican/html/images/content-updates/sync-subsurf-case1-5.png
new file mode 100644
index 00000000..1b2ebc3b
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-subsurf-case1-5.png differ
diff --git a/doc/publican/html/images/content-updates/sync-subsurf-case1.drawio b/doc/publican/html/images/content-updates/sync-subsurf-case1.drawio
new file mode 100644
index 00000000..385c6fd7
--- /dev/null
+++ b/doc/publican/html/images/content-updates/sync-subsurf-case1.drawio
@@ -0,0 +1,500 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/publican/html/images/content-updates/sync-subsurf-case2-1.png b/doc/publican/html/images/content-updates/sync-subsurf-case2-1.png
new file mode 100644
index 00000000..25408cfc
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-subsurf-case2-1.png differ
diff --git a/doc/publican/html/images/content-updates/sync-subsurf-case2-2.png b/doc/publican/html/images/content-updates/sync-subsurf-case2-2.png
new file mode 100644
index 00000000..63ea066c
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-subsurf-case2-2.png differ
diff --git a/doc/publican/html/images/content-updates/sync-subsurf-case2-3.png b/doc/publican/html/images/content-updates/sync-subsurf-case2-3.png
new file mode 100644
index 00000000..3948988d
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-subsurf-case2-3.png differ
diff --git a/doc/publican/html/images/content-updates/sync-subsurf-case2.drawio b/doc/publican/html/images/content-updates/sync-subsurf-case2.drawio
new file mode 100644
index 00000000..c1eaff66
--- /dev/null
+++ b/doc/publican/html/images/content-updates/sync-subsurf-case2.drawio
@@ -0,0 +1,287 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/publican/html/images/content-updates/sync-to-desync-subsurf-1.png b/doc/publican/html/images/content-updates/sync-to-desync-subsurf-1.png
new file mode 100644
index 00000000..3a56f260
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-to-desync-subsurf-1.png differ
diff --git a/doc/publican/html/images/content-updates/sync-to-desync-subsurf-2.png b/doc/publican/html/images/content-updates/sync-to-desync-subsurf-2.png
new file mode 100644
index 00000000..9cb6210c
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-to-desync-subsurf-2.png differ
diff --git a/doc/publican/html/images/content-updates/sync-to-desync-subsurf-3.png b/doc/publican/html/images/content-updates/sync-to-desync-subsurf-3.png
new file mode 100644
index 00000000..34bf7475
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-to-desync-subsurf-3.png differ
diff --git a/doc/publican/html/images/content-updates/sync-to-desync-subsurf.drawio b/doc/publican/html/images/content-updates/sync-to-desync-subsurf.drawio
new file mode 100644
index 00000000..7a72e0f6
--- /dev/null
+++ b/doc/publican/html/images/content-updates/sync-to-desync-subsurf.drawio
@@ -0,0 +1,223 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/publican/html/images/content-updates/sync-to-desync-transition-1.png b/doc/publican/html/images/content-updates/sync-to-desync-transition-1.png
new file mode 100644
index 00000000..cd69f3c3
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-to-desync-transition-1.png differ
diff --git a/doc/publican/html/images/content-updates/sync-to-desync-transition-2.png b/doc/publican/html/images/content-updates/sync-to-desync-transition-2.png
new file mode 100644
index 00000000..677a0cdb
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-to-desync-transition-2.png differ
diff --git a/doc/publican/html/images/content-updates/sync-to-desync-transition-3.png b/doc/publican/html/images/content-updates/sync-to-desync-transition-3.png
new file mode 100644
index 00000000..bdfdb8eb
Binary files /dev/null and b/doc/publican/html/images/content-updates/sync-to-desync-transition-3.png differ
diff --git a/doc/publican/html/images/content-updates/sync-to-desync-transition.drawio b/doc/publican/html/images/content-updates/sync-to-desync-transition.drawio
new file mode 100644
index 00000000..9843acb6
--- /dev/null
+++ b/doc/publican/html/images/content-updates/sync-to-desync-transition.drawio
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/publican/html/images/meson.build b/doc/publican/html/images/meson.build
index de4cc181..c06e9be8 100644
--- a/doc/publican/html/images/meson.build
+++ b/doc/publican/html/images/meson.build
@@ -10,6 +10,8 @@ foreach src : files([
)
endforeach
+subdir('content-updates')
+
foreach src : files([
'wayland-architecture.gv',
'x-architecture.gv',
diff --git a/doc/publican/meson.build b/doc/publican/meson.build
index 2edf7988..fb730f5f 100644
--- a/doc/publican/meson.build
+++ b/doc/publican/meson.build
@@ -15,6 +15,7 @@ foreach src : files([
'Protocol.xml',
'Xwayland.xml',
'Compositors.xml',
+ 'Content_Updates.xml',
'Color.xml',
'Client.xml',
'Server.xml',
diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index 5a6a189d..de6756b4 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -1687,21 +1687,48 @@
etc.) is double-buffered. Protocol requests modify the pending state,
as opposed to the active state in use by the compositor.
- A commit request atomically creates a content update from the pending
- state, even if the pending state has not been touched. The content
- update is placed in a queue until it becomes active. After commit, the
- new pending state is as documented for each related request.
-
- When the content update is applied, the wl_buffer is applied before all
- other state. This means that all coordinates in double-buffered state
- are relative to the newly attached wl_buffers, except for
- wl_surface.attach itself. If there is no newly attached wl_buffer, the
- coordinates are relative to the previous content update.
-
All requests that need a commit to become effective are documented
to affect double-buffered state.
Other interfaces may add further double-buffered surface state.
+
+ A commit request atomically creates a Content Update (CU) from the
+ pending state, even if the pending state has not been touched. The
+ content update is placed at the end of a per-surface queue until it
+ becomes active. After commit, the new pending state is as documented for
+ each related request.
+
+ A CU is either a Desync Content Update (DCU) or a Sync Content Update
+ (SCU). If the surface is effectively synchronized at the commit request,
+ it is a SCU, otherwise a DCU.
+
+ When a surface transitions from effectively synchronized to effectively
+ desynchronized, all SCUs in its queue which are not reachable by any
+ DCU become DCUs and dependency edges from outside the queue to these CUs
+ are removed.
+
+ See wl_subsurface for the definition of 'effectively synchronized' and
+ 'effectively desynchronized'.
+
+ When a CU is placed in the queue, the CU has a dependency on the CU in
+ front of it and to the SCU at end of the queue of every direct child
+ surface if that SCU exists and does not have another dependent. This can
+ form a directed acyclic graph of CUs with dependencies as edges.
+
+ In addition to surface state, the CU can have constraints that must be
+ satisfied before it can be applied. Other interfaces may add CU
+ constraints.
+
+ All DCUs which do not have a SCU in front of themselves in their queue,
+ are candidates. If the graph that's reachable by a candidate does not
+ have any unsatisfied constraints, the entire graph must be applied
+ atomically.
+
+ When a CU is applied, the wl_buffer is applied before all other state.
+ This means that all coordinates in double-buffered state are relative to
+ the newly attached wl_buffers, except for wl_surface.attach itself. If
+ there is no newly attached wl_buffer, the coordinates are relative to
+ the previous content update.
@@ -3140,23 +3167,9 @@
hidden, or if a NULL wl_buffer is applied. These rules apply
recursively through the tree of surfaces.
- The behaviour of a wl_surface.commit request on a sub-surface
- depends on the sub-surface's mode. The possible modes are
- synchronized and desynchronized, see methods
- wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
- mode caches the wl_surface state to be applied when the parent's
- state gets applied, and desynchronized mode applies the pending
- wl_surface state directly. A sub-surface is initially in the
- synchronized mode.
-
- Sub-surfaces also have another kind of state, which is managed by
- wl_subsurface requests, as opposed to wl_surface requests. This
- state includes the sub-surface position relative to the parent
- surface (wl_subsurface.set_position), and the stacking order of
- the parent and its sub-surfaces (wl_subsurface.place_above and
- .place_below). This state is applied when the parent surface's
- wl_surface state is applied, regardless of the sub-surface's mode.
- As the exception, set_sync and set_desync are effective immediately.
+ A sub-surface can be in one of two modes. The possible modes are
+ synchronized and desynchronized, see methods wl_subsurface.set_sync and
+ wl_subsurface.set_desync.
The main surface can be thought to be always in desynchronized mode,
since it does not have a parent in the sub-surfaces sense.
@@ -3168,6 +3181,15 @@
synchronized mode, and then assume that all its child and grand-child
sub-surfaces are synchronized, too, without explicitly setting them.
+ If a surface behaves as in synchronized mode, it is effectively
+ synchronized, otherwise it is effectively desynchronized.
+
+ A sub-surface is initially in the synchronized mode.
+
+ The wl_subsurface interface has requests which modify double-buffered
+ state of the parent surface (wl_subsurface.set_position, .place_above and
+ .place_below).
+
Destroying a sub-surface takes effect immediately. If you need to
synchronize the removal of a sub-surface to the parent surface update,
unmap the sub-surface first by attaching a NULL wl_buffer, update parent,
@@ -3198,20 +3220,18 @@
- This schedules a sub-surface position change.
+ This sets the position of the sub-surface, relative to the parent
+ surface.
+
The sub-surface will be moved so that its origin (top left
corner pixel) will be at the location x, y of the parent surface
coordinate system. The coordinates are not restricted to the parent
surface area. Negative values are allowed.
- The scheduled coordinates will take effect whenever the state of the
- parent surface is applied.
-
- If more than one set_position request is invoked by the client before
- the commit of the parent surface, the position of a new request always
- replaces the scheduled position from any previous request.
-
The initial position is 0, 0.
+
+ Position is double-buffered state on the parent surface, see
+ wl_subsurface and wl_surface.commit for more information.
@@ -3225,13 +3245,11 @@
parent surface. Using any other surface, including this sub-surface,
will cause a protocol error.
- The z-order is double-buffered. Requests are handled in order and
- applied immediately to a pending state. The final pending state is
- copied to the active state the next time the state of the parent
- surface is applied.
-
A new sub-surface is initially added as the top-most in the stack
of its siblings and parent.
+
+ Z-order is double-buffered state on the parent surface, see
+ wl_subsurface and wl_surface.commit for more information.
@@ -3240,6 +3258,7 @@
The sub-surface is placed just below the reference surface.
+
See wl_subsurface.place_above.
Change the commit behaviour of the sub-surface to synchronized
- mode, also described as the parent dependent mode.
+ mode.
- In synchronized mode, wl_surface.commit on a sub-surface will
- accumulate the committed state in a cache, but the state will
- not be applied and hence will not change the compositor output.
- The cached state is applied to the sub-surface immediately after
- the parent surface's state is applied. This ensures atomic
- updates of the parent and all its synchronized sub-surfaces.
- Applying the cached state will invalidate the cache, so further
- parent surface commits do not (re-)apply old state.
-
- See wl_subsurface for the recursive effect of this mode.
+ See wl_subsurface and wl_surface.commit for more information.
Change the commit behaviour of the sub-surface to desynchronized
- mode, also described as independent or freely running mode.
+ mode.
- In desynchronized mode, wl_surface.commit on a sub-surface will
- apply the pending state directly, without caching, as happens
- normally with a wl_surface. Calling wl_surface.commit on the
- parent surface has no effect on the sub-surface's wl_surface
- state. This mode allows a sub-surface to be updated on its own.
-
- If cached state exists when wl_surface.commit is called in
- desynchronized mode, the pending state is added to the cached
- state, and applied as a whole. This invalidates the cache.
-
- Note: even if a sub-surface is set to desynchronized, a parent
- sub-surface may override it to behave as synchronized. For details,
- see wl_subsurface.
-
- If a surface's parent surface behaves as desynchronized, then
- the cached state is applied on set_desync.
+ See wl_subsurface and wl_surface.commit for more information.