drm: Make KMS hw cursors work again
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 21e59c8..7023a8c 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -95,6 +95,8 @@
drmModeCrtcPtr original_crtc;
struct gbm_surface *surface;
+ struct gbm_bo *cursor_bo[2];
+ int current_cursor;
EGLSurface egl_surface;
struct drm_fb *current, *next;
struct backlight *backlight;
@@ -657,8 +659,7 @@
} else {
if (!prior_was_hardware)
weston_surface_damage_below(device->sprite);
- pixman_region32_fini(&device->sprite->damage);
- pixman_region32_init(&device->sprite->damage);
+ wl_list_remove(&device->sprite->link);
device->hw_cursor = 1;
}
@@ -670,7 +671,7 @@
drm_assign_planes(struct weston_output *output)
{
struct weston_compositor *ec = output->compositor;
- struct weston_surface *es;
+ struct weston_surface *es, *next;
pixman_region32_t overlap, surface_overlap;
struct weston_input_device *device;
@@ -688,7 +689,7 @@
* as we do for flipping full screen surfaces.
*/
pixman_region32_init(&overlap);
- wl_list_for_each(es, &ec->surface_list, link) {
+ wl_list_for_each_safe(es, next, &ec->surface_list, link) {
/*
* FIXME: try to assign hw cursors here too, they're just
* special overlays
@@ -730,36 +731,42 @@
EGLint handle, stride;
int ret = -1;
struct gbm_bo *bo;
+ uint32_t buf[64 * 64];
+ unsigned char *d, *s, *end;
if (eid == NULL) {
drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
return 0;
}
- if (eid->sprite->image == EGL_NO_IMAGE_KHR)
+ if (eid->sprite->buffer == NULL ||
+ !wl_buffer_is_shm(eid->sprite->buffer))
goto out;
if (eid->sprite->geometry.width > 64 ||
eid->sprite->geometry.height > 64)
goto out;
- bo = gbm_bo_create_from_egl_image(c->gbm,
- c->base.display,
- eid->sprite->image, 64, 64,
- GBM_BO_USE_CURSOR_64X64);
- /* Not suitable for hw cursor, fall back */
+ output->current_cursor ^= 1;
+ bo = output->cursor_bo[output->current_cursor];
if (bo == NULL)
goto out;
- handle = gbm_bo_get_handle(bo).s32;
- stride = gbm_bo_get_pitch(bo);
- gbm_bo_destroy(bo);
+ memset(buf, 0, sizeof buf);
+ d = (unsigned char *) buf;
+ stride = wl_shm_buffer_get_stride(eid->sprite->buffer);
+ s = wl_shm_buffer_get_data(eid->sprite->buffer);
+ end = s + stride * eid->sprite->geometry.height;
+ while (s < end) {
+ memcpy(d, s, eid->sprite->geometry.width * 4);
+ s += stride;
+ d += 64 * 4;
+ }
- /* gbm_bo_create_from_egl_image() didn't always validate the usage
- * flags, and in that case we might end up with a bad stride. */
- if (stride != 64 * 4)
+ if (gbm_bo_write(bo, buf, sizeof buf) < 0)
goto out;
+ handle = gbm_bo_get_handle(bo).s32;
ret = drmModeSetCursor(c->drm.fd, output->crtc_id, handle, 64, 64);
if (ret) {
fprintf(stderr, "failed to set cursor: %s\n", strerror(-ret));
@@ -1304,6 +1311,13 @@
goto err_surface;
}
+ output->cursor_bo[0] =
+ gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888,
+ GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
+ output->cursor_bo[1] =
+ gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888,
+ GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
+
output->backlight = backlight_init(drm_device,
connector->connector_type);
if (output->backlight) {