diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-03-27 14:15:30 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-03-27 15:23:15 +0000 |
commit | 25ca8f136cef9e1bdf06967bf8e78c87b54ffce2 (patch) | |
tree | 832f63db652ea1ccef14965784dc92b44d8b57ee /src | |
parent | e3810cff42bca1badc5844002694a6f582c0f423 (diff) |
sna: Support variable sized cursors
One of the downsides with supporting large cursors is that the full size
is very rarely used leading to a waste of permanently allocated
resources. Refactor our cursor handling so that we can allocate fresh
cursors on the fly that are appropriately sized.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src')
-rw-r--r-- | src/sna/sna.h | 21 | ||||
-rw-r--r-- | src/sna/sna_display.c | 706 | ||||
-rw-r--r-- | src/sna/sna_driver.c | 20 |
3 files changed, 604 insertions, 143 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h index f0ddda59..5253475e 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -108,6 +108,7 @@ void LogF(const char *f, ...); #define SNA_CURSOR_X 64 #define SNA_CURSOR_Y SNA_CURSOR_X +struct sna_cursor; struct sna_client { int is_compositor; /* only 4 bits used */ @@ -279,14 +280,26 @@ struct sna { int shadow_flip; int front_active; - unsigned short cursor_width; - unsigned short cursor_height; - unsigned num_real_crtc; unsigned num_real_output; unsigned num_fake; } mode; + struct { + struct sna_cursor *cursors; + xf86CursorInfoPtr info; + CursorPtr ref; + + unsigned serial; + uint32_t fg, bg; + + int last_x; + int last_y; + + unsigned short max_width; + unsigned short max_height; + } cursor; + struct sna_dri { void *flip_pending; } dri; @@ -369,6 +382,8 @@ extern void sna_mode_redisplay(struct sna *sna); extern void sna_mode_close(struct sna *sna); extern void sna_mode_fini(struct sna *sna); +extern bool sna_cursors_init(ScreenPtr screen, struct sna *sna); + extern int sna_page_flip(struct sna *sna, struct kgem_bo *bo, void *data, diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index c5992e8f..d3275836 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -1,6 +1,6 @@ /* * Copyright © 2007 Red Hat, Inc. - * Copyright © 2013 Intel Corporation + * Copyright © 2013-2014 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -33,6 +33,7 @@ #include <stdint.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/mman.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> @@ -46,6 +47,7 @@ #include "backlight.h" #include <xf86Crtc.h> +#include <cursorstr.h> #if XF86_CRTC_VERSION >= 3 #define HAS_GAMMA 1 @@ -275,14 +277,33 @@ static uint32_t gem_create(int fd, int size) { struct drm_i915_gem_create create; + assert((size & 4095) == 0); + VG_CLEAR(create); create.handle = 0; - create.size = ALIGN(size, 4096); + create.size = size; (void)drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); return create.handle; } +static void *gem_mmap(int fd, int handle, int size) +{ + struct drm_i915_gem_mmap_gtt mmap_arg; + void *ptr; + + VG_CLEAR(mmap_arg); + mmap_arg.handle = handle; + if (drmIoctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg)) + return NULL; + + ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mmap_arg.offset); + if (ptr == MAP_FAILED) + return NULL; + + return ptr; +} + static void gem_close(int fd, uint32_t handle) { struct drm_gem_close close; @@ -1618,83 +1639,6 @@ void sna_mode_adjust_frame(struct sna *sna, int x, int y) } static void -sna_crtc_hide_cursor(xf86CrtcPtr crtc) -{ - struct sna_crtc *sna_crtc = to_sna_crtc(crtc); - struct drm_mode_cursor arg; - - __DBG(("%s: CRTC:%d\n", __FUNCTION__, sna_crtc->id)); - - VG_CLEAR(arg); - arg.flags = DRM_MODE_CURSOR_BO; - arg.crtc_id = sna_crtc->id; - arg.width = arg.height = 0; - arg.handle = 0; - - (void)drmIoctl(to_sna(crtc->scrn)->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg); -} - -static void -sna_crtc_show_cursor(xf86CrtcPtr crtc) -{ - struct sna_crtc *sna_crtc = to_sna_crtc(crtc); - struct sna *sna = to_sna(crtc->scrn); - struct drm_mode_cursor arg; - - __DBG(("%s: CRTC:%d\n", __FUNCTION__, sna_crtc->id)); - - VG_CLEAR(arg); - arg.flags = DRM_MODE_CURSOR_BO; - arg.crtc_id = sna_crtc->id; - arg.width = sna->mode.cursor_width; - arg.height = sna->mode.cursor_height; - arg.handle = sna_crtc->cursor; - - (void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg); -} - -static void -sna_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg) -{ - __DBG(("%s: CRTC:%d (bg=%x, fg=%x)\n", __FUNCTION__, - to_sna_crtc(crtc)->id, bg, fg)); -} - -static void -sna_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y) -{ - struct sna_crtc *sna_crtc = to_sna_crtc(crtc); - struct drm_mode_cursor arg; - - __DBG(("%s: CRTC:%d (%d, %d)\n", __FUNCTION__, sna_crtc->id, x, y)); - - VG_CLEAR(arg); - arg.flags = DRM_MODE_CURSOR_MOVE; - arg.crtc_id = sna_crtc->id; - arg.x = x; - arg.y = y; - arg.handle = sna_crtc->cursor; - - (void)drmIoctl(to_sna(crtc->scrn)->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg); -} - -static void -sna_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image) -{ - struct sna *sna = to_sna(crtc->scrn); - struct drm_i915_gem_pwrite pwrite; - - __DBG(("%s: CRTC:%d\n", __FUNCTION__, to_sna_crtc(crtc)->id)); - - VG_CLEAR(pwrite); - pwrite.handle = to_sna_crtc(crtc)->cursor; - pwrite.offset = 0; - pwrite.size = sna->mode.cursor_width*sna->mode.cursor_height*4; - pwrite.data_ptr = (uintptr_t)image; - (void)drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite); -} - -static void sna_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, int size) { @@ -1711,9 +1655,6 @@ sna_crtc_destroy(xf86CrtcPtr crtc) if (sna_crtc == NULL) return; - sna_crtc_hide_cursor(crtc); - gem_close(to_sna(crtc->scrn)->kgem.fd, sna_crtc->cursor); - free(sna_crtc); crtc->driver_private = NULL; } @@ -1735,11 +1676,6 @@ static const xf86CrtcFuncsRec sna_crtc_funcs = { .dpms = sna_crtc_dpms, #endif .set_mode_major = sna_crtc_set_mode_major, - .set_cursor_colors = sna_crtc_set_cursor_colors, - .set_cursor_position = sna_crtc_set_cursor_position, - .show_cursor = sna_crtc_show_cursor, - .hide_cursor = sna_crtc_hide_cursor, - .load_cursor_argb = sna_crtc_load_cursor_argb, .gamma_set = sna_crtc_gamma_set, .destroy = sna_crtc_destroy, #if HAS_PIXMAP_SHARING @@ -1812,6 +1748,20 @@ sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *sna_crtc) sna_crtc->sprite_rotation.supported, sna_crtc->sprite_rotation.current)); } +static void +sna_crtc_init__cursor(struct sna *sna, struct sna_crtc *crtc) +{ + struct drm_mode_cursor arg; + + VG_CLEAR(arg); + arg.flags = DRM_MODE_CURSOR_BO; + arg.crtc_id = crtc->id; + arg.width = arg.height = 0; + arg.handle = 0; + + (void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg); +} + static bool sna_crtc_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num) { @@ -1853,17 +1803,8 @@ sna_crtc_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num) return false; } - sna_crtc->cursor = gem_create(sna->kgem.fd, - sna->mode.cursor_width*sna->mode.cursor_height*4); - if (!sna_crtc->cursor) { - xf86CrtcDestroy(crtc); - free(sna_crtc); - return false; - } - DBG(("%s: created handle=%d for cursor on CRTC:%d\n", - __FUNCTION__, sna_crtc->cursor, sna_crtc->id)); - sna_crtc_init__rotation(sna, sna_crtc); + sna_crtc_init__cursor(sna, sna_crtc); crtc->driver_private = sna_crtc; DBG(("%s: attached crtc[%d] id=%d, pipe=%d\n", @@ -3037,6 +2978,543 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height) return TRUE; } +/* cursor handling */ +struct sna_cursor { + struct sna_cursor *next; + uint32_t *image; + Rotation rotation; + int size; + unsigned handle; + unsigned serial; + unsigned alloc; +}; + +static void +rotate_coord(Rotation rotation, int width, int height, + int x_dst, int y_dst, + int *x_src, int *y_src) +{ + int t; + + switch (rotation & 0xf) { + case RR_Rotate_0: + break; + case RR_Rotate_90: + t = x_dst; + x_dst = height - y_dst - 1; + y_dst = t; + break; + case RR_Rotate_180: + x_dst = width - x_dst - 1; + y_dst = height - y_dst - 1; + break; + case RR_Rotate_270: + t = x_dst; + x_dst = y_dst; + y_dst = width - t - 1; + break; + } + + if (rotation & RR_Reflect_X) + x_dst = width - x_dst - 1; + if (rotation & RR_Reflect_Y) + y_dst = height - y_dst - 1; + + *x_src = x_dst; + *y_src = y_dst; +} + +static void +rotate_coord_back(Rotation rotation, int width, int height, + int x_dst, int y_dst, + int *x_src, int *y_src) +{ + int t; + + if (rotation & RR_Reflect_X) + x_dst = width - x_dst - 1; + if (rotation & RR_Reflect_Y) + y_dst = height - y_dst - 1; + + switch (rotation & 0xf) { + case RR_Rotate_0: + break; + case RR_Rotate_90: + t = x_dst; + x_dst = y_dst; + y_dst = width - t - 1; + break; + case RR_Rotate_180: + x_dst = width - x_dst - 1; + y_dst = height - y_dst - 1; + break; + case RR_Rotate_270: + t = x_dst; + x_dst = height - y_dst - 1; + y_dst = t; + break; + } + *x_src = x_dst; + *y_src = y_dst; +} + +static struct sna_cursor *__sna_create_cursor(struct sna *sna, unsigned size) +{ + struct sna_cursor *c; + + __DBG(("%s(size=%d)\n", __FUNCTION__, size)); + + c = malloc(sizeof(*c)); + if (c == NULL) + return NULL; + + size = size * size * 4; + c->alloc = ALIGN(size, 4096); + c->handle = gem_create(sna->kgem.fd, c->alloc); + if (c->handle == 0) { + free(c); + return NULL; + } + + c->image = gem_mmap(sna->kgem.fd, c->handle, c->alloc); + if (c->image == NULL) { + gem_close(sna->kgem.fd, c->handle); + free(c); + return NULL; + } + + __DBG(("%s: handle=%d, allocated %d\n", __FUNCTION__, c->handle, size)); + + c->serial = 0; + c->next = sna->cursor.cursors; + sna->cursor.cursors = c; + + return c; +} + +static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc) +{ + struct sna_cursor *cursor; + Rotation rotation; + int width, height, size; + int i, x, y; + uint32_t *src; + + if (sna->cursor.ref == NULL || sna->cursor.ref->bits == NULL) + return NULL; + + __DBG(("%s: cursor=%dx%d\n", __FUNCTION__, + sna->cursor.ref->bits->width, + sna->cursor.ref->bits->height)); + + i = MAX(sna->cursor.ref->bits->width, sna->cursor.ref->bits->height); + for (size = 64; size < i; size <<= 1) + ; + assert(size <= sna->cursor.max_width && size <= sna->cursor.max_height); + + rotation = crtc->transform_in_use ? crtc->rotation : RR_Rotate_0; + for (cursor = sna->cursor.cursors; cursor; cursor = cursor->next) + if (cursor->size >= size && cursor->rotation == rotation) + break; + + if (cursor == NULL) { + cursor = __sna_create_cursor(sna, size); + if (cursor == NULL) + return NULL; + } + + __DBG(("%s: using handle=%d, serial=%d, current=%d\n", + __FUNCTION__, cursor->handle, cursor->serial, sna->cursor.serial)); + if (cursor->serial == sna->cursor.serial) + return cursor; + + width = sna->cursor.ref->bits->width; + height = sna->cursor.ref->bits->height; + src = sna->cursor.ref->bits->argb; + if (src == NULL) { + const uint8_t *source = sna->cursor.ref->bits->source; + const uint8_t *mask = sna->cursor.ref->bits->mask; + uint32_t *p; + + __DBG(("%s: converting from 2-color to ARGB\n", __FUNCTION__)); + + src = malloc(4*width*height); + if (src == NULL) + return NULL; + + p = src; + for (y = 0; y < height; y++) { + for (x = 0; x < width / 8; x++) { + uint32_t pixel; + for (i = 0; i < 8; i++) { + if (mask[x] & (1 << i)) { + if (source[x] & (1 << i)) + pixel = sna->cursor.fg; + else + pixel = sna->cursor.bg; + } else + pixel = 0; + *p++ = pixel; + + } + } + } + } + + if (rotation == RR_Rotate_0) { + memcpy_blt(src, cursor->image, 32, + width * 4, size * 4, + 0, 0, + 0, 0, + width, height); + } else { + for (y = 0; y < size; y++) + for (x = 0; x < size; x++) { + uint32_t pixel; + int xin, yin; + + rotate_coord(rotation, size, size, x, y, &xin, &yin); + if (xin < width && yin < height) + pixel = src[yin * width + xin]; + else + pixel = 0; + cursor->image[y * size + x] = pixel; + } + } + + if (src != sna->cursor.ref->bits->argb) + free(src); + + cursor->size = size; + cursor->rotation = rotation; + cursor->serial = sna->cursor.serial; + return cursor; +} + +static unsigned char * +sna_realize_cursor(xf86CursorInfoPtr info, CursorPtr cursor) +{ + return NULL; +} + +static void +sna_show_cursors(ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + struct sna *sna = to_sna(scrn); + int c; + + __DBG(("%s\n", __FUNCTION__)); + + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + struct sna_crtc *sna_crtc = to_sna_crtc(crtc); + struct drm_mode_cursor arg; + struct sna_cursor *cursor; + + if (!sna_crtc) + continue; + + if (!crtc->enabled) + continue; + + if (!crtc->cursor_in_range) + continue; + + cursor = __sna_get_cursor(sna, crtc); + if (cursor == NULL) { + assert(sna_crtc->cursor == 0); + continue; + } + + if (sna_crtc->cursor == cursor->handle) + continue; + + __DBG(("%s: CRTC:%d, handle=%d->%d\n", __FUNCTION__, + sna_crtc->id, sna_crtc->cursor, cursor->handle)); + + VG_CLEAR(arg); + arg.flags = DRM_MODE_CURSOR_BO; + arg.crtc_id = sna_crtc->id; + arg.width = arg.height = cursor->size; + arg.handle = cursor->handle; + + if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) + sna_crtc->cursor = cursor->handle; + } +} + +static void +sna_set_cursor_colors(ScrnInfoPtr scrn, int bg, int fg) +{ + struct sna *sna = to_sna(scrn); + + __DBG(("%s(%08x, %08x)\n", __FUNCTION__, bg, fg)); + + /* Save ARGB versions of these colors */ + sna->cursor.fg = (CARD32) fg | 0xff000000; + sna->cursor.bg = (CARD32) bg | 0xff000000; + + if (sna->cursor.ref == NULL) + return; + + if (sna->cursor.ref->bits->argb) + return; + + sna->cursor.serial++; + sna_show_cursors(scrn); +} + +static void +sna_hide_cursors(ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + struct sna *sna = to_sna(scrn); + int c; + + __DBG(("%s\n", __FUNCTION__)); + + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + struct sna_crtc *sna_crtc = to_sna_crtc(crtc); + struct drm_mode_cursor arg; + + if (!sna_crtc) + continue; + + if (!crtc->enabled) + continue; + + if (!sna_crtc->cursor) + continue; + + __DBG(("%s: CRTC:%d, handle=%d\n", __FUNCTION__, sna_crtc->id, sna_crtc->cursor)); + + VG_CLEAR(arg); + arg.flags = DRM_MODE_CURSOR_BO; + arg.crtc_id = sna_crtc->id; + arg.width = arg.height = 0; + arg.handle = 0; + + if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) + sna_crtc->cursor = 0; + } + + while (sna->cursor.cursors) { + struct sna_cursor *cursor = sna->cursor.cursors; + sna->cursor.cursors = cursor->next; + munmap(cursor->image, cursor->alloc); + gem_close(sna->kgem.fd, cursor->handle); + free(cursor); + } +} + +static void +sna_set_cursor_position(ScrnInfoPtr scrn, int x, int y) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + struct sna *sna = to_sna(scrn); + int c; + + __DBG(("%s(%d, %d)\n", __FUNCTION__, x, y)); + + sna->cursor.last_x = x; + sna->cursor.last_y = y; + + /* undo what xf86HWCurs did to the coordinates */ + x += scrn->frameX0; + y += scrn->frameY0; + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + struct sna_crtc *sna_crtc = to_sna_crtc(crtc); + struct sna_cursor *cursor; + struct drm_mode_cursor arg; + + if (!sna_crtc) + continue; + + VG_CLEAR(arg); + arg.flags = 0; + arg.crtc_id = sna_crtc->id; + arg.handle = 0; + + if (!crtc->enabled) + goto disable; + + cursor = __sna_get_cursor(sna, crtc); + if (cursor == NULL) + goto disable; + + if (crtc->transform_in_use) { + int xhot = sna->cursor.ref->bits->xhot; + int yhot = sna->cursor.ref->bits->yhot; + struct pict_f_vector v; + int dx, dy; + + v.v[0] = (x + xhot) + 0.5; + v.v[1] = (y + yhot) + 0.5; + v.v[2] = 1; + pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &v); + + /* cursor will have 0.5 added to it already so floor is sufficent */ + x = floor(v.v[0]); + y = floor(v.v[1]); + + rotate_coord_back(crtc->rotation, cursor->size, cursor->size, + xhot, yhot, + &dx, &dy); + x -= dx; + y -= dy; + } else { + x -= crtc->x; + y -= crtc->y; + } + + if (x < crtc->mode.HDisplay && x > -cursor->size && + y < crtc->mode.VDisplay && y > -cursor->size) { + arg.flags = DRM_MODE_CURSOR_MOVE; + arg.handle = cursor->handle; + arg.x = x; + arg.y = y; + + if (sna_crtc->cursor != arg.handle) { + arg.flags |= DRM_MODE_CURSOR_BO; + arg.width = arg.height = cursor->size; + } + + crtc->cursor_in_range = true; + } else { +disable: + crtc->cursor_in_range = false; + if (sna_crtc->cursor) { + arg.flags = DRM_MODE_CURSOR_BO; + arg.width = arg.height = arg.handle = 0; + } + } + + __DBG(("%s: CRTC:%d (%d, %d), handle=%d\n", + __FUNCTION__, sna_crtc->id, x, y, arg.handle)); + + if (arg.flags && + drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) + sna_crtc->cursor = arg.handle; + } +} + +static void +sna_load_cursor_argb(ScrnInfoPtr scrn, CursorPtr cursor) +{ +} + +static void +sna_load_cursor_image(ScrnInfoPtr scrn, unsigned char *src) +{ +} + +static Bool +sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor) +{ + struct sna *sna = to_sna_from_screen(screen); + + cursor = RefCursor(cursor); + if (sna->cursor.ref) + FreeCursor(sna->cursor.ref, None); + sna->cursor.ref = cursor; + sna->cursor.serial++; + + __DBG(("%s(%dx%d): ARGB?=%d, serial->%d\n", __FUNCTION__, + cursor->bits->width, + cursor->bits->height, + cursor->bits->argb!=NULL, + sna->cursor.serial)); + + return (cursor->bits->width <= sna->cursor.max_width && + cursor->bits->height <= sna->cursor.max_height); +} + +static void +sna_cursor_pre_init(struct sna *sna) +{ + uint64_t value; + +#define DRM_CAP_CURSOR_WIDTH 8 +#define DRM_CAP_CURSOR_HEIGHT 9 + + sna->cursor.max_width = SNA_CURSOR_X; + sna->cursor.max_height = SNA_CURSOR_Y; + + if (drmGetCap(sna->kgem.fd, DRM_CAP_CURSOR_WIDTH, &value) == 0) + sna->cursor.max_width = value; + + if (drmGetCap(sna->kgem.fd, DRM_CAP_CURSOR_HEIGHT, &value) == 0) + sna->cursor.max_height = value; + + xf86DrvMsg(sna->scrn->scrnIndex, X_PROBED, + "Using a maximum size of %dx%d for hardware cursors\n", + sna->cursor.max_width, + sna->cursor.max_height); + assert(sna->cursor.max_width == sna->cursor.max_height); +} + +bool +sna_cursors_init(ScreenPtr screen, struct sna *sna) +{ + xf86CursorInfoPtr cursor_info; + + if ((sna->cursor.max_width | sna->cursor.max_height) == 0) + return false; + + cursor_info = xf86CreateCursorInfoRec(); + if (cursor_info == NULL) + return false; + + cursor_info->MaxWidth = sna->cursor.max_width; + cursor_info->MaxHeight = sna->cursor.max_height; + cursor_info->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_UPDATE_UNHIDDEN | + HARDWARE_CURSOR_ARGB); + + cursor_info->RealizeCursor = sna_realize_cursor; + cursor_info->SetCursorColors = sna_set_cursor_colors; + cursor_info->SetCursorPosition = sna_set_cursor_position; + cursor_info->LoadCursorImage = sna_load_cursor_image; + cursor_info->HideCursor = sna_hide_cursors; + cursor_info->ShowCursor = sna_show_cursors; + cursor_info->UseHWCursor = sna_use_hw_cursor; +#ifdef ARGB_CURSOR + cursor_info->UseHWCursorARGB = sna_use_hw_cursor; + cursor_info->LoadCursorARGB = sna_load_cursor_argb; +#endif + + if (!xf86InitCursor(screen, cursor_info)) { + xf86DestroyCursorInfoRec(cursor_info); + return false; + } + + sna->cursor.info = cursor_info; + return true; +} + +static void +sna_cursors_reload(struct sna *sna) +{ + sna_set_cursor_position(sna->scrn, sna->cursor.last_x, sna->cursor.last_y); +} + +static void +sna_cursors_fini(struct sna *sna) +{ + if (sna->cursor.info) { + xf86DestroyCursorInfoRec(sna->cursor.info); + sna->cursor.info = NULL; + } + + if (sna->cursor.ref) { + FreeCursor(sna->cursor.ref, None); + sna->cursor.ref = NULL; + } +} + static int do_page_flip(struct sna *sna, struct kgem_bo *bo, void *data, int ref_crtc_hw_id) { @@ -3465,32 +3943,12 @@ sanitize_outputs(struct sna *sna) static void sna_crtc_config_notify(ScreenPtr screen) { - DBG(("%s\n", __FUNCTION__)); - sna_mode_update(to_sna_from_screen(screen)); - xf86_reload_cursors(screen); -} - -static void -sna_cursor_pre_init(struct sna *sna) -{ - uint64_t value; - -#define DRM_CAP_CURSOR_WIDTH 8 -#define DRM_CAP_CURSOR_HEIGHT 9 - - sna->mode.cursor_width = SNA_CURSOR_X; - sna->mode.cursor_height = SNA_CURSOR_Y; + struct sna *sna = to_sna_from_screen(screen); - if (drmGetCap(sna->kgem.fd, DRM_CAP_CURSOR_WIDTH, &value) == 0) - sna->mode.cursor_width = value; - - if (drmGetCap(sna->kgem.fd, DRM_CAP_CURSOR_HEIGHT, &value) == 0) - sna->mode.cursor_height = value; + DBG(("%s\n", __FUNCTION__)); - xf86DrvMsg(sna->scrn->scrnIndex, X_PROBED, - "Using a maximum size of %dx%d for hardware cursors\n", - sna->mode.cursor_width, - sna->mode.cursor_height); + sna_mode_update(sna); + sna_cursors_reload(sna); } #if HAS_PIXMAP_SHARING @@ -3575,6 +4033,8 @@ sna_mode_close(struct sna *sna) if (sna->flags & SNA_IS_HOSTED) return; + sna_hide_cursors(sna->scrn); + for (i = 0; i < config->num_crtc; i++) { struct sna_crtc *crtc; @@ -3584,6 +4044,8 @@ sna_mode_close(struct sna *sna) sna_crtc_disable_shadow(sna, crtc); } + + sna_cursors_fini(sna); } void @@ -4096,6 +4558,8 @@ void sna_mode_reset(struct sna *sna) if (sna->flags & SNA_IS_HOSTED) return; + sna_hide_cursors(sna->scrn); + for (i = 0; i < config->num_crtc; i++) { struct sna_crtc *sna_crtc = to_sna_crtc(config->crtc[i]); if (sna_crtc == NULL) diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c index f9e58d40..42065f1b 100644 --- a/src/sna/sna_driver.c +++ b/src/sna/sna_driver.c @@ -806,8 +806,6 @@ static void sna_leave_vt(VT_FUNC_ARGS_DECL) DBG(("%s\n", __FUNCTION__)); - xf86_hide_cursors(scrn); - sna_mode_reset(to_sna(scrn)); if (intel_put_master(scrn)) @@ -824,9 +822,7 @@ static Bool sna_early_close_screen(CLOSE_SCREEN_ARGS_DECL) /* XXX Note that we will leak kernel resources if !vtSema */ - xf86_hide_cursors(scrn); sna_uevent_fini(scrn); - sna_mode_close(sna); if (sna->dri_open) { @@ -844,8 +840,6 @@ static Bool sna_early_close_screen(CLOSE_SCREEN_ARGS_DECL) scrn->vtSema = FALSE; } - xf86_cursors_fini(screen); - return sna->CloseScreen(CLOSE_SCREEN_ARGS); } @@ -999,19 +993,7 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL) if (!miDCInitialize(screen, xf86GetPointerScreenFuncs())) return FALSE; - if (sna->mode.cursor_width && - sna->mode.cursor_height && - xf86_cursors_init(screen, - sna->mode.cursor_width, - sna->mode.cursor_height, - HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | - HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | - HARDWARE_CURSOR_INVERT_MASK | - HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | - HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | - HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | - HARDWARE_CURSOR_UPDATE_UNHIDDEN | - HARDWARE_CURSOR_ARGB)) + if (sna_cursors_init(screen, sna)) xf86DrvMsg(scrn->scrnIndex, X_INFO, "HW Cursor enabled\n"); /* Must force it before EnterVT, so we are in control of VT and |