summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-03-27 14:15:30 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2014-03-27 15:23:15 +0000
commit25ca8f136cef9e1bdf06967bf8e78c87b54ffce2 (patch)
tree832f63db652ea1ccef14965784dc92b44d8b57ee
parente3810cff42bca1badc5844002694a6f582c0f423 (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>
-rw-r--r--src/sna/sna.h21
-rw-r--r--src/sna/sna_display.c706
-rw-r--r--src/sna/sna_driver.c20
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