backend-drm: Clear drm_output cursor_view when view is destroyed
The DRM backend uses changes in the cursor view memory address and surface damage to detect when it needs to re-upload to a cursor plane framebuffer. However, when a cursor view is destroyed and then recreated, e.g., when the pointer cursor surface is updated, the newly created view may have the same memory address as the just destroyed one. If no new cursor buffer is provided (because it was attached, committed and used previously) when this address reuse occurs, then there also isn't any updated surface damage and the backend doesn't update the cursor plane framebuffer at all. To fix this issue utilize the destroy signal to track when the cursor view is destroyed, and clear the cached cursor_view value in drm_output. After clearing the cached value, the next cursor view is always considered new and thus uploaded to the plane properly. Signed-off-by: Alexandros Frantzis <alexandros.frantzis@collabora.com>
This commit is contained in:
parent
f0c6104444
commit
10937feef8
|
@ -511,6 +511,7 @@ struct drm_output {
|
|||
struct drm_fb *gbm_cursor_fb[2];
|
||||
struct drm_plane *cursor_plane;
|
||||
struct weston_view *cursor_view;
|
||||
struct wl_listener cursor_view_destroy_listener;
|
||||
int current_cursor;
|
||||
|
||||
struct gbm_surface *gbm_surface;
|
||||
|
@ -688,6 +689,9 @@ struct drm_fb *
|
|||
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend,
|
||||
bool is_opaque, enum drm_fb_type type);
|
||||
|
||||
void
|
||||
drm_output_set_cursor_view(struct drm_output *output, struct weston_view *ev);
|
||||
|
||||
#ifdef BUILD_DRM_GBM
|
||||
extern struct drm_fb *
|
||||
drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev);
|
||||
|
|
|
@ -1793,6 +1793,8 @@ drm_output_destroy(struct weston_output *base)
|
|||
return;
|
||||
}
|
||||
|
||||
drm_output_set_cursor_view(output, NULL);
|
||||
|
||||
if (output->base.enabled)
|
||||
drm_output_deinit(&output->base);
|
||||
|
||||
|
|
|
@ -669,7 +669,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
|
|||
* cursor plane set up.
|
||||
*/
|
||||
if (output->base.disable_planes) {
|
||||
output->cursor_view = NULL;
|
||||
drm_output_set_cursor_view(output, NULL);
|
||||
if (output->cursor_plane) {
|
||||
output->cursor_plane->base.x = INT32_MIN;
|
||||
output->cursor_plane->base.y = INT32_MIN;
|
||||
|
@ -777,7 +777,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
|
|||
return 0;
|
||||
|
||||
err:
|
||||
output->cursor_view = NULL;
|
||||
drm_output_set_cursor_view(output, NULL);
|
||||
drm_output_state_free(state);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -381,7 +381,7 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state,
|
|||
needs_update = true;
|
||||
}
|
||||
|
||||
output->cursor_view = ev;
|
||||
drm_output_set_cursor_view(output, ev);
|
||||
plane_state->ev = ev;
|
||||
|
||||
plane_state->fb =
|
||||
|
@ -1156,6 +1156,41 @@ drm_assign_planes(struct weston_output *output_base, void *repaint_data)
|
|||
drm_output_state_get_existing_plane(state,
|
||||
output->cursor_plane);
|
||||
if (!plane_state || !plane_state->fb)
|
||||
output->cursor_view = NULL;
|
||||
drm_output_set_cursor_view(output, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
drm_output_handle_cursor_view_destroy(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct drm_output *output =
|
||||
container_of(listener, struct drm_output,
|
||||
cursor_view_destroy_listener);
|
||||
|
||||
drm_output_set_cursor_view(output, NULL);
|
||||
}
|
||||
|
||||
/** Set the current cursor view used for an output.
|
||||
*
|
||||
* Ensure the stored value will be properly cleared if the view is destroyed.
|
||||
* The stored cursor view helps avoid unnecessary uploads of cursor data to
|
||||
* cursor plane buffer objects (see drm_output_prepare_cursor_view).
|
||||
*/
|
||||
void
|
||||
drm_output_set_cursor_view(struct drm_output *output, struct weston_view *ev)
|
||||
{
|
||||
if (output->cursor_view == ev)
|
||||
return;
|
||||
|
||||
if (output->cursor_view)
|
||||
wl_list_remove(&output->cursor_view_destroy_listener.link);
|
||||
|
||||
output->cursor_view = ev;
|
||||
|
||||
if (ev) {
|
||||
output->cursor_view_destroy_listener.notify =
|
||||
drm_output_handle_cursor_view_destroy;
|
||||
wl_signal_add(&ev->destroy_signal,
|
||||
&output->cursor_view_destroy_listener);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue