compositor-drm: Use plane_state_coords_for_view for cursor
Use the new helper to populate the cursor state as well, with some special-case handling to account for how we always upload a full-size BO. As this now fully takes care of buffer transformations, HiDPI client cursors work, and we also clip the cursor plane completely to CRTC bounds. Signed-off-by: Daniel Stone <daniels@collabora.com> Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> Reported-by: Derek Foreman <derekf@osg.samsung.com> Tested-by: Emre Ucan <eucan@de.adit-jv.com> Fixes: https://gitlab.freedesktop.org/wayland/weston/issues/118
This commit is contained in:
+34
-36
@@ -2876,14 +2876,14 @@ err:
|
|||||||
/**
|
/**
|
||||||
* Update the image for the current cursor surface
|
* Update the image for the current cursor surface
|
||||||
*
|
*
|
||||||
* @param b DRM backend structure
|
* @param plane_state DRM cursor plane state
|
||||||
* @param bo GBM buffer object to write into
|
* @param ev Source view for cursor
|
||||||
* @param ev View to use for cursor image
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
cursor_bo_update(struct drm_backend *b, struct gbm_bo *bo,
|
cursor_bo_update(struct drm_plane_state *plane_state, struct weston_view *ev)
|
||||||
struct weston_view *ev)
|
|
||||||
{
|
{
|
||||||
|
struct drm_backend *b = plane_state->plane->backend;
|
||||||
|
struct gbm_bo *bo = plane_state->fb->bo;
|
||||||
struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
|
struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
|
||||||
uint32_t buf[b->cursor_width * b->cursor_height];
|
uint32_t buf[b->cursor_width * b->cursor_height];
|
||||||
int32_t stride;
|
int32_t stride;
|
||||||
@@ -2892,18 +2892,18 @@ cursor_bo_update(struct drm_backend *b, struct gbm_bo *bo,
|
|||||||
|
|
||||||
assert(buffer && buffer->shm_buffer);
|
assert(buffer && buffer->shm_buffer);
|
||||||
assert(buffer->shm_buffer == wl_shm_buffer_get(buffer->resource));
|
assert(buffer->shm_buffer == wl_shm_buffer_get(buffer->resource));
|
||||||
assert(ev->surface->width <= b->cursor_width);
|
assert(buffer->width <= b->cursor_width);
|
||||||
assert(ev->surface->height <= b->cursor_height);
|
assert(buffer->height <= b->cursor_height);
|
||||||
|
|
||||||
memset(buf, 0, sizeof buf);
|
memset(buf, 0, sizeof buf);
|
||||||
stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
|
stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
|
||||||
s = wl_shm_buffer_get_data(buffer->shm_buffer);
|
s = wl_shm_buffer_get_data(buffer->shm_buffer);
|
||||||
|
|
||||||
wl_shm_buffer_begin_access(buffer->shm_buffer);
|
wl_shm_buffer_begin_access(buffer->shm_buffer);
|
||||||
for (i = 0; i < ev->surface->height; i++)
|
for (i = 0; i < buffer->height; i++)
|
||||||
memcpy(buf + i * b->cursor_width,
|
memcpy(buf + i * b->cursor_width,
|
||||||
s + i * stride,
|
s + i * stride,
|
||||||
ev->surface->width * 4);
|
buffer->width * 4);
|
||||||
wl_shm_buffer_end_access(buffer->shm_buffer);
|
wl_shm_buffer_end_access(buffer->shm_buffer);
|
||||||
|
|
||||||
if (gbm_bo_write(bo, buf, sizeof buf) < 0)
|
if (gbm_bo_write(bo, buf, sizeof buf) < 0)
|
||||||
@@ -2918,10 +2918,8 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state,
|
|||||||
struct drm_backend *b = to_drm_backend(output->base.compositor);
|
struct drm_backend *b = to_drm_backend(output->base.compositor);
|
||||||
struct drm_plane *plane = output->cursor_plane;
|
struct drm_plane *plane = output->cursor_plane;
|
||||||
struct drm_plane_state *plane_state;
|
struct drm_plane_state *plane_state;
|
||||||
struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
|
|
||||||
struct wl_shm_buffer *shmbuf;
|
struct wl_shm_buffer *shmbuf;
|
||||||
bool needs_update = false;
|
bool needs_update = false;
|
||||||
float x, y;
|
|
||||||
|
|
||||||
if (!plane)
|
if (!plane)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2951,26 +2949,25 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state,
|
|||||||
if (wl_shm_buffer_get_format(shmbuf) != WL_SHM_FORMAT_ARGB8888)
|
if (wl_shm_buffer_get_format(shmbuf) != WL_SHM_FORMAT_ARGB8888)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
|
|
||||||
return NULL;
|
|
||||||
if (ev->transform.enabled &&
|
|
||||||
(ev->transform.matrix.type > WESTON_MATRIX_TRANSFORM_TRANSLATE))
|
|
||||||
return NULL;
|
|
||||||
if (viewport->buffer.scale != output->base.current_scale)
|
|
||||||
return NULL;
|
|
||||||
if (ev->geometry.scissor_enabled)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (ev->surface->width > b->cursor_width ||
|
|
||||||
ev->surface->height > b->cursor_height)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
plane_state =
|
plane_state =
|
||||||
drm_output_state_get_plane(output_state, output->cursor_plane);
|
drm_output_state_get_plane(output_state, output->cursor_plane);
|
||||||
|
|
||||||
if (plane_state && plane_state->fb)
|
if (plane_state && plane_state->fb)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* We can't scale with the legacy API, and we don't try to account for
|
||||||
|
* simple cropping/translation in cursor_bo_update. */
|
||||||
|
plane_state->output = output;
|
||||||
|
if (!drm_plane_state_coords_for_view(plane_state, ev))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (plane_state->src_x != 0 || plane_state->src_y != 0 ||
|
||||||
|
plane_state->src_w > (unsigned) b->cursor_width << 16 ||
|
||||||
|
plane_state->src_h > (unsigned) b->cursor_height << 16 ||
|
||||||
|
plane_state->src_w != plane_state->dest_w << 16 ||
|
||||||
|
plane_state->src_h != plane_state->dest_h << 16)
|
||||||
|
goto err;
|
||||||
|
|
||||||
/* Since we're setting plane state up front, we need to work out
|
/* Since we're setting plane state up front, we need to work out
|
||||||
* whether or not we need to upload a new cursor. We can't use the
|
* whether or not we need to upload a new cursor. We can't use the
|
||||||
* plane damage, since the planes haven't actually been calculated
|
* plane damage, since the planes haven't actually been calculated
|
||||||
@@ -2987,26 +2984,27 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
output->cursor_view = ev;
|
output->cursor_view = ev;
|
||||||
weston_view_to_global_float(ev, 0, 0, &x, &y);
|
|
||||||
plane->base.x = x;
|
|
||||||
plane->base.y = y;
|
|
||||||
|
|
||||||
plane_state->fb =
|
plane_state->fb =
|
||||||
drm_fb_ref(output->gbm_cursor_fb[output->current_cursor]);
|
drm_fb_ref(output->gbm_cursor_fb[output->current_cursor]);
|
||||||
plane_state->output = output;
|
|
||||||
plane_state->src_x = 0;
|
if (needs_update)
|
||||||
plane_state->src_y = 0;
|
cursor_bo_update(plane_state, ev);
|
||||||
|
|
||||||
|
/* The cursor API is somewhat special: in cursor_bo_update(), we upload
|
||||||
|
* a buffer which is always cursor_width x cursor_height, even if the
|
||||||
|
* surface we want to promote is actually smaller than this. Manually
|
||||||
|
* mangle the plane state to deal with this. */
|
||||||
plane_state->src_w = b->cursor_width << 16;
|
plane_state->src_w = b->cursor_width << 16;
|
||||||
plane_state->src_h = b->cursor_height << 16;
|
plane_state->src_h = b->cursor_height << 16;
|
||||||
plane_state->dest_x = (x - output->base.x) * output->base.current_scale;
|
|
||||||
plane_state->dest_y = (y - output->base.y) * output->base.current_scale;
|
|
||||||
plane_state->dest_w = b->cursor_width;
|
plane_state->dest_w = b->cursor_width;
|
||||||
plane_state->dest_h = b->cursor_height;
|
plane_state->dest_h = b->cursor_height;
|
||||||
|
|
||||||
if (needs_update)
|
|
||||||
cursor_bo_update(b, plane_state->fb->bo, ev);
|
|
||||||
|
|
||||||
return &plane->base;
|
return &plane->base;
|
||||||
|
|
||||||
|
err:
|
||||||
|
drm_plane_state_put_back(plane_state);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
Reference in New Issue
Block a user