backend-drm can't place surface on plane until next buffer commit after disabling and re-enabling planes
(This issue was first discussed in comments in !636 (merged))
When an output is repainted, after the backend and the renderer have seen the damage for the surfaces, the core references to the buffers held by the surfaces themselves are dropped. In some cases the backend wants to retain that core buffer reference and can use the weston_surface.keep_buffer
flag for that.
The DRM backend uses keep_buffer
to maintain the buffer reference, to ensure that it has access to all the information to attempt to place the buffer into a plane in some future repaint. The DRM backend sets the keep_buffer
flag in the drm_assign_planes()
function.
Normally this is enough, but there are some scenarios that cause a surface to become unable to be placed on a plane (when it normally would be a candidate) until a new buffer attachment/commit. In particular, issues can occur when some component uses weston_output_disable_planes_incr() to disable planes, causing the drm_assign_planes() call to be skipped, thus not setting the keep_buffer
flag and dropping the core surface buffer reference. Without that core reference, the DRM backend can't place
the surface on the plane even after planes have been reenabled, until the next buffer attach/commit for that surface which introduces a new surface buffer reference.
Here is an example that involves the cursor plane:
- Zoom in (zoom disables planes with weston_output_disable_planes_incr())
- Pointer enters a surface that sets a cursor surface with a pre-attached/committed buffer.
- Since drm_assign_planes() is skipped (due to zoom) at next redraw the weston_surface.buffer_ref is dropped.
- Zoom out
- Since we don't have a valid weston_surface.buffer_ref, a plane cannot be used for that cursor_surface (e.g., when pointer reenters), until we commit a new buffer.