drm: Make KMS hw cursors work again

dev
Kristian Høgsberg 13 years ago
parent 1493d2ae1c
commit 8e1f77fee3
  1. 46
      src/compositor-drm.c

@ -95,6 +95,8 @@ struct drm_output {
drmModeCrtcPtr original_crtc; drmModeCrtcPtr original_crtc;
struct gbm_surface *surface; struct gbm_surface *surface;
struct gbm_bo *cursor_bo[2];
int current_cursor;
EGLSurface egl_surface; EGLSurface egl_surface;
struct drm_fb *current, *next; struct drm_fb *current, *next;
struct backlight *backlight; struct backlight *backlight;
@ -657,8 +659,7 @@ weston_output_set_cursor(struct weston_output *output,
} else { } else {
if (!prior_was_hardware) if (!prior_was_hardware)
weston_surface_damage_below(device->sprite); weston_surface_damage_below(device->sprite);
pixman_region32_fini(&device->sprite->damage); wl_list_remove(&device->sprite->link);
pixman_region32_init(&device->sprite->damage);
device->hw_cursor = 1; device->hw_cursor = 1;
} }
@ -670,7 +671,7 @@ static void
drm_assign_planes(struct weston_output *output) drm_assign_planes(struct weston_output *output)
{ {
struct weston_compositor *ec = output->compositor; struct weston_compositor *ec = output->compositor;
struct weston_surface *es; struct weston_surface *es, *next;
pixman_region32_t overlap, surface_overlap; pixman_region32_t overlap, surface_overlap;
struct weston_input_device *device; struct weston_input_device *device;
@ -688,7 +689,7 @@ drm_assign_planes(struct weston_output *output)
* as we do for flipping full screen surfaces. * as we do for flipping full screen surfaces.
*/ */
pixman_region32_init(&overlap); 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 * FIXME: try to assign hw cursors here too, they're just
* special overlays * special overlays
@ -730,36 +731,42 @@ drm_output_set_cursor(struct weston_output *output_base,
EGLint handle, stride; EGLint handle, stride;
int ret = -1; int ret = -1;
struct gbm_bo *bo; struct gbm_bo *bo;
uint32_t buf[64 * 64];
unsigned char *d, *s, *end;
if (eid == NULL) { if (eid == NULL) {
drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0); drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
return 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; goto out;
if (eid->sprite->geometry.width > 64 || if (eid->sprite->geometry.width > 64 ||
eid->sprite->geometry.height > 64) eid->sprite->geometry.height > 64)
goto out; goto out;
bo = gbm_bo_create_from_egl_image(c->gbm, output->current_cursor ^= 1;
c->base.display, bo = output->cursor_bo[output->current_cursor];
eid->sprite->image, 64, 64,
GBM_BO_USE_CURSOR_64X64);
/* Not suitable for hw cursor, fall back */
if (bo == NULL) if (bo == NULL)
goto out; goto out;
handle = gbm_bo_get_handle(bo).s32; memset(buf, 0, sizeof buf);
stride = gbm_bo_get_pitch(bo); d = (unsigned char *) buf;
gbm_bo_destroy(bo); 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 if (gbm_bo_write(bo, buf, sizeof buf) < 0)
* flags, and in that case we might end up with a bad stride. */
if (stride != 64 * 4)
goto out; goto out;
handle = gbm_bo_get_handle(bo).s32;
ret = drmModeSetCursor(c->drm.fd, output->crtc_id, handle, 64, 64); ret = drmModeSetCursor(c->drm.fd, output->crtc_id, handle, 64, 64);
if (ret) { if (ret) {
fprintf(stderr, "failed to set cursor: %s\n", strerror(-ret)); fprintf(stderr, "failed to set cursor: %s\n", strerror(-ret));
@ -1304,6 +1311,13 @@ create_output_for_connector(struct drm_compositor *ec,
goto err_surface; 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, output->backlight = backlight_init(drm_device,
connector->connector_type); connector->connector_type);
if (output->backlight) { if (output->backlight) {

Loading…
Cancel
Save